diff options
author | konablend <[email protected]> | 2009-04-21 02:36:46 +0000 |
---|---|---|
committer | konablend <[email protected]> | 2009-04-21 02:36:46 +0000 |
commit | f86f171f05ed4732264befad4d5f8fead750553e (patch) | |
tree | dc894bb8596ecaab493a43df0e8230bc0080a615 /libhb | |
parent | 3dfb0337b4a31bb6416320ca4e095074568b82f6 (diff) |
bump libmp4v2 r224 ->r286; chunk duration; tags; cover-art
The major changes to libmp4v2 include the new Tags API for iTunes metadata management
and new API to set track chunk duration limits. Additionally, the patches for libmp4v2
are no longer required and libmp4v2 should build significantly faster as it now
enabled precompiled headers on various platforms.
Tags API effects common.h, decmetdata.c and muxmp4.c and replaces the operations in
a near 1:1 mapping for functionality except all access happens in between alloc/fetch
and store/free pattern.
libhb no longer checks the bits of cover-art in order to determine image type. That
functionality is now delegated to libmp4v2; and libhb identify_art_type() has been
removed accordingly.
Chunk duration support has been added which makes use of new API from libmp4v2:
MP4SetTrackDurationPerChunk( MP4File, MP4TrackId );
And muxmp4 adds new internal function MP4TuneTrackDurationPerChunk() which is
invoked after all video/audio track creation which tunes chunk duration to the
equivalent of 4-frames in track timescale; as per van's suggestion.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2347 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.h | 1 | ||||
-rw-r--r-- | libhb/decmetadata.c | 131 | ||||
-rw-r--r-- | libhb/muxmp4.c | 93 |
3 files changed, 120 insertions, 105 deletions
diff --git a/libhb/common.h b/libhb/common.h index b7c468672..5a6320a43 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -465,7 +465,6 @@ struct hb_metadata_s char comment[1024]; char album[255]; char genre[255]; - enum arttype {UNKNOWN, BMP, GIF87A, GIF89A, JPG, PNG, TIFFL, TIFFB} coverart_type; uint32_t coverart_size; uint8_t *coverart; }; diff --git a/libhb/decmetadata.c b/libhb/decmetadata.c index 85c3cd28b..754eb7a25 100644 --- a/libhb/decmetadata.c +++ b/libhb/decmetadata.c @@ -8,117 +8,60 @@ #include "common.h" -void identify_art_type( hb_metadata_t *metadata ) -{ - typedef struct header_s { - enum arttype type; - char* name; // short string describing name of type - char* data; // header-bytes to match - } header; - - // types which may be detected by first-bytes only - static header headers[] = { - { BMP, "bmp", "\x4d\x42" }, - { GIF87A, "GIF (87a)", "GIF87a" }, - { GIF89A, "GIF (89a)", "GIF89a" }, - { JPG, "JPEG", "\xff\xd8\xff\xe0" }, - { PNG, "PNG", "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" }, - { TIFFL, "TIFF (little-endian)", "II42" }, - { TIFFB, "TIFF (big-endian)", "MM42" }, - { UNKNOWN } // must be last - }; - header* p; - header* found = NULL; - for( p = headers; p->type != UNKNOWN; p++ ) { - header *h = p; - - if( metadata->coverart_size < strlen(h->data) ) - continue; - - if( memcmp(h->data, metadata->coverart, strlen(h->data)) == 0 ) { - metadata->coverart_type = h->type; - break; - } - } -} - static void decmp4metadata( hb_title_t *title ) { MP4FileHandle input_file; - hb_deep_log( 2, "Got an MP4 input, read the metadata"); input_file = MP4Read( title->dvd, 0 ); if( input_file != MP4_INVALID_FILE_HANDLE ) { - char *value = NULL; - uint8_t *cover_art = NULL; - uint32_t size; - uint32_t count; - /* * Store iTunes MetaData */ - if( MP4GetMetadataName( input_file, &value) && value ) - { - hb_deep_log( 2, "Metadata Name in input file is '%s'", value); - strncpy( title->metadata->name, value, 255); - MP4Free(value); - value = NULL; - } + const MP4Tags* tags; - if( MP4GetMetadataArtist( input_file, &value) && value ) - { - strncpy( title->metadata->artist, value, 255); - MP4Free(value); - value = NULL; - } - - if( MP4GetMetadataComposer( input_file, &value) && value ) - { - strncpy( title->metadata->composer, value, 255); - MP4Free(value); - value = NULL; - } + /* alloc,fetch tags */ + tags = MP4TagsAlloc(); + MP4TagsFetch( tags, input_file ); - if( MP4GetMetadataComment( input_file, &value) && value ) - { - strncpy( title->metadata->comment, value, 1024); - value = NULL; - } - - if( MP4GetMetadataReleaseDate( input_file, &value) && value ) - { - strncpy( title->metadata->release_date, value, 255); - MP4Free(value); - value = NULL; + if( tags->name ) { + hb_deep_log( 2, "Metadata Name in input file is '%s'", tags->name ); + strncpy( title->metadata->name, tags->name, 255 ); } - - if( MP4GetMetadataAlbum( input_file, &value) && value ) - { - strncpy( title->metadata->album, value, 255); - MP4Free(value); - value = NULL; - } - - if( MP4GetMetadataGenre( input_file, &value) && value ) - { - strncpy( title->metadata->genre, value, 255); - MP4Free(value); - value = NULL; - } - - if( MP4GetMetadataCoverArt( input_file, &cover_art, &size, 0) && - cover_art ) - { - title->metadata->coverart = cover_art; - title->metadata->coverart_size = size; - identify_art_type( title->metadata ); + + if( tags->artist ) + strncpy( title->metadata->artist, tags->artist, 255 ); + + if( tags->composer ) + strncpy( title->metadata->composer, tags->composer, 255 ); + + if( tags->comments ) + strncpy( title->metadata->comment, tags->comments, 1024 ); + + if( tags->releaseDate ) + strncpy( title->metadata->release_date, tags->releaseDate, 255 ); + + if( tags->album ) + strncpy( title->metadata->album, tags->album, 255 ); + + if( tags->genre ) + strncpy( title->metadata->genre, tags->genre, 255 ); + + if( tags->artworkCount > 0 ) { + const MP4TagArtwork* art = tags->artwork + 0; // first element + title->metadata->coverart = (uint8_t*)malloc( art->size ); + title->metadata->coverart_size = art->size; + memcpy( title->metadata->coverart, art->data, art->size ); hb_deep_log( 2, "Got some cover art of type %d, size %d", - title->metadata->coverart_type, - title->metadata->coverart_size); + art->type, + title->metadata->coverart_size ); } + + /* store,free tags */ + MP4TagsStore( tags, input_file ); + MP4TagsFree( tags ); /* * Handle the chapters. diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index 3f9b2314f..9698fafcb 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -41,6 +41,31 @@ struct hb_mux_data_s MP4TrackId track; }; +/* Tune video track chunk duration. + * libmp4v2 default duration == dusamplerate == 1 second. + * Per van's suggestion we desire duration == 4 frames. + * Should be invoked immediately after track creation. + * + * return true on fail, false on success. + */ +static int MP4TuneTrackDurationPerChunk( hb_mux_object_t* m, MP4TrackId trackId ) +{ + uint32_t tscale; + MP4Duration dur; + + tscale = MP4GetTrackTimeScale( m->file, trackId ); + dur = (MP4Duration)ceil( (double)tscale * (double)m->job->vrate_base / (double)m->job->vrate * 4.0 ); + + if( !MP4SetTrackDurationPerChunk( m->file, trackId, dur )) + { + hb_error( "muxmp4.c: MP4SetTrackDurationPerChunk failed!" ); + *m->job->die = 1; + return 0; + } + + hb_deep_log( 2, "muxmp4: track %u, chunk duration %llu", MP4FindTrackIndex( m->file, trackId ), dur ); + return 1; +} /********************************************************************** * MP4Init @@ -115,7 +140,18 @@ static int MP4Init( hb_mux_object_t * m ) job->config.h264.sps[2], /* profile_compat */ job->config.h264.sps[3], /* AVCLevelIndication */ 3 ); /* 4 bytes length before each NAL unit */ + if ( mux_data->track == MP4_INVALID_TRACK_ID ) + { + hb_error( "muxmp4.c: MP4AddH264VideoTrack failed!" ); + *job->die = 1; + return 0; + } + /* Tune track chunk duration */ + if( !MP4TuneTrackDurationPerChunk( m, mux_data->track )) + { + return 0; + } MP4AddH264SequenceParameterSet( m->file, mux_data->track, job->config.h264.sps, job->config.h264.sps_length ); @@ -143,6 +179,11 @@ static int MP4Init( hb_mux_object_t * m ) return 0; } + /* Tune track chunk duration */ + if( !MP4TuneTrackDurationPerChunk( m, mux_data->track )) + { + return 0; + } /* VOL from FFmpeg or XviD */ if (!(MP4SetTrackESConfiguration( m->file, mux_data->track, @@ -310,6 +351,9 @@ static int MP4Init( hb_mux_object_t * m ) lfeon, bit_rate_code); + /* Tune track chunk duration */ + MP4TuneTrackDurationPerChunk( m, mux_data->track ); + if (audio->config.out.name == NULL) { MP4SetTrackBytesProperty( m->file, mux_data->track, @@ -327,6 +371,10 @@ static int MP4Init( hb_mux_object_t * m ) mux_data->track = MP4AddAudioTrack( m->file, audio->config.out.samplerate, 1024, MP4_MPEG4_AUDIO_TYPE ); + + /* Tune track chunk duration */ + MP4TuneTrackDurationPerChunk( m, mux_data->track ); + if (audio->config.out.name == NULL) { MP4SetTrackBytesProperty( m->file, mux_data->track, @@ -368,7 +416,7 @@ static int MP4Init( hb_mux_object_t * m ) them all at once. */ { MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.flags", (TRACK_DISABLED | TRACK_IN_MOVIE)); - hb_deep_log( 2, "muxp4: disabled extra audio track %i", mux_data->track-1); + hb_deep_log( 2, "muxmp4: disabled extra audio track %u", MP4FindTrackIndex( m->file, mux_data->track )); } } @@ -391,7 +439,15 @@ static int MP4Init( hb_mux_object_t * m ) char *tool_string; tool_string = (char *)malloc(80); snprintf( tool_string, 80, "HandBrake %s %i", HB_PROJECT_VERSION, HB_PROJECT_BUILD); - MP4SetMetadataTool(m->file, tool_string); + + /* allocate,fetch,populate,store,free tags structure */ + const MP4Tags* tags; + tags = MP4TagsAlloc(); + MP4TagsFetch( tags, m->file ); + MP4TagsSetEncodingTool( tags, tool_string ); + MP4TagsStore( tags, m->file ); + MP4TagsFree( tags ); + free(tool_string); return 0; @@ -549,20 +605,37 @@ static int MP4End( hb_mux_object_t * m ) if( title->metadata ) { hb_metadata_t *md = title->metadata; + const MP4Tags* tags; hb_deep_log( 2, "Writing Metadata to output file..."); - MP4SetMetadataName( m->file, md->name ); - MP4SetMetadataArtist( m->file, md->artist ); - MP4SetMetadataComposer( m->file, md->composer ); - MP4SetMetadataComment( m->file, md->comment ); - MP4SetMetadataReleaseDate( m->file, md->release_date ); - MP4SetMetadataAlbum( m->file, md->album ); - MP4SetMetadataGenre( m->file, md->genre ); + /* allocate tags structure */ + tags = MP4TagsAlloc(); + /* fetch data from MP4 file (in case it already has some data) */ + MP4TagsFetch( tags, m->file ); + + /* populate */ + MP4TagsSetName( tags, md->name ); + MP4TagsSetArtist( tags, md->artist ); + MP4TagsSetComposer( tags, md->composer ); + MP4TagsSetComments( tags, md->comment ); + MP4TagsSetReleaseDate( tags, md->release_date ); + MP4TagsSetAlbum( tags, md->album ); + MP4TagsSetGenre( tags, md->genre ); + if( md->coverart ) { - MP4SetMetadataCoverArt( m->file, md->coverart, md->coverart_size); + MP4TagArtwork art; + art.data = md->coverart; + art.size = md->coverart_size; + art.type = MP4_ART_UNDEFINED; // delegate typing to libmp4v2 + MP4TagsAddArtwork( tags, &art ); } + + /* push data to MP4 file */ + MP4TagsStore( tags, m->file ); + /* free memory associated with structure */ + MP4TagsFree( tags ); } MP4Close( m->file ); |