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. */
7 #include "mp4v2/mp4v2.h"
8 #include "a52dec/a52.h"
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
47 /**********************************************************************
49 **********************************************************************
50 * Allocates hb_mux_data_t structures, create file and write headers
51 *********************************************************************/
52 static int MP4Init( hb_mux_object_t * m )
54 hb_job_t * job = m->job;
55 hb_title_t * title = job->title;
58 hb_mux_data_t * mux_data;
60 uint16_t language_code;
62 /* Flags for enabling/disabling tracks in an MP4. */
63 typedef enum { TRACK_DISABLED = 0x0, TRACK_ENABLED = 0x1, TRACK_IN_MOVIE = 0x2, TRACK_IN_PREVIEW = 0x4, TRACK_IN_POSTER = 0x8} track_header_flags;
65 if( (audio = hb_list_item(title->list_audio, 0)) != NULL )
67 /* Need the sample rate of the first audio track to use as the timescale. */
68 m->samplerate = audio->config.out.samplerate;
73 m->samplerate = 90000;
76 /* Create an empty mp4 file */
77 if (job->largeFileSize)
78 /* Use 64-bit MP4 file */
80 m->file = MP4Create( job->file, MP4_DETAILS_ERROR, MP4_CREATE_64BIT_DATA );
81 hb_deep_log( 2, "muxmp4: using 64-bit MP4 formatting.");
84 /* Limit MP4s to less than 4 GB */
86 m->file = MP4Create( job->file, MP4_DETAILS_ERROR, 0 );
89 if (m->file == MP4_INVALID_FILE_HANDLE)
91 hb_error("muxmp4.c: MP4Create failed!");
97 mux_data = malloc( sizeof( hb_mux_data_t ) );
98 job->mux_data = mux_data;
100 /* When using the standard 90000 timescale, QuickTime tends to have
101 synchronization issues (audio not playing at the correct speed).
102 To workaround this, we use the audio samplerate as the
104 if (!(MP4SetTimeScale( m->file, m->samplerate )))
106 hb_error("muxmp4.c: MP4SetTimeScale failed!");
111 if( job->vcodec == HB_VCODEC_X264 )
113 /* Stolen from mp4creator */
114 MP4SetVideoProfileLevel( m->file, 0x7F );
115 mux_data->track = MP4AddH264VideoTrack( m->file, m->samplerate,
116 MP4_INVALID_DURATION, job->width, job->height,
117 job->config.h264.sps[1], /* AVCProfileIndication */
118 job->config.h264.sps[2], /* profile_compat */
119 job->config.h264.sps[3], /* AVCLevelIndication */
120 3 ); /* 4 bytes length before each NAL unit */
123 MP4AddH264SequenceParameterSet( m->file, mux_data->track,
124 job->config.h264.sps, job->config.h264.sps_length );
125 MP4AddH264PictureParameterSet( m->file, mux_data->track,
126 job->config.h264.pps, job->config.h264.pps_length );
128 if( job->h264_level == 30 || job->ipod_atom)
130 hb_deep_log( 2, "muxmp4: adding iPod atom");
131 MP4AddIPodUUID(m->file, mux_data->track);
134 m->init_delay = job->config.h264.init_delay;
136 else /* FFmpeg or XviD */
138 MP4SetVideoProfileLevel( m->file, MPEG4_SP_L3 );
139 mux_data->track = MP4AddVideoTrack( m->file, m->samplerate,
140 MP4_INVALID_DURATION, job->width, job->height,
141 MP4_MPEG4_VIDEO_TYPE );
142 if (mux_data->track == MP4_INVALID_TRACK_ID)
144 hb_error("muxmp4.c: MP4AddVideoTrack failed!");
150 /* VOL from FFmpeg or XviD */
151 if (!(MP4SetTrackESConfiguration( m->file, mux_data->track,
152 job->config.mpeg4.bytes, job->config.mpeg4.length )))
154 hb_error("muxmp4.c: MP4SetTrackESConfiguration failed!");
160 // COLR atom for color and gamma correction.
162 // http://developer.apple.com/quicktime/icefloe/dispatch019.html#colr
163 // http://forum.doom9.org/showthread.php?t=133982#post1090068
164 // the user can set it from job->color_matrix, otherwise by default
165 // we say anything that's likely to be HD content is ITU BT.709 and
166 // DVD, SD TV & other content is ITU BT.601. We look at the title height
167 // rather than the job height here to get uncropped input dimensions.
168 if( job->color_matrix == 1 )
170 // ITU BT.601 DVD or SD TV content
171 MP4AddColr(m->file, mux_data->track, 6, 1, 6);
173 else if( job->color_matrix == 2 )
175 // ITU BT.709 HD content
176 MP4AddColr(m->file, mux_data->track, 1, 1, 1);
178 else if ( job->title->width >= 1280 || job->title->height >= 720 )
180 // we guess that 720p or above is ITU BT.709 HD content
181 MP4AddColr(m->file, mux_data->track, 1, 1, 1);
185 // ITU BT.601 DVD or SD TV content
186 MP4AddColr(m->file, mux_data->track, 6, 1, 6);
189 if( job->pixel_ratio )
191 /* PASP atom for anamorphic video */
194 width = job->pixel_aspect_width;
196 height = job->pixel_aspect_height;
198 MP4AddPixelAspectRatio(m->file, mux_data->track, (uint32_t)width, (uint32_t)height);
200 MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width * (width / height));
203 /* add the audio tracks */
204 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
206 static uint8_t reserved2[16] = {
207 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x02, 0x00, 0x10,
210 0x00, 0x00, 0x00, 0x00,
213 audio = hb_list_item( title->list_audio, i );
214 mux_data = malloc( sizeof( hb_mux_data_t ) );
215 audio->priv.mux_data = mux_data;
217 if( audio->config.out.codec == HB_ACODEC_AC3 )
220 uint8_t bsid = audio->config.in.version;
221 uint8_t bsmod = audio->config.in.mode;
222 uint8_t acmod = audio->config.flags.ac3 & 0x7;
223 uint8_t lfeon = (audio->config.flags.ac3 & A52_LFE) ? 1 : 0;
224 uint8_t bit_rate_code = 0;
227 * Rewrite AC3 information into correct format for dac3 atom
229 switch( audio->config.in.samplerate )
242 * Error value, tells decoder to not decode this audio.
248 switch( audio->config.in.bitrate )
308 hb_error("Unknown AC3 bitrate");
313 mux_data->track = MP4AddAC3AudioTrack(
323 if (audio->config.out.name == NULL) {
324 MP4SetTrackBytesProperty(
325 m->file, mux_data->track,
327 (const uint8_t*)"Surround", strlen("Surround"));
330 MP4SetTrackBytesProperty(
331 m->file, mux_data->track,
333 (const uint8_t*)(audio->config.out.name),
334 strlen(audio->config.out.name));
337 mux_data->track = MP4AddAudioTrack(
339 m->samplerate, 1024, MP4_MPEG4_AUDIO_TYPE );
340 if (audio->config.out.name == NULL) {
341 MP4SetTrackBytesProperty(
342 m->file, mux_data->track,
344 (const uint8_t*)"Stereo", strlen("Stereo"));
347 MP4SetTrackBytesProperty(
348 m->file, mux_data->track,
350 (const uint8_t*)(audio->config.out.name),
351 strlen(audio->config.out.name));
354 MP4SetAudioProfileLevel( m->file, 0x0F );
355 MP4SetTrackESConfiguration(
356 m->file, mux_data->track,
357 audio->priv.config.aac.bytes, audio->priv.config.aac.length );
359 /* Set the correct number of channels for this track */
360 MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.channels", (uint16_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown));
363 /* Set the language for this track */
364 /* The language is stored as 5-bit text - 0x60 */
365 language_code = audio->config.lang.iso639_2[0] - 0x60; language_code <<= 5;
366 language_code |= audio->config.lang.iso639_2[1] - 0x60; language_code <<= 5;
367 language_code |= audio->config.lang.iso639_2[2] - 0x60;
368 MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.mdhd.language", language_code);
370 if( hb_list_count( title->list_audio ) > 1 )
372 /* Set the audio track alternate group */
373 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1);
377 /* Enable the first audio track */
378 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_ENABLED | TRACK_IN_MOVIE));
381 /* Disable the other audio tracks so QuickTime doesn't play
384 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_DISABLED | TRACK_IN_MOVIE));
385 hb_deep_log( 2, "muxp4: disabled extra audio track %i", mux_data->track-1);
390 if (job->chapter_markers)
392 /* add a text track for the chapters. We add the 'chap' atom to track
393 one which is usually the video track & should never be disabled.
394 The Quicktime spec says it doesn't matter which media track the
395 chap atom is on but it has to be an enabled track. */
396 MP4TrackId textTrack;
397 textTrack = MP4AddChapterTextTrack(m->file, 1, 0);
399 m->chapter_track = textTrack;
400 m->chapter_duration = 0;
401 m->current_chapter = job->chapter_start;
404 /* Add encoded-by metadata listing version and build date */
406 tool_string = (char *)malloc(80);
407 snprintf( tool_string, 80, "HandBrake %s %i", HB_VERSION, HB_BUILD);
408 MP4SetMetadataTool(m->file, tool_string);
414 static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
417 hb_job_t * job = m->job;
421 if( mux_data == job->mux_data )
425 // if there are b-frames compute the render offset
426 // (we'll need it for both the video frame & the chapter track)
429 offset = ( buf->start + m->init_delay ) * m->samplerate / 90000 -
433 /* Add the sample before the new frame.
434 It is important that this be calculated prior to the duration
435 of the new video sample, as we want to sync to right after it.
436 (This is because of how durations for text tracks work in QT) */
437 if( job->chapter_markers && buf->new_chap )
439 hb_chapter_t *chapter = NULL;
441 // this chapter is postioned by writing out the previous chapter.
442 // the duration of the previous chapter is the duration up to but
443 // not including the current frame minus the duration of all
444 // chapters up to the previous.
445 duration = m->sum_dur - m->chapter_duration + offset;
448 /* The initial & final chapters can have very short durations
449 * (less than the error in our total duration estimate) so
450 * the duration calc above can result in a negative number.
451 * when this happens give the chapter a short duration (1/3
452 * of an ntsc frame time). */
453 duration = 1000 * m->samplerate / 90000;
456 chapter = hb_list_item( m->job->title->list_chapter,
459 MP4AddChapter( m->file,
462 (chapter != NULL) ? chapter->title : NULL);
464 m->current_chapter = buf->new_chap;
465 m->chapter_duration += duration;
468 // since we're changing the sample rate we need to keep track of
469 // the truncation bias so that the audio and video don't go out
470 // of sync. m->sum_dur_in is the sum of the input durations so far.
471 // m->sum_dur is the sum of the output durations. Their difference
472 // (in output sample rate units) is the accumulated truncation bias.
473 int64_t bias = ( m->sum_dur_in * m->samplerate / 90000 ) - m->sum_dur;
474 int64_t dur_in = buf->stop - buf->start;
475 duration = dur_in * m->samplerate / 90000 + bias;
478 /* We got an illegal mp4/h264 duration. This shouldn't
479 be possible and usually indicates a bug in the upstream code.
480 Complain in the hope that someone will go find the bug but
481 try to fix the error so that the file will still be playable. */
482 hb_log("MP4Mux: illegal duration %lld, bias %lld, start %lld (%lld),"
483 "stop %lld (%lld), sum_dur %lld",
484 duration, bias, buf->start * m->samplerate / 90000, buf->start,
485 buf->stop * m->samplerate / 90000, buf->stop, m->sum_dur );
486 /* we don't know when the next frame starts so we can't pick a
487 valid duration for this one so we pick something "short"
488 (roughly 1/3 of an NTSC frame time) and rely on the bias calc
489 for the next frame to correct things (a duration underestimate
490 just results in a large bias on the next frame). */
491 duration = 1000 * m->samplerate / 90000;
493 m->sum_dur += duration;
494 m->sum_dur_in += dur_in;
499 duration = MP4_INVALID_DURATION;
502 // Here's where the sample actually gets muxed.
503 if( !MP4WriteSample( m->file,
509 ((buf->frametype & HB_FRAME_KEY) != 0) ) )
511 hb_error("Failed to write to output file, disk full?");
518 static int MP4End( hb_mux_object_t * m )
520 hb_job_t * job = m->job;
521 hb_title_t * title = job->title;
523 /* Write our final chapter marker */
524 if( m->job->chapter_markers )
526 hb_chapter_t *chapter = NULL;
527 int64_t duration = m->sum_dur - m->chapter_duration;
528 /* The final chapter can have a very short duration - if it's less
529 * than a second just skip it. */
530 if ( duration >= m->samplerate )
533 chapter = hb_list_item( m->job->title->list_chapter,
534 m->current_chapter - 1 );
536 MP4AddChapter( m->file,
539 (chapter != NULL) ? chapter->title : NULL);
545 // Insert track edit to get A/V back in sync. The edit amount is
547 int64_t edit_amt = m->init_delay * m->samplerate / 90000;
548 MP4AddTrackEdit(m->file, 1, MP4_INVALID_EDIT_ID, edit_amt,
549 MP4GetTrackDuration(m->file, 1), 0);
550 if ( m->job->chapter_markers )
552 // apply same edit to chapter track to keep it in sync with video
553 MP4AddTrackEdit(m->file, m->chapter_track, MP4_INVALID_EDIT_ID,
555 MP4GetTrackDuration(m->file, m->chapter_track), 0);
560 * Write the MP4 iTunes metadata if we have any metadata
562 if( title->metadata )
564 hb_metadata_t *md = title->metadata;
566 hb_deep_log( 2, "Writing Metadata to output file...");
568 MP4SetMetadataName( m->file, md->name );
569 MP4SetMetadataArtist( m->file, md->artist );
570 MP4SetMetadataComposer( m->file, md->composer );
571 MP4SetMetadataComment( m->file, md->comment );
572 MP4SetMetadataReleaseDate( m->file, md->release_date );
573 MP4SetMetadataAlbum( m->file, md->album );
574 MP4SetMetadataGenre( m->file, md->genre );
577 MP4SetMetadataCoverArt( m->file, md->coverart, md->coverart_size);
583 if ( job->mp4_optimize )
585 hb_log( "muxmp4: optimizing file" );
586 char filename[1024]; memset( filename, 0, 1024 );
587 snprintf( filename, 1024, "%s.tmp", job->file );
588 MP4Optimize( job->file, filename, MP4_DETAILS_ERROR );
590 rename( filename, job->file );
596 hb_mux_object_t * hb_mux_mp4_init( hb_job_t * job )
598 hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );