summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
Diffstat (limited to 'libhb')
-rw-r--r--libhb/common.h1
-rw-r--r--libhb/decmetadata.c131
-rw-r--r--libhb/muxmp4.c93
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 );