1 /*****************************************************************************
2 * libmp4mux.c: mp4/mov muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2003, 2006, 20115 VLC authors and VideoLAN
5 *
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7 * Gildas Bazin <gbazin at videolan dot org>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include "libmp4mux.h"
28 #include "../demux/mp4/libmp4.h" /* flags */
29 #include "../packetizer/hevc_nal.h"
30 #include "../packetizer/h264_nal.h" /* h264_AnnexB_get_spspps */
31 #include "../packetizer/hxxx_nal.h"
32
33 #include <vlc_es.h>
34 #include <vlc_iso_lang.h>
35 #include <vlc_bits.h>
36 #include <assert.h>
37 #include <time.h>
38
mp4mux_trackinfo_Init(mp4mux_trackinfo_t * p_stream,unsigned i_id,uint32_t i_timescale)39 bool mp4mux_trackinfo_Init(mp4mux_trackinfo_t *p_stream, unsigned i_id,
40 uint32_t i_timescale)
41 {
42 memset(p_stream, 0, sizeof(*p_stream));
43 p_stream->i_track_id = i_id;
44
45 p_stream->i_timescale = i_timescale;
46 p_stream->i_entry_count = 0;
47 p_stream->i_entry_max = 1000;
48
49 p_stream->entry = calloc(p_stream->i_entry_max, sizeof(mp4mux_entry_t));
50 if(!p_stream->entry)
51 return false;
52
53 return true;
54 }
55
mp4mux_trackinfo_Clear(mp4mux_trackinfo_t * p_stream)56 void mp4mux_trackinfo_Clear(mp4mux_trackinfo_t *p_stream)
57 {
58 es_format_Clean(&p_stream->fmt);
59 if (p_stream->a52_frame)
60 block_Release(p_stream->a52_frame);
61 free(p_stream->entry);
62 free(p_stream->p_edits);
63 }
64
65
box_new(const char * fcc)66 bo_t *box_new(const char *fcc)
67 {
68 bo_t *box = malloc(sizeof(*box));
69 if (!box)
70 return NULL;
71
72 if(!bo_init(box, 1024))
73 {
74 bo_free(box);
75 return NULL;
76 }
77
78 bo_add_32be (box, 0);
79 bo_add_fourcc(box, fcc);
80
81 return box;
82 }
83
box_full_new(const char * fcc,uint8_t v,uint32_t f)84 bo_t *box_full_new(const char *fcc, uint8_t v, uint32_t f)
85 {
86 bo_t *box = box_new(fcc);
87 if (!box)
88 return NULL;
89
90 bo_add_8 (box, v);
91 bo_add_24be (box, f);
92
93 return box;
94 }
95
box_fix(bo_t * box,uint32_t i_size)96 void box_fix(bo_t *box, uint32_t i_size)
97 {
98 bo_set_32be(box, 0, i_size);
99 }
100
box_gather(bo_t * box,bo_t * box2)101 void box_gather (bo_t *box, bo_t *box2)
102 {
103 if(box2 && box2->b && box && box->b)
104 {
105 box_fix(box2, box2->b->i_buffer);
106 size_t i_offset = box->b->i_buffer;
107 box->b = block_Realloc(box->b, 0, box->b->i_buffer + box2->b->i_buffer);
108 if(likely(box->b))
109 memcpy(&box->b->p_buffer[i_offset], box2->b->p_buffer, box2->b->i_buffer);
110 }
111 bo_free(box2);
112 }
113
bo_add_mp4_tag_descr(bo_t * box,uint8_t tag,uint32_t size)114 static inline void bo_add_mp4_tag_descr(bo_t *box, uint8_t tag, uint32_t size)
115 {
116 bo_add_8(box, tag);
117 for (int i = 3; i>0; i--)
118 bo_add_8(box, (size>>(7*i)) | 0x80);
119 bo_add_8(box, size & 0x7F);
120 }
121
get_timestamp(void)122 static int64_t get_timestamp(void)
123 {
124 int64_t i_timestamp = time(NULL);
125
126 i_timestamp += 2082844800; // MOV/MP4 start date is 1/1/1904
127 // 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60
128
129 return i_timestamp;
130 }
131
132 /****************************************************************************/
133
matrix_apply_rotation(es_format_t * fmt,uint32_t mvhd_matrix[9])134 static void matrix_apply_rotation(es_format_t *fmt, uint32_t mvhd_matrix[9])
135 {
136 enum video_orientation_t orientation = ORIENT_NORMAL;
137 if (fmt->i_cat == VIDEO_ES)
138 orientation = fmt->video.orientation;
139
140 #define ATAN(a, b) \
141 do { \
142 mvhd_matrix[1] = ((uint32_t)(a)) << 16; \
143 mvhd_matrix[0] = ((uint32_t)(b)) << 16; \
144 } while(0)
145
146 switch (orientation) {
147 case ORIENT_ROTATED_90: ATAN( 1, 0); break;
148 case ORIENT_ROTATED_180: ATAN( 0, -1); break;
149 case ORIENT_ROTATED_270: ATAN(-1, 0); break;
150 default: ATAN( 0, 1); break;
151 }
152
153 mvhd_matrix[3] = mvhd_matrix[0] ? 0 : 0x10000;
154 mvhd_matrix[4] = mvhd_matrix[1] ? 0 : 0x10000;
155 }
156
AddEdit(bo_t * elst,int64_t i_movie_scaled_duration,int64_t i_media_scaled_time,bool b_64_ext)157 static void AddEdit(bo_t *elst,
158 int64_t i_movie_scaled_duration,
159 int64_t i_media_scaled_time,
160 bool b_64_ext)
161 {
162 if(b_64_ext)
163 {
164 bo_add_64be(elst, i_movie_scaled_duration);
165 bo_add_64be(elst, i_media_scaled_time);
166 }
167 else
168 {
169 bo_add_32be(elst, i_movie_scaled_duration);
170 bo_add_32be(elst, i_media_scaled_time);
171 }
172 bo_add_16be(elst, 1);
173 bo_add_16be(elst, 0);
174 }
175
GetEDTS(mp4mux_trackinfo_t * p_track,uint32_t i_movietimescale,bool b_64_ext)176 static bo_t *GetEDTS( mp4mux_trackinfo_t *p_track, uint32_t i_movietimescale, bool b_64_ext)
177 {
178 if(p_track->i_edits_count == 0)
179 return NULL;
180
181 bo_t *edts = box_new("edts");
182 bo_t *elst = box_full_new("elst", b_64_ext ? 1 : 0, 0);
183 if(!elst || !edts)
184 {
185 bo_free(elst);
186 bo_free(edts);
187 return NULL;
188 }
189
190 uint32_t i_total_edits = p_track->i_edits_count;
191 for(unsigned i=0; i<p_track->i_edits_count; i++)
192 {
193 /* !WARN! media time must start sample time 0, we need a -1 edit for start offsets */
194 if(p_track->p_edits[i].i_start_offset)
195 i_total_edits++;
196 }
197
198 bo_add_32be(elst, i_total_edits);
199
200 for(unsigned i=0; i<p_track->i_edits_count; i++)
201 {
202 if(p_track->p_edits[i].i_start_offset)
203 {
204 AddEdit(elst,
205 p_track->p_edits[i].i_start_offset * i_movietimescale / CLOCK_FREQ,
206 -1,
207 b_64_ext);
208 }
209
210 /* !WARN AGAIN! Uses different Timescales ! */
211 AddEdit(elst,
212 p_track->p_edits[i].i_duration * i_movietimescale / CLOCK_FREQ,
213 p_track->p_edits[i].i_start_time * p_track->i_timescale / CLOCK_FREQ,
214 b_64_ext);
215 }
216
217 box_gather(edts, elst);
218 return edts;
219 }
220
GetESDS(mp4mux_trackinfo_t * p_track)221 static bo_t *GetESDS(mp4mux_trackinfo_t *p_track)
222 {
223 bo_t *esds;
224
225 /* */
226 int i_decoder_specific_info_size = (p_track->fmt.i_extra > 0) ? 5 + p_track->fmt.i_extra : 0;
227
228 esds = box_full_new("esds", 0, 0);
229 if(!esds)
230 return NULL;
231
232 /* Compute Max bitrate */
233 int64_t i_bitrate_avg = 0;
234 int64_t i_bitrate_max = 0;
235 /* Compute avg/max bitrate */
236 for (unsigned i = 0; i < p_track->i_entry_count; i++) {
237 i_bitrate_avg += p_track->entry[i].i_size;
238 if (p_track->entry[i].i_length > 0) {
239 int64_t i_bitrate = INT64_C(8000000) * p_track->entry[i].i_size / p_track->entry[i].i_length;
240 if (i_bitrate > i_bitrate_max)
241 i_bitrate_max = i_bitrate;
242 }
243 }
244
245 if (p_track->i_read_duration > 0)
246 i_bitrate_avg = INT64_C(8000000) * i_bitrate_avg / p_track->i_read_duration;
247 else
248 i_bitrate_avg = 0;
249 if (i_bitrate_max <= 1)
250 i_bitrate_max = 0x7fffffff;
251
252 /* ES_Descr */
253 bo_add_mp4_tag_descr(esds, 0x03, 3 + 5 + 13 + i_decoder_specific_info_size + 5 + 1);
254 bo_add_16be(esds, p_track->i_track_id);
255 bo_add_8 (esds, 0x1f); // flags=0|streamPriority=0x1f
256
257 /* DecoderConfigDescr */
258 bo_add_mp4_tag_descr(esds, 0x04, 13 + i_decoder_specific_info_size);
259
260 int i_object_type_indication;
261 switch(p_track->fmt.i_codec)
262 {
263 case VLC_CODEC_MP4V:
264 i_object_type_indication = 0x20;
265 break;
266 case VLC_CODEC_MPGV:
267 if(p_track->fmt.i_original_fourcc == VLC_CODEC_MP1V)
268 {
269 i_object_type_indication = 0x6a; /* Visual ISO/IEC 11172-2 */
270 break;
271 }
272 /* fallthrough */
273 case VLC_CODEC_MP2V:
274 /* MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */
275 i_object_type_indication = 0x61; /* Visual 13818-2 Main Profile */
276 break;
277 case VLC_CODEC_MP1V:
278 i_object_type_indication = 0x6a; /* Visual ISO/IEC 11172-2 */
279 break;
280 case VLC_CODEC_MP4A:
281 /* FIXME for mpeg2-aac == 0x66->0x68 */
282 i_object_type_indication = 0x40;
283 break;
284 case VLC_CODEC_MP3:
285 case VLC_CODEC_MPGA:
286 i_object_type_indication =
287 p_track->fmt.audio.i_rate < 32000 ? 0x69 : 0x6b;
288 break;
289 case VLC_CODEC_DTS:
290 i_object_type_indication = 0xa9;
291 break;
292 default:
293 i_object_type_indication = 0xFE; /* No profile specified */
294 break;
295 }
296
297 uint8_t i_stream_type;
298 switch(p_track->fmt.i_cat)
299 {
300 case VIDEO_ES:
301 i_stream_type = 0x04;
302 break;
303 case AUDIO_ES:
304 i_stream_type = 0x05;
305 break;
306 case SPU_ES:
307 i_stream_type = 0x0D;
308 break;
309 default:
310 i_stream_type = 0x20; /* Private */
311 break;
312 }
313
314 bo_add_8 (esds, i_object_type_indication);
315 bo_add_8 (esds, (i_stream_type << 2) | 1);
316 bo_add_24be(esds, 1024 * 1024); // bufferSizeDB
317 bo_add_32be(esds, i_bitrate_max); // maxBitrate
318 bo_add_32be(esds, i_bitrate_avg); // avgBitrate
319
320 if (p_track->fmt.i_extra > 0) {
321 /* DecoderSpecificInfo */
322 bo_add_mp4_tag_descr(esds, 0x05, p_track->fmt.i_extra);
323
324 for (int i = 0; i < p_track->fmt.i_extra; i++)
325 bo_add_8(esds, ((uint8_t*)p_track->fmt.p_extra)[i]);
326 }
327
328 /* SL_Descr mandatory */
329 bo_add_mp4_tag_descr(esds, 0x06, 1);
330 bo_add_8 (esds, 0x02); // sl_predefined
331
332 return esds;
333 }
334
GetWaveTag(mp4mux_trackinfo_t * p_track)335 static bo_t *GetWaveTag(mp4mux_trackinfo_t *p_track)
336 {
337 bo_t *wave;
338 bo_t *box;
339
340 wave = box_new("wave");
341 if(wave)
342 {
343 box = box_new("frma");
344 if(box)
345 {
346 bo_add_fourcc(box, "mp4a");
347 box_gather(wave, box);
348 }
349
350 box = box_new("mp4a");
351 if(box)
352 {
353 bo_add_32be(box, 0);
354 box_gather(wave, box);
355 }
356
357 box = GetESDS(p_track);
358 box_gather(wave, box);
359
360 box = box_new("srcq");
361 if(box)
362 {
363 bo_add_32be(box, 0x40);
364 box_gather(wave, box);
365 }
366
367 /* wazza ? */
368 bo_add_32be(wave, 8); /* new empty box */
369 bo_add_32be(wave, 0); /* box label */
370 }
371 return wave;
372 }
373
GetDec3Tag(es_format_t * p_fmt,block_t * a52_frame)374 static bo_t *GetDec3Tag(es_format_t *p_fmt, block_t *a52_frame)
375 {
376 if (!a52_frame)
377 return NULL;
378
379 bs_t s;
380 bs_write_init(&s, a52_frame->p_buffer, sizeof(a52_frame->i_buffer));
381 bs_skip(&s, 16); // syncword
382
383 uint8_t fscod, bsid, bsmod, acmod, lfeon, strmtyp;
384
385 bsmod = 0;
386
387 strmtyp = bs_read(&s, 2);
388
389 if (strmtyp & 0x1) // dependent or reserved stream
390 return NULL;
391
392 if (bs_read(&s, 3) != 0x0) // substreamid: we don't support more than 1 stream
393 return NULL;
394
395 int numblkscod;
396 bs_skip(&s, 11); // frmsizecod
397 fscod = bs_read(&s, 2);
398 if (fscod == 0x03) {
399 bs_skip(&s, 2); // fscod2
400 numblkscod = 3;
401 } else {
402 numblkscod = bs_read(&s, 2);
403 }
404
405 acmod = bs_read(&s, 3);
406 lfeon = bs_read1(&s);
407
408 bsid = bs_read(&s, 5);
409
410 bs_skip(&s, 5); // dialnorm
411 if (bs_read1(&s)) // compre
412 bs_skip(&s, 5); // compr
413
414 if (acmod == 0) {
415 bs_skip(&s, 5); // dialnorm2
416 if (bs_read1(&s)) // compr2e
417 bs_skip(&s, 8); // compr2
418 }
419
420 if (strmtyp == 0x1) // dependent stream XXX: unsupported
421 if (bs_read1(&s)) // chanmape
422 bs_skip(&s, 16); // chanmap
423
424 /* we have to skip mixing info to read bsmod */
425 if (bs_read1(&s)) { // mixmdate
426 if (acmod > 0x2) // 2+ channels
427 bs_skip(&s, 2); // dmixmod
428 if ((acmod & 0x1) && (acmod > 0x2)) // 3 front channels
429 bs_skip(&s, 3 + 3); // ltrtcmixlev + lorocmixlev
430 if (acmod & 0x4) // surround channel
431 bs_skip(&s, 3 + 3); // ltrsurmixlev + lorosurmixlev
432 if (lfeon)
433 if (bs_read1(&s))
434 bs_skip(&s, 5); // lfemixlevcod
435 if (strmtyp == 0) { // independent stream
436 if (bs_read1(&s)) // pgmscle
437 bs_skip(&s, 6); // pgmscl
438 if (acmod == 0x0) // dual mono
439 if (bs_read1(&s)) // pgmscl2e
440 bs_skip(&s, 6); // pgmscl2
441 if (bs_read1(&s)) // extpgmscle
442 bs_skip(&s, 6); // extpgmscl
443 uint8_t mixdef = bs_read(&s, 2);
444 if (mixdef == 0x1)
445 bs_skip(&s, 5);
446 else if (mixdef == 0x2)
447 bs_skip(&s, 12);
448 else if (mixdef == 0x3) {
449 uint8_t mixdeflen = bs_read(&s, 5);
450 bs_skip(&s, 8 * (mixdeflen + 2));
451 }
452 if (acmod < 0x2) { // mono or dual mono
453 if (bs_read1(&s)) // paninfoe
454 bs_skip(&s, 14); // paninfo
455 if (acmod == 0) // dual mono
456 if (bs_read1(&s)) // paninfo2e
457 bs_skip(&s, 14); // paninfo2
458 }
459 if (bs_read1(&s)) { // frmmixcfginfoe
460 static const int blocks[4] = { 1, 2, 3, 6 };
461 int number_of_blocks = blocks[numblkscod];
462 if (number_of_blocks == 1)
463 bs_skip(&s, 5); // blkmixcfginfo[0]
464 else for (int i = 0; i < number_of_blocks; i++)
465 if (bs_read1(&s)) // blkmixcfginfoe
466 bs_skip(&s, 5); // blkmixcfginfo[i]
467 }
468 }
469 }
470
471 if (bs_read1(&s)) // infomdate
472 bsmod = bs_read(&s, 3);
473
474 uint8_t mp4_eac3_header[5] = {0};
475 bs_init(&s, mp4_eac3_header, sizeof(mp4_eac3_header));
476
477 int data_rate = p_fmt->i_bitrate / 1000;
478 bs_write(&s, 13, data_rate);
479 bs_write(&s, 3, 0); // num_ind_sub - 1
480 bs_write(&s, 2, fscod);
481 bs_write(&s, 5, bsid);
482 bs_write(&s, 5, bsmod);
483 bs_write(&s, 3, acmod);
484 bs_write(&s, 1, lfeon);
485 bs_write(&s, 3, 0); // reserved
486 bs_write(&s, 4, 0); // num_dep_sub
487 bs_write(&s, 1, 0); // reserved
488
489 bo_t *dec3 = box_new("dec3");
490 if(dec3)
491 bo_add_mem(dec3, sizeof(mp4_eac3_header), mp4_eac3_header);
492
493 return dec3;
494 }
495
GetDac3Tag(block_t * a52_frame)496 static bo_t *GetDac3Tag(block_t *a52_frame)
497 {
498 if (!a52_frame)
499 return NULL;
500
501 bo_t *dac3 = box_new("dac3");
502 if(!dac3)
503 return NULL;
504
505 bs_t s;
506 bs_init(&s, a52_frame->p_buffer, sizeof(a52_frame->i_buffer));
507
508 uint8_t fscod, bsid, bsmod, acmod, lfeon, frmsizecod;
509
510 bs_skip(&s, 16 + 16); // syncword + crc
511
512 fscod = bs_read(&s, 2);
513 frmsizecod = bs_read(&s, 6);
514 bsid = bs_read(&s, 5);
515 bsmod = bs_read(&s, 3);
516 acmod = bs_read(&s, 3);
517 if (acmod == 2)
518 bs_skip(&s, 2); // dsurmod
519 else {
520 if ((acmod & 1) && acmod != 1)
521 bs_skip(&s, 2); // cmixlev
522 if (acmod & 4)
523 bs_skip(&s, 2); // surmixlev
524 }
525
526 lfeon = bs_read1(&s);
527
528 uint8_t mp4_a52_header[3];
529 bs_init(&s, mp4_a52_header, sizeof(mp4_a52_header));
530
531 bs_write(&s, 2, fscod);
532 bs_write(&s, 5, bsid);
533 bs_write(&s, 3, bsmod);
534 bs_write(&s, 3, acmod);
535 bs_write(&s, 1, lfeon);
536 bs_write(&s, 5, frmsizecod >> 1); // bit_rate_code
537 bs_write(&s, 5, 0); // reserved
538
539 bo_add_mem(dac3, sizeof(mp4_a52_header), mp4_a52_header);
540
541 return dac3;
542 }
543
GetDamrTag(es_format_t * p_fmt)544 static bo_t *GetDamrTag(es_format_t *p_fmt)
545 {
546 bo_t *damr = box_new("damr");
547 if(!damr)
548 return NULL;
549
550 bo_add_fourcc(damr, "REFC");
551 bo_add_8(damr, 0);
552
553 if (p_fmt->i_codec == VLC_CODEC_AMR_NB)
554 bo_add_16be(damr, 0x81ff); /* Mode set (all modes for AMR_NB) */
555 else
556 bo_add_16be(damr, 0x83ff); /* Mode set (all modes for AMR_WB) */
557 bo_add_16be(damr, 0x1); /* Mode change period (no restriction) */
558
559 return damr;
560 }
561
GetD263Tag(void)562 static bo_t *GetD263Tag(void)
563 {
564 bo_t *d263 = box_new("d263");
565 if(!d263)
566 return NULL;
567
568 bo_add_fourcc(d263, "VLC ");
569 bo_add_16be(d263, 0xa);
570 bo_add_8(d263, 0);
571
572 return d263;
573 }
574
GetHvcCTag(es_format_t * p_fmt,bool b_completeness)575 static bo_t *GetHvcCTag(es_format_t *p_fmt, bool b_completeness)
576 {
577 /* Generate hvcC box matching iso/iec 14496-15 3rd edition */
578 bo_t *hvcC = box_new("hvcC");
579 if(!hvcC || !p_fmt->i_extra)
580 return hvcC;
581
582 /* Extradata is already an HEVCDecoderConfigurationRecord */
583 if(hevc_ishvcC(p_fmt->p_extra, p_fmt->i_extra))
584 {
585 (void) bo_add_mem(hvcC, p_fmt->i_extra, p_fmt->p_extra);
586 return hvcC;
587 }
588
589 struct hevc_dcr_params params = { };
590 const uint8_t *p_nal;
591 size_t i_nal;
592
593 hxxx_iterator_ctx_t it;
594 hxxx_iterator_init(&it, p_fmt->p_extra, p_fmt->i_extra, 0);
595 while(hxxx_annexb_iterate_next(&it, &p_nal, &i_nal))
596 {
597 switch (hevc_getNALType(p_nal))
598 {
599 case HEVC_NAL_VPS:
600 if(params.i_vps_count != HEVC_DCR_VPS_COUNT)
601 {
602 params.p_vps[params.i_vps_count] = p_nal;
603 params.rgi_vps[params.i_vps_count] = i_nal;
604 params.i_vps_count++;
605 }
606 break;
607 case HEVC_NAL_SPS:
608 if(params.i_sps_count != HEVC_DCR_SPS_COUNT)
609 {
610 params.p_sps[params.i_sps_count] = p_nal;
611 params.rgi_sps[params.i_sps_count] = i_nal;
612 params.i_sps_count++;
613 }
614 break;
615 case HEVC_NAL_PPS:
616 if(params.i_pps_count != HEVC_DCR_PPS_COUNT)
617 {
618 params.p_pps[params.i_pps_count] = p_nal;
619 params.rgi_pps[params.i_pps_count] = i_nal;
620 params.i_pps_count++;
621 }
622 break;
623 case HEVC_NAL_PREF_SEI:
624 if(params.i_seipref_count != HEVC_DCR_SEI_COUNT)
625 {
626 params.p_seipref[params.i_seipref_count] = p_nal;
627 params.rgi_seipref[params.i_seipref_count] = i_nal;
628 params.i_seipref_count++;
629 }
630 break;
631 case HEVC_NAL_SUFF_SEI:
632 if(params.i_seisuff_count != HEVC_DCR_SEI_COUNT)
633 {
634 params.p_seisuff[params.i_seisuff_count] = p_nal;
635 params.rgi_seisuff[params.i_seisuff_count] = i_nal;
636 params.i_seisuff_count++;
637 }
638 break;
639
640 default:
641 break;
642 }
643 }
644
645 size_t i_dcr;
646 uint8_t *p_dcr = hevc_create_dcr(¶ms, 4, b_completeness, &i_dcr);
647 if(!p_dcr)
648 {
649 bo_free(hvcC);
650 return NULL;
651 }
652
653 bo_add_mem(hvcC, i_dcr, p_dcr);
654 free(p_dcr);
655
656 return hvcC;
657 }
658
GetWaveFormatExTag(es_format_t * p_fmt,const char * tag)659 static bo_t *GetWaveFormatExTag(es_format_t *p_fmt, const char *tag)
660 {
661 bo_t *box = box_new(tag);
662 if(!box)
663 return NULL;
664
665 uint16_t wFormatTag;
666 fourcc_to_wf_tag(p_fmt->i_codec, &wFormatTag);
667 bo_add_16le(box, wFormatTag); //wFormatTag
668 bo_add_16le(box, p_fmt->audio.i_channels); //nChannels
669 bo_add_32le(box, p_fmt->audio.i_rate); //nSamplesPerSec
670 bo_add_32le(box, p_fmt->i_bitrate / 8); //nAvgBytesPerSec
671 bo_add_16le(box, p_fmt->audio.i_blockalign); //nBlockAlign
672 bo_add_16le(box, p_fmt->audio.i_bitspersample); //wBitsPerSample
673 bo_add_16le(box, p_fmt->i_extra); //cbSize
674
675 bo_add_mem(box, p_fmt->i_extra, p_fmt->p_extra);
676
677 return box;
678 }
679
GetxxxxTag(es_format_t * p_fmt,const char * tag)680 static bo_t *GetxxxxTag(es_format_t *p_fmt, const char *tag)
681 {
682 bo_t *box = box_new(tag);
683 if(!box)
684 return NULL;
685 bo_add_mem(box, p_fmt->i_extra, p_fmt->p_extra);
686 return box;
687 }
688
GetAvcCTag(es_format_t * p_fmt)689 static bo_t *GetAvcCTag(es_format_t *p_fmt)
690 {
691 bo_t *avcC = box_new("avcC");/* FIXME use better value */
692 if(!avcC)
693 return NULL;
694 const uint8_t *p_sps, *p_pps, *p_ext;
695 size_t i_sps_size, i_pps_size, i_ext_size;
696
697 if(! h264_AnnexB_get_spspps(p_fmt->p_extra, p_fmt->i_extra,
698 &p_sps, &i_sps_size,
699 &p_pps, &i_pps_size,
700 &p_ext, &i_ext_size ) )
701 {
702 p_sps = p_pps = p_ext = NULL;
703 i_sps_size = i_pps_size = i_ext_size = 0;
704 }
705
706 bo_add_8(avcC, 1); /* configuration version */
707 bo_add_8(avcC, i_sps_size > 3 ? p_sps[1] : PROFILE_H264_MAIN);
708 bo_add_8(avcC, i_sps_size > 3 ? p_sps[2] : 64);
709 bo_add_8(avcC, i_sps_size > 3 ? p_sps[3] : 30); /* level, 5.1 */
710 bo_add_8(avcC, 0xff); /* 0b11111100 | lengthsize = 0x11 */
711
712 bo_add_8(avcC, 0xe0 | (i_sps_size > 0 ? 1 : 0)); /* 0b11100000 | sps_count */
713 if (i_sps_size > 0) {
714 bo_add_16be(avcC, i_sps_size);
715 bo_add_mem(avcC, i_sps_size, p_sps);
716 }
717
718 bo_add_8(avcC, (i_pps_size > 0 ? 1 : 0)); /* pps_count */
719 if (i_pps_size > 0) {
720 bo_add_16be(avcC, i_pps_size);
721 bo_add_mem(avcC, i_pps_size, p_pps);
722 }
723
724 if( i_sps_size > 3 &&
725 (p_sps[1] == PROFILE_H264_HIGH ||
726 p_sps[1] == PROFILE_H264_HIGH_10 ||
727 p_sps[1] == PROFILE_H264_HIGH_422 ||
728 p_sps[1] == PROFILE_H264_HIGH_444 ||
729 p_sps[1] == PROFILE_H264_HIGH_444_PREDICTIVE) )
730 {
731 h264_sequence_parameter_set_t *p_spsdata = h264_decode_sps( p_sps, i_sps_size, true );
732 if( p_spsdata )
733 {
734 uint8_t data[3];
735 if( h264_get_chroma_luma( p_spsdata, &data[0], &data[1], &data[2]) )
736 {
737 bo_add_8(avcC, 0xFC | data[0]);
738 bo_add_8(avcC, 0xF8 | (data[1] - 8));
739 bo_add_8(avcC, 0xF8 | (data[2] - 8));
740 bo_add_8(avcC, (i_ext_size > 0 ? 1 : 0));
741 if (i_ext_size > 0) {
742 bo_add_16be(avcC, i_ext_size);
743 bo_add_mem(avcC, i_ext_size, p_ext);
744 }
745 }
746 h264_release_sps( p_spsdata );
747 }
748 }
749
750 return avcC;
751 }
752
753 /* TODO: No idea about these values */
GetSVQ3Tag(es_format_t * p_fmt)754 static bo_t *GetSVQ3Tag(es_format_t *p_fmt)
755 {
756 bo_t *smi = box_new("SMI ");
757 if(!smi)
758 return NULL;
759
760 if (p_fmt->i_extra > 0x4e) {
761 uint8_t *p_end = &((uint8_t*)p_fmt->p_extra)[p_fmt->i_extra];
762 uint8_t *p = &((uint8_t*)p_fmt->p_extra)[0x46];
763
764 while (p + 8 < p_end) {
765 int i_size = GetDWBE(p);
766 if (i_size <= 1) /* FIXME handle 1 as long size */
767 break;
768 if (!strncmp((const char *)&p[4], "SMI ", 4)) {
769 bo_add_mem(smi, p_end - p - 8, &p[8]);
770 return smi;
771 }
772 p += i_size;
773 }
774 }
775
776 /* Create a dummy one in fallback */
777 bo_add_fourcc(smi, "SEQH");
778 bo_add_32be(smi, 0x5);
779 bo_add_32be(smi, 0xe2c0211d);
780 bo_add_8(smi, 0xc0);
781
782 return smi;
783 }
784
GetUdtaTag(mp4mux_trackinfo_t ** pp_tracks,unsigned int i_tracks)785 static bo_t *GetUdtaTag(mp4mux_trackinfo_t **pp_tracks, unsigned int i_tracks)
786 {
787 bo_t *udta = box_new("udta");
788 if (!udta)
789 return NULL;
790
791 /* Requirements */
792 for (unsigned int i = 0; i < i_tracks; i++) {
793 mp4mux_trackinfo_t *p_stream = pp_tracks[i];
794 vlc_fourcc_t codec = p_stream->fmt.i_codec;
795
796 if (codec == VLC_CODEC_MP4V || codec == VLC_CODEC_MP4A) {
797 bo_t *box = box_new("\251req");
798 if(!box)
799 break;
800 /* String length */
801 bo_add_16be(box, sizeof("QuickTime 6.0 or greater") - 1);
802 bo_add_16be(box, 0);
803 bo_add_mem(box, sizeof("QuickTime 6.0 or greater") - 1,
804 (uint8_t *)"QuickTime 6.0 or greater");
805 box_gather(udta, box);
806 break;
807 }
808 }
809
810 /* Encoder */
811 {
812 bo_t *box = box_new("\251enc");
813 if(box)
814 {
815 /* String length */
816 bo_add_16be(box, sizeof(PACKAGE_STRING " stream output") - 1);
817 bo_add_16be(box, 0);
818 bo_add_mem(box, sizeof(PACKAGE_STRING " stream output") - 1,
819 (uint8_t*)PACKAGE_STRING " stream output");
820 box_gather(udta, box);
821 }
822 }
823 #if 0
824 /* Misc atoms */
825 vlc_meta_t *p_meta = p_mux->p_sout->p_meta;
826 if (p_meta) {
827 #define ADD_META_BOX(type, box_string) { \
828 bo_t *box = NULL; \
829 if (vlc_meta_Get(p_meta, vlc_meta_##type)) \
830 box = box_new("\251" box_string); \
831 if (box) { \
832 bo_add_16be(box, strlen(vlc_meta_Get(p_meta, vlc_meta_##type))); \
833 bo_add_16be(box, 0); \
834 bo_add_mem(box, strlen(vlc_meta_Get(p_meta, vlc_meta_##type)), \
835 (uint8_t*)(vlc_meta_Get(p_meta, vlc_meta_##type))); \
836 box_gather(udta, box); \
837 } }
838
839 ADD_META_BOX(Title, "nam");
840 ADD_META_BOX(Artist, "ART");
841 ADD_META_BOX(Genre, "gen");
842 ADD_META_BOX(Copyright, "cpy");
843 ADD_META_BOX(Description, "des");
844 ADD_META_BOX(Date, "day");
845 ADD_META_BOX(URL, "url");
846 #undef ADD_META_BOX
847 }
848 #endif
849 return udta;
850 }
851
GetSounBox(vlc_object_t * p_obj,mp4mux_trackinfo_t * p_track,bool b_mov)852 static bo_t *GetSounBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b_mov)
853 {
854 VLC_UNUSED(p_obj);
855
856 bool b_descr = true;
857 vlc_fourcc_t codec = p_track->fmt.i_codec;
858 char fcc[4];
859
860 if (codec == VLC_CODEC_MPGA ||
861 codec == VLC_CODEC_MP3) {
862 if (b_mov) {
863 b_descr = false;
864 memcpy(fcc, ".mp3", 4);
865 } else
866 memcpy(fcc, "mp4a", 4);
867 } else if (codec == VLC_CODEC_A52) {
868 memcpy(fcc, "ac-3", 4);
869 } else if (codec == VLC_CODEC_EAC3) {
870 memcpy(fcc, "ec-3", 4);
871 } else if (codec == VLC_CODEC_DTS) {
872 memcpy(fcc, "DTS ", 4);
873 } else if (codec == VLC_CODEC_WMAP) {
874 memcpy(fcc, "wma ", 4);
875 } else
876 vlc_fourcc_to_char(codec, fcc);
877
878 bo_t *soun = box_new(fcc);
879 if(!soun)
880 return NULL;
881 for (int i = 0; i < 6; i++)
882 bo_add_8(soun, 0); // reserved;
883 bo_add_16be(soun, 1); // data-reference-index
884
885 /* SoundDescription */
886 if (b_mov && codec == VLC_CODEC_MP4A)
887 bo_add_16be(soun, 1); // version 1;
888 else
889 bo_add_16be(soun, 0); // version 0;
890 bo_add_16be(soun, 0); // revision level (0)
891 bo_add_32be(soun, 0); // vendor
892 // channel-count
893 bo_add_16be(soun, p_track->fmt.audio.i_channels);
894 // sample size
895 bo_add_16be(soun, p_track->fmt.audio.i_bitspersample ?
896 p_track->fmt.audio.i_bitspersample : 16);
897 bo_add_16be(soun, -2); // compression id
898 bo_add_16be(soun, 0); // packet size (0)
899 bo_add_16be(soun, p_track->fmt.audio.i_rate); // sampleratehi
900 bo_add_16be(soun, 0); // sampleratelo
901
902 /* Extended data for SoundDescription V1 */
903 if (b_mov && p_track->fmt.i_codec == VLC_CODEC_MP4A) {
904 /* samples per packet */
905 bo_add_32be(soun, p_track->fmt.audio.i_frame_length);
906 bo_add_32be(soun, 1536); /* bytes per packet */
907 bo_add_32be(soun, 2); /* bytes per frame */
908 /* bytes per sample */
909 bo_add_32be(soun, 2 /*p_fmt->audio.i_bitspersample/8 */);
910 }
911
912 /* Add an ES Descriptor */
913 if (b_descr) {
914 bo_t *box;
915
916 if (b_mov && codec == VLC_CODEC_MP4A)
917 box = GetWaveTag(p_track);
918 else if (codec == VLC_CODEC_AMR_NB)
919 box = GetDamrTag(&p_track->fmt);
920 else if (codec == VLC_CODEC_A52)
921 box = GetDac3Tag(p_track->a52_frame);
922 else if (codec == VLC_CODEC_EAC3)
923 box = GetDec3Tag(&p_track->fmt, p_track->a52_frame);
924 else if (codec == VLC_CODEC_WMAP)
925 box = GetWaveFormatExTag(&p_track->fmt, "wfex");
926 else
927 box = GetESDS(p_track);
928
929 if (box)
930 box_gather(soun, box);
931 }
932
933 return soun;
934 }
935
GetVideBox(vlc_object_t * p_obj,mp4mux_trackinfo_t * p_track,bool b_mov)936 static bo_t *GetVideBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b_mov)
937 {
938 VLC_UNUSED(p_obj);
939 VLC_UNUSED(b_mov);
940
941 char fcc[4];
942
943 switch(p_track->fmt.i_codec)
944 {
945 case VLC_CODEC_MP4V:
946 case VLC_CODEC_MPGV: memcpy(fcc, "mp4v", 4); break;
947 case VLC_CODEC_MJPG: memcpy(fcc, "mjpa", 4); break;
948 case VLC_CODEC_SVQ1: memcpy(fcc, "SVQ1", 4); break;
949 case VLC_CODEC_SVQ3: memcpy(fcc, "SVQ3", 4); break;
950 case VLC_CODEC_H263: memcpy(fcc, "s263", 4); break;
951 case VLC_CODEC_H264: memcpy(fcc, "avc1", 4); break;
952 case VLC_CODEC_VC1 : memcpy(fcc, "vc-1", 4); break;
953 /* FIXME: find a way to know if no non-VCL units are in the stream (->hvc1)
954 * see 14496-15 8.4.1.1.1 */
955 case VLC_CODEC_HEVC: memcpy(fcc, "hev1", 4); break;
956 case VLC_CODEC_YV12: memcpy(fcc, "yv12", 4); break;
957 case VLC_CODEC_YUYV: memcpy(fcc, "YUY2", 4); break;
958 default:
959 vlc_fourcc_to_char(p_track->fmt.i_codec, fcc);
960 break;
961 }
962
963 bo_t *vide = box_new(fcc);
964 if(!vide)
965 return NULL;
966 for (int i = 0; i < 6; i++)
967 bo_add_8(vide, 0); // reserved;
968 bo_add_16be(vide, 1); // data-reference-index
969
970 bo_add_16be(vide, 0); // predefined;
971 bo_add_16be(vide, 0); // reserved;
972 for (int i = 0; i < 3; i++)
973 bo_add_32be(vide, 0); // predefined;
974
975 bo_add_16be(vide, p_track->fmt.video.i_visible_width); // i_width
976 bo_add_16be(vide, p_track->fmt.video.i_visible_height); // i_height
977
978 bo_add_32be(vide, 0x00480000); // h 72dpi
979 bo_add_32be(vide, 0x00480000); // v 72dpi
980
981 bo_add_32be(vide, 0); // data size, always 0
982 bo_add_16be(vide, 1); // frames count per sample
983
984 // compressor name;
985 for (int i = 0; i < 32; i++)
986 bo_add_8(vide, 0);
987
988 bo_add_16be(vide, 0x18); // depth
989 bo_add_16be(vide, 0xffff); // predefined
990
991 /* add an ES Descriptor */
992 switch(p_track->fmt.i_codec)
993 {
994 case VLC_CODEC_MP4V:
995 case VLC_CODEC_MPGV:
996 box_gather(vide, GetESDS(p_track));
997 break;
998
999 case VLC_CODEC_H263:
1000 box_gather(vide, GetD263Tag());
1001 break;
1002
1003 case VLC_CODEC_SVQ3:
1004 box_gather(vide, GetSVQ3Tag(&p_track->fmt));
1005 break;
1006
1007 case VLC_CODEC_H264:
1008 box_gather(vide, GetAvcCTag(&p_track->fmt));
1009 break;
1010
1011 case VLC_CODEC_VC1:
1012 box_gather(vide, GetxxxxTag(&p_track->fmt, "dvc1"));
1013 break;
1014
1015 case VLC_CODEC_HEVC:
1016 /* Write HvcC without forcing VPS/SPS/PPS/SEI array_completeness */
1017 box_gather(vide, GetHvcCTag(&p_track->fmt, false));
1018 break;
1019 }
1020
1021 return vide;
1022 }
1023
GetTextBox(void)1024 static bo_t *GetTextBox(void)
1025 {
1026 bo_t *text = box_new("text");
1027 if(!text)
1028 return NULL;
1029
1030 for (int i = 0; i < 6; i++)
1031 bo_add_8(text, 0); // reserved;
1032 bo_add_16be(text, 1); // data-reference-index
1033
1034 bo_add_32be(text, 0); // display flags
1035 bo_add_32be(text, 0); // justification
1036 for (int i = 0; i < 3; i++)
1037 bo_add_16be(text, 0); // back ground color
1038
1039 bo_add_16be(text, 0); // box text
1040 bo_add_16be(text, 0); // box text
1041 bo_add_16be(text, 0); // box text
1042 bo_add_16be(text, 0); // box text
1043
1044 bo_add_64be(text, 0); // reserved
1045 for (int i = 0; i < 3; i++)
1046 bo_add_16be(text, 0xff); // foreground color
1047
1048 bo_add_8 (text, 9);
1049 bo_add_mem(text, 9, (uint8_t*)"Helvetica");
1050
1051 return text;
1052 }
1053
GetScaledEntryDuration(const mp4mux_entry_t * p_entry,uint32_t i_timescale,mtime_t * pi_total_mtime,int64_t * pi_total_scaled)1054 static int64_t GetScaledEntryDuration( const mp4mux_entry_t *p_entry, uint32_t i_timescale,
1055 mtime_t *pi_total_mtime, int64_t *pi_total_scaled )
1056 {
1057 const mtime_t i_totalscaledtototalmtime = *pi_total_scaled * CLOCK_FREQ / i_timescale;
1058 const mtime_t i_diff = *pi_total_mtime - i_totalscaledtototalmtime;
1059
1060 /* Ensure to compensate the drift due to loss from time, and from scale, conversions */
1061 int64_t i_scaled = (p_entry->i_length + i_diff) * i_timescale / CLOCK_FREQ;
1062 *pi_total_mtime += p_entry->i_length;
1063 *pi_total_scaled += i_scaled;
1064
1065 return i_scaled;
1066 }
1067
GetStblBox(vlc_object_t * p_obj,mp4mux_trackinfo_t * p_track,bool b_mov,bool b_stco64)1068 static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b_mov, bool b_stco64)
1069 {
1070 /* sample description */
1071 bo_t *stsd = box_full_new("stsd", 0, 0);
1072 if(!stsd)
1073 return NULL;
1074 bo_add_32be(stsd, 1);
1075 if (p_track->fmt.i_cat == AUDIO_ES)
1076 box_gather(stsd, GetSounBox(p_obj, p_track, b_mov));
1077 else if (p_track->fmt.i_cat == VIDEO_ES)
1078 box_gather(stsd, GetVideBox(p_obj, p_track, b_mov));
1079 else if (p_track->fmt.i_cat == SPU_ES)
1080 box_gather(stsd, GetTextBox());
1081
1082 /* chunk offset table */
1083 bo_t *stco;
1084
1085 if (b_stco64) {
1086 /* 64 bits version */
1087 stco = box_full_new("co64", 0, 0);
1088 } else {
1089 /* 32 bits version */
1090 stco = box_full_new("stco", 0, 0);
1091 }
1092 if(!stco)
1093 {
1094 bo_free(stsd);
1095 return NULL;
1096 }
1097 bo_add_32be(stco, 0); // entry-count (fixed latter)
1098
1099 /* sample to chunk table */
1100 bo_t *stsc = box_full_new("stsc", 0, 0);
1101 if(!stsc)
1102 {
1103 bo_free(stco);
1104 bo_free(stsd);
1105 return NULL;
1106 }
1107 bo_add_32be(stsc, 0); // entry-count (fixed latter)
1108
1109 unsigned i_chunk = 0;
1110 unsigned i_stsc_last_val = 0, i_stsc_entries = 0;
1111 for (unsigned i = 0; i < p_track->i_entry_count; i_chunk++) {
1112 mp4mux_entry_t *entry = p_track->entry;
1113 int i_first = i;
1114
1115 if (b_stco64)
1116 bo_add_64be(stco, entry[i].i_pos);
1117 else
1118 bo_add_32be(stco, entry[i].i_pos);
1119
1120 for (; i < p_track->i_entry_count; i++)
1121 if (i >= p_track->i_entry_count - 1 ||
1122 entry[i].i_pos + entry[i].i_size != entry[i+1].i_pos) {
1123 i++;
1124 break;
1125 }
1126
1127 /* Add entry to the stsc table */
1128 if (i_stsc_last_val != i - i_first) {
1129 bo_add_32be(stsc, 1 + i_chunk); // first-chunk
1130 bo_add_32be(stsc, i - i_first) ; // samples-per-chunk
1131 bo_add_32be(stsc, 1); // sample-descr-index
1132 i_stsc_last_val = i - i_first;
1133 i_stsc_entries++;
1134 }
1135 }
1136
1137 /* Fix stco entry count */
1138 bo_swap_32be(stco, 12, i_chunk);
1139 if(p_obj)
1140 msg_Dbg(p_obj, "created %d chunks (stco)", i_chunk);
1141
1142 /* Fix stsc entry count */
1143 bo_swap_32be(stsc, 12, i_stsc_entries );
1144
1145 /* add stts */
1146 bo_t *stts = box_full_new("stts", 0, 0);
1147 if(!stts)
1148 {
1149 bo_free(stsd);
1150 bo_free(stco);
1151 bo_free(stsc);
1152 return NULL;
1153 }
1154 bo_add_32be(stts, 0); // entry-count (fixed latter)
1155
1156 mtime_t i_total_mtime = 0;
1157 int64_t i_total_scaled = 0;
1158 unsigned i_index = 0;
1159 for (unsigned i = 0; i < p_track->i_entry_count; i_index++) {
1160 int i_first = i;
1161
1162 int64_t i_scaled = GetScaledEntryDuration(&p_track->entry[i], p_track->i_timescale,
1163 &i_total_mtime, &i_total_scaled);
1164 for (unsigned j=i+1; j < p_track->i_entry_count; j++)
1165 {
1166 mtime_t i_total_mtime_next = i_total_mtime;
1167 int64_t i_total_scaled_next = i_total_scaled;
1168 int64_t i_scalednext = GetScaledEntryDuration(&p_track->entry[j], p_track->i_timescale,
1169 &i_total_mtime_next, &i_total_scaled_next);
1170 if( i_scalednext != i_scaled )
1171 break;
1172
1173 i_total_mtime = i_total_mtime_next;
1174 i_total_scaled = i_total_scaled_next;
1175 i = j;
1176 }
1177
1178 bo_add_32be(stts, ++i - i_first); // sample-count
1179 bo_add_32be(stts, i_scaled); // sample-delta
1180 }
1181 bo_swap_32be(stts, 12, i_index);
1182
1183 //msg_Dbg(p_obj, "total sout duration %"PRId64" reconverted from scaled %"PRId64,
1184 // i_total_mtime, i_total_scaled * CLOCK_FREQ / p_track->i_timescale );
1185
1186 /* composition time handling */
1187 bo_t *ctts = NULL;
1188 if ( p_track->b_hasbframes && (ctts = box_full_new("ctts", 0, 0)) )
1189 {
1190 bo_add_32be(ctts, 0);
1191 i_index = 0;
1192 for (unsigned i = 0; i < p_track->i_entry_count; i_index++)
1193 {
1194 int i_first = i;
1195 mtime_t i_offset = p_track->entry[i].i_pts_dts;
1196
1197 for (; i < p_track->i_entry_count; ++i)
1198 if (i == p_track->i_entry_count || p_track->entry[i].i_pts_dts != i_offset)
1199 break;
1200
1201 bo_add_32be(ctts, i - i_first); // sample-count
1202 bo_add_32be(ctts, i_offset * p_track->i_timescale / CLOCK_FREQ ); // sample-offset
1203 }
1204 bo_swap_32be(ctts, 12, i_index);
1205 }
1206
1207 bo_t *stsz = box_full_new("stsz", 0, 0);
1208 if(!stsz)
1209 {
1210 bo_free(stsd);
1211 bo_free(stco);
1212 bo_free(stts);
1213 return NULL;
1214 }
1215 int i_size = 0;
1216 for (unsigned i = 0; i < p_track->i_entry_count; i++)
1217 {
1218 if ( i == 0 )
1219 i_size = p_track->entry[i].i_size;
1220 else if ( p_track->entry[i].i_size != i_size )
1221 {
1222 i_size = 0;
1223 break;
1224 }
1225 }
1226 bo_add_32be(stsz, i_size); // sample-size
1227 bo_add_32be(stsz, p_track->i_entry_count); // sample-count
1228 if ( i_size == 0 ) // all samples have different size
1229 {
1230 for (unsigned i = 0; i < p_track->i_entry_count; i++)
1231 bo_add_32be(stsz, p_track->entry[i].i_size); // sample-size
1232 }
1233
1234 /* create stss table */
1235 bo_t *stss = NULL;
1236 i_index = 0;
1237 if ( p_track->fmt.i_cat == VIDEO_ES || p_track->fmt.i_cat == AUDIO_ES )
1238 {
1239 mtime_t i_interval = -1;
1240 for (unsigned i = 0; i < p_track->i_entry_count; i++)
1241 {
1242 if ( i_interval != -1 )
1243 {
1244 i_interval += p_track->entry[i].i_length + p_track->entry[i].i_pts_dts;
1245 if ( i_interval < CLOCK_FREQ * 2 )
1246 continue;
1247 }
1248
1249 if (p_track->entry[i].i_flags & BLOCK_FLAG_TYPE_I) {
1250 if (stss == NULL) {
1251 stss = box_full_new("stss", 0, 0);
1252 if(!stss)
1253 break;
1254 bo_add_32be(stss, 0); /* fixed later */
1255 }
1256 bo_add_32be(stss, 1 + i);
1257 i_index++;
1258 i_interval = 0;
1259 }
1260 }
1261 }
1262
1263 if (stss)
1264 bo_swap_32be(stss, 12, i_index);
1265
1266 /* Now gather all boxes into stbl */
1267 bo_t *stbl = box_new("stbl");
1268 if(!stbl)
1269 {
1270 bo_free(stsd);
1271 bo_free(stco);
1272 bo_free(stts);
1273 bo_free(stsz);
1274 bo_free(stss);
1275 bo_free(ctts);
1276 return NULL;
1277 }
1278 box_gather(stbl, stsd);
1279 box_gather(stbl, stts);
1280 if (stss)
1281 box_gather(stbl, stss);
1282 if (ctts)
1283 box_gather(stbl, ctts);
1284 box_gather(stbl, stsc);
1285 box_gather(stbl, stsz);
1286 p_track->i_stco_pos = stbl->b->i_buffer + 16;
1287 box_gather(stbl, stco);
1288
1289 return stbl;
1290 }
1291
ApplyARtoWidth(const video_format_t * vfmt)1292 static unsigned ApplyARtoWidth(const video_format_t *vfmt)
1293 {
1294 if (vfmt->i_sar_num > 0 && vfmt->i_sar_den > 0)
1295 {
1296 return (int64_t)vfmt->i_sar_num *
1297 (int64_t)vfmt->i_visible_width / vfmt->i_sar_den;
1298 }
1299 else return vfmt->i_visible_width;
1300 }
1301
mp4mux_GetMoovBox(vlc_object_t * p_obj,mp4mux_trackinfo_t ** pp_tracks,unsigned int i_tracks,int64_t i_movie_duration,bool b_fragmented,bool b_mov,bool b_64_ext,bool b_stco64)1302 bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, unsigned int i_tracks,
1303 int64_t i_movie_duration,
1304 bool b_fragmented, bool b_mov, bool b_64_ext, bool b_stco64 )
1305 {
1306 bo_t *moov, *mvhd;
1307
1308 uint32_t i_movie_timescale = 90000;
1309 int64_t i_timestamp = get_timestamp();
1310
1311 /* Important for smooth streaming where its (not muxed here) media time offsets
1312 * are in timescale == track timescale */
1313 if( i_tracks == 1 )
1314 i_movie_timescale = pp_tracks[0]->i_timescale;
1315
1316 moov = box_new("moov");
1317 if(!moov)
1318 return NULL;
1319 /* Create general info */
1320 if( i_movie_duration == 0 && !b_fragmented )
1321 {
1322 for (unsigned int i = 0; i < i_tracks; i++) {
1323 mp4mux_trackinfo_t *p_stream = pp_tracks[i];
1324 i_movie_duration = __MAX(i_movie_duration, p_stream->i_read_duration);
1325 }
1326 if(p_obj)
1327 msg_Dbg(p_obj, "movie duration %"PRId64"s", i_movie_duration / CLOCK_FREQ);
1328
1329 i_movie_duration = i_movie_duration * i_movie_timescale / CLOCK_FREQ;
1330 }
1331
1332 /* *** add /moov/mvhd *** */
1333 if (!b_64_ext) {
1334 mvhd = box_full_new("mvhd", 0, 0);
1335 if(!mvhd)
1336 {
1337 bo_free(moov);
1338 return NULL;
1339 }
1340 bo_add_32be(mvhd, i_timestamp); // creation time
1341 bo_add_32be(mvhd, i_timestamp); // modification time
1342 bo_add_32be(mvhd, i_movie_timescale); // timescale
1343 bo_add_32be(mvhd, i_movie_duration); // duration
1344 } else {
1345 mvhd = box_full_new("mvhd", 1, 0);
1346 if(!mvhd)
1347 {
1348 bo_free(moov);
1349 return NULL;
1350 }
1351 bo_add_64be(mvhd, i_timestamp); // creation time
1352 bo_add_64be(mvhd, i_timestamp); // modification time
1353 bo_add_32be(mvhd, i_movie_timescale); // timescale
1354 bo_add_64be(mvhd, i_movie_duration); // duration
1355 }
1356 bo_add_32be(mvhd, 0x10000); // rate
1357 bo_add_16be(mvhd, 0x100); // volume
1358 bo_add_16be(mvhd, 0); // reserved
1359 for (int i = 0; i < 2; i++)
1360 bo_add_32be(mvhd, 0); // reserved
1361
1362 uint32_t mvhd_matrix[9] = { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };
1363
1364 for (int i = 0; i < 9; i++)
1365 bo_add_32be(mvhd, mvhd_matrix[i]);// matrix
1366 for (int i = 0; i < 6; i++)
1367 bo_add_32be(mvhd, 0); // pre-defined
1368
1369 /* Next available track id */
1370 bo_add_32be(mvhd, (i_tracks) ? pp_tracks[i_tracks -1]->i_track_id + 1: 1); // next-track-id
1371
1372 box_gather(moov, mvhd);
1373
1374 for (unsigned int i_trak = 0; i_trak < i_tracks; i_trak++) {
1375 mp4mux_trackinfo_t *p_stream = pp_tracks[i_trak];
1376
1377 mtime_t i_stream_duration;
1378 if ( !b_fragmented )
1379 i_stream_duration = p_stream->i_read_duration * i_movie_timescale / CLOCK_FREQ;
1380 else
1381 i_stream_duration = 0;
1382
1383 /* *** add /moov/trak *** */
1384 bo_t *trak = box_new("trak");
1385 if(!trak)
1386 continue;
1387
1388 /* *** add /moov/trak/tkhd *** */
1389 bo_t *tkhd;
1390 if (!b_64_ext) {
1391 if (b_mov)
1392 tkhd = box_full_new("tkhd", 0, 0x0f);
1393 else
1394 tkhd = box_full_new("tkhd", 0, 1);
1395 if(!tkhd)
1396 {
1397 bo_free(trak);
1398 continue;
1399 }
1400 bo_add_32be(tkhd, i_timestamp); // creation time
1401 bo_add_32be(tkhd, i_timestamp); // modification time
1402 bo_add_32be(tkhd, p_stream->i_track_id);
1403 bo_add_32be(tkhd, 0); // reserved 0
1404 bo_add_32be(tkhd, i_stream_duration); // duration
1405 } else {
1406 if (b_mov)
1407 tkhd = box_full_new("tkhd", 1, 0x0f);
1408 else
1409 tkhd = box_full_new("tkhd", 1, 1);
1410 if(!tkhd)
1411 {
1412 bo_free(trak);
1413 continue;
1414 }
1415 bo_add_64be(tkhd, i_timestamp); // creation time
1416 bo_add_64be(tkhd, i_timestamp); // modification time
1417 bo_add_32be(tkhd, p_stream->i_track_id);
1418 bo_add_32be(tkhd, 0); // reserved 0
1419 bo_add_64be(tkhd, i_stream_duration); // duration
1420 }
1421
1422 for (int i = 0; i < 2; i++)
1423 bo_add_32be(tkhd, 0); // reserved
1424 bo_add_16be(tkhd, 0); // layer
1425 bo_add_16be(tkhd, 0); // pre-defined
1426 // volume
1427 bo_add_16be(tkhd, p_stream->fmt.i_cat == AUDIO_ES ? 0x100 : 0);
1428 bo_add_16be(tkhd, 0); // reserved
1429 matrix_apply_rotation(&p_stream->fmt, mvhd_matrix);
1430 for (int i = 0; i < 9; i++)
1431 bo_add_32be(tkhd, mvhd_matrix[i]); // matrix
1432 if (p_stream->fmt.i_cat == AUDIO_ES) {
1433 bo_add_32be(tkhd, 0); // width (presentation)
1434 bo_add_32be(tkhd, 0); // height(presentation)
1435 } else if (p_stream->fmt.i_cat == VIDEO_ES) {
1436 // width (presentation)
1437 bo_add_32be(tkhd, ApplyARtoWidth(&p_stream->fmt.video) << 16);
1438 // height(presentation)
1439 bo_add_32be(tkhd, p_stream->fmt.video.i_visible_height << 16);
1440 } else {
1441 unsigned i_width = 320;
1442 unsigned i_height = 200;
1443 /* Find video track for SPU representation */
1444 for (unsigned int i = 0; i < i_tracks; i++)
1445 {
1446 const mp4mux_trackinfo_t *tk = pp_tracks[i];
1447 if (tk->fmt.i_cat != VIDEO_ES)
1448 continue;
1449 i_width = ApplyARtoWidth(&tk->fmt.video);
1450 i_height = tk->fmt.video.i_visible_height;
1451 break;
1452 }
1453 bo_add_32be(tkhd, i_width << 16); // width (presentation)
1454 bo_add_32be(tkhd, i_height << 16); // height(presentation)
1455 }
1456
1457 box_gather(trak, tkhd);
1458
1459 /* *** add /moov/trak/edts and elst */
1460 bo_t *edts = GetEDTS(p_stream, i_movie_timescale, b_64_ext);
1461 if(edts)
1462 box_gather(trak, edts);
1463
1464 /* *** add /moov/trak/mdia *** */
1465 bo_t *mdia = box_new("mdia");
1466 if(!mdia)
1467 {
1468 bo_free(trak);
1469 continue;
1470 }
1471
1472 /* media header */
1473 bo_t *mdhd;
1474 if (!b_64_ext) {
1475 mdhd = box_full_new("mdhd", 0, 0);
1476 if(!mdhd)
1477 {
1478 bo_free(mdia);
1479 bo_free(trak);
1480 continue;
1481 }
1482 bo_add_32be(mdhd, i_timestamp); // creation time
1483 bo_add_32be(mdhd, i_timestamp); // modification time
1484 bo_add_32be(mdhd, p_stream->i_timescale); // timescale
1485 bo_add_32be(mdhd, i_stream_duration * p_stream->i_timescale / i_movie_timescale); // duration
1486 } else {
1487 mdhd = box_full_new("mdhd", 1, 0);
1488 if(!mdhd)
1489 {
1490 bo_free(mdia);
1491 bo_free(trak);
1492 continue;
1493 }
1494 bo_add_64be(mdhd, i_timestamp); // creation time
1495 bo_add_64be(mdhd, i_timestamp); // modification time
1496 bo_add_32be(mdhd, p_stream->i_timescale); // timescale
1497 bo_add_64be(mdhd, i_stream_duration * p_stream->i_timescale / i_movie_timescale); // duration
1498 }
1499
1500 if (p_stream->fmt.psz_language) {
1501 char *psz = p_stream->fmt.psz_language;
1502 const iso639_lang_t *pl = NULL;
1503 uint16_t lang = 0x0;
1504
1505 if (strlen(psz) == 2)
1506 pl = GetLang_1(psz);
1507 else if (strlen(psz) == 3) {
1508 pl = GetLang_2B(psz);
1509 if (!strcmp(pl->psz_iso639_1, "??"))
1510 pl = GetLang_2T(psz);
1511 }
1512
1513 if (pl && strcmp(pl->psz_iso639_1, "??"))
1514 lang = ((pl->psz_iso639_2T[0] - 0x60) << 10) |
1515 ((pl->psz_iso639_2T[1] - 0x60) << 5) |
1516 ((pl->psz_iso639_2T[2] - 0x60));
1517 bo_add_16be(mdhd, lang); // language
1518 } else
1519 bo_add_16be(mdhd, 0 ); // language
1520 bo_add_16be(mdhd, 0 ); // predefined
1521 box_gather(mdia, mdhd);
1522
1523 /* handler reference */
1524 bo_t *hdlr = box_full_new("hdlr", 0, 0);
1525 if(!hdlr)
1526 {
1527 bo_free(mdia);
1528 bo_free(trak);
1529 continue;
1530 }
1531
1532 if (b_mov)
1533 bo_add_fourcc(hdlr, "mhlr"); // media handler
1534 else
1535 bo_add_32be(hdlr, 0);
1536
1537 if (p_stream->fmt.i_cat == AUDIO_ES)
1538 bo_add_fourcc(hdlr, "soun");
1539 else if (p_stream->fmt.i_cat == VIDEO_ES)
1540 bo_add_fourcc(hdlr, "vide");
1541 else if (p_stream->fmt.i_cat == SPU_ES)
1542 bo_add_fourcc(hdlr, "text");
1543
1544 bo_add_32be(hdlr, 0); // reserved
1545 bo_add_32be(hdlr, 0); // reserved
1546 bo_add_32be(hdlr, 0); // reserved
1547
1548 if (b_mov)
1549 bo_add_8(hdlr, 12); /* Pascal string for .mov */
1550
1551 if (p_stream->fmt.i_cat == AUDIO_ES)
1552 bo_add_mem(hdlr, 12, (uint8_t*)"SoundHandler");
1553 else if (p_stream->fmt.i_cat == VIDEO_ES)
1554 bo_add_mem(hdlr, 12, (uint8_t*)"VideoHandler");
1555 else
1556 bo_add_mem(hdlr, 12, (uint8_t*)"Text Handler");
1557
1558 if (!b_mov)
1559 bo_add_8(hdlr, 0); /* asciiz string for .mp4, yes that's BRAIN DAMAGED F**K MP4 */
1560
1561 box_gather(mdia, hdlr);
1562
1563 /* minf*/
1564 bo_t *minf = box_new("minf");
1565 if(!minf)
1566 {
1567 bo_free(mdia);
1568 bo_free(trak);
1569 continue;
1570 }
1571
1572 /* add smhd|vmhd */
1573 if (p_stream->fmt.i_cat == AUDIO_ES) {
1574 bo_t *smhd = box_full_new("smhd", 0, 0);
1575 if(smhd)
1576 {
1577 bo_add_16be(smhd, 0); // balance
1578 bo_add_16be(smhd, 0); // reserved
1579
1580 box_gather(minf, smhd);
1581 }
1582 } else if (p_stream->fmt.i_cat == VIDEO_ES) {
1583 bo_t *vmhd = box_full_new("vmhd", 0, 1);
1584 if(vmhd)
1585 {
1586 bo_add_16be(vmhd, 0); // graphicsmode
1587 for (int i = 0; i < 3; i++)
1588 bo_add_16be(vmhd, 0); // opcolor
1589 box_gather(minf, vmhd);
1590 }
1591 } else if (p_stream->fmt.i_cat == SPU_ES) {
1592 bo_t *gmin = box_full_new("gmin", 0, 1);
1593 if(gmin)
1594 {
1595 bo_add_16be(gmin, 0); // graphicsmode
1596 for (int i = 0; i < 3; i++)
1597 bo_add_16be(gmin, 0); // opcolor
1598 bo_add_16be(gmin, 0); // balance
1599 bo_add_16be(gmin, 0); // reserved
1600
1601 bo_t *gmhd = box_new("gmhd");
1602 if(gmhd)
1603 {
1604 box_gather(gmhd, gmin);
1605 box_gather(minf, gmhd);
1606 }
1607 else bo_free(gmin);
1608 }
1609 }
1610
1611 /* dinf */
1612 bo_t *dref = box_full_new("dref", 0, 0);
1613 if(dref)
1614 {
1615 bo_add_32be(dref, 1);
1616
1617 bo_t *url = box_full_new("url ", 0, 0x01);
1618 if(url)
1619 box_gather(dref, url);
1620
1621 bo_t *dinf = box_new("dinf");
1622 if(dinf)
1623 {
1624 box_gather(dinf, dref);
1625
1626 /* append dinf to mdia */
1627 box_gather(minf, dinf);
1628 }
1629 else bo_free(dref);
1630 }
1631
1632 /* add stbl */
1633 bo_t *stbl;
1634 if ( b_fragmented )
1635 {
1636 uint32_t i_backup = p_stream->i_entry_count;
1637 p_stream->i_entry_count = 0;
1638 stbl = GetStblBox(p_obj, p_stream, b_mov, b_stco64);
1639 p_stream->i_entry_count = i_backup;
1640 }
1641 else
1642 stbl = GetStblBox(p_obj, p_stream, b_mov, b_stco64);
1643
1644 /* append stbl to minf */
1645 p_stream->i_stco_pos += minf->b->i_buffer;
1646 box_gather(minf, stbl);
1647
1648 /* append minf to mdia */
1649 p_stream->i_stco_pos += mdia->b->i_buffer;
1650 box_gather(mdia, minf);
1651
1652 /* append mdia to trak */
1653 p_stream->i_stco_pos += trak->b->i_buffer;
1654 box_gather(trak, mdia);
1655
1656 /* append trak to moov */
1657 p_stream->i_stco_pos += moov->b->i_buffer;
1658 box_gather(moov, trak);
1659 }
1660
1661 /* Add user data tags */
1662 box_gather(moov, GetUdtaTag(pp_tracks, i_tracks));
1663
1664 if ( b_fragmented )
1665 {
1666 bo_t *mvex = box_new("mvex");
1667 if( mvex )
1668 {
1669 if( i_movie_duration )
1670 {
1671 bo_t *mehd = box_full_new("mehd", b_64_ext ? 1 : 0, 0);
1672 if(mehd)
1673 {
1674 if(b_64_ext)
1675 bo_add_64be(mehd, i_movie_duration * i_movie_timescale / CLOCK_FREQ);
1676 else
1677 bo_add_32be(mehd, i_movie_duration * i_movie_timescale / CLOCK_FREQ);
1678 box_gather(mvex, mehd);
1679 }
1680 }
1681 for (unsigned int i_trak = 0; mvex && i_trak < i_tracks; i_trak++)
1682 {
1683 mp4mux_trackinfo_t *p_stream = pp_tracks[i_trak];
1684
1685 /* Try to find some defaults */
1686 if ( p_stream->i_entry_count )
1687 {
1688 // FIXME: find highest occurence
1689 p_stream->i_trex_default_length = p_stream->entry[0].i_length;
1690 p_stream->i_trex_default_size = p_stream->entry[0].i_size;
1691 }
1692
1693 /* *** add /mvex/trex *** */
1694 bo_t *trex = box_full_new("trex", 0, 0);
1695 bo_add_32be(trex, p_stream->i_track_id);
1696 bo_add_32be(trex, 1); // sample desc index
1697 bo_add_32be(trex, (uint64_t)p_stream->i_trex_default_length * p_stream->i_timescale / CLOCK_FREQ); // sample duration
1698 bo_add_32be(trex, p_stream->i_trex_default_size); // sample size
1699 bo_add_32be(trex, 0); // sample flags
1700 box_gather(mvex, trex);
1701 }
1702 box_gather(moov, mvex);
1703 }
1704 }
1705
1706 if(moov->b)
1707 box_fix(moov, moov->b->i_buffer);
1708 return moov;
1709 }
1710
mp4mux_GetFtyp(vlc_fourcc_t major,uint32_t minor,vlc_fourcc_t extra[],size_t i_fourcc)1711 bo_t *mp4mux_GetFtyp(vlc_fourcc_t major, uint32_t minor, vlc_fourcc_t extra[], size_t i_fourcc)
1712 {
1713 bo_t *box = box_new("ftyp");
1714 if(box)
1715 {
1716 bo_add_fourcc(box, &major);
1717 bo_add_32be (box, minor);
1718 for(size_t i=0; i<i_fourcc; i++)
1719 bo_add_fourcc(box, &extra[i]);
1720 if(!box->b)
1721 {
1722 free(box);
1723 return NULL;
1724 }
1725 box_fix(box, box->b->i_buffer);
1726 }
1727 return box;
1728 }
1729
mp4mux_CanMux(vlc_object_t * p_obj,const es_format_t * p_fmt)1730 bool mp4mux_CanMux(vlc_object_t *p_obj, const es_format_t *p_fmt)
1731 {
1732 switch(p_fmt->i_codec)
1733 {
1734 case VLC_CODEC_A52:
1735 case VLC_CODEC_DTS:
1736 case VLC_CODEC_EAC3:
1737 case VLC_CODEC_MP4A:
1738 case VLC_CODEC_MP4V:
1739 case VLC_CODEC_MPGA:
1740 case VLC_CODEC_MP3:
1741 case VLC_CODEC_MPGV:
1742 case VLC_CODEC_MP2V:
1743 case VLC_CODEC_MP1V:
1744 case VLC_CODEC_MJPG:
1745 case VLC_CODEC_MJPGB:
1746 case VLC_CODEC_SVQ1:
1747 case VLC_CODEC_SVQ3:
1748 case VLC_CODEC_H263:
1749 case VLC_CODEC_AMR_NB:
1750 case VLC_CODEC_AMR_WB:
1751 case VLC_CODEC_YV12:
1752 case VLC_CODEC_YUYV:
1753 case VLC_CODEC_VC1:
1754 case VLC_CODEC_WMAP:
1755 break;
1756 case VLC_CODEC_H264:
1757 if(!p_fmt->i_extra && p_obj)
1758 msg_Warn(p_obj, "H264 muxing from AnnexB source will set an incorrect default profile");
1759 break;
1760 case VLC_CODEC_HEVC:
1761 if(!p_fmt->i_extra && p_obj)
1762 {
1763 msg_Err(p_obj, "HEVC muxing from AnnexB source is unsupported");
1764 return false;
1765 }
1766 break;
1767 case VLC_CODEC_SUBT:
1768 if(p_obj)
1769 msg_Warn(p_obj, "subtitle track added like in .mov (even when creating .mp4)");
1770 break;
1771 default:
1772 return false;
1773 }
1774 return true;
1775 }
1776