OSDN Git Service

bump libmp4v2 r224 ->r286; chunk duration; tags; cover-art
authorkonablend <konablend@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Tue, 21 Apr 2009 02:36:46 +0000 (02:36 +0000)
committerkonablend <konablend@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Tue, 21 Apr 2009 02:36:46 +0000 (02:36 +0000)
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://localhost/HandBrake/trunk@2347 b64f7644-9d1e-0410-96f1-a4d463321fa5

contrib/libmp4v2/P00-mingw-static.patch [deleted file]
contrib/libmp4v2/P01-mingw-msvcrt-lower.patch [deleted file]
contrib/libmp4v2/P02-mingw-configure.patch [deleted file]
contrib/libmp4v2/module.defs
libhb/common.h
libhb/decmetadata.c
libhb/muxmp4.c

diff --git a/contrib/libmp4v2/P00-mingw-static.patch b/contrib/libmp4v2/P00-mingw-static.patch
deleted file mode 100644 (file)
index 268ff76..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Index: mp4v2/include/mp4v2/platform.h
-===================================================================
---- mp4v2/include/mp4v2/platform.h     (revision 272)
-+++ mp4v2/include/mp4v2/platform.h     (working copy)
-@@ -24,8 +24,10 @@
- #if defined( _WIN32 ) || defined( __MINGW32__ )
- #   if defined( _WINDLL ) || defined( DLL_EXPORT )
- #       define MP4V2_EXPORT __declspec(dllexport)
-+#   elif defined( _DLL ) || defined( DLL_IMPORT ) 
-+#       define MP4V2_EXPORT __declspec(dllimport)
- #   else
--#       define MP4V2_EXPORT __declspec(dllimport)
-+#       define MP4V2_EXPORT
- #   endif
- #else
- #   define MP4V2_EXPORT __attribute__((visibility("default")))
diff --git a/contrib/libmp4v2/P01-mingw-msvcrt-lower.patch b/contrib/libmp4v2/P01-mingw-msvcrt-lower.patch
deleted file mode 100644 (file)
index 384542b..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-diff -Naur libmp4v2.orig/libplatform/io/File_win32.cpp libmp4v2/libplatform/io/File_win32.cpp
---- libmp4v2.orig/libplatform/io/File_win32.cpp        2008-11-16 02:50:26.000000000 -0500
-+++ libmp4v2/libplatform/io/File_win32.cpp     2009-03-13 02:00:09.000000000 -0400
-@@ -8,7 +8,8 @@
- bool
- StdioFile::getPosition( Size& pos_ )
- {
--    pos_ = _ftelli64( _handle );
-+    fflush( _handle ); // must flush because we're using _fileno routines
-+    pos_ = _telli64( _fileno( _handle ));
-     return pos_ == -1;
- }
-@@ -17,6 +18,7 @@
- bool
- StdioFile::getSize( Size& size_ )
- {
-+    fflush( _handle ); // must flush because we're using _fileno routines
-     LARGE_INTEGER n;
-     if( !GetFileSizeEx( (HANDLE)_get_osfhandle( _fileno( _handle )), &n ))
-         return true;
-@@ -29,7 +31,8 @@
- bool
- StdioFile::setPosition( Size pos_ )
- {
--    return _fseeki64( _handle, pos_, SEEK_SET ) != 0;
-+    fflush( _handle ); // must flush because we're using _fileno routines
-+    return _lseeki64( _fileno( _handle ), pos_, SEEK_SET ) == -1;
- }
- ///////////////////////////////////////////////////////////////////////////////
diff --git a/contrib/libmp4v2/P02-mingw-configure.patch b/contrib/libmp4v2/P02-mingw-configure.patch
deleted file mode 100644 (file)
index ba74920..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-diff -Naur libmp4v2.orig/configure.ac libmp4v2/configure.ac
---- libmp4v2.orig/configure.ac 2009-01-10 12:44:40.000000000 -0500
-+++ libmp4v2/configure.ac      2009-03-13 18:18:38.000000000 -0400
-@@ -103,11 +103,11 @@
-         X_CXX_ARCH="$X_CXX_ARCH -mwin32"
-     fi
-     ;;
--*-*-mingw32)
-+*-*-mingw*)
-     # do not support shared
-     enable_shared=no
-     X_PLATFORM=win32
--    X_MINGW_LIBS="$X_MINGW_LIBS -lmsvcr80"
-+    X_MINGW_LIBS="$X_MINGW_LIBS"
-     X_CXX_W="$X_CXX_W -Wno-format"
-     if test "$enable_mingw_threads" = "yes"; then
-         X_CXX_ARCH="$X_CXX_ARCH -mthreads"
-@@ -197,7 +197,7 @@
-     case ${host} in
-         *-*-cygwin)
-             ;;
--        *-*-mingw32)
-+        *-*-mingw*)
-             ;;
-         *)
-             AC_LANG(C++)
index ede6025..434d93f 100644 (file)
@@ -1,7 +1,7 @@
 $(eval $(call import.MODULE.defs,LIBMP4V2,libmp4v2))
 $(eval $(call import.CONTRIB.defs,LIBMP4V2))
 
-LIBMP4V2.FETCH.url = http://download.m0k.org/handbrake/contrib/libmp4v2-2.0-r224-repack.tar.gz
+LIBMP4V2.FETCH.url = http://download.m0k.org/handbrake/contrib/libmp4v2-2.0-r286.tar.gz
 LIBMP4V2.EXTRACT.tarbase = libmp4v2
 
 ## propagate more flags
@@ -10,8 +10,4 @@ LIBMP4V2.CONFIGURE.env.CXXFLAGS = CXXFLAGS="$(call fn.ARGS,LIBMP4V2.GCC,*archs *
 
 ## save some build-time by disabling utils
 LIBMP4V2.CONFIGURE.extra += --disable-util
-
-ifeq ($(BUILD.system),mingw)
-    ## mingw platform patches configure.ac and requires bootstrap
-    LIBMP4V2.CONFIGURE.bootstrap = autoreconf -fiv;
-endif
+LIBMP4V2.CONFIGURE.extra += --enable-gch
index b7c4686..5a6320a 100644 (file)
@@ -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;
 };
index 85c3cd2..754eb7a 100644 (file)
 
 #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. 
index 3f9b231..9698faf 100644 (file)
@@ -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 );