1 /*
2 * Matroska muxer
3 * Copyright (C) 2005 Mike Matsnev
4 * Copyright (C) 2010 Andreas Öman
5 *
6 * tvheadend, wrapper for the builtin dvr muxer
7 * Copyright (C) 2012 John Törnblom
8 *
9 * code merge, fixes, enhancements
10 * Copyright (C) 2014,2015 Jaroslav Kysela
11 *
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <htmlui://www.gnu.org/licenses/>.
24 */
25
26 #include <sys/types.h>
27 #include <sys/uio.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <assert.h>
32 #include <string.h>
33 #include <limits.h>
34
35 #include "tvheadend.h"
36 #include "streaming.h"
37 #include "dvr/dvr.h"
38 #include "ebml.h"
39 #include "lang_codes.h"
40 #include "epg.h"
41 #include "parsers/parser_avc.h"
42 #include "parsers/parser_hevc.h"
43 #include "muxer_mkv.h"
44
45 extern int dvr_iov_max;
46
47 TAILQ_HEAD(mk_cue_queue, mk_cue);
48 TAILQ_HEAD(mk_chapter_queue, mk_chapter);
49
50 #define MATROSKA_TIMESCALE 1000000 // in nS
51
52
53 /**
54 *
55 */
56 typedef struct mk_track {
57 int index;
58 int avc;
59 int hevc;
60 int type;
61 int tracknum;
62 int tracktype;
63 int disabled;
64 int64_t nextpts;
65
66 uint8_t channels;
67 uint8_t sri;
68 uint8_t ext_sri;
69
70 uint16_t aspect_num;
71 uint16_t aspect_den;
72
73 uint8_t commercial;
74 } mk_track_t;
75
76 /**
77 *
78 */
79 typedef struct mk_cue {
80 TAILQ_ENTRY(mk_cue) link;
81 int64_t ts;
82 int tracknum;
83 off_t cluster_pos;
84 } mk_cue_t;
85
86 /**
87 *
88 */
89 typedef struct mk_chapter {
90 TAILQ_ENTRY(mk_chapter) link;
91 uint32_t uuid;
92 int64_t ts;
93 } mk_chapter_t;
94
95 typedef struct mk_muxer {
96 muxer_t;
97 int fd;
98 char *filename;
99 int error;
100 off_t fdpos; // Current position in file
101 int seekable;
102
103 mk_track_t *tracks;
104 int ntracks;
105 int has_video;
106
107 int64_t totduration;
108
109 htsbuf_queue_t *cluster;
110 int64_t cluster_tc;
111 off_t cluster_pos;
112 int64_t cluster_last_close;
113 int64_t cluster_maxsize;
114
115 off_t segment_header_pos;
116
117 off_t segment_pos;
118
119 off_t segmentinfo_pos;
120 off_t trackinfo_pos;
121 off_t metadata_pos;
122 off_t cue_pos;
123 off_t chapters_pos;
124
125 int addcue;
126
127 struct mk_cue_queue cues;
128 struct mk_chapter_queue chapters;
129
130 uint8_t uuid[16];
131 char *title;
132
133 int webm;
134 } mk_muxer_t;
135
136 /* --- */
137
138 static int mk_mux_insert_chapter(mk_muxer_t *mk);
139
140 /**
141 *
142 */
143 static htsbuf_queue_t *
mk_build_ebmlheader(mk_muxer_t * mk)144 mk_build_ebmlheader(mk_muxer_t *mk)
145 {
146 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
147
148 ebml_append_uint(q, 0x4286, 1);
149 ebml_append_uint(q, 0x42f7, 1);
150 ebml_append_uint(q, 0x42f2, 4);
151 ebml_append_uint(q, 0x42f3, 8);
152 ebml_append_string(q, 0x4282, mk->webm ? "webm" : "matroska");
153 ebml_append_uint(q, 0x4287, 2);
154 ebml_append_uint(q, 0x4285, 2);
155 return q;
156 }
157
158
159 /**
160 *
161 */
162 static int
mk_split_vorbis_headers(uint8_t * extradata,int extradata_size,uint8_t * header_start[3],int header_len[3])163 mk_split_vorbis_headers(uint8_t *extradata, int extradata_size,
164 uint8_t *header_start[3], int header_len[3])
165 {
166 int i;
167 if (extradata_size >= 3 && extradata_size < INT_MAX - 0x1ff && extradata[0] == 2) {
168 int overall_len = 3;
169 extradata++;
170 for (i=0; i<2; i++, extradata++) {
171 header_len[i] = 0;
172 for (; overall_len < extradata_size && *extradata==0xff; extradata++) {
173 header_len[i] += 0xff;
174 overall_len += 0xff + 1;
175 }
176 header_len[i] += *extradata;
177 overall_len += *extradata;
178 if (overall_len > extradata_size)
179 return -1;
180 }
181 header_len[2] = extradata_size - overall_len;
182 header_start[0] = extradata;
183 header_start[1] = header_start[0] + header_len[0];
184 header_start[2] = header_start[1] + header_len[1];
185 } else {
186 return -1;
187 }
188 return 0;
189 }
190
191
192 /**
193 *
194 */
195 static htsbuf_queue_t *
mk_build_segment_info(mk_muxer_t * mk)196 mk_build_segment_info(mk_muxer_t *mk)
197 {
198 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
199 char app[128];
200
201 snprintf(app, sizeof(app), "Tvheadend %s", tvheadend_version);
202
203 if(!mk->webm)
204 ebml_append_bin(q, 0x73a4, mk->uuid, sizeof(mk->uuid));
205
206 if(!mk->webm)
207 ebml_append_string(q, 0x7ba9, mk->title);
208
209 ebml_append_string(q, 0x4d80, "Tvheadend Matroska muxer");
210 ebml_append_string(q, 0x5741, app);
211 ebml_append_uint(q, 0x2ad7b1, MATROSKA_TIMESCALE);
212
213 if(mk->totduration)
214 ebml_append_float(q, 0x4489, (float)mk->totduration);
215 else
216 ebml_append_pad(q, 7); // Must be equal to floatingpoint duration
217 return q;
218 }
219
220
221 /**
222 *
223 */
224 static htsbuf_queue_t *
mk_build_tracks(mk_muxer_t * mk,streaming_start_t * ss)225 mk_build_tracks(mk_muxer_t *mk, streaming_start_t *ss)
226 {
227 streaming_start_component_t *ssc;
228 const char *codec_id;
229 int i, tracktype;
230 htsbuf_queue_t *q = htsbuf_queue_alloc(0), *t;
231 int tracknum = 0;
232 uint8_t buf4[4];
233 uint32_t bit_depth = 0;
234 mk_track_t *tr;
235
236 mk->tracks = calloc(1, sizeof(mk_track_t) * ss->ss_num_components);
237 mk->ntracks = ss->ss_num_components;
238 mk->cluster_maxsize = 4000000;
239 for(i = 0; i < ss->ss_num_components; i++) {
240 ssc = &ss->ss_components[i];
241 tr = &mk->tracks[i];
242
243 tr->disabled = ssc->ssc_disabled;
244 tr->index = ssc->ssc_index;
245
246 if(tr->disabled)
247 continue;
248
249 tr->type = ssc->ssc_type;
250 tr->channels = ssc->ssc_channels;
251 tr->aspect_num = ssc->ssc_aspect_num;
252 tr->aspect_den = ssc->ssc_aspect_den;
253 tr->commercial = COMMERCIAL_UNKNOWN;
254 tr->sri = ssc->ssc_sri;
255 tr->nextpts = PTS_UNSET;
256
257 if (mk->webm && ssc->ssc_type != SCT_VP8 && ssc->ssc_type != SCT_VORBIS)
258 tvhwarn(LS_MKV, "WEBM format supports only VP8+VORBIS streams (detected %s)",
259 streaming_component_type2txt(ssc->ssc_type));
260
261 switch(ssc->ssc_type) {
262 case SCT_MPEG2VIDEO:
263 tracktype = 1;
264 codec_id = "V_MPEG2";
265 break;
266
267 case SCT_H264:
268 tracktype = 1;
269 codec_id = "V_MPEG4/ISO/AVC";
270 tr->avc = 1;
271 mk->cluster_maxsize = 10000000;
272 break;
273
274 case SCT_HEVC:
275 tracktype = 1;
276 codec_id = "V_MPEGH/ISO/HEVC";
277 mk->cluster_maxsize = 20000000;
278 tr->hevc = 1;
279 break;
280
281 case SCT_VP8:
282 tracktype = 1;
283 codec_id = "V_VP8";
284 mk->cluster_maxsize = 10000000;
285 break;
286
287 case SCT_VP9:
288 tracktype = 1;
289 codec_id = "V_VP9";
290 mk->cluster_maxsize = 10000000;
291 break;
292
293 case SCT_MPEG2AUDIO:
294 tracktype = 2;
295 codec_id = "A_MPEG/L2";
296 if (ssc->ssc_audio_version == 3)
297 codec_id = "A_MPEG/L3";
298 else if (ssc->ssc_audio_version == 1)
299 codec_id = "A_MPEG/L1";
300 break;
301
302 case SCT_AC3:
303 tracktype = 2;
304 codec_id = "A_AC3";
305 break;
306
307 case SCT_EAC3:
308 tracktype = 2;
309 codec_id = "A_EAC3";
310 break;
311
312 case SCT_MP4A:
313 case SCT_AAC:
314 tracktype = 2;
315 codec_id = "A_AAC";
316 bit_depth = 16;
317 break;
318
319 case SCT_VORBIS:
320 tracktype = 2;
321 codec_id = "A_VORBIS";
322 break;
323
324 case SCT_DVBSUB:
325 tracktype = 0x11;
326 codec_id = "S_DVBSUB";
327 break;
328
329 case SCT_TEXTSUB:
330 tracktype = 0x11;
331 codec_id = "S_TEXT/UTF8";
332 break;
333
334 default:
335 ssc->ssc_muxer_disabled = 1;
336 tr->disabled = 1;
337 continue;
338 }
339
340 tr->tracknum = ++tracknum;
341 tr->tracktype = tracktype;
342 mk->has_video |= (tracktype == 1);
343
344 t = htsbuf_queue_alloc(0);
345
346 ebml_append_uint(t, 0xd7, tr->tracknum);
347 ebml_append_uint(t, 0x73c5, tr->tracknum);
348 ebml_append_uint(t, 0x83, tracktype);
349 ebml_append_uint(t, 0x9c, 0); // Lacing
350 ebml_append_string(t, 0x86, codec_id);
351
352 if(ssc->ssc_lang[0])
353 ebml_append_string(t, 0x22b59c, ssc->ssc_lang);
354
355 switch(ssc->ssc_type) {
356 case SCT_HEVC:
357 case SCT_H264:
358 case SCT_MPEG2VIDEO:
359 case SCT_MP4A:
360 case SCT_AAC:
361 if(ssc->ssc_gh) {
362 sbuf_t hdr;
363 sbuf_init(&hdr);
364 if (tr->avc) {
365 isom_write_avcc(&hdr, pktbuf_ptr(ssc->ssc_gh),
366 pktbuf_len(ssc->ssc_gh));
367 } else if (tr->hevc) {
368 isom_write_hvcc(&hdr, pktbuf_ptr(ssc->ssc_gh),
369 pktbuf_len(ssc->ssc_gh));
370 } else {
371 sbuf_append(&hdr, pktbuf_ptr(ssc->ssc_gh),
372 pktbuf_len(ssc->ssc_gh));
373 }
374 ebml_append_bin(t, 0x63a2, hdr.sb_data, hdr.sb_ptr);
375 sbuf_free(&hdr);
376 }
377 break;
378
379 case SCT_VORBIS:
380 if(ssc->ssc_gh) {
381 htsbuf_queue_t *cp;
382 uint8_t *header_start[3];
383 int header_len[3];
384 int j;
385 if(mk_split_vorbis_headers(pktbuf_ptr(ssc->ssc_gh),
386 pktbuf_len(ssc->ssc_gh),
387 header_start,
388 header_len) < 0)
389 break;
390
391 cp = htsbuf_queue_alloc(0);
392
393 ebml_append_xiph_size(cp, 2);
394
395 for (j = 0; j < 2; j++)
396 ebml_append_xiph_size(cp, header_len[j]);
397
398 for (j = 0; j < 3; j++)
399 htsbuf_append(cp, header_start[j], header_len[j]);
400
401 ebml_append_master(t, 0x63a2, cp);
402 }
403 break;
404
405 case SCT_DVBSUB:
406 buf4[0] = ssc->ssc_composition_id >> 8;
407 buf4[1] = ssc->ssc_composition_id;
408 buf4[2] = ssc->ssc_ancillary_id >> 8;
409 buf4[3] = ssc->ssc_ancillary_id;
410 ebml_append_bin(t, 0x63a2, buf4, 4);
411 break;
412 }
413
414 if(SCT_ISVIDEO(ssc->ssc_type)) {
415 htsbuf_queue_t *vi = htsbuf_queue_alloc(0);
416
417 if(ssc->ssc_frameduration) {
418 int d = ts_rescale(ssc->ssc_frameduration, 1000000000);
419 ebml_append_uint(t, 0x23e383, d);
420 }
421 ebml_append_uint(vi, 0xb0, ssc->ssc_width);
422 ebml_append_uint(vi, 0xba, ssc->ssc_height);
423
424 if(mk->webm && ssc->ssc_aspect_num && ssc->ssc_aspect_den) {
425 // DAR is not supported by webm
426 ebml_append_uint(vi, 0x54b2, 1);
427 ebml_append_uint(vi, 0x54b0, (ssc->ssc_height * ssc->ssc_aspect_num) / ssc->ssc_aspect_den);
428 ebml_append_uint(vi, 0x54ba, ssc->ssc_height);
429 } else if(ssc->ssc_aspect_num && ssc->ssc_aspect_den) {
430 ebml_append_uint(vi, 0x54b2, 3); // Display width/height is in DAR
431 ebml_append_uint(vi, 0x54b0, ssc->ssc_aspect_num);
432 ebml_append_uint(vi, 0x54ba, ssc->ssc_aspect_den);
433 }
434
435 ebml_append_master(t, 0xe0, vi);
436 }
437
438 if(SCT_ISAUDIO(ssc->ssc_type)) {
439 htsbuf_queue_t *au = htsbuf_queue_alloc(0);
440
441 ebml_append_float(au, 0xb5, sri_to_rate(ssc->ssc_sri));
442 if (ssc->ssc_ext_sri)
443 ebml_append_float(au, 0x78b5, sri_to_rate(ssc->ssc_ext_sri - 1));
444 ebml_append_uint(au, 0x9f, ssc->ssc_channels);
445 if (bit_depth)
446 ebml_append_uint(au, 0x6264, bit_depth);
447
448 ebml_append_master(t, 0xe1, au);
449 }
450
451
452 ebml_append_master(q, 0xae, t);
453 }
454 return q;
455 }
456
457
458 /**
459 *
460 */
461 static int
mk_write_to_fd(mk_muxer_t * mk,htsbuf_queue_t * hq)462 mk_write_to_fd(mk_muxer_t *mk, htsbuf_queue_t *hq)
463 {
464 htsbuf_data_t *hd;
465 int i = 0;
466 off_t oldpos = mk->fdpos;
467
468 TAILQ_FOREACH(hd, &hq->hq_q, hd_link)
469 i++;
470
471 struct iovec *iov = alloca(sizeof(struct iovec) * i);
472
473 i = 0;
474 TAILQ_FOREACH(hd, &hq->hq_q, hd_link) {
475 iov[i ].iov_base = hd->hd_data + hd->hd_data_off;
476 iov[i++].iov_len = hd->hd_data_len - hd->hd_data_off;
477 }
478
479 do {
480 ssize_t r;
481 int iovcnt = i < dvr_iov_max ? i : dvr_iov_max;
482 if((r = writev(mk->fd, iov, iovcnt)) == -1) {
483 if (ERRNO_AGAIN(errno))
484 continue;
485 mk->error = errno;
486 return -1;
487 }
488 mk->fdpos += r;
489 i -= iovcnt;
490 iov += iovcnt;
491 } while(i);
492
493 if (mk->seekable)
494 muxer_cache_update((muxer_t *)mk, mk->fd, oldpos, 0);
495
496 return 0;
497 }
498
499
500 /**
501 *
502 */
503 static void
mk_write_queue(mk_muxer_t * mk,htsbuf_queue_t * q)504 mk_write_queue(mk_muxer_t *mk, htsbuf_queue_t *q)
505 {
506 if(!mk->error && mk_write_to_fd(mk, q) && !MC_IS_EOS_ERROR(mk->error))
507 tvherror(LS_MKV, "%s: Write failed -- %s", mk->filename, strerror(errno));
508
509 htsbuf_queue_flush(q);
510 }
511
512
513 /**
514 *
515 */
516 static void
mk_write_master(mk_muxer_t * mk,uint32_t id,htsbuf_queue_t * p)517 mk_write_master(mk_muxer_t *mk, uint32_t id, htsbuf_queue_t *p)
518 {
519 htsbuf_queue_t q;
520 htsbuf_queue_init(&q, 0);
521 ebml_append_master(&q, id, p);
522 mk_write_queue(mk, &q);
523 }
524
525
526 /**
527 *
528 */
529 static htsbuf_queue_t *
mk_build_segment_header(int64_t size)530 mk_build_segment_header(int64_t size)
531 {
532 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
533 uint8_t u8[8];
534
535 ebml_append_id(q, 0x18538067);
536
537 u8[0] = 1;
538 if(size == 0) {
539 memset(u8+1, 0xff, 7);
540 } else {
541 u8[1] = size >> 56;
542 u8[2] = size >> 48;
543 u8[3] = size >> 32;
544 u8[4] = size >> 24;
545 u8[5] = size >> 16;
546 u8[6] = size >> 8;
547 u8[7] = size;
548 }
549 htsbuf_append(q, &u8, 8);
550
551 return q;
552 }
553
554
555 /**
556 *
557 */
558 static void
mk_write_segment_header(mk_muxer_t * mk,int64_t size)559 mk_write_segment_header(mk_muxer_t *mk, int64_t size)
560 {
561 htsbuf_queue_t *q;
562 q = mk_build_segment_header(size);
563 mk_write_queue(mk, q);
564 htsbuf_queue_free(q);
565 }
566
567
568 /**
569 *
570 */
571 static htsbuf_queue_t *
mk_build_one_chapter(mk_chapter_t * ch)572 mk_build_one_chapter(mk_chapter_t *ch)
573 {
574 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
575
576 ebml_append_uint(q, 0x73C4, ch->uuid);
577 ebml_append_uint(q, 0x91, ch->ts * MATROSKA_TIMESCALE);
578 ebml_append_uint(q, 0x98, 0); //ChapterFlagHidden
579 ebml_append_uint(q, 0x4598, 1); //ChapterFlagEnabled
580
581 return q;
582 }
583
584
585 /**
586 *
587 */
588 static htsbuf_queue_t *
mk_build_edition_entry(mk_muxer_t * mk)589 mk_build_edition_entry(mk_muxer_t *mk)
590 {
591 mk_chapter_t *ch;
592 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
593
594 ebml_append_uint(q, 0x45bd, 0); //EditionFlagHidden
595 ebml_append_uint(q, 0x45db, 1); //EditionFlagDefault
596
597 TAILQ_FOREACH(ch, &mk->chapters, link) {
598 ebml_append_master(q, 0xB6, mk_build_one_chapter(ch));
599 }
600
601 return q;
602 }
603
604
605 /**
606 *
607 */
608 static htsbuf_queue_t *
mk_build_chapters(mk_muxer_t * mk)609 mk_build_chapters(mk_muxer_t *mk)
610 {
611 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
612
613 ebml_append_master(q, 0x45b9, mk_build_edition_entry(mk));
614
615 return q;
616 }
617
618 /**
619 *
620 */
621 static void
mk_write_chapters(mk_muxer_t * mk)622 mk_write_chapters(mk_muxer_t *mk)
623 {
624 if(TAILQ_FIRST(&mk->chapters) == NULL)
625 return;
626
627 mk->chapters_pos = mk->fdpos;
628 mk_write_master(mk, 0x1043a770, mk_build_chapters(mk));
629 }
630
631
632 /**
633 *
634 */
635 static htsbuf_queue_t *
build_tag_string(const char * name,const char * value,const char * lang,int targettype,const char * targettypename)636 build_tag_string(const char *name, const char *value, const char *lang,
637 int targettype, const char *targettypename)
638 {
639 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
640 htsbuf_queue_t *st = htsbuf_queue_alloc(0);
641
642 htsbuf_queue_t *t = htsbuf_queue_alloc(0);
643 ebml_append_uint(t, 0x68ca, targettype ?: 50);
644
645 if(targettypename)
646 ebml_append_string(t, 0x63ca, targettypename);
647 ebml_append_master(q, 0x63c0, t);
648
649 ebml_append_string(st, 0x45a3, name);
650 ebml_append_string(st, 0x4487, value);
651 ebml_append_uint(st, 0x4484, 1);
652 ebml_append_string(st, 0x447a, lang ?: "und");
653
654 ebml_append_master(q, 0x67c8, st);
655 return q;
656 }
657
658
659 /**
660 *
661 */
662 static htsbuf_queue_t *
build_tag_int(const char * name,int value,int targettype,const char * targettypename)663 build_tag_int(const char *name, int value,
664 int targettype, const char *targettypename)
665 {
666 char str[64];
667 snprintf(str, sizeof(str), "%d", value);
668 return build_tag_string(name, str, NULL, targettype, targettypename);
669 }
670
671
672 /**
673 *
674 */
675 static void
addtag(htsbuf_queue_t * q,htsbuf_queue_t * t)676 addtag(htsbuf_queue_t *q, htsbuf_queue_t *t)
677 {
678 ebml_append_master(q, 0x7373, t);
679 }
680
681
682 /**
683 *
684 */
685 static htsbuf_queue_t *
_mk_build_metadata(const dvr_entry_t * de,const epg_broadcast_t * ebc,const char * comment)686 _mk_build_metadata(const dvr_entry_t *de, const epg_broadcast_t *ebc,
687 const char *comment)
688 {
689 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
690 char datestr[64], ctype[100];
691 const epg_genre_t *eg = NULL;
692 epg_genre_t eg0;
693 struct tm tm;
694 time_t t;
695 epg_episode_t *ee = NULL;
696 channel_t *ch = NULL;
697 lang_str_t *ls = NULL, *ls2 = NULL;
698 const char **langs, *lang;
699
700 if (ebc) ee = ebc->episode;
701 else if (de && de->de_bcast) ee = de->de_bcast->episode;
702
703 if (de) ch = de->de_channel;
704 else if (ebc) ch = ebc->channel;
705
706 if (de || ebc) {
707 localtime_r(de ? &de->de_start : &ebc->start, &tm);
708 } else {
709 t = time(NULL);
710 localtime_r(&t, &tm);
711 }
712 snprintf(datestr, sizeof(datestr),
713 "%04d-%02d-%02d %02d:%02d:%02d",
714 tm.tm_year + 1900,
715 tm.tm_mon + 1,
716 tm.tm_mday,
717 tm.tm_hour,
718 tm.tm_min,
719 tm.tm_sec);
720
721 addtag(q, build_tag_string("DATE_BROADCASTED", datestr, NULL, 0, NULL));
722
723 addtag(q, build_tag_string("ORIGINAL_MEDIA_TYPE", "TV", NULL, 0, NULL));
724
725 if(de && de->de_content_type) {
726 memset(&eg0, 0, sizeof(eg0));
727 eg0.code = de->de_content_type;
728 eg = &eg0;
729 } else if (ee) {
730 eg = LIST_FIRST(&ee->genre);
731 }
732 if(eg && epg_genre_get_str(eg, 1, 0, ctype, 100, NULL))
733 addtag(q, build_tag_string("CONTENT_TYPE", ctype, NULL, 0, NULL));
734
735 if(ch)
736 addtag(q, build_tag_string("TVCHANNEL",
737 channel_get_name(ch), NULL, 0, NULL));
738
739 if (ee && ee->summary)
740 ls = ee->summary;
741 else if (ebc && ebc->summary)
742 ls = ebc->summary;
743
744 if(de && de->de_desc)
745 ls2 = de->de_desc;
746 else if (ee && ee->description)
747 ls2 = ee->description;
748 else if (ebc && ebc->description)
749 ls2 = ebc->description;
750
751 if (!ls)
752 ls = ls2;
753
754 if (ls) {
755 lang_str_ele_t *e;
756 RB_FOREACH(e, ls, link)
757 addtag(q, build_tag_string("SUMMARY", e->str, e->lang, 0, NULL));
758 }
759
760 if (ls2 && ls != ls2) {
761 lang_str_ele_t *e;
762 RB_FOREACH(e, ls2, link)
763 addtag(q, build_tag_string("DESCRIPTION", e->str, e->lang, 0, NULL));
764 }
765
766 if (ee) {
767 epg_episode_num_t num;
768 epg_episode_get_epnum(ee, &num);
769 if(num.e_num)
770 addtag(q, build_tag_int("PART_NUMBER", num.e_num,
771 0, NULL));
772 if(num.s_num)
773 addtag(q, build_tag_int("PART_NUMBER", num.s_num,
774 60, "SEASON"));
775 if(num.p_num)
776 addtag(q, build_tag_int("PART_NUMBER", num.p_num,
777 40, "PART"));
778 if (num.text)
779 addtag(q, build_tag_string("SYNOPSIS",
780 num.text, NULL, 0, NULL));
781 }
782
783 if (comment) {
784 lang = "eng";
785 if ((langs = lang_code_split(NULL)) && langs[0])
786 lang = tvh_strdupa(langs[0]);
787 free(langs);
788
789 addtag(q, build_tag_string("COMMENT", comment, lang, 0, NULL));
790 }
791
792 return q;
793 }
794
795
796 /**
797 *
798 */
799 static htsbuf_queue_t *
mk_build_one_metaseek(mk_muxer_t * mk,uint32_t id,off_t pos)800 mk_build_one_metaseek(mk_muxer_t *mk, uint32_t id, off_t pos)
801 {
802 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
803
804 ebml_append_idid(q, 0x53ab, id);
805 ebml_append_uint(q, 0x53ac, pos - mk->segment_pos);
806 return q;
807 }
808
809
810 /**
811 *
812 */
813 static void
mk_append_master(mk_muxer_t * mk,htsbuf_queue_t * q,off_t id1,off_t id2,off_t val)814 mk_append_master(mk_muxer_t *mk, htsbuf_queue_t *q,
815 off_t id1, off_t id2, off_t val)
816 {
817 ebml_append_master(q, id1, mk_build_one_metaseek(mk, id2, val));
818
819 }
820
821 /**
822 *
823 */
824 static htsbuf_queue_t *
mk_build_metaseek(mk_muxer_t * mk)825 mk_build_metaseek(mk_muxer_t *mk)
826 {
827 htsbuf_queue_t *q = htsbuf_queue_alloc(0);
828
829 if(mk->segmentinfo_pos)
830 mk_append_master(mk, q, 0x4dbb, 0x1549a966, mk->segmentinfo_pos);
831 if(mk->trackinfo_pos)
832 mk_append_master(mk, q, 0x4dbb, 0x1654ae6b, mk->trackinfo_pos);
833 if(mk->metadata_pos)
834 mk_append_master(mk, q, 0x4dbb, 0x1254c367, mk->metadata_pos);
835 if(mk->cue_pos)
836 mk_append_master(mk, q, 0x4dbb, 0x1c53bb6b, mk->cue_pos);
837 if(mk->chapters_pos)
838 mk_append_master(mk, q, 0x4dbb, 0x1043a770, mk->chapters_pos);
839 return q;
840 }
841
842
843 /**
844 *
845 */
846 static void
mk_write_metaseek(mk_muxer_t * mk,int first)847 mk_write_metaseek(mk_muxer_t *mk, int first)
848 {
849 htsbuf_queue_t q;
850
851 htsbuf_queue_init(&q, 0);
852
853 ebml_append_master(&q, 0x114d9b74, mk_build_metaseek(mk));
854
855 assert(q.hq_size < 498);
856
857 ebml_append_pad(&q, 500 - q.hq_size);
858
859 if(first) {
860 mk_write_to_fd(mk, &q);
861 } else if(mk->seekable) {
862 off_t prev = mk->fdpos;
863 mk->fdpos = mk->segment_pos;
864 if(lseek(mk->fd, mk->segment_pos, SEEK_SET) == (off_t) -1)
865 mk->error = errno;
866
867 mk_write_queue(mk, &q);
868 mk->fdpos = prev;
869 if(lseek(mk->fd, mk->fdpos, SEEK_SET) == (off_t) -1)
870 mk->error = errno;
871 }
872 htsbuf_queue_flush(&q);
873 }
874
875
876 /**
877 *
878 */
879 static htsbuf_queue_t *
mk_build_segment(mk_muxer_t * mk,streaming_start_t * ss)880 mk_build_segment(mk_muxer_t *mk,
881 streaming_start_t *ss)
882 {
883 htsbuf_queue_t *p = htsbuf_queue_alloc(0);
884
885 assert(mk->segment_pos != 0);
886
887 // Meta seek
888 if(mk->seekable)
889 ebml_append_pad(p, 500);
890
891 mk->segmentinfo_pos = mk->segment_pos + p->hq_size;
892 ebml_append_master(p, 0x1549a966, mk_build_segment_info(mk));
893
894 mk->trackinfo_pos = mk->segment_pos + p->hq_size;
895 ebml_append_master(p, 0x1654ae6b, mk_build_tracks(mk, ss));
896
897 return p;
898 }
899
900
901 /**
902 *
903 */
904 static void
addcue(mk_muxer_t * mk,int64_t pts,int tracknum)905 addcue(mk_muxer_t *mk, int64_t pts, int tracknum)
906 {
907 mk_cue_t *mc = malloc(sizeof(mk_cue_t));
908 mc->ts = pts;
909 mc->tracknum = tracknum;
910 mc->cluster_pos = mk->cluster_pos;
911 TAILQ_INSERT_TAIL(&mk->cues, mc, link);
912 }
913
914
915 /**
916 *
917 */
918 static void
mk_add_chapter0(mk_muxer_t * mk,uint32_t uuid,int64_t ts)919 mk_add_chapter0(mk_muxer_t *mk, uint32_t uuid, int64_t ts)
920 {
921 mk_chapter_t *ch;
922
923 ch = malloc(sizeof(mk_chapter_t));
924
925 ch->uuid = uuid;
926 ch->ts = ts;
927
928 TAILQ_INSERT_TAIL(&mk->chapters, ch, link);
929 }
930
931 /**
932 *
933 */
934 static void
mk_add_chapter(mk_muxer_t * mk,int64_t ts)935 mk_add_chapter(mk_muxer_t *mk, int64_t ts)
936 {
937 mk_chapter_t *ch;
938 int uuid;
939
940 ch = TAILQ_LAST(&mk->chapters, mk_chapter_queue);
941 if(ch) {
942 /* don't add a new chapter if the previous one was added less than 5s ago */
943 if(ts - ch->ts < 5000)
944 return;
945
946 uuid = ch->uuid + 1;
947 } else {
948 uuid = 1;
949 /* create first chapter at zero position */
950 if (ts >= 5000) {
951 mk_add_chapter0(mk, uuid++, 0);
952 } else {
953 ts = 0;
954 }
955 }
956 mk_add_chapter0(mk, uuid, ts);
957 }
958
959 /**
960 *
961 */
962 static void
mk_close_cluster(mk_muxer_t * mk)963 mk_close_cluster(mk_muxer_t *mk)
964 {
965 if(mk->cluster != NULL)
966 mk_write_master(mk, 0x1f43b675, mk->cluster);
967 mk->cluster = NULL;
968 mk->cluster_last_close = mclk();
969 }
970
971
972 /**
973 *
974 */
975 static void
mk_write_frame_i(mk_muxer_t * mk,mk_track_t * t,th_pkt_t * pkt)976 mk_write_frame_i(mk_muxer_t *mk, mk_track_t *t, th_pkt_t *pkt)
977 {
978 int64_t pts = pkt->pkt_pts, delta, nxt;
979 unsigned char c_delta_flags[3];
980 const int video = t->tracktype == 1;
981 const int audio = t->tracktype == 2;
982 int keyframe = 0, skippable = 0;
983
984 if (video) {
985 keyframe = pkt->v.pkt_frametype < PKT_P_FRAME;
986 skippable = pkt->v.pkt_frametype == PKT_B_FRAME;
987 }
988
989 uint8_t *data = pktbuf_ptr(pkt->pkt_payload);
990 size_t len = pktbuf_len(pkt->pkt_payload);
991
992 if(!data || len <= 0)
993 return;
994
995 if(pts == PTS_UNSET)
996 // This is our best guess, it might be wrong but... oh well
997 pts = t->nextpts;
998
999 if(pts != PTS_UNSET) {
1000 t->nextpts = pts + (pkt->pkt_duration >> (video ? pkt->v.pkt_field : 0));
1001
1002 nxt = ts_rescale(t->nextpts, 1000000000 / MATROSKA_TIMESCALE);
1003 pts = ts_rescale(pts, 1000000000 / MATROSKA_TIMESCALE);
1004
1005 if((t->tracktype == 1 || t->tracktype == 2) && mk->totduration < nxt)
1006 mk->totduration = nxt;
1007
1008 delta = pts - mk->cluster_tc;
1009 if((keyframe || !mk->has_video) && (delta > 30000ll || delta < -30000ll))
1010 mk_close_cluster(mk);
1011
1012 } else {
1013 return;
1014 }
1015
1016 if(mk->cluster) {
1017
1018 if(keyframe &&
1019 (mk->cluster->hq_size > mk->cluster_maxsize ||
1020 mk->cluster_last_close + sec2mono(1) < mclk()))
1021 mk_close_cluster(mk);
1022
1023 else if(!mk->has_video &&
1024 (mk->cluster->hq_size > mk->cluster_maxsize/40 ||
1025 mk->cluster_last_close + sec2mono(1) < mclk()))
1026 mk_close_cluster(mk);
1027
1028 else if(mk->cluster->hq_size > mk->cluster_maxsize)
1029 mk_close_cluster(mk);
1030
1031 }
1032
1033 if(mk->cluster == NULL) {
1034 mk->cluster_tc = pts;
1035 mk->cluster = htsbuf_queue_alloc(0);
1036
1037 mk->cluster_pos = mk->fdpos;
1038 mk->addcue = 1;
1039
1040 ebml_append_uint(mk->cluster, 0xe7, mk->cluster_tc);
1041 delta = 0;
1042 }
1043
1044 if(mk->addcue && keyframe) {
1045 mk->addcue = 0;
1046 addcue(mk, pts, t->tracknum);
1047 }
1048
1049 if(t->type == SCT_AAC || t->type == SCT_MP4A) {
1050 // Skip ADTS header
1051 if(len < 7)
1052 return;
1053
1054 len -= 7;
1055 data += 7;
1056 }
1057
1058 ebml_append_id(mk->cluster, 0xa3 ); // SimpleBlock
1059 ebml_append_size(mk->cluster, len + 4);
1060 ebml_append_size(mk->cluster, t->tracknum);
1061
1062 c_delta_flags[0] = delta >> 8;
1063 c_delta_flags[1] = delta;
1064 if (audio && pkt->a.pkt_keyframe) keyframe = 1;
1065 c_delta_flags[2] = (keyframe << 7) | skippable;
1066 htsbuf_append(mk->cluster, c_delta_flags, 3);
1067 htsbuf_append(mk->cluster, data, len);
1068 }
1069
1070
1071 /**
1072 *
1073 */
1074 static void
mk_write_cues(mk_muxer_t * mk)1075 mk_write_cues(mk_muxer_t *mk)
1076 {
1077 mk_cue_t *mc;
1078 htsbuf_queue_t *q, *c, *p;
1079
1080 if(TAILQ_FIRST(&mk->cues) == NULL)
1081 return;
1082
1083 q = htsbuf_queue_alloc(0);
1084
1085 while((mc = TAILQ_FIRST(&mk->cues)) != NULL) {
1086 TAILQ_REMOVE(&mk->cues, mc, link);
1087
1088 c = htsbuf_queue_alloc(0);
1089
1090 ebml_append_uint(c, 0xb3, mc->ts);
1091
1092 p = htsbuf_queue_alloc(0);
1093 ebml_append_uint(p, 0xf7, mc->tracknum);
1094 ebml_append_uint(p, 0xf1, mc->cluster_pos - mk->segment_pos);
1095
1096 ebml_append_master(c, 0xb7, p);
1097 ebml_append_master(q, 0xbb, c);
1098 free(mc);
1099 }
1100
1101 mk->cue_pos = mk->fdpos;
1102 mk_write_master(mk, 0x1c53bb6b, q);
1103 }
1104
1105
1106 /**
1107 * Append a packet to the muxer
1108 */
1109 static int
mk_mux_write_pkt(mk_muxer_t * mk,th_pkt_t * pkt)1110 mk_mux_write_pkt(mk_muxer_t *mk, th_pkt_t *pkt)
1111 {
1112 int i, mark;
1113 mk_track_t *t = NULL;
1114 th_pkt_t *opkt;
1115
1116 for (i = 0; i < mk->ntracks; i++) {
1117 t = &mk->tracks[i];
1118 if (t->index == pkt->pkt_componentindex && !t->disabled)
1119 break;
1120 }
1121
1122 if(i >= mk->ntracks || pkt->pkt_payload == NULL) {
1123 pkt_ref_dec(pkt);
1124 return mk->error;
1125 }
1126
1127 mark = 0;
1128 if(SCT_ISAUDIO(pkt->pkt_type)) {
1129 if(pkt->a.pkt_channels != t->channels &&
1130 pkt->a.pkt_channels) {
1131 mark = 1;
1132 t->channels = pkt->a.pkt_channels;
1133 }
1134 if(pkt->a.pkt_sri != t->sri &&
1135 pkt->a.pkt_sri) {
1136 mark = 1;
1137 t->sri = pkt->a.pkt_sri;
1138 t->ext_sri = pkt->a.pkt_ext_sri;
1139 }
1140 } else if (SCT_ISVIDEO(pkt->pkt_type)) {
1141 if(pkt->v.pkt_aspect_num != t->aspect_num &&
1142 pkt->v.pkt_aspect_num) {
1143 mark = 1;
1144 t->aspect_num = pkt->v.pkt_aspect_num;
1145 }
1146 if(pkt->v.pkt_aspect_den != t->aspect_den &&
1147 pkt->v.pkt_aspect_den) {
1148 mark = 1;
1149 t->aspect_den = pkt->v.pkt_aspect_den;
1150 }
1151 }
1152 if(pkt->pkt_commercial != t->commercial &&
1153 pkt->pkt_commercial != COMMERCIAL_UNKNOWN) {
1154 mark = 1;
1155 t->commercial = pkt->pkt_commercial;
1156 }
1157
1158 if(mark)
1159 mk_mux_insert_chapter(mk);
1160
1161 if(t->hevc) {
1162 pkt = hevc_convert_pkt(opkt = pkt);
1163 pkt_ref_dec(opkt);
1164 } else if(t->avc) {
1165 pkt = avc_convert_pkt(opkt = pkt);
1166 pkt_ref_dec(opkt);
1167 }
1168
1169 mk_write_frame_i(mk, t, pkt);
1170
1171 pkt_ref_dec(pkt);
1172
1173 return mk->error;
1174 }
1175
1176
1177 /**
1178 * Insert a new chapter at the current location
1179 */
1180 static int
mk_mux_insert_chapter(mk_muxer_t * mk)1181 mk_mux_insert_chapter(mk_muxer_t *mk)
1182 {
1183 if(mk->totduration != PTS_UNSET)
1184 mk_add_chapter(mk, mk->totduration);
1185
1186 return mk->error;
1187 }
1188
1189
1190 /**
1191 * Close the muxer
1192 */
1193 static int
mk_mux_close(mk_muxer_t * mk)1194 mk_mux_close(mk_muxer_t *mk)
1195 {
1196 int64_t totsize;
1197 mk_close_cluster(mk);
1198 mk_write_cues(mk);
1199 mk_write_chapters(mk);
1200
1201 mk_write_metaseek(mk, 0);
1202 totsize = mk->fdpos;
1203
1204 if(mk->seekable) {
1205 // Rewrite segment info to update duration
1206 if(lseek(mk->fd, mk->segmentinfo_pos, SEEK_SET) == mk->segmentinfo_pos)
1207 mk_write_master(mk, 0x1549a966, mk_build_segment_info(mk));
1208 else {
1209 mk->error = errno;
1210 tvherror(LS_MKV, "%s: Unable to write duration, seek failed -- %s",
1211 mk->filename, strerror(errno));
1212 }
1213
1214 // Rewrite segment header to update total size
1215 if(lseek(mk->fd, mk->segment_header_pos, SEEK_SET) == mk->segment_header_pos) {
1216 mk_write_segment_header(mk, totsize - mk->segment_header_pos - 12);
1217 } else {
1218 mk->error = errno;
1219 tvherror(LS_MKV, "%s: Unable to write total size, seek failed -- %s",
1220 mk->filename, strerror(errno));
1221 }
1222
1223 if(close(mk->fd)) {
1224 mk->error = errno;
1225 tvherror(LS_MKV, "%s: Unable to close the file descriptor, close failed -- %s",
1226 mk->filename, strerror(errno));
1227 }
1228 }
1229
1230 return mk->error;
1231 }
1232
1233 /**
1234 * Figure out the mimetype
1235 */
1236 static const char*
mkv_muxer_mime(muxer_t * m,const struct streaming_start * ss)1237 mkv_muxer_mime(muxer_t* m, const struct streaming_start *ss)
1238 {
1239 int i;
1240 int has_audio;
1241 int has_video;
1242 const streaming_start_component_t *ssc;
1243
1244 has_audio = 0;
1245 has_video = 0;
1246
1247 for(i=0; i < ss->ss_num_components; i++) {
1248 ssc = &ss->ss_components[i];
1249
1250 if(ssc->ssc_disabled)
1251 continue;
1252
1253 has_video |= SCT_ISVIDEO(ssc->ssc_type);
1254 has_audio |= SCT_ISAUDIO(ssc->ssc_type);
1255 }
1256
1257 if(has_video)
1258 return muxer_container_type2mime(m->m_config.m_type, 1);
1259 else if(has_audio)
1260 return muxer_container_type2mime(m->m_config.m_type, 0);
1261 else
1262 return muxer_container_type2mime(MC_UNKNOWN, 0);
1263 }
1264
1265 /**
1266 * Init the muxer with a title and some tracks
1267 */
1268 static int
mkv_muxer_init(muxer_t * m,streaming_start_t * ss,const char * name)1269 mkv_muxer_init(muxer_t *m, streaming_start_t *ss, const char *name)
1270 {
1271 mk_muxer_t *mk = (mk_muxer_t *)m;
1272 htsbuf_queue_t q, *a;
1273
1274 uuid_random(mk->uuid, sizeof(mk->uuid));
1275
1276 if(name)
1277 mk->title = strdup(name);
1278 else
1279 mk->title = strdup(mk->filename);
1280
1281 TAILQ_INIT(&mk->cues);
1282 TAILQ_INIT(&mk->chapters);
1283
1284 htsbuf_queue_init(&q, 0);
1285
1286 ebml_append_master(&q, 0x1a45dfa3, mk_build_ebmlheader(mk));
1287
1288 mk->segment_header_pos = q.hq_size;
1289 a = mk_build_segment_header(0);
1290 htsbuf_appendq(&q, a);
1291 htsbuf_queue_free(a);
1292
1293 mk->segment_pos = q.hq_size;
1294 a = mk_build_segment(mk, ss);
1295 htsbuf_appendq(&q, a);
1296 htsbuf_queue_free(a);
1297
1298 mk_write_queue(mk, &q);
1299
1300 htsbuf_queue_flush(&q);
1301
1302 return mk->error;
1303 }
1304
1305
1306 /**
1307 * Insert a new chapter at the current location
1308 */
1309 static int
mkv_muxer_add_marker(muxer_t * m)1310 mkv_muxer_add_marker(muxer_t* m)
1311 {
1312 mk_muxer_t *mk = (mk_muxer_t*)m;
1313
1314 if(mk_mux_insert_chapter(mk)) {
1315 mk->m_errors++;
1316 return -1;
1317 }
1318
1319 return 0;
1320 }
1321
1322
1323 /**
1324 * Multisegment matroska files do exist but I am not sure if they are supported
1325 * by many media players. For now, we'll treat it as an error.
1326 */
1327 static int
mkv_muxer_reconfigure(muxer_t * m,const struct streaming_start * ss)1328 mkv_muxer_reconfigure(muxer_t* m, const struct streaming_start *ss)
1329 {
1330 mk_muxer_t *mk = (mk_muxer_t*)m;
1331
1332 mk->m_errors++;
1333
1334 return -1;
1335 }
1336
1337
1338 /**
1339 * Open the muxer as a stream muxer (using a non-seekable socket)
1340 */
1341 static int
mkv_muxer_open_stream(muxer_t * m,int fd)1342 mkv_muxer_open_stream(muxer_t *m, int fd)
1343 {
1344 mk_muxer_t *mk = (mk_muxer_t*)m;
1345
1346 mk->filename = strdup("Live stream");
1347 mk->fd = fd;
1348 mk->cluster_maxsize = 0;
1349 mk->totduration = 0;
1350
1351 return 0;
1352 }
1353
1354
1355 /**
1356 * Open a file
1357 */
1358 static int
mkv_muxer_open_file(muxer_t * m,const char * filename)1359 mkv_muxer_open_file(muxer_t *m, const char *filename)
1360 {
1361 mk_muxer_t *mk = (mk_muxer_t*)m;
1362 int fd, permissions = mk->m_config.m_file_permissions;
1363
1364 tvhtrace(LS_MKV, "Creating file \"%s\" with file permissions \"%o\"",
1365 filename, permissions);
1366
1367 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, permissions);
1368
1369 if(fd < 0) {
1370 mk->error = errno;
1371 tvherror(LS_MKV, "%s: Unable to create file, open failed -- %s",
1372 mk->filename, strerror(errno));
1373 mk->m_errors++;
1374 return -1;
1375 }
1376
1377 /* bypass umask settings */
1378 if (fchmod(fd, permissions))
1379 tvherror(LS_MKV, "%s: Unable to change permissions -- %s",
1380 filename, strerror(errno));
1381
1382 mk->filename = strdup(filename);
1383 mk->fd = fd;
1384 mk->cluster_maxsize = 2000000;
1385 mk->seekable = 1;
1386 mk->totduration = 0;
1387
1388 return 0;
1389 }
1390
1391
1392 /**
1393 * Write a packet to the muxer
1394 */
1395 static int
mkv_muxer_write_pkt(muxer_t * m,streaming_message_type_t smt,void * data)1396 mkv_muxer_write_pkt(muxer_t *m, streaming_message_type_t smt, void *data)
1397 {
1398 th_pkt_t *pkt = (th_pkt_t*)data;
1399 mk_muxer_t *mk = (mk_muxer_t*)m;
1400 int r;
1401
1402 assert(smt == SMT_PACKET);
1403
1404 if((r = mk_mux_write_pkt(mk, pkt)) != 0) {
1405 if (MC_IS_EOS_ERROR(r))
1406 mk->m_eos = 1;
1407 mk->m_errors++;
1408 return -1;
1409 }
1410
1411 return 0;
1412 }
1413
1414
1415 /**
1416 * Append meta data when a channel changes its programme
1417 */
1418 static int
mkv_muxer_write_meta(muxer_t * m,struct epg_broadcast * eb,const char * comment)1419 mkv_muxer_write_meta(muxer_t *m, struct epg_broadcast *eb,
1420 const char *comment)
1421 {
1422 mk_muxer_t *mk = (mk_muxer_t*)m;
1423 htsbuf_queue_t q;
1424
1425 if(!mk->metadata_pos)
1426 mk->metadata_pos = mk->fdpos;
1427
1428 htsbuf_queue_init(&q, 0);
1429 ebml_append_master(&q, 0x1254c367, _mk_build_metadata(NULL, eb, comment));
1430 mk_write_queue(mk, &q);
1431
1432 if (mk->error) {
1433 mk->m_errors++;
1434 return -1;
1435 }
1436
1437 return 0;
1438 }
1439
1440
1441 /**
1442 * Close the muxer and append trailer to output
1443 */
1444 static int
mkv_muxer_close(muxer_t * m)1445 mkv_muxer_close(muxer_t *m)
1446 {
1447 mk_muxer_t *mk = (mk_muxer_t*)m;
1448
1449 if(mk_mux_close(mk)) {
1450 mk->m_errors++;
1451 return -1;
1452 }
1453
1454 return 0;
1455 }
1456
1457
1458 /**
1459 * Free all memory associated with the muxer
1460 */
1461 static void
mkv_muxer_destroy(muxer_t * m)1462 mkv_muxer_destroy(muxer_t *m)
1463 {
1464 mk_muxer_t *mk = (mk_muxer_t*)m;
1465 mk_chapter_t *ch;
1466
1467 while((ch = TAILQ_FIRST(&mk->chapters)) != NULL) {
1468 TAILQ_REMOVE(&mk->chapters, ch, link);
1469 free(ch);
1470 }
1471
1472 free(mk->filename);
1473 free(mk->tracks);
1474 free(mk->title);
1475 free(mk);
1476 }
1477
1478 /**
1479 * Create a new builtin muxer
1480 */
1481 muxer_t*
mkv_muxer_create(const muxer_config_t * m_cfg)1482 mkv_muxer_create(const muxer_config_t *m_cfg)
1483 {
1484 mk_muxer_t *mk;
1485
1486 if(m_cfg->m_type != MC_MATROSKA && m_cfg->m_type != MC_WEBM)
1487 return NULL;
1488
1489 mk = calloc(1, sizeof(mk_muxer_t));
1490 mk->m_open_stream = mkv_muxer_open_stream;
1491 mk->m_open_file = mkv_muxer_open_file;
1492 mk->m_mime = mkv_muxer_mime;
1493 mk->m_init = mkv_muxer_init;
1494 mk->m_reconfigure = mkv_muxer_reconfigure;
1495 mk->m_add_marker = mkv_muxer_add_marker;
1496 mk->m_write_meta = mkv_muxer_write_meta;
1497 mk->m_write_pkt = mkv_muxer_write_pkt;
1498 mk->m_close = mkv_muxer_close;
1499 mk->m_destroy = mkv_muxer_destroy;
1500 mk->webm = m_cfg->m_type == MC_WEBM;
1501 mk->fd = -1;
1502
1503 return (muxer_t*)mk;
1504 }
1505