OSDN Git Service

Add metadata support to libhb, add importing of MP4 metadata, add export of MP4 metad...
[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 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
47 /**********************************************************************
48  * MP4Init
49  **********************************************************************
50  * Allocates hb_mux_data_t structures, create file and write headers
51  *********************************************************************/
52 static int MP4Init( hb_mux_object_t * m )
53 {
54     hb_job_t   * job   = m->job;
55     hb_title_t * title = job->title;
56
57     hb_audio_t    * audio;
58     hb_mux_data_t * mux_data;
59     int i;
60     uint16_t language_code;
61
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;
64
65     if( (audio = hb_list_item(title->list_audio, 0)) != NULL )
66     {
67         /* Need the sample rate of the first audio track to use as the timescale. */
68         m->samplerate = audio->config.out.samplerate;
69         audio = NULL;
70     }
71     else
72     {
73         m->samplerate = 90000;
74     }
75
76     /* Create an empty mp4 file */
77     if (job->largeFileSize)
78     /* Use 64-bit MP4 file */
79     {
80         m->file = MP4Create( job->file, MP4_DETAILS_ERROR, MP4_CREATE_64BIT_DATA );
81         hb_deep_log( 2, "muxmp4: using 64-bit MP4 formatting.");
82     }
83     else
84     /* Limit MP4s to less than 4 GB */
85     {
86         m->file = MP4Create( job->file, MP4_DETAILS_ERROR, 0 );
87     }
88
89     if (m->file == MP4_INVALID_FILE_HANDLE)
90     {
91         hb_error("muxmp4.c: MP4Create failed!");
92         *job->die = 1;
93         return 0;
94     }
95
96     /* Video track */
97     mux_data      = malloc( sizeof( hb_mux_data_t ) );
98     job->mux_data = mux_data;
99
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
103        timescale */
104     if (!(MP4SetTimeScale( m->file, m->samplerate )))
105     {
106         hb_error("muxmp4.c: MP4SetTimeScale failed!");
107         *job->die = 1;
108         return 0;
109     }
110
111     if( job->vcodec == HB_VCODEC_X264 )
112     {
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 */
121
122
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 );
127
128                 if( job->h264_level == 30 || job->ipod_atom)
129                 {
130                         hb_deep_log( 2, "muxmp4: adding iPod atom");
131                         MP4AddIPodUUID(m->file, mux_data->track);
132                 }
133
134         m->init_delay = job->config.h264.init_delay;
135     }
136     else /* FFmpeg or XviD */
137     {
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)
143         {
144             hb_error("muxmp4.c: MP4AddVideoTrack failed!");
145             *job->die = 1;
146             return 0;
147         }
148
149
150         /* VOL from FFmpeg or XviD */
151         if (!(MP4SetTrackESConfiguration( m->file, mux_data->track,
152                 job->config.mpeg4.bytes, job->config.mpeg4.length )))
153         {
154             hb_error("muxmp4.c: MP4SetTrackESConfiguration failed!");
155             *job->die = 1;
156             return 0;
157         }
158     }
159
160     // COLR atom for color and gamma correction.
161     // Per the notes at:
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 )
169     {
170         // ITU BT.601 DVD or SD TV content
171         MP4AddColr(m->file, mux_data->track, 6, 1, 6);
172     }
173     else if( job->color_matrix == 2 )
174     {
175         // ITU BT.709 HD content
176         MP4AddColr(m->file, mux_data->track, 1, 1, 1);        
177     }
178     else if ( job->title->width >= 1280 || job->title->height >= 720 )
179     {
180         // we guess that 720p or above is ITU BT.709 HD content
181         MP4AddColr(m->file, mux_data->track, 1, 1, 1);
182     }
183     else
184     {
185         // ITU BT.601 DVD or SD TV content
186         MP4AddColr(m->file, mux_data->track, 6, 1, 6);
187     }
188
189     if( job->pixel_ratio )
190     {
191         /* PASP atom for anamorphic video */
192         float width, height;
193
194         width = job->pixel_aspect_width;
195
196         height = job->pixel_aspect_height;
197
198         MP4AddPixelAspectRatio(m->file, mux_data->track, (uint32_t)width, (uint32_t)height);
199
200         MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width * (width / height));
201     }
202
203         /* add the audio tracks */
204     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
205     {
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,
211             };
212
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;
216
217         if( audio->config.out.codec == HB_ACODEC_AC3 )
218         {
219             uint8_t fscod = 0;
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;
225
226             /*
227              * Rewrite AC3 information into correct format for dac3 atom
228              */
229             switch( audio->config.in.samplerate )
230             {
231             case 48000:
232                 fscod = 0;
233                 break;
234             case 44100:
235                 fscod = 1;
236                 break;
237             case 32000:
238                 fscod = 2;
239                 break;
240             default:
241                 /*
242                  * Error value, tells decoder to not decode this audio.
243                  */
244                 fscod = 3;
245                 break;
246             }
247
248             switch( audio->config.in.bitrate )
249             {
250             case 32000:
251                 bit_rate_code = 0;
252                 break;
253             case 40000:
254                 bit_rate_code = 1;
255                 break;
256             case 48000:
257                 bit_rate_code = 2;
258                 break;
259             case 56000:
260                 bit_rate_code = 3;
261                 break;
262             case 64000:
263                 bit_rate_code = 4;
264                 break;
265             case 80000:
266                 bit_rate_code = 5;
267                 break;
268             case 96000:
269                 bit_rate_code = 6;
270                 break;
271             case 112000:
272                 bit_rate_code = 7;
273                 break;
274             case 128000:
275                 bit_rate_code = 8;
276                 break;
277             case 160000:
278                 bit_rate_code = 9;
279                 break;
280             case 192000:
281                 bit_rate_code = 10;
282                 break;
283             case 224000:
284                 bit_rate_code = 11;
285                 break;
286             case 256000:
287                 bit_rate_code = 12;
288                 break;
289             case 320000:
290                 bit_rate_code = 13;
291                 break;
292             case 384000:
293                 bit_rate_code = 14;
294                 break;
295             case 448000:
296                 bit_rate_code = 15;
297                 break;
298             case 512000:
299                 bit_rate_code = 16;
300                 break;
301             case 576000:
302                 bit_rate_code = 17;
303                 break;
304             case 640000:
305                 bit_rate_code = 18;
306                 break;
307             default:
308                 hb_error("Unknown AC3 bitrate");
309                 bit_rate_code = 0;
310                 break;
311             }
312
313             mux_data->track = MP4AddAC3AudioTrack(
314                 m->file,
315                 m->samplerate, 
316                 fscod,
317                 bsid,
318                 bsmod,
319                 acmod,
320                 lfeon,
321                 bit_rate_code);
322
323             if (audio->config.out.name == NULL) {
324                 MP4SetTrackBytesProperty(
325                     m->file, mux_data->track,
326                     "udta.name.value",
327                     (const uint8_t*)"Surround", strlen("Surround"));
328             }
329             else {
330                 MP4SetTrackBytesProperty(
331                     m->file, mux_data->track,
332                     "udta.name.value",
333                     (const uint8_t*)(audio->config.out.name),
334                     strlen(audio->config.out.name));
335             }
336         } else {
337             mux_data->track = MP4AddAudioTrack(
338                 m->file,
339                 m->samplerate, 1024, MP4_MPEG4_AUDIO_TYPE );
340             if (audio->config.out.name == NULL) {
341                 MP4SetTrackBytesProperty(
342                     m->file, mux_data->track,
343                     "udta.name.value",
344                     (const uint8_t*)"Stereo", strlen("Stereo"));
345             }
346             else {
347                 MP4SetTrackBytesProperty(
348                     m->file, mux_data->track,
349                     "udta.name.value",
350                     (const uint8_t*)(audio->config.out.name),
351                     strlen(audio->config.out.name));
352             }
353
354             MP4SetAudioProfileLevel( m->file, 0x0F );
355             MP4SetTrackESConfiguration(
356                 m->file, mux_data->track,
357                 audio->priv.config.aac.bytes, audio->priv.config.aac.length );
358
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));
361         }
362
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);
369
370         if( hb_list_count( title->list_audio ) > 1 )
371         {
372             /* Set the audio track alternate group */
373             MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1);
374         }
375
376         if (i == 0) {
377             /* Enable the first audio track */
378             MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_ENABLED | TRACK_IN_MOVIE));
379         }
380         else
381             /* Disable the other audio tracks so QuickTime doesn't play
382                them all at once. */
383         {
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);
386         }
387
388     }
389
390     if (job->chapter_markers)
391     {
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);
398
399         m->chapter_track = textTrack;
400         m->chapter_duration = 0;
401         m->current_chapter = job->chapter_start;
402     }
403
404     /* Add encoded-by metadata listing version and build date */
405     char *tool_string;
406     tool_string = (char *)malloc(80);
407     snprintf( tool_string, 80, "HandBrake %s %i", HB_VERSION, HB_BUILD);
408     MP4SetMetadataTool(m->file, tool_string);
409     free(tool_string);
410
411     return 0;
412 }
413
414 static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
415                    hb_buffer_t * buf )
416 {
417     hb_job_t * job = m->job;
418     int64_t duration;
419     int64_t offset = 0;
420
421     if( mux_data == job->mux_data )
422     {
423         /* Video */
424
425         // if there are b-frames compute the render offset
426         // (we'll need it for both the video frame & the chapter track)
427         if ( m->init_delay )
428         {
429             offset = ( buf->start + m->init_delay ) * m->samplerate / 90000 -
430                      m->sum_dur;
431         }
432
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 )
438         {    
439             hb_chapter_t *chapter = NULL;
440
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;
446             if ( duration <= 0 )
447             {
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;
454             }
455
456             chapter = hb_list_item( m->job->title->list_chapter,
457                                     buf->new_chap - 2 );
458
459             MP4AddChapter( m->file,
460                            m->chapter_track,
461                            duration,
462                            (chapter != NULL) ? chapter->title : NULL);
463
464             m->current_chapter = buf->new_chap;
465             m->chapter_duration += duration;
466         }
467
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;
476         if ( duration <= 0 )
477         {
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;
492         }
493         m->sum_dur += duration;
494         m->sum_dur_in += dur_in;
495     }
496     else
497     {
498         /* Audio */
499         duration = MP4_INVALID_DURATION;
500     }
501
502     // Here's where the sample actually gets muxed.
503     if( !MP4WriteSample( m->file,
504                          mux_data->track,
505                          buf->data,
506                          buf->size,
507                          duration,
508                          offset,
509                          ((buf->frametype & HB_FRAME_KEY) != 0) ) )
510     {
511         hb_error("Failed to write to output file, disk full?");
512         *job->die = 1;
513     }
514
515     return 0;
516 }
517
518 static int MP4End( hb_mux_object_t * m )
519 {
520     hb_job_t   * job   = m->job;
521     hb_title_t * title = job->title;
522
523     /* Write our final chapter marker */
524     if( m->job->chapter_markers )
525     {
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 )
531         {
532
533             chapter = hb_list_item( m->job->title->list_chapter,
534                                     m->current_chapter - 1 );
535
536             MP4AddChapter( m->file,
537                            m->chapter_track,
538                            duration,
539                            (chapter != NULL) ? chapter->title : NULL);
540         }
541     }
542
543     if (job->areBframes)
544     {
545            // Insert track edit to get A/V back in sync.  The edit amount is
546            // the init_delay.
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 )
551             {
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,
554                                 edit_amt,
555                                 MP4GetTrackDuration(m->file, m->chapter_track), 0);
556             }
557      }
558
559     /*
560      * Write the MP4 iTunes metadata if we have any metadata
561      */
562     if( title->metadata )
563     {
564         hb_metadata_t *md = title->metadata;
565
566         hb_deep_log( 2, "Writing Metadata to output file...");
567
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 );
575         if( md->coverart )
576         {
577             MP4SetMetadataCoverArt( m->file, md->coverart, md->coverart_size);
578         }
579     }
580
581     MP4Close( m->file );
582
583     if ( job->mp4_optimize )
584     {
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 );
589         remove( job->file );
590         rename( filename, job->file );
591     }
592
593     return 0;
594 }
595
596 hb_mux_object_t * hb_mux_mp4_init( hb_job_t * job )
597 {
598     hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );
599     m->init      = MP4Init;
600     m->mux       = MP4Mux;
601     m->end       = MP4End;
602     m->job       = job;
603     return m;
604 }
605