[SCM] handbrake/master: Use libav/ffmpeg for reading metadata

rbrito-guest at users.alioth.debian.org rbrito-guest at users.alioth.debian.org
Sat Jun 16 05:56:09 UTC 2012


The following commit has been merged in the master branch:
commit 3e1bde73579abdc9d8a2aaac6efd22995850186e
Author: Rogério Brito <rbrito at ime.usp.br>
Date:   Sat Jun 16 01:03:07 2012 -0300

    Use libav/ffmpeg for reading metadata
    
    This substitutes mp4v2 for reading metadata from files. It is currently full
    of FIXME's and it was only lightly tested with a pair of MP4 files.
    
    It needs a lot of love, but it is my first try at learning how to use
    libav/ffmpeg's API.
    
    Note to self: in a call to `avformat_open_input`, the `AVFormatContext`
    pointer that is passed must be initialized to `NULL` or bad things happen
    (e.g., segfaults).
    
    Signed-off-by: Rogério Brito <rbrito at ime.usp.br>

diff --git a/debian/patches/0015-use-metadata-reading-from-libav.patch b/debian/patches/0015-use-metadata-reading-from-libav.patch
new file mode 100644
index 0000000..9238472
--- /dev/null
+++ b/debian/patches/0015-use-metadata-reading-from-libav.patch
@@ -0,0 +1,202 @@
+Author: Rogério Theodoro de Brito <rbrito at ime.usp.br>
+Description: (WIP) Use libav/ffmpeg for reading metadata
+ This substitutes mp4v2 for reading metadata from files. It is currently
+ full of FIXME's and it was not even tested to see if it builds.
+Last-Update: 2012-06-16
+Forwarded: no
+
+--- a/libhb/decmetadata.c
++++ b/libhb/decmetadata.c
+@@ -4,96 +4,111 @@
+    Homepage: <http://handbrake.fr/>.
+    It may be used under the terms of the GNU General Public License. */
+ 
+-#include <mp4v2/mp4v2.h>
++#include <libavformat/avformat.h>
++#include <libavutil/dict.h>
++#include <libavutil/rational.h>
+ 
+ #include "common.h"
+ 
+ static void decmp4metadata( hb_title_t *title )
+ {
+-    MP4FileHandle input_file;
+-    hb_deep_log( 2, "Got an MP4 input, read the metadata");
++    /* FIXME: Is av_registar_all already called here? --- rbrito */
++    av_register_all();
++    AVFormatContext *fmt_ctx = NULL; /* context for the file */
++    AVDictionaryEntry *tags; /* each entry of metadata of the file */
++
++    AVDictionary *dict; /* shorthand, not strictly necessary */
++    hb_metadata_t *hb_metadata; /* shorthand, not strictly necessary */
++
++    hb_deep_log(2, "Got an MP4 input, read the metadata");
++
++    /* Bail out early in case of problems. */
++    if (avformat_open_input(&fmt_ctx, title->path, NULL, NULL) != 0)
++	return;
++
++    /* avoid typing too much in what follows */
++    dict = fmt_ctx->metadata;
++    hb_metadata = title->metadata;
++
++    /*
++     * Store iTunes MetaData
++     */
++    if ((tags = av_dict_get(dict, "title", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL) {
++	hb_deep_log(2, "Metadata Name in input file is '%s'", tags->value);
++	strncpy(hb_metadata->name, tags->value, sizeof(hb_metadata->name));
++    }
++
++    if ((tags = av_dict_get(dict, "artist", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL)
++	strncpy(hb_metadata->artist, tags->value, sizeof(hb_metadata->artist));
++
++    if ((tags = av_dict_get(dict, "composer", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL)
++	strncpy(hb_metadata->composer, tags->value, sizeof(hb_metadata->composer));
++
++    if ((tags = av_dict_get(dict, "comment", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL)
++	strncpy(hb_metadata->comment, tags->value, sizeof(hb_metadata->comment));
++
++    if ((tags = av_dict_get(dict, "album", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL)
++	strncpy(hb_metadata->album, tags->value, sizeof(hb_metadata->album));
++
++    if ((tags = av_dict_get(dict, "genre", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL)
++	strncpy(hb_metadata->genre, tags->value, sizeof(hb_metadata->genre));
++
++    if ((tags = av_dict_get(dict, "date", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL)
++	strncpy(hb_metadata->release_date, tags->value, sizeof(hb_metadata->release_date));
++
++    /* FIXME: take care of artwork here and put it in
++     * title->metadata->coverart and in title->metadata->coverart_size */
++
++    /*
++     * Handle the chapters.
++     */
++    if (fmt_ctx->nb_chapters <= 0 || hb_list_count(title->list_chapter) > 0)
++	goto finished;
++
++    AVChapter **chapter_list = fmt_ctx->chapters;
++    AVRational tb = chapter_list[0]->time_base; /* FIXME: the timebases may be different for each chapter. */
++    uint32_t i; /* handbrake wants chapters to be 1-based */
+ 
+-    input_file = MP4Read(title->path);
++    uint64_t curstart, oldstart, duration;
++    hb_chapter_t *chapter;
+ 
+-    if( input_file != MP4_INVALID_FILE_HANDLE )
+-    { 
+-        /*
+-         * Store iTunes MetaData
+-         */
+-        const MP4Tags* tags;
+-
+-        /* alloc,fetch tags */
+-        tags = MP4TagsAlloc();
+-        MP4TagsFetch( tags, input_file );
+-
+-        if( tags->name ) {
+-            hb_deep_log( 2, "Metadata Name in input file is '%s'", tags->name );
+-            strncpy( title->metadata->name, tags->name, sizeof(title->metadata->name) );
+-        }
+-
+-        if( tags->artist )
+-            strncpy( title->metadata->artist, tags->artist, sizeof(title->metadata->artist) );
+-
+-        if( tags->composer )
+-            strncpy( title->metadata->composer, tags->composer, sizeof(title->metadata->composer) );
+-
+-        if( tags->comments )
+-            strncpy( title->metadata->comment, tags->comments, sizeof(title->metadata->comment) );
+-
+-        if( tags->releaseDate )
+-            strncpy( title->metadata->release_date, tags->releaseDate, sizeof(title->metadata->release_date) );
+-
+-        if( tags->album )
+-            strncpy( title->metadata->album, tags->album, sizeof(title->metadata->album) );
+-
+-        if( tags->genre )
+-            strncpy( title->metadata->genre, tags->genre, sizeof(title->metadata->genre) );
+-
+-        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", 
+-                         art->type,
+-                         title->metadata->coverart_size );
+-        }
+-
+-        /* store,free tags */
+-        MP4TagsStore( tags, input_file );
+-        MP4TagsFree( tags );
+-        
+-        /*
+-         * Handle the chapters. 
+-         */
+-        MP4Chapter_t *chapter_list = NULL;
+-        uint32_t      chapter_count;
+-        
+-        MP4GetChapters( input_file, &chapter_list, &chapter_count, 
+-                        MP4ChapterTypeQt );
+-
+-        if( chapter_list && ( hb_list_count( title->list_chapter ) == 0 ) ) {
+-            uint32_t i = 1;
+-            while( i <= chapter_count )
+-            {
+-                hb_chapter_t * chapter;
+-                chapter = calloc( sizeof( hb_chapter_t ), 1 );
+-                chapter->index = i;
+-                chapter->duration = chapter_list[i-1].duration * 90;
+-                chapter->hours    = chapter->duration / 90000 / 3600;
+-                chapter->minutes  = ( ( chapter->duration / 90000 ) % 3600 ) / 60;
+-                chapter->seconds  = ( chapter->duration / 90000 ) % 60;
+-                strcpy( chapter->title, chapter_list[i-1].title );
+-                hb_deep_log( 2, "Added chapter %i, name='%s', dur=%"PRId64", (%02i:%02i:%02i)", chapter->index, chapter->title, 
+-                       chapter->duration, chapter->hours, 
+-                       chapter->minutes, chapter->seconds);
+-                hb_list_add( title->list_chapter, chapter );
+-                i++;
+-            }
+-        }
++    oldstart = 0;
++    for (i = 0; i < fmt_ctx->nb_chapters; i++) {
++	chapter           = calloc(sizeof(hb_chapter_t), 1); /* FIXME: verify errors */
+ 
+-        MP4Close(input_file, 0);
++	curstart          = (chapter_list[i]->start * tb.num)/tb.den;
++	duration          = curstart - oldstart;
++
++	chapter->index    = i+1; /* 1-based */
++	chapter->duration = 9000 * duration; /* handbrake's time units is 1/90000 s */
++	chapter->hours    = duration / 3600;
++	chapter->minutes  = ( duration % 3600 ) / 60;
++	chapter->seconds  = ( duration ) % 60;
++
++	/* FIXME: ffmpeg/libav probably exposes the chapter names as
++
++	        av_dict_get(chapter_list[i]->metadata, "title", NULL, AV_DICT_IGNORE_SUFFIX)->value
++
++	   if the metadata has the "title" key (i.e., not NULL). In essence, we should do:
++
++	        strcpy(chapter->title,
++	               av_dict_get(chapter_list[i]->metadata,
++	                           "title", NULL, AV_DICT_IGNORE_SUFFIX)->value);
++
++	   I'm lazy now to write the few lines of code for that and we should do:
++	*/
++	strcpy( chapter->title, "" );
++
++	hb_deep_log(2, "Added chapter %i, name='%s', dur=%"PRId64", (%02i:%02i:%02i)",
++		    chapter->index, chapter->title, chapter->duration, chapter->hours,
++		    chapter->minutes, chapter->seconds);
++	hb_list_add(title->list_chapter, chapter);
++
++	oldstart = chapter_list[i]->start; /* avoid typing */
+     }
++
++finished:
++	avformat_free_context(fmt_ctx);
+ }
+ 
+ /*
diff --git a/debian/patches/series b/debian/patches/series
index d599ae0..fe8d44e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -12,3 +12,4 @@
 0012-FLAGS.patch
 0013-format-security.patch
 #0014-Use-unpatched-a52.patch
+#0015-use-metadata-reading-from-libav.patch

-- 
handbrake packaging



More information about the pkg-multimedia-commits mailing list