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 struct hb_mux_object_s
21 /* Cumulated durations so far, in output & input timescale units (see MP4Mux) */
22 int64_t sum_dur; // duration in output timescale units
23 int64_t sum_dur_in; // duration in input 90KHz timescale units
25 // bias to keep render offsets in ctts atom positive (set up by encx264)
28 /* Chapter state information for muxing */
29 MP4TrackId chapter_track;
31 uint64_t chapter_duration;
33 /* Sample rate of the first audio track.
34 * Used for the timescale
45 /**********************************************************************
47 **********************************************************************
48 * Allocates hb_mux_data_t structures, create file and write headers
49 *********************************************************************/
50 static int MP4Init( hb_mux_object_t * m )
52 hb_job_t * job = m->job;
53 hb_title_t * title = job->title;
56 hb_mux_data_t * mux_data;
59 /* Flags for enabling/disabling tracks in an MP4. */
60 typedef enum { TRACK_DISABLED = 0x0, TRACK_ENABLED = 0x1, TRACK_IN_MOVIE = 0x2, TRACK_IN_PREVIEW = 0x4, TRACK_IN_POSTER = 0x8} track_header_flags;
62 if( (audio = hb_list_item(title->list_audio, 0)) != NULL )
64 /* Need the sample rate of the first audio track to use as the timescale. */
65 m->samplerate = audio->config.out.samplerate;
70 m->samplerate = 90000;
73 /* Create an empty mp4 file */
74 if (job->largeFileSize)
75 /* Use 64-bit MP4 file */
77 m->file = MP4Create( job->file, MP4_DETAILS_ERROR, MP4_CREATE_64BIT_DATA );
78 hb_deep_log( 2, "muxmp4: using 64-bit MP4 formatting.");
81 /* Limit MP4s to less than 4 GB */
83 m->file = MP4Create( job->file, MP4_DETAILS_ERROR, 0 );
86 if (m->file == MP4_INVALID_FILE_HANDLE)
88 hb_error("muxmp4.c: MP4Create failed!");
94 mux_data = malloc( sizeof( hb_mux_data_t ) );
95 job->mux_data = mux_data;
97 /* When using the standard 90000 timescale, QuickTime tends to have
98 synchronization issues (audio not playing at the correct speed).
99 To workaround this, we use the audio samplerate as the
101 if (!(MP4SetTimeScale( m->file, m->samplerate )))
103 hb_error("muxmp4.c: MP4SetTimeScale failed!");
108 if( job->vcodec == HB_VCODEC_X264 )
110 /* Stolen from mp4creator */
111 MP4SetVideoProfileLevel( m->file, 0x7F );
112 mux_data->track = MP4AddH264VideoTrack( m->file, m->samplerate,
113 MP4_INVALID_DURATION, job->width, job->height,
114 job->config.h264.sps[1], /* AVCProfileIndication */
115 job->config.h264.sps[2], /* profile_compat */
116 job->config.h264.sps[3], /* AVCLevelIndication */
117 3 ); /* 4 bytes length before each NAL unit */
120 MP4AddH264SequenceParameterSet( m->file, mux_data->track,
121 job->config.h264.sps, job->config.h264.sps_length );
122 MP4AddH264PictureParameterSet( m->file, mux_data->track,
123 job->config.h264.pps, job->config.h264.pps_length );
125 if( job->h264_level == 30 || job->ipod_atom)
127 hb_deep_log( 2, "muxmp4: adding iPod atom");
128 MP4AddIPodUUID(m->file, mux_data->track);
131 m->init_delay = job->config.h264.init_delay;
133 else /* FFmpeg or XviD */
135 MP4SetVideoProfileLevel( m->file, MPEG4_SP_L3 );
136 mux_data->track = MP4AddVideoTrack( m->file, m->samplerate,
137 MP4_INVALID_DURATION, job->width, job->height,
138 MP4_MPEG4_VIDEO_TYPE );
139 if (mux_data->track == MP4_INVALID_TRACK_ID)
141 hb_error("muxmp4.c: MP4AddVideoTrack failed!");
147 /* VOL from FFmpeg or XviD */
148 if (!(MP4SetTrackESConfiguration( m->file, mux_data->track,
149 job->config.mpeg4.bytes, job->config.mpeg4.length )))
151 hb_error("muxmp4.c: MP4SetTrackESConfiguration failed!");
157 // COLR atom for color and gamma correction.
159 // http://developer.apple.com/quicktime/icefloe/dispatch019.html#colr
160 // http://forum.doom9.org/showthread.php?t=133982#post1090068
161 // the user can set it from job->color_matrix, otherwise by default
162 // we say anything that's likely to be HD content is ITU BT.709 and
163 // DVD, SD TV & other content is ITU BT.601. We look at the title height
164 // rather than the job height here to get uncropped input dimensions.
165 if( job->color_matrix == 1 )
167 // ITU BT.601 DVD or SD TV content
168 MP4AddColr(m->file, mux_data->track, 6, 1, 6);
170 else if( job->color_matrix == 2 )
172 // ITU BT.709 HD content
173 MP4AddColr(m->file, mux_data->track, 1, 1, 1);
175 else if ( job->title->width >= 1280 || job->title->height >= 720 )
177 // we guess that 720p or above is ITU BT.709 HD content
178 MP4AddColr(m->file, mux_data->track, 1, 1, 1);
182 // ITU BT.601 DVD or SD TV content
183 MP4AddColr(m->file, mux_data->track, 6, 1, 6);
186 if( job->anamorphic.mode )
188 /* PASP atom for anamorphic video */
191 width = job->anamorphic.par_width;
193 height = job->anamorphic.par_height;
195 MP4AddPixelAspectRatio(m->file, mux_data->track, (uint32_t)width, (uint32_t)height);
197 MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width * (width / height));
200 /* add the audio tracks */
201 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
203 audio = hb_list_item( title->list_audio, i );
204 mux_data = malloc( sizeof( hb_mux_data_t ) );
205 audio->priv.mux_data = mux_data;
207 if( audio->config.out.codec == HB_ACODEC_AC3 )
210 uint8_t bsid = audio->config.in.version;
211 uint8_t bsmod = audio->config.in.mode;
212 uint8_t acmod = audio->config.flags.ac3 & 0x7;
213 uint8_t lfeon = (audio->config.flags.ac3 & A52_LFE) ? 1 : 0;
214 uint8_t bit_rate_code = 0;
217 * Rewrite AC3 information into correct format for dac3 atom
219 switch( audio->config.in.samplerate )
232 * Error value, tells decoder to not decode this audio.
238 switch( audio->config.in.bitrate )
298 hb_error("Unknown AC3 bitrate");
303 mux_data->track = MP4AddAC3AudioTrack(
305 audio->config.out.samplerate,
313 if (audio->config.out.name == NULL) {
314 MP4SetTrackBytesProperty(
315 m->file, mux_data->track,
317 (const uint8_t*)"Surround", strlen("Surround"));
320 MP4SetTrackBytesProperty(
321 m->file, mux_data->track,
323 (const uint8_t*)(audio->config.out.name),
324 strlen(audio->config.out.name));
327 mux_data->track = MP4AddAudioTrack(
329 audio->config.out.samplerate, 1024, MP4_MPEG4_AUDIO_TYPE );
330 if (audio->config.out.name == NULL) {
331 MP4SetTrackBytesProperty(
332 m->file, mux_data->track,
334 (const uint8_t*)"Stereo", strlen("Stereo"));
337 MP4SetTrackBytesProperty(
338 m->file, mux_data->track,
340 (const uint8_t*)(audio->config.out.name),
341 strlen(audio->config.out.name));
344 MP4SetAudioProfileLevel( m->file, 0x0F );
345 MP4SetTrackESConfiguration(
346 m->file, mux_data->track,
347 audio->priv.config.aac.bytes, audio->priv.config.aac.length );
349 /* Set the correct number of channels for this track */
350 MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.channels", (uint16_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown));
353 /* Set the language for this track */
354 MP4SetTrackLanguage(m->file, mux_data->track, audio->config.lang.iso639_2);
356 if( hb_list_count( title->list_audio ) > 1 )
358 /* Set the audio track alternate group */
359 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1);
363 /* Enable the first audio track */
364 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_ENABLED | TRACK_IN_MOVIE));
367 /* Disable the other audio tracks so QuickTime doesn't play
370 MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_DISABLED | TRACK_IN_MOVIE));
371 hb_deep_log( 2, "muxp4: disabled extra audio track %i", mux_data->track-1);
376 if (job->chapter_markers)
378 /* add a text track for the chapters. We add the 'chap' atom to track
379 one which is usually the video track & should never be disabled.
380 The Quicktime spec says it doesn't matter which media track the
381 chap atom is on but it has to be an enabled track. */
382 MP4TrackId textTrack;
383 textTrack = MP4AddChapterTextTrack(m->file, 1, 0);
385 m->chapter_track = textTrack;
386 m->chapter_duration = 0;
387 m->current_chapter = job->chapter_start;
390 /* Add encoded-by metadata listing version and build date */
392 tool_string = (char *)malloc(80);
393 snprintf( tool_string, 80, "HandBrake %s %i", HB_PROJECT_VERSION, HB_PROJECT_BUILD);
394 MP4SetMetadataTool(m->file, tool_string);
400 static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
403 hb_job_t * job = m->job;
407 if( mux_data == job->mux_data )
411 // if there are b-frames compute the render offset
412 // (we'll need it for both the video frame & the chapter track)
415 offset = ( buf->start + m->init_delay ) * m->samplerate / 90000 -
419 /* Add the sample before the new frame.
420 It is important that this be calculated prior to the duration
421 of the new video sample, as we want to sync to right after it.
422 (This is because of how durations for text tracks work in QT) */
423 if( job->chapter_markers && buf->new_chap )
425 hb_chapter_t *chapter = NULL;
427 // this chapter is postioned by writing out the previous chapter.
428 // the duration of the previous chapter is the duration up to but
429 // not including the current frame minus the duration of all
430 // chapters up to the previous.
431 duration = m->sum_dur - m->chapter_duration + offset;
434 /* The initial & final chapters can have very short durations
435 * (less than the error in our total duration estimate) so
436 * the duration calc above can result in a negative number.
437 * when this happens give the chapter a short duration (1/3
438 * of an ntsc frame time). */
439 duration = 1000 * m->samplerate / 90000;
442 chapter = hb_list_item( m->job->title->list_chapter,
445 MP4AddChapter( m->file,
448 (chapter != NULL) ? chapter->title : NULL);
450 m->current_chapter = buf->new_chap;
451 m->chapter_duration += duration;
454 // since we're changing the sample rate we need to keep track of
455 // the truncation bias so that the audio and video don't go out
456 // of sync. m->sum_dur_in is the sum of the input durations so far.
457 // m->sum_dur is the sum of the output durations. Their difference
458 // (in output sample rate units) is the accumulated truncation bias.
459 int64_t bias = ( m->sum_dur_in * m->samplerate / 90000 ) - m->sum_dur;
460 int64_t dur_in = buf->stop - buf->start;
461 duration = dur_in * m->samplerate / 90000 + bias;
464 /* We got an illegal mp4/h264 duration. This shouldn't
465 be possible and usually indicates a bug in the upstream code.
466 Complain in the hope that someone will go find the bug but
467 try to fix the error so that the file will still be playable. */
468 hb_log("MP4Mux: illegal duration %lld, bias %lld, start %lld (%lld),"
469 "stop %lld (%lld), sum_dur %lld",
470 duration, bias, buf->start * m->samplerate / 90000, buf->start,
471 buf->stop * m->samplerate / 90000, buf->stop, m->sum_dur );
472 /* we don't know when the next frame starts so we can't pick a
473 valid duration for this one so we pick something "short"
474 (roughly 1/3 of an NTSC frame time) and rely on the bias calc
475 for the next frame to correct things (a duration underestimate
476 just results in a large bias on the next frame). */
477 duration = 1000 * m->samplerate / 90000;
479 m->sum_dur += duration;
480 m->sum_dur_in += dur_in;
485 duration = MP4_INVALID_DURATION;
488 // Here's where the sample actually gets muxed.
489 if( !MP4WriteSample( m->file,
495 ( job->vcodec == HB_VCODEC_X264 && mux_data == job->mux_data ) ?
496 ( buf->frametype == HB_FRAME_IDR ) : ( ( buf->frametype & HB_FRAME_KEY ) != 0 ) ) )
498 hb_error("Failed to write to output file, disk full?");
505 static int MP4End( hb_mux_object_t * m )
507 hb_job_t * job = m->job;
508 hb_title_t * title = job->title;
510 /* Write our final chapter marker */
511 if( m->job->chapter_markers )
513 hb_chapter_t *chapter = NULL;
514 int64_t duration = m->sum_dur - m->chapter_duration;
515 /* The final chapter can have a very short duration - if it's less
516 * than a second just skip it. */
517 if ( duration >= m->samplerate )
520 chapter = hb_list_item( m->job->title->list_chapter,
521 m->current_chapter - 1 );
523 MP4AddChapter( m->file,
526 (chapter != NULL) ? chapter->title : NULL);
532 // Insert track edit to get A/V back in sync. The edit amount is
534 int64_t edit_amt = m->init_delay * m->samplerate / 90000;
535 MP4AddTrackEdit(m->file, 1, MP4_INVALID_EDIT_ID, edit_amt,
536 MP4GetTrackDuration(m->file, 1), 0);
537 if ( m->job->chapter_markers )
539 // apply same edit to chapter track to keep it in sync with video
540 MP4AddTrackEdit(m->file, m->chapter_track, MP4_INVALID_EDIT_ID,
542 MP4GetTrackDuration(m->file, m->chapter_track), 0);
547 * Write the MP4 iTunes metadata if we have any metadata
549 if( title->metadata )
551 hb_metadata_t *md = title->metadata;
553 hb_deep_log( 2, "Writing Metadata to output file...");
555 MP4SetMetadataName( m->file, md->name );
556 MP4SetMetadataArtist( m->file, md->artist );
557 MP4SetMetadataComposer( m->file, md->composer );
558 MP4SetMetadataComment( m->file, md->comment );
559 MP4SetMetadataReleaseDate( m->file, md->release_date );
560 MP4SetMetadataAlbum( m->file, md->album );
561 MP4SetMetadataGenre( m->file, md->genre );
564 MP4SetMetadataCoverArt( m->file, md->coverart, md->coverart_size);
570 if ( job->mp4_optimize )
572 hb_log( "muxmp4: optimizing file" );
573 char filename[1024]; memset( filename, 0, 1024 );
574 snprintf( filename, 1024, "%s.tmp", job->file );
575 MP4Optimize( job->file, filename, MP4_DETAILS_ERROR );
577 rename( filename, job->file );
583 hb_mux_object_t * hb_mux_mp4_init( hb_job_t * job )
585 hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );