1 /* $Id: muxmp4.c,v 1.24 2005/11/04 13:09:41 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.fr/>.
5 It may be used under the terms of the GNU General Public License. */
12 void AddIPodUUID(MP4FileHandle, MP4TrackId);
14 struct hb_mux_object_s
23 /* Cumulated durations so far, in output & input timescale units (see MP4Mux) */
24 int64_t sum_dur; // duration in output timescale units
25 int64_t sum_dur_in; // duration in input 90KHz timescale units
27 // bias to keep render offsets in ctts atom positive (set up by encx264)
30 /* Chapter state information for muxing */
31 MP4TrackId chapter_track;
33 uint64_t chapter_duration;
35 /* Sample rate of the first audio track.
36 * Used for the timescale
46 struct hb_text_sample_s
53 /**********************************************************************
55 **********************************************************************
56 * Creates a buffer for a text track sample
57 *********************************************************************/
58 static struct hb_text_sample_s *MP4CreateTextSample( char *textString, uint64_t duration )
60 struct hb_text_sample_s *sample = NULL;
61 int stringLength = strlen(textString);
64 if( stringLength < 1024 )
66 sample = malloc( sizeof( struct hb_text_sample_s ) );
68 //textLength = (stringLength; // Account for BOM
69 sample->length = stringLength + 2 + 12; // Account for text length code and other marker
70 sample->duration = (MP4Duration)duration;
72 // 2-byte length marker
73 sample->sample[0] = (stringLength >> 8) & 0xff;
74 sample->sample[1] = stringLength & 0xff;
76 strncpy( (char *)&(sample->sample[2]), textString, stringLength );
80 // Modifier Length Marker
81 sample->sample[x] = 0x00;
82 sample->sample[x+1] = 0x00;
83 sample->sample[x+2] = 0x00;
84 sample->sample[x+3] = 0x0C;
87 sample->sample[x+4] = 'e';
88 sample->sample[x+5] = 'n';
89 sample->sample[x+6] = 'c';
90 sample->sample[x+7] = 'd';
93 sample->sample[x+8] = 0x00;
94 sample->sample[x+9] = 0x00;
95 sample->sample[x+10] = (256 >> 8) & 0xff;
96 sample->sample[x+11] = 256 & 0xff;
102 /**********************************************************************
103 * MP4GenerateChapterSample
104 **********************************************************************
105 * Creates a buffer for a text track sample
106 *********************************************************************/
107 static struct hb_text_sample_s *MP4GenerateChapterSample( hb_mux_object_t * m,
111 // We substract 1 from the chapter number because the chapters start at
112 // 1 but our name array starts at 0. We substract another 1 because we're
113 // writing the text of the previous chapter mark (when we get the start
114 // of chapter 2 we know the duration of chapter 1 & can write its mark).
115 hb_chapter_t *chapter_data = hb_list_item( m->job->title->list_chapter,
117 char tmp_buffer[1024];
118 char *string = tmp_buffer;
120 tmp_buffer[0] = '\0';
122 if( chapter_data != NULL )
124 string = chapter_data->title;
127 if( strlen(string) == 0 || strlen(string) >= 1024 )
129 snprintf( tmp_buffer, 1023, "Chapter %03i", chapter - 2 );
133 return MP4CreateTextSample( string, duration );
137 /**********************************************************************
139 **********************************************************************
140 * Allocates hb_mux_data_t structures, create file and write headers
141 *********************************************************************/
142 static int MP4Init( hb_mux_object_t * m )
144 hb_job_t * job = m->job;
145 hb_title_t * title = job->title;
148 hb_mux_data_t * mux_data;
150 u_int16_t language_code;
152 /* Flags for enabling/disabling tracks in an MP4. */
153 typedef enum { TRACK_DISABLED = 0x0, TRACK_ENABLED = 0x1, TRACK_IN_MOVIE = 0x2, TRACK_IN_PREVIEW = 0x4, TRACK_IN_POSTER = 0x8} track_header_flags;
155 if( (audio = hb_list_item(title->list_audio, 0)) != NULL )
157 /* Need the sample rate of the first audio track to use as the timescale. */
158 m->samplerate = audio->config.out.samplerate;
163 m->samplerate = 90000;
166 /* Create an empty mp4 file */
167 if (job->largeFileSize)
168 /* Use 64-bit MP4 file */
170 m->file = MP4Create( job->file, MP4_DETAILS_ERROR, MP4_CREATE_64BIT_DATA );
171 hb_deep_log( 2, "muxmp4: using 64-bit MP4 formatting.");
174 /* Limit MP4s to less than 4 GB */
176 m->file = MP4Create( job->file, MP4_DETAILS_ERROR, 0 );
179 if (m->file == MP4_INVALID_FILE_HANDLE)
181 hb_error("muxmp4.c: MP4Create failed!");
187 mux_data = malloc( sizeof( hb_mux_data_t ) );
188 job->mux_data = mux_data;
190 /* When using the standard 90000 timescale, QuickTime tends to have
191 synchronization issues (audio not playing at the correct speed).
192 To workaround this, we use the audio samplerate as the
194 if (!(MP4SetTimeScale( m->file, m->samplerate )))
196 hb_error("muxmp4.c: MP4SetTimeScale failed!");
201 if( job->vcodec == HB_VCODEC_X264 )
203 /* Stolen from mp4creator */
204 if(!(MP4SetVideoProfileLevel( m->file, 0x7F )))
206 hb_error("muxmp4.c: MP4SetVideoProfileLevel failed!");
211 mux_data->track = MP4AddH264VideoTrack( m->file, m->samplerate,
212 MP4_INVALID_DURATION, job->width, job->height,
213 job->config.h264.sps[1], /* AVCProfileIndication */
214 job->config.h264.sps[2], /* profile_compat */
215 job->config.h264.sps[3], /* AVCLevelIndication */
216 3 ); /* 4 bytes length before each NAL unit */
219 MP4AddH264SequenceParameterSet( m->file, mux_data->track,
220 job->config.h264.sps, job->config.h264.sps_length );
221 MP4AddH264PictureParameterSet( m->file, mux_data->track,
222 job->config.h264.pps, job->config.h264.pps_length );
224 if( job->h264_level == 30 || job->ipod_atom)
226 hb_deep_log( 2, "muxmp4: adding iPod atom");
227 AddIPodUUID(m->file, mux_data->track);
230 m->init_delay = job->config.h264.init_delay;
232 else /* FFmpeg or XviD */
234 if(!(MP4SetVideoProfileLevel( m->file, MPEG4_SP_L3 )))
236 hb_error("muxmp4.c: MP4SetVideoProfileLevel failed!");
240 mux_data->track = MP4AddVideoTrack( m->file, m->samplerate,
241 MP4_INVALID_DURATION, job->width, job->height,
242 MP4_MPEG4_VIDEO_TYPE );
243 if (mux_data->track == MP4_INVALID_TRACK_ID)
245 hb_error("muxmp4.c: MP4AddVideoTrack failed!");
251 /* VOL from FFmpeg or XviD */
252 if (!(MP4SetTrackESConfiguration( m->file, mux_data->track,
253 job->config.mpeg4.bytes, job->config.mpeg4.length )))
255 hb_error("muxmp4.c: MP4SetTrackESConfiguration failed!");
261 // COLR atom for color and gamma correction.
263 // http://developer.apple.com/quicktime/icefloe/dispatch019.html#colr
264 // http://forum.doom9.org/showthread.php?t=133982#post1090068
265 // we say anything that's likely to be HD content is ITU BT.709 and
266 // DVD, SD TV & other content is ITU BT.601. We look at the title height
267 // rather than the job height here to get uncropped input dimensions.
268 if ( job->title->height >= 720 )
270 // we guess that 720p or above is ITU BT.709 HD content
271 MP4AddColr(m->file, mux_data->track, 1, 1, 1);
275 // ITU BT.601 DVD or SD TV content
276 MP4AddColr(m->file, mux_data->track, 6, 1, 6);
279 if( job->pixel_ratio )
281 /* PASP atom for anamorphic video */
284 width = job->pixel_aspect_width;
286 height = job->pixel_aspect_height;
288 MP4AddPixelAspectRatio(m->file, mux_data->track, (uint32_t)width, (uint32_t)height);
290 MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width * (width / height));
293 /* add the audio tracks */
294 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
296 static u_int8_t reserved2[16] = {
297 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x02, 0x00, 0x10,
300 0x00, 0x00, 0x00, 0x00,
303 audio = hb_list_item( title->list_audio, i );
304 mux_data = malloc( sizeof( hb_mux_data_t ) );
305 audio->priv.mux_data = mux_data;
307 if( audio->config.out.codec == HB_ACODEC_AC3 )
309 mux_data->track = MP4AddAC3AudioTrack(
311 m->samplerate, 1536, MP4_MPEG4_AUDIO_TYPE );
312 if (audio->config.out.name == NULL) {
313 MP4SetTrackBytesProperty(
314 m->file, mux_data->track,
316 (const u_int8_t*)"Surround", strlen("Surround"));
319 MP4SetTrackBytesProperty(
320 m->file, mux_data->track,
322 (const u_int8_t*)(audio->config.out.name),
323 strlen(audio->config.out.name));
326 mux_data->track = MP4AddAudioTrack(
328 m->samplerate, 1024, MP4_MPEG4_AUDIO_TYPE );
329 if (audio->config.out.name == NULL) {
330 MP4SetTrackBytesProperty(
331 m->file, mux_data->track,
333 (const u_int8_t*)"Stereo", strlen("Stereo"));
336 MP4SetTrackBytesProperty(
337 m->file, mux_data->track,
339 (const u_int8_t*)(audio->config.out.name),
340 strlen(audio->config.out.name));
343 MP4SetAudioProfileLevel( m->file, 0x0F );
344 MP4SetTrackESConfiguration(
345 m->file, mux_data->track,
346 audio->priv.config.aac.bytes, audio->priv.config.aac.length );
348 /* Set the correct number of channels for this track */
349 reserved2[9] = (u_int8_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
350 MP4SetTrackBytesProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.reserved2", reserved2, sizeof(reserved2));
352 /* If we ever upgrade mpeg4ip, the line above should be replaced with the line below.*/
353 // MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.channels", (u_int16_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown));
356 /* Set the language for this track */
357 /* The language is stored as 5-bit text - 0x60 */
358 language_code = audio->config.lang.iso639_2[0] - 0x60; language_code <<= 5;
359 language_code |= audio->config.lang.iso639_2[1] - 0x60; language_code <<= 5;
360 language_code |= audio->config.lang.iso639_2[2] - 0x60;
361 MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.mdhd.language", language_code);
363 if( hb_list_count( title->list_audio ) > 1 )
365 /* Set the audio track alternate group */
366 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1);
370 /* Enable the first audio track */
371 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_ENABLED | TRACK_IN_MOVIE));
374 /* Disable the other audio tracks so QuickTime doesn't play
377 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_DISABLED | TRACK_IN_MOVIE));
378 hb_deep_log( 2, "muxp4: disabled extra audio track %i", mux_data->track-1);
383 if (job->chapter_markers)
385 /* add a text track for the chapters. We add the 'chap' atom to track
386 one which is usually the video track & should never be disabled.
387 The Quicktime spec says it doesn't matter which media track the
388 chap atom is on but it has to be an enabled track. */
389 MP4TrackId textTrack;
390 textTrack = MP4AddChapterTextTrack(m->file, 1);
392 m->chapter_track = textTrack;
393 m->chapter_duration = 0;
394 m->current_chapter = job->chapter_start;
397 /* Add encoded-by metadata listing version and build date */
399 tool_string = (char *)malloc(80);
400 snprintf( tool_string, 80, "HandBrake %s %i", HB_VERSION, HB_BUILD);
401 MP4SetMetadataTool(m->file, tool_string);
407 static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
410 hb_job_t * job = m->job;
414 if( mux_data == job->mux_data )
418 // if there are b-frames compute the render offset
419 // (we'll need it for both the video frame & the chapter track)
422 offset = ( buf->start + m->init_delay ) * m->samplerate / 90000 -
425 /* Add the sample before the new frame.
426 It is important that this be calculated prior to the duration
427 of the new video sample, as we want to sync to right after it.
428 (This is because of how durations for text tracks work in QT) */
429 if( job->chapter_markers && buf->new_chap )
431 struct hb_text_sample_s *sample;
433 // this chapter is postioned by writing out the previous chapter.
434 // the duration of the previous chapter is the duration up to but
435 // not including the current frame minus the duration of all
436 // chapters up to the previous.
437 duration = m->sum_dur - m->chapter_duration + offset;
440 /* The initial & final chapters can have very short durations
441 * (less than the error in our total duration estimate) so
442 * the duration calc above can result in a negative number.
443 * when this happens give the chapter a short duration (1/3
444 * of an ntsc frame time). */
445 duration = 1000 * m->samplerate / 90000;
448 sample = MP4GenerateChapterSample( m, duration, buf->new_chap );
450 if( !MP4WriteSample(m->file,
457 hb_error("Failed to write to output file, disk full?");
461 m->current_chapter = buf->new_chap;
462 m->chapter_duration += duration;
465 // since we're changing the sample rate we need to keep track of
466 // the truncation bias so that the audio and video don't go out
467 // of sync. m->sum_dur_in is the sum of the input durations so far.
468 // m->sum_dur is the sum of the output durations. Their difference
469 // (in output sample rate units) is the accumulated truncation bias.
470 int64_t bias = ( m->sum_dur_in * m->samplerate / 90000 ) - m->sum_dur;
471 int64_t dur_in = buf->stop - buf->start;
472 duration = dur_in * m->samplerate / 90000 + bias;
475 /* We got an illegal mp4/h264 duration. This shouldn't
476 be possible and usually indicates a bug in the upstream code.
477 Complain in the hope that someone will go find the bug but
478 try to fix the error so that the file will still be playable. */
479 hb_log("MP4Mux: illegal duration %lld, bias %lld, start %lld (%lld),"
480 "stop %lld (%lld), sum_dur %lld",
481 duration, bias, buf->start * m->samplerate / 90000, buf->start,
482 buf->stop * m->samplerate / 90000, buf->stop, m->sum_dur );
483 /* we don't know when the next frame starts so we can't pick a
484 valid duration for this one so we pick something "short"
485 (roughly 1/3 of an NTSC frame time) and rely on the bias calc
486 for the next frame to correct things (a duration underestimate
487 just results in a large bias on the next frame). */
488 duration = 1000 * m->samplerate / 90000;
490 m->sum_dur += duration;
491 m->sum_dur_in += dur_in;
496 duration = MP4_INVALID_DURATION;
499 // Here's where the sample actually gets muxed.
500 if( !MP4WriteSample( m->file,
506 ((buf->frametype & HB_FRAME_KEY) != 0) ) )
508 hb_error("Failed to write to output file, disk full?");
515 static int MP4End( hb_mux_object_t * m )
517 hb_job_t * job = m->job;
519 /* Write our final chapter marker */
520 if( m->job->chapter_markers )
522 int64_t duration = m->sum_dur - m->chapter_duration;
523 /* The final chapter can have a very short duration - if it's less
524 * than a second just skip it. */
525 if ( duration >= m->samplerate )
528 struct hb_text_sample_s *sample = MP4GenerateChapterSample( m, duration,
529 m->current_chapter + 1 );
530 if( ! MP4WriteSample(m->file, m->chapter_track, sample->sample,
531 sample->length, sample->duration, 0, true) )
533 hb_error("Failed to write to output file, disk full?");
542 // Insert track edit to get A/V back in sync. The edit amount is
544 int64_t edit_amt = m->init_delay * m->samplerate / 90000;
545 MP4AddTrackEdit(m->file, 1, MP4_INVALID_EDIT_ID, edit_amt,
546 MP4GetTrackDuration(m->file, 1), 0);
547 if ( m->job->chapter_markers )
549 // apply same edit to chapter track to keep it in sync with video
550 MP4AddTrackEdit(m->file, m->chapter_track, MP4_INVALID_EDIT_ID,
552 MP4GetTrackDuration(m->file, m->chapter_track), 0);
558 if ( job->mp4_optimize )
560 hb_log( "muxmp4: optimizing file" );
561 char filename[1024]; memset( filename, 0, 1024 );
562 snprintf( filename, 1024, "%s.tmp", job->file );
563 MP4Optimize( job->file, filename, MP4_DETAILS_ERROR );
565 rename( filename, job->file );
571 hb_mux_object_t * hb_mux_mp4_init( hb_job_t * job )
573 hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );