diff options
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 ); |