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.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
12 struct hb_mux_object_s
21 /* Cumulated durations so far, in timescale units (see MP4Mux) */
30 /**********************************************************************
32 **********************************************************************
33 * Allocates hb_mux_data_t structures, create file and write headers
34 *********************************************************************/
35 static int MP4Init( hb_mux_object_t * m )
37 hb_job_t * job = m->job;
38 hb_title_t * title = job->title;
41 hb_mux_data_t * mux_data;
44 /* Create an empty mp4 file */
45 m->file = MP4Create( job->file, MP4_DETAILS_ERROR, 0 );
48 mux_data = malloc( sizeof( hb_mux_data_t ) );
49 job->mux_data = mux_data;
51 /* When using the standard 90000 timescale, QuickTime tends to have
52 synchronization issues (audio not playing at the correct speed).
53 To workaround this, we use the audio samplerate as the
55 MP4SetTimeScale( m->file, job->arate );
57 if( job->vcodec == HB_VCODEC_X264 )
59 #define c job->config.h264
60 /* Stolen from mp4creator */
61 MP4SetVideoProfileLevel( m->file, 0x7F );
63 mux_data->track = MP4AddH264VideoTrack( m->file, job->arate,
64 MP4_INVALID_DURATION, job->width, job->height,
65 c.sps[1], /* AVCProfileIndication */
66 c.sps[2], /* profile_compat */
67 c.sps[3], /* AVCLevelIndication */
68 3 ); /* 4 bytes length before each NAL unit */
70 MP4AddH264SequenceParameterSet( m->file, mux_data->track,
71 c.sps, c.sps_length );
72 MP4AddH264PictureParameterSet( m->file, mux_data->track,
73 c.pps, c.pps_length );
76 else /* FFmpeg or XviD */
78 #define c job->config.mpeg4
79 MP4SetVideoProfileLevel( m->file, MPEG4_SP_L3 );
80 mux_data->track = MP4AddVideoTrack( m->file, job->arate,
81 MP4_INVALID_DURATION, job->width, job->height,
82 MP4_MPEG4_VIDEO_TYPE );
84 /* VOL from FFmpeg or XviD */
85 MP4SetTrackESConfiguration( m->file, mux_data->track,
86 c.config, c.config_length );
90 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
92 audio = hb_list_item( title->list_audio, i );
93 mux_data = malloc( sizeof( hb_mux_data_t ) );
94 audio->mux_data = mux_data;
96 mux_data->track = MP4AddAudioTrack( m->file,
97 job->arate, 1024, MP4_MPEG4_AUDIO_TYPE );
98 MP4SetAudioProfileLevel( m->file, 0x0F );
99 MP4SetTrackESConfiguration( m->file, mux_data->track,
100 audio->config.faac.decinfo, audio->config.faac.size );
106 static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
109 hb_job_t * job = m->job;
113 if( mux_data == job->mux_data )
116 /* Because we use the audio samplerate as the timescale,
117 we have to use potentially variable durations so the video
118 doesn't go out of sync */
119 duration = ( buf->stop * job->arate / 90000 ) - m->sum_dur;
120 m->sum_dur += duration;
125 duration = MP4_INVALID_DURATION;
128 MP4WriteSample( m->file, mux_data->track, buf->data, buf->size,
129 duration, 0, buf->key );
133 static int MP4End( hb_mux_object_t * m )
136 hb_job_t * job = m->job;
138 char filename[1024]; memset( filename, 0, 1024 );
143 hb_log( "muxmp4: optimizing file" );
144 snprintf( filename, 1024, "%s.tmp", job->file );
145 MP4Optimize( job->file, filename, MP4_DETAILS_ERROR );
147 rename( filename, job->file );
153 hb_mux_object_t * hb_mux_mp4_init( hb_job_t * job )
155 hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );