summaryrefslogtreecommitdiffstats
path: root/libhb/decmetadata.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/decmetadata.c')
-rw-r--r--libhb/decmetadata.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/libhb/decmetadata.c b/libhb/decmetadata.c
new file mode 100644
index 000000000..7ac9bcffa
--- /dev/null
+++ b/libhb/decmetadata.c
@@ -0,0 +1,191 @@
+/* decmetadata.c - Extract and decode metadata from the source
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include <mp4v2/mp4v2.h>
+
+#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;
+ }
+
+ 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;
+ }
+
+ 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( 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 );
+ hb_deep_log( 2, "Got some cover art of type %d, size %d",
+ title->metadata->coverart_type,
+ title->metadata->coverart_size);
+ }
+
+ /*
+ * Handle the chapters.
+ */
+ MP4Chapter_t *chapter_list = NULL;
+ uint32_t chapter_count;
+
+ MP4GetChapters( input_file, &chapter_list, &chapter_count,
+ MP4ChapterTypeQt );
+
+ if( chapter_list ) {
+ uint 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=%lld, (%02i:%02i:%02i)", chapter->index, chapter->title,
+ chapter->duration, chapter->hours,
+ chapter->minutes, chapter->seconds);
+ hb_list_add( title->list_chapter, chapter );
+ i++;
+ }
+ }
+
+ MP4Close( input_file );
+ }
+}
+
+/*
+ * decmetadata()
+ *
+ * Look at the title and extract whatever metadata we can from that title.
+ */
+void decmetadata( hb_title_t *title )
+{
+ if( !title )
+ {
+ return;
+ }
+
+ if( title->metadata )
+ {
+ free( title->metadata );
+ title->metadata = NULL;
+ }
+
+ title->metadata = calloc( sizeof(hb_metadata_t), 1);
+
+ if( !title->metadata )
+ {
+ return;
+ }
+
+ /*
+ * Hacky way of figuring out if this is an MP4, in which case read the data using libmp4v2
+ */
+ if( title->container_name && strcmp(title->container_name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
+ {
+ decmp4metadata( title );
+ } else {
+ free( title->metadata );
+ title->metadata = NULL;
+ }
+}