OSDN Git Service

9698fafcbf8b353eb2616ef2532af2d54eb78564
[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 #include "mp4v2/mp4v2.h"
8 #include "a52dec/a52.h"
9
10 #include "hb.h"
11
12 struct hb_mux_object_s
13 {
14     HB_MUX_COMMON;
15
16     hb_job_t * job;
17
18     /* libmp4v2 handle */
19     MP4FileHandle file;
20
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
24
25     // bias to keep render offsets in ctts atom positive (set up by encx264)
26     int64_t init_delay;
27
28     /* Chapter state information for muxing */
29     MP4TrackId chapter_track;
30     int current_chapter;
31     uint64_t chapter_duration;
32
33     /* Sample rate of the first audio track.
34      * Used for the timescale
35      */
36     int samplerate;
37 };
38
39 struct hb_mux_data_s
40 {
41     MP4TrackId track;
42 };
43
44 /* Tune video track chunk duration.
45  * libmp4v2 default duration == dusamplerate == 1 second.
46  * Per van's suggestion we desire duration == 4 frames.
47  * Should be invoked immediately after track creation.
48  *
49  * return true on fail, false on success.
50  */
51 static int MP4TuneTrackDurationPerChunk( hb_mux_object_t* m, MP4TrackId trackId )
52 {
53     uint32_t tscale;
54     MP4Duration dur;
55
56     tscale = MP4GetTrackTimeScale( m->file, trackId );
57     dur = (MP4Duration)ceil( (double)tscale * (double)m->job->vrate_base / (double)m->job->vrate * 4.0 );
58
59     if( !MP4SetTrackDurationPerChunk( m->file, trackId, dur ))
60     {
61         hb_error( "muxmp4.c: MP4SetTrackDurationPerChunk failed!" );
62         *m->job->die = 1;
63         return 0;
64     }
65
66     hb_deep_log( 2, "muxmp4: track %u, chunk duration %llu", MP4FindTrackIndex( m->file, trackId ), dur );
67     return 1;
68 }
69
70 /**********************************************************************
71  * MP4Init
72  **********************************************************************
73  * Allocates hb_mux_data_t structures, create file and write headers
74  *********************************************************************/
75 static int MP4Init( hb_mux_object_t * m )
76 {
77     hb_job_t   * job   = m->job;
78     hb_title_t * title = job->title;
79
80     hb_audio_t    * audio;
81     hb_mux_data_t * mux_data;
82     int i;
83
84     /* Flags for enabling/disabling tracks in an MP4. */
85     typedef enum { TRACK_DISABLED = 0x0, TRACK_ENABLED = 0x1, TRACK_IN_MOVIE = 0x2, TRACK_IN_PREVIEW = 0x4, TRACK_IN_POSTER = 0x8}  track_header_flags;
86
87     if( (audio = hb_list_item(title->list_audio, 0)) != NULL )
88     {
89         /* Need the sample rate of the first audio track to use as the timescale. */
90         m->samplerate = audio->config.out.samplerate;
91         audio = NULL;
92     }
93     else
94     {
95         m->samplerate = 90000;
96     }
97
98     /* Create an empty mp4 file */
99     if (job->largeFileSize)
100     /* Use 64-bit MP4 file */
101     {
102         m->file = MP4Create( job->file, MP4_DETAILS_ERROR, MP4_CREATE_64BIT_DATA );
103         hb_deep_log( 2, "muxmp4: using 64-bit MP4 formatting.");
104     }
105     else
106     /* Limit MP4s to less than 4 GB */
107     {
108         m->file = MP4Create( job->file, MP4_DETAILS_ERROR, 0 );
109     }
110
111     if (m->file == MP4_INVALID_FILE_HANDLE)
112     {
113         hb_error("muxmp4.c: MP4Create failed!");
114         *job->die = 1;
115         return 0;
116     }
117
118     /* Video track */
119     mux_data      = malloc( sizeof( hb_mux_data_t ) );
120     job->mux_data = mux_data;
121
122     /* When using the standard 90000 timescale, QuickTime tends to have
123        synchronization issues (audio not playing at the correct speed).
124        To workaround this, we use the audio samplerate as the
125        timescale */
126     if (!(MP4SetTimeScale( m->file, m->samplerate )))
127     {
128         hb_error("muxmp4.c: MP4SetTimeScale failed!");
129         *job->die = 1;
130         return 0;
131     }
132
133     if( job->vcodec == HB_VCODEC_X264 )
134     {
135         /* Stolen from mp4creator */
136         MP4SetVideoProfileLevel( m->file, 0x7F );
137                 mux_data->track = MP4AddH264VideoTrack( m->file, m->samplerate,
138                         MP4_INVALID_DURATION, job->width, job->height,
139                         job->config.h264.sps[1], /* AVCProfileIndication */
140                         job->config.h264.sps[2], /* profile_compat */
141                         job->config.h264.sps[3], /* AVCLevelIndication */
142                         3 );      /* 4 bytes length before each NAL unit */
143         if ( mux_data->track == MP4_INVALID_TRACK_ID )
144         {
145             hb_error( "muxmp4.c: MP4AddH264VideoTrack failed!" );
146             *job->die = 1;
147             return 0;
148         }
149
150         /* Tune track chunk duration */
151         if( !MP4TuneTrackDurationPerChunk( m, mux_data->track ))
152         {
153             return 0;
154         }
155
156         MP4AddH264SequenceParameterSet( m->file, mux_data->track,
157                 job->config.h264.sps, job->config.h264.sps_length );
158         MP4AddH264PictureParameterSet( m->file, mux_data->track,
159                 job->config.h264.pps, job->config.h264.pps_length );
160
161                 if( job->h264_level == 30 || job->ipod_atom)
162                 {
163                         hb_deep_log( 2, "muxmp4: adding iPod atom");
164                         MP4AddIPodUUID(m->file, mux_data->track);
165                 }
166
167         m->init_delay = job->config.h264.init_delay;
168     }
169     else /* FFmpeg or XviD */
170     {
171         MP4SetVideoProfileLevel( m->file, MPEG4_SP_L3 );
172         mux_data->track = MP4AddVideoTrack( m->file, m->samplerate,
173                 MP4_INVALID_DURATION, job->width, job->height,
174                 MP4_MPEG4_VIDEO_TYPE );
175         if (mux_data->track == MP4_INVALID_TRACK_ID)
176         {
177             hb_error("muxmp4.c: MP4AddVideoTrack failed!");
178             *job->die = 1;
179             return 0;
180         }
181
182         /* Tune track chunk duration */
183         if( !MP4TuneTrackDurationPerChunk( m, mux_data->track ))
184         {
185             return 0;
186         }
187
188         /* VOL from FFmpeg or XviD */
189         if (!(MP4SetTrackESConfiguration( m->file, mux_data->track,
190                 job->config.mpeg4.bytes, job->config.mpeg4.length )))
191         {
192             hb_error("muxmp4.c: MP4SetTrackESConfiguration failed!");
193             *job->die = 1;
194             return 0;
195         }
196     }
197
198     // COLR atom for color and gamma correction.
199     // Per the notes at:
200     //   http://developer.apple.com/quicktime/icefloe/dispatch019.html#colr
201     //   http://forum.doom9.org/showthread.php?t=133982#post1090068
202     // the user can set it from job->color_matrix, otherwise by default
203     // we say anything that's likely to be HD content is ITU BT.709 and
204     // DVD, SD TV & other content is ITU BT.601.  We look at the title height
205     // rather than the job height here to get uncropped input dimensions.
206     if( job->color_matrix == 1 )
207     {
208         // ITU BT.601 DVD or SD TV content
209         MP4AddColr(m->file, mux_data->track, 6, 1, 6);
210     }
211     else if( job->color_matrix == 2 )
212     {
213         // ITU BT.709 HD content
214         MP4AddColr(m->file, mux_data->track, 1, 1, 1);        
215     }
216     else if ( job->title->width >= 1280 || job->title->height >= 720 )
217     {
218         // we guess that 720p or above is ITU BT.709 HD content
219         MP4AddColr(m->file, mux_data->track, 1, 1, 1);
220     }
221     else
222     {
223         // ITU BT.601 DVD or SD TV content
224         MP4AddColr(m->file, mux_data->track, 6, 1, 6);
225     }
226
227     if( job->anamorphic.mode )
228     {
229         /* PASP atom for anamorphic video */
230         float width, height;
231
232         width  = job->anamorphic.par_width;
233
234         height = job->anamorphic.par_height;
235
236         MP4AddPixelAspectRatio(m->file, mux_data->track, (uint32_t)width, (uint32_t)height);
237
238         MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width * (width / height));
239     }
240
241         /* add the audio tracks */
242     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
243     {
244         audio = hb_list_item( title->list_audio, i );
245         mux_data = malloc( sizeof( hb_mux_data_t ) );
246         audio->priv.mux_data = mux_data;
247
248         if( audio->config.out.codec == HB_ACODEC_AC3 )
249         {
250             uint8_t fscod = 0;
251             uint8_t bsid = audio->config.in.version;
252             uint8_t bsmod = audio->config.in.mode;
253             uint8_t acmod = audio->config.flags.ac3 & 0x7;
254             uint8_t lfeon = (audio->config.flags.ac3 & A52_LFE) ? 1 : 0;
255             uint8_t bit_rate_code = 0;
256
257             /*
258              * Rewrite AC3 information into correct format for dac3 atom
259              */
260             switch( audio->config.in.samplerate )
261             {
262             case 48000:
263                 fscod = 0;
264                 break;
265             case 44100:
266                 fscod = 1;
267                 break;
268             case 32000:
269                 fscod = 2;
270                 break;
271             default:
272                 /*
273                  * Error value, tells decoder to not decode this audio.
274                  */
275                 fscod = 3;
276                 break;
277             }
278
279             switch( audio->config.in.bitrate )
280             {
281             case 32000:
282                 bit_rate_code = 0;
283                 break;
284             case 40000:
285                 bit_rate_code = 1;
286                 break;
287             case 48000:
288                 bit_rate_code = 2;
289                 break;
290             case 56000:
291                 bit_rate_code = 3;
292                 break;
293             case 64000:
294                 bit_rate_code = 4;
295                 break;
296             case 80000:
297                 bit_rate_code = 5;
298                 break;
299             case 96000:
300                 bit_rate_code = 6;
301                 break;
302             case 112000:
303                 bit_rate_code = 7;
304                 break;
305             case 128000:
306                 bit_rate_code = 8;
307                 break;
308             case 160000:
309                 bit_rate_code = 9;
310                 break;
311             case 192000:
312                 bit_rate_code = 10;
313                 break;
314             case 224000:
315                 bit_rate_code = 11;
316                 break;
317             case 256000:
318                 bit_rate_code = 12;
319                 break;
320             case 320000:
321                 bit_rate_code = 13;
322                 break;
323             case 384000:
324                 bit_rate_code = 14;
325                 break;
326             case 448000:
327                 bit_rate_code = 15;
328                 break;
329             case 512000:
330                 bit_rate_code = 16;
331                 break;
332             case 576000:
333                 bit_rate_code = 17;
334                 break;
335             case 640000:
336                 bit_rate_code = 18;
337                 break;
338             default:
339                 hb_error("Unknown AC3 bitrate");
340                 bit_rate_code = 0;
341                 break;
342             }
343
344             mux_data->track = MP4AddAC3AudioTrack(
345                 m->file,
346                 audio->config.out.samplerate, 
347                 fscod,
348                 bsid,
349                 bsmod,
350                 acmod,
351                 lfeon,
352                 bit_rate_code);
353
354             /* Tune track chunk duration */
355             MP4TuneTrackDurationPerChunk( m, mux_data->track );
356
357             if (audio->config.out.name == NULL) {
358                 MP4SetTrackBytesProperty(
359                     m->file, mux_data->track,
360                     "udta.name.value",
361                     (const uint8_t*)"Surround", strlen("Surround"));
362             }
363             else {
364                 MP4SetTrackBytesProperty(
365                     m->file, mux_data->track,
366                     "udta.name.value",
367                     (const uint8_t*)(audio->config.out.name),
368                     strlen(audio->config.out.name));
369             }
370         } else {
371             mux_data->track = MP4AddAudioTrack(
372                 m->file,
373                 audio->config.out.samplerate, 1024, MP4_MPEG4_AUDIO_TYPE );
374
375             /* Tune track chunk duration */
376             MP4TuneTrackDurationPerChunk( m, mux_data->track );
377
378             if (audio->config.out.name == NULL) {
379                 MP4SetTrackBytesProperty(
380                     m->file, mux_data->track,
381                     "udta.name.value",
382                     (const uint8_t*)"Stereo", strlen("Stereo"));
383             }
384             else {
385                 MP4SetTrackBytesProperty(
386                     m->file, mux_data->track,
387                     "udta.name.value",
388                     (const uint8_t*)(audio->config.out.name),
389                     strlen(audio->config.out.name));
390             }
391
392             MP4SetAudioProfileLevel( m->file, 0x0F );
393             MP4SetTrackESConfiguration(
394                 m->file, mux_data->track,
395                 audio->priv.config.aac.bytes, audio->priv.config.aac.length );
396
397             /* Set the correct number of channels for this track */
398              MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.channels", (uint16_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown));
399         }
400
401         /* Set the language for this track */
402         MP4SetTrackLanguage(m->file, mux_data->track, audio->config.lang.iso639_2);
403
404         if( hb_list_count( title->list_audio ) > 1 )
405         {
406             /* Set the audio track alternate group */
407             MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1);
408         }
409
410         if (i == 0) {
411             /* Enable the first audio track */
412             MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_ENABLED | TRACK_IN_MOVIE));
413         }
414         else
415             /* Disable the other audio tracks so QuickTime doesn't play
416                them all at once. */
417         {
418             MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_DISABLED | TRACK_IN_MOVIE));
419             hb_deep_log( 2, "muxmp4: disabled extra audio track %u", MP4FindTrackIndex( m->file, mux_data->track ));
420         }
421
422     }
423
424     if (job->chapter_markers)
425     {
426         /* add a text track for the chapters. We add the 'chap' atom to track
427            one which is usually the video track & should never be disabled.
428            The Quicktime spec says it doesn't matter which media track the
429            chap atom is on but it has to be an enabled track. */
430         MP4TrackId textTrack;
431         textTrack = MP4AddChapterTextTrack(m->file, 1, 0);
432
433         m->chapter_track = textTrack;
434         m->chapter_duration = 0;
435         m->current_chapter = job->chapter_start;
436     }
437
438     /* Add encoded-by metadata listing version and build date */
439     char *tool_string;
440     tool_string = (char *)malloc(80);
441     snprintf( tool_string, 80, "HandBrake %s %i", HB_PROJECT_VERSION, HB_PROJECT_BUILD);
442
443     /* allocate,fetch,populate,store,free tags structure */
444     const MP4Tags* tags;
445     tags = MP4TagsAlloc();
446     MP4TagsFetch( tags, m->file );
447     MP4TagsSetEncodingTool( tags, tool_string );
448     MP4TagsStore( tags, m->file );
449     MP4TagsFree( tags );
450
451     free(tool_string);
452
453     return 0;
454 }
455
456 static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
457                    hb_buffer_t * buf )
458 {
459     hb_job_t * job = m->job;
460     int64_t duration;
461     int64_t offset = 0;
462
463     if( mux_data == job->mux_data )
464     {
465         /* Video */
466
467         // if there are b-frames compute the render offset
468         // (we'll need it for both the video frame & the chapter track)
469         if ( m->init_delay )
470         {
471             offset = ( buf->start + m->init_delay ) * m->samplerate / 90000 -
472                      m->sum_dur;
473         }
474
475         /* Add the sample before the new frame.
476            It is important that this be calculated prior to the duration
477            of the new video sample, as we want to sync to right after it.
478            (This is because of how durations for text tracks work in QT) */
479         if( job->chapter_markers && buf->new_chap )
480         {    
481             hb_chapter_t *chapter = NULL;
482
483             // this chapter is postioned by writing out the previous chapter.
484             // the duration of the previous chapter is the duration up to but
485             // not including the current frame minus the duration of all
486             // chapters up to the previous.
487             duration = m->sum_dur - m->chapter_duration + offset;
488             if ( duration <= 0 )
489             {
490                 /* The initial & final chapters can have very short durations
491                  * (less than the error in our total duration estimate) so
492                  * the duration calc above can result in a negative number.
493                  * when this happens give the chapter a short duration (1/3
494                  * of an ntsc frame time). */
495                 duration = 1000 * m->samplerate / 90000;
496             }
497
498             chapter = hb_list_item( m->job->title->list_chapter,
499                                     buf->new_chap - 2 );
500
501             MP4AddChapter( m->file,
502                            m->chapter_track,
503                            duration,
504                            (chapter != NULL) ? chapter->title : NULL);
505
506             m->current_chapter = buf->new_chap;
507             m->chapter_duration += duration;
508         }
509
510         // since we're changing the sample rate we need to keep track of
511         // the truncation bias so that the audio and video don't go out
512         // of sync. m->sum_dur_in is the sum of the input durations so far.
513         // m->sum_dur is the sum of the output durations. Their difference
514         // (in output sample rate units) is the accumulated truncation bias.
515         int64_t bias = ( m->sum_dur_in * m->samplerate / 90000 ) - m->sum_dur;
516         int64_t dur_in = buf->stop - buf->start;
517         duration = dur_in * m->samplerate / 90000 + bias;
518         if ( duration <= 0 )
519         {
520             /* We got an illegal mp4/h264 duration. This shouldn't
521                be possible and usually indicates a bug in the upstream code.
522                Complain in the hope that someone will go find the bug but
523                try to fix the error so that the file will still be playable. */
524             hb_log("MP4Mux: illegal duration %lld, bias %lld, start %lld (%lld),"
525                    "stop %lld (%lld), sum_dur %lld",
526                    duration, bias, buf->start * m->samplerate / 90000, buf->start,
527                    buf->stop * m->samplerate / 90000, buf->stop, m->sum_dur );
528             /* we don't know when the next frame starts so we can't pick a
529                valid duration for this one so we pick something "short"
530                (roughly 1/3 of an NTSC frame time) and rely on the bias calc
531                for the next frame to correct things (a duration underestimate
532                just results in a large bias on the next frame). */
533             duration = 1000 * m->samplerate / 90000;
534         }
535         m->sum_dur += duration;
536         m->sum_dur_in += dur_in;
537     }
538     else
539     {
540         /* Audio */
541         duration = MP4_INVALID_DURATION;
542     }
543
544     // Here's where the sample actually gets muxed.
545     if( !MP4WriteSample( m->file,
546                          mux_data->track,
547                          buf->data,
548                          buf->size,
549                          duration,
550                          offset,
551                          ( job->vcodec == HB_VCODEC_X264 && mux_data == job->mux_data ) ?
552                             ( buf->frametype == HB_FRAME_IDR ) : ( ( buf->frametype & HB_FRAME_KEY ) != 0 ) ) )
553     {
554         hb_error("Failed to write to output file, disk full?");
555         *job->die = 1;
556     }
557
558     return 0;
559 }
560
561 static int MP4End( hb_mux_object_t * m )
562 {
563     hb_job_t   * job   = m->job;
564     hb_title_t * title = job->title;
565
566     /* Write our final chapter marker */
567     if( m->job->chapter_markers )
568     {
569         hb_chapter_t *chapter = NULL;
570         int64_t duration = m->sum_dur - m->chapter_duration;
571         /* The final chapter can have a very short duration - if it's less
572          * than a second just skip it. */
573         if ( duration >= m->samplerate )
574         {
575
576             chapter = hb_list_item( m->job->title->list_chapter,
577                                     m->current_chapter - 1 );
578
579             MP4AddChapter( m->file,
580                            m->chapter_track,
581                            duration,
582                            (chapter != NULL) ? chapter->title : NULL);
583         }
584     }
585
586     if (job->areBframes)
587     {
588            // Insert track edit to get A/V back in sync.  The edit amount is
589            // the init_delay.
590            int64_t edit_amt = m->init_delay * m->samplerate / 90000;
591            MP4AddTrackEdit(m->file, 1, MP4_INVALID_EDIT_ID, edit_amt,
592                            MP4GetTrackDuration(m->file, 1), 0);
593             if ( m->job->chapter_markers )
594             {
595                 // apply same edit to chapter track to keep it in sync with video
596                 MP4AddTrackEdit(m->file, m->chapter_track, MP4_INVALID_EDIT_ID,
597                                 edit_amt,
598                                 MP4GetTrackDuration(m->file, m->chapter_track), 0);
599             }
600      }
601
602     /*
603      * Write the MP4 iTunes metadata if we have any metadata
604      */
605     if( title->metadata )
606     {
607         hb_metadata_t *md = title->metadata;
608         const MP4Tags* tags;
609
610         hb_deep_log( 2, "Writing Metadata to output file...");
611
612         /* allocate tags structure */
613         tags = MP4TagsAlloc();
614         /* fetch data from MP4 file (in case it already has some data) */
615         MP4TagsFetch( tags, m->file );
616
617         /* populate */
618         MP4TagsSetName( tags, md->name );
619         MP4TagsSetArtist( tags, md->artist );
620         MP4TagsSetComposer( tags, md->composer );
621         MP4TagsSetComments( tags, md->comment );
622         MP4TagsSetReleaseDate( tags, md->release_date );
623         MP4TagsSetAlbum( tags, md->album );
624         MP4TagsSetGenre( tags, md->genre );
625
626         if( md->coverart )
627         {
628             MP4TagArtwork art;
629             art.data = md->coverart;
630             art.size = md->coverart_size;
631             art.type = MP4_ART_UNDEFINED; // delegate typing to libmp4v2
632             MP4TagsAddArtwork( tags, &art );
633         }
634
635         /* push data to MP4 file */
636         MP4TagsStore( tags, m->file );
637         /* free memory associated with structure */
638         MP4TagsFree( tags );
639     }
640
641     MP4Close( m->file );
642
643     if ( job->mp4_optimize )
644     {
645         hb_log( "muxmp4: optimizing file" );
646         char filename[1024]; memset( filename, 0, 1024 );
647         snprintf( filename, 1024, "%s.tmp", job->file );
648         MP4Optimize( job->file, filename, MP4_DETAILS_ERROR );
649         remove( job->file );
650         rename( filename, job->file );
651     }
652
653     return 0;
654 }
655
656 hb_mux_object_t * hb_mux_mp4_init( hb_job_t * job )
657 {
658     hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );
659     m->init      = MP4Init;
660     m->mux       = MP4Mux;
661     m->end       = MP4End;
662     m->job       = job;
663     return m;
664 }
665