OSDN Git Service

a6ddedf5dda7d972e6a04f6fcbd51a0359514f04
[handbrake-jp/handbrake-jp-git.git] / libhb / muxmp4.c
1 /* $Id: muxmp4.c,v 1.24 2005/11/04 13:09:41 titer Exp $
2
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. */
6
7 /* libmp4v2 header */
8 #include "mp4.h"
9
10 #include "hb.h"
11
12 void AddIPodUUID(MP4FileHandle, MP4TrackId);
13
14 struct hb_mux_object_s
15 {
16     HB_MUX_COMMON;
17
18     hb_job_t * job;
19
20     /* libmp4v2 handle */
21     MP4FileHandle file;
22
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
26
27     // bias to keep render offsets in ctts atom positive (set up by encx264)
28     int64_t init_delay;
29
30     /* Chapter state information for muxing */
31     MP4TrackId chapter_track;
32     int current_chapter;
33     uint64_t chapter_duration;
34
35     /* Sample rate of the first audio track.
36      * Used for the timescale
37      */
38     int samplerate;
39 };
40
41 struct hb_mux_data_s
42 {
43     MP4TrackId track;
44 };
45
46 struct hb_text_sample_s
47 {
48     uint8_t     sample[1280];
49     uint32_t    length;
50     MP4Duration duration;
51 };
52
53 /**********************************************************************
54  * MP4CreateTextSample
55  **********************************************************************
56  * Creates a buffer for a text track sample
57  *********************************************************************/
58 static struct hb_text_sample_s *MP4CreateTextSample( char *textString, uint64_t duration )
59 {
60     struct hb_text_sample_s *sample = NULL;
61     int stringLength = strlen(textString);
62     int x;
63
64     if( stringLength < 1024 )
65     {
66         sample = malloc( sizeof( struct hb_text_sample_s ) );
67
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;
71
72         // 2-byte length marker
73         sample->sample[0] = (stringLength >> 8) & 0xff;
74         sample->sample[1] = stringLength & 0xff;
75
76         strncpy( (char *)&(sample->sample[2]), textString, stringLength );
77
78         x = 2 + stringLength;
79
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;
85
86         // Modifier Type Code
87         sample->sample[x+4] = 'e';
88         sample->sample[x+5] = 'n';
89         sample->sample[x+6] = 'c';
90         sample->sample[x+7] = 'd';
91
92         // Modifier Value
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;
97     }
98
99     return sample;
100 }
101
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,
108                                                           uint64_t duration,
109                                                           int chapter )
110 {
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,
116                                                chapter - 2 );
117     char tmp_buffer[1024];
118     char *string = tmp_buffer;
119
120     tmp_buffer[0] = '\0';
121
122     if( chapter_data != NULL )
123     {
124         string = chapter_data->title;
125     }
126
127     if( strlen(string) == 0 || strlen(string) >= 1024 )
128     {
129         snprintf( tmp_buffer, 1023, "Chapter %03i", chapter - 2 );
130         string = tmp_buffer;
131     }
132
133     return MP4CreateTextSample( string, duration );
134 }
135
136
137 /**********************************************************************
138  * MP4Init
139  **********************************************************************
140  * Allocates hb_mux_data_t structures, create file and write headers
141  *********************************************************************/
142 static int MP4Init( hb_mux_object_t * m )
143 {
144     hb_job_t   * job   = m->job;
145     hb_title_t * title = job->title;
146
147     hb_audio_t    * audio;
148     hb_mux_data_t * mux_data;
149     int i;
150     uint16_t language_code;
151
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;
154
155     if( (audio = hb_list_item(title->list_audio, 0)) != NULL )
156     {
157         /* Need the sample rate of the first audio track to use as the timescale. */
158         m->samplerate = audio->config.out.samplerate;
159         audio = NULL;
160     }
161     else
162     {
163         m->samplerate = 90000;
164     }
165
166     /* Create an empty mp4 file */
167     if (job->largeFileSize)
168     /* Use 64-bit MP4 file */
169     {
170         m->file = MP4Create( job->file, MP4_DETAILS_ERROR, MP4_CREATE_64BIT_DATA );
171         hb_deep_log( 2, "muxmp4: using 64-bit MP4 formatting.");
172     }
173     else
174     /* Limit MP4s to less than 4 GB */
175     {
176         m->file = MP4Create( job->file, MP4_DETAILS_ERROR, 0 );
177     }
178
179     if (m->file == MP4_INVALID_FILE_HANDLE)
180     {
181         hb_error("muxmp4.c: MP4Create failed!");
182         *job->die = 1;
183         return 0;
184     }
185
186     /* Video track */
187     mux_data      = malloc( sizeof( hb_mux_data_t ) );
188     job->mux_data = mux_data;
189
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
193        timescale */
194     if (!(MP4SetTimeScale( m->file, m->samplerate )))
195     {
196         hb_error("muxmp4.c: MP4SetTimeScale failed!");
197         *job->die = 1;
198         return 0;
199     }
200
201     if( job->vcodec == HB_VCODEC_X264 )
202     {
203         /* Stolen from mp4creator */
204         MP4SetVideoProfileLevel( m->file, 0x7F );
205                 mux_data->track = MP4AddH264VideoTrack( m->file, m->samplerate,
206                         MP4_INVALID_DURATION, job->width, job->height,
207                         job->config.h264.sps[1], /* AVCProfileIndication */
208                         job->config.h264.sps[2], /* profile_compat */
209                         job->config.h264.sps[3], /* AVCLevelIndication */
210                         3 );      /* 4 bytes length before each NAL unit */
211
212
213         MP4AddH264SequenceParameterSet( m->file, mux_data->track,
214                 job->config.h264.sps, job->config.h264.sps_length );
215         MP4AddH264PictureParameterSet( m->file, mux_data->track,
216                 job->config.h264.pps, job->config.h264.pps_length );
217
218                 if( job->h264_level == 30 || job->ipod_atom)
219                 {
220                         hb_deep_log( 2, "muxmp4: adding iPod atom");
221                         MP4AddIPodUUID(m->file, mux_data->track);
222                 }
223
224         m->init_delay = job->config.h264.init_delay;
225     }
226     else /* FFmpeg or XviD */
227     {
228         MP4SetVideoProfileLevel( m->file, MPEG4_SP_L3 );
229         mux_data->track = MP4AddVideoTrack( m->file, m->samplerate,
230                 MP4_INVALID_DURATION, job->width, job->height,
231                 MP4_MPEG4_VIDEO_TYPE );
232         if (mux_data->track == MP4_INVALID_TRACK_ID)
233         {
234             hb_error("muxmp4.c: MP4AddVideoTrack failed!");
235             *job->die = 1;
236             return 0;
237         }
238
239
240         /* VOL from FFmpeg or XviD */
241         if (!(MP4SetTrackESConfiguration( m->file, mux_data->track,
242                 job->config.mpeg4.bytes, job->config.mpeg4.length )))
243         {
244             hb_error("muxmp4.c: MP4SetTrackESConfiguration failed!");
245             *job->die = 1;
246             return 0;
247         }
248     }
249
250     // COLR atom for color and gamma correction.
251     // Per the notes at:
252     //   http://developer.apple.com/quicktime/icefloe/dispatch019.html#colr
253     //   http://forum.doom9.org/showthread.php?t=133982#post1090068
254     // we say anything that's likely to be HD content is ITU BT.709 and
255     // DVD, SD TV & other content is ITU BT.601.  We look at the title height
256     // rather than the job height here to get uncropped input dimensions.
257     if ( job->title->height >= 720 )
258     {
259         // we guess that 720p or above is ITU BT.709 HD content
260         MP4AddColr(m->file, mux_data->track, 1, 1, 1);
261     }
262     else
263     {
264         // ITU BT.601 DVD or SD TV content
265         MP4AddColr(m->file, mux_data->track, 6, 1, 6);
266     }
267
268     if( job->pixel_ratio )
269     {
270         /* PASP atom for anamorphic video */
271         float width, height;
272
273         width = job->pixel_aspect_width;
274
275         height = job->pixel_aspect_height;
276
277         MP4AddPixelAspectRatio(m->file, mux_data->track, (uint32_t)width, (uint32_t)height);
278
279         MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width * (width / height));
280     }
281
282         /* add the audio tracks */
283     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
284     {
285         static uint8_t reserved2[16] = {
286                 0x00, 0x00, 0x00, 0x00,
287                 0x00, 0x00, 0x00, 0x00,
288                 0x00, 0x02, 0x00, 0x10,
289                 0x00, 0x00, 0x00, 0x00,
290             };
291
292         audio = hb_list_item( title->list_audio, i );
293         mux_data = malloc( sizeof( hb_mux_data_t ) );
294         audio->priv.mux_data = mux_data;
295
296         if( audio->config.out.codec == HB_ACODEC_AC3 )
297         {
298             mux_data->track = MP4AddAC3AudioTrack(
299                 m->file,
300                 m->samplerate, 1536, MP4_MPEG4_AUDIO_TYPE );
301             if (audio->config.out.name == NULL) {
302                 MP4SetTrackBytesProperty(
303                     m->file, mux_data->track,
304                     "udta.name.value",
305                     (const uint8_t*)"Surround", strlen("Surround"));
306             }
307             else {
308                 MP4SetTrackBytesProperty(
309                     m->file, mux_data->track,
310                     "udta.name.value",
311                     (const uint8_t*)(audio->config.out.name),
312                     strlen(audio->config.out.name));
313             }
314         } else {
315             mux_data->track = MP4AddAudioTrack(
316                 m->file,
317                 m->samplerate, 1024, MP4_MPEG4_AUDIO_TYPE );
318             if (audio->config.out.name == NULL) {
319                 MP4SetTrackBytesProperty(
320                     m->file, mux_data->track,
321                     "udta.name.value",
322                     (const uint8_t*)"Stereo", strlen("Stereo"));
323             }
324             else {
325                 MP4SetTrackBytesProperty(
326                     m->file, mux_data->track,
327                     "udta.name.value",
328                     (const uint8_t*)(audio->config.out.name),
329                     strlen(audio->config.out.name));
330             }
331
332             MP4SetAudioProfileLevel( m->file, 0x0F );
333             MP4SetTrackESConfiguration(
334                 m->file, mux_data->track,
335                 audio->priv.config.aac.bytes, audio->priv.config.aac.length );
336
337             /* Set the correct number of channels for this track */
338              MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.channels", (uint16_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown));
339         }
340
341         /* Set the language for this track */
342         /* The language is stored as 5-bit text - 0x60 */
343         language_code = audio->config.lang.iso639_2[0] - 0x60;   language_code <<= 5;
344         language_code |= audio->config.lang.iso639_2[1] - 0x60;  language_code <<= 5;
345         language_code |= audio->config.lang.iso639_2[2] - 0x60;
346         MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.mdhd.language", language_code);
347
348         if( hb_list_count( title->list_audio ) > 1 )
349         {
350             /* Set the audio track alternate group */
351             MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1);
352         }
353
354         if (i == 0) {
355             /* Enable the first audio track */
356             MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_ENABLED | TRACK_IN_MOVIE));
357         }
358         else
359             /* Disable the other audio tracks so QuickTime doesn't play
360                them all at once. */
361         {
362             MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_DISABLED | TRACK_IN_MOVIE));
363             hb_deep_log( 2, "muxp4: disabled extra audio track %i", mux_data->track-1);
364         }
365
366     }
367
368         if (job->chapter_markers)
369     {
370         /* add a text track for the chapters. We add the 'chap' atom to track
371            one which is usually the video track & should never be disabled.
372            The Quicktime spec says it doesn't matter which media track the
373            chap atom is on but it has to be an enabled track. */
374         MP4TrackId textTrack;
375         textTrack = MP4AddChapterTextTrack(m->file, 1);
376
377         m->chapter_track = textTrack;
378         m->chapter_duration = 0;
379         m->current_chapter = job->chapter_start;
380     }
381
382     /* Add encoded-by metadata listing version and build date */
383     char *tool_string;
384     tool_string = (char *)malloc(80);
385     snprintf( tool_string, 80, "HandBrake %s %i", HB_VERSION, HB_BUILD);
386     MP4SetMetadataTool(m->file, tool_string);
387     free(tool_string);
388
389     return 0;
390 }
391
392 static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
393                    hb_buffer_t * buf )
394 {
395     hb_job_t * job = m->job;
396     int64_t duration;
397     int64_t offset = 0;
398
399     if( mux_data == job->mux_data )
400     {
401         /* Video */
402
403         // if there are b-frames compute the render offset
404         // (we'll need it for both the video frame & the chapter track)
405         if ( m->init_delay )
406         {
407             offset = ( buf->start + m->init_delay ) * m->samplerate / 90000 -
408                      m->sum_dur;
409         }
410         /* Add the sample before the new frame.
411            It is important that this be calculated prior to the duration
412            of the new video sample, as we want to sync to right after it.
413            (This is because of how durations for text tracks work in QT) */
414         if( job->chapter_markers && buf->new_chap )
415         {
416             struct hb_text_sample_s *sample;
417
418             // this chapter is postioned by writing out the previous chapter.
419             // the duration of the previous chapter is the duration up to but
420             // not including the current frame minus the duration of all
421             // chapters up to the previous.
422             duration = m->sum_dur - m->chapter_duration + offset;
423             if ( duration <= 0 )
424             {
425                 /* The initial & final chapters can have very short durations
426                  * (less than the error in our total duration estimate) so
427                  * the duration calc above can result in a negative number.
428                  * when this happens give the chapter a short duration (1/3
429                  * of an ntsc frame time). */
430                 duration = 1000 * m->samplerate / 90000;
431             }
432
433             sample = MP4GenerateChapterSample( m, duration, buf->new_chap );
434
435             if( !MP4WriteSample(m->file,
436                                 m->chapter_track,
437                                 sample->sample,
438                                 sample->length,
439                                 sample->duration,
440                                 0, true) )
441             {
442                 hb_error("Failed to write to output file, disk full?");
443                 *job->die = 1;
444             }
445             free(sample);
446             m->current_chapter = buf->new_chap;
447             m->chapter_duration += duration;
448         }
449
450         // since we're changing the sample rate we need to keep track of
451         // the truncation bias so that the audio and video don't go out
452         // of sync. m->sum_dur_in is the sum of the input durations so far.
453         // m->sum_dur is the sum of the output durations. Their difference
454         // (in output sample rate units) is the accumulated truncation bias.
455         int64_t bias = ( m->sum_dur_in * m->samplerate / 90000 ) - m->sum_dur;
456         int64_t dur_in = buf->stop - buf->start;
457         duration = dur_in * m->samplerate / 90000 + bias;
458         if ( duration <= 0 )
459         {
460             /* We got an illegal mp4/h264 duration. This shouldn't
461                be possible and usually indicates a bug in the upstream code.
462                Complain in the hope that someone will go find the bug but
463                try to fix the error so that the file will still be playable. */
464             hb_log("MP4Mux: illegal duration %lld, bias %lld, start %lld (%lld),"
465                    "stop %lld (%lld), sum_dur %lld",
466                    duration, bias, buf->start * m->samplerate / 90000, buf->start,
467                    buf->stop * m->samplerate / 90000, buf->stop, m->sum_dur );
468             /* we don't know when the next frame starts so we can't pick a
469                valid duration for this one so we pick something "short"
470                (roughly 1/3 of an NTSC frame time) and rely on the bias calc
471                for the next frame to correct things (a duration underestimate
472                just results in a large bias on the next frame). */
473             duration = 1000 * m->samplerate / 90000;
474         }
475         m->sum_dur += duration;
476         m->sum_dur_in += dur_in;
477     }
478     else
479     {
480         /* Audio */
481         duration = MP4_INVALID_DURATION;
482     }
483
484     // Here's where the sample actually gets muxed.
485     if( !MP4WriteSample( m->file,
486                          mux_data->track,
487                          buf->data,
488                          buf->size,
489                          duration,
490                          offset,
491                          ((buf->frametype & HB_FRAME_KEY) != 0) ) )
492     {
493         hb_error("Failed to write to output file, disk full?");
494         *job->die = 1;
495     }
496
497     return 0;
498 }
499
500 static int MP4End( hb_mux_object_t * m )
501 {
502     hb_job_t   * job   = m->job;
503
504     /* Write our final chapter marker */
505     if( m->job->chapter_markers )
506     {
507         int64_t duration = m->sum_dur - m->chapter_duration;
508         /* The final chapter can have a very short duration - if it's less
509          * than a second just skip it. */
510         if ( duration >= m->samplerate )
511         {
512
513             struct hb_text_sample_s *sample = MP4GenerateChapterSample( m, duration,
514                                                     m->current_chapter + 1 );
515             if( ! MP4WriteSample(m->file, m->chapter_track, sample->sample,
516                                  sample->length, sample->duration, 0, true) )
517             {
518                 hb_error("Failed to write to output file, disk full?");
519                 *job->die = 1;
520             }
521             free(sample);
522         }
523     }
524
525     if (job->areBframes)
526     {
527            // Insert track edit to get A/V back in sync.  The edit amount is
528            // the init_delay.
529            int64_t edit_amt = m->init_delay * m->samplerate / 90000;
530            MP4AddTrackEdit(m->file, 1, MP4_INVALID_EDIT_ID, edit_amt,
531                            MP4GetTrackDuration(m->file, 1), 0);
532             if ( m->job->chapter_markers )
533             {
534                 // apply same edit to chapter track to keep it in sync with video
535                 MP4AddTrackEdit(m->file, m->chapter_track, MP4_INVALID_EDIT_ID,
536                                 edit_amt,
537                                 MP4GetTrackDuration(m->file, m->chapter_track), 0);
538             }
539      }
540
541     MP4Close( m->file );
542
543     if ( job->mp4_optimize )
544     {
545         hb_log( "muxmp4: optimizing file" );
546         char filename[1024]; memset( filename, 0, 1024 );
547         snprintf( filename, 1024, "%s.tmp", job->file );
548         MP4Optimize( job->file, filename, MP4_DETAILS_ERROR );
549         remove( job->file );
550         rename( filename, job->file );
551     }
552
553     return 0;
554 }
555
556 hb_mux_object_t * hb_mux_mp4_init( hb_job_t * job )
557 {
558     hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );
559     m->init      = MP4Init;
560     m->mux       = MP4Mux;
561     m->end       = MP4End;
562     m->job       = job;
563     return m;
564 }
565