OSDN Git Service

235fc69fdfb3e95d0653f323c4c792ae5e576ca5
[handbrake-jp/handbrake-jp-git.git] / libhb / decmetadata.c
1 /* decmetadata.c - Extract and decode metadata from the source
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include <mp4v2/mp4v2.h>
8
9 #include "common.h"
10
11 void identify_art_type( hb_metadata_t *metadata )
12 {
13     typedef struct header_s {
14         enum arttype type;
15         char*   name;   // short string describing name of type
16         char*   data;   // header-bytes to match
17     } header;
18
19     // types which may be detected by first-bytes only
20     static header headers[] = {
21         { BMP,    "bmp", "\x4d\x42" },
22         { GIF87A, "GIF (87a)", "GIF87a" },
23         { GIF89A, "GIF (89a)", "GIF89a" },
24         { JPG,    "JPEG", "\xff\xd8\xff\xe0" },
25         { PNG,    "PNG", "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" },
26         { TIFFL,  "TIFF (little-endian)", "II42" },
27         { TIFFB,  "TIFF (big-endian)", "MM42" },
28         { UNKNOWN } // must be last
29     };
30     header* p;
31     header* found = NULL;
32     for( p = headers; p->type != UNKNOWN; p++ ) {
33         header *h = p;
34
35         if( metadata->coverart_size < strlen(h->data) )
36             continue;
37
38         if( memcmp(h->data, metadata->coverart, strlen(h->data)) == 0 ) {
39             metadata->coverart_type = h->type;
40             break;
41         }
42     }
43 }
44
45 static void decmp4metadata( hb_title_t *title )
46 {
47     MP4FileHandle input_file;
48
49     hb_deep_log( 2, "Got an MP4 input, read the metadata");
50
51     input_file = MP4Read( title->dvd, 0 );
52
53     if( input_file != MP4_INVALID_FILE_HANDLE )
54     { 
55         char         *value = NULL;
56         uint8_t      *cover_art = NULL;
57         uint32_t      size;
58         uint32_t      count;
59         
60         /*
61          * Store iTunes MetaData
62          */
63         if( MP4GetMetadataName( input_file, &value) && value )
64         {
65             hb_deep_log( 2, "Metadata Name in input file is '%s'", value);
66             strncpy( title->metadata->name, value, 255);
67             MP4Free(value);
68             value = NULL;
69         }
70
71         if( MP4GetMetadataArtist( input_file, &value) && value )
72         {
73             strncpy( title->metadata->artist, value, 255);
74             MP4Free(value);
75             value = NULL;
76         }
77         
78         if( MP4GetMetadataComposer( input_file, &value) && value )
79         {
80             strncpy( title->metadata->composer, value, 255);
81             MP4Free(value);
82             value = NULL;
83         }
84
85         if( MP4GetMetadataComment( input_file, &value) && value )
86         {
87             strncpy( title->metadata->comment, value, 1024);
88             value = NULL;
89         }
90         
91         if( MP4GetMetadataReleaseDate( input_file, &value) && value )
92         {
93             strncpy( title->metadata->release_date, value, 255);
94             MP4Free(value);
95             value = NULL;
96         }
97         
98         if( MP4GetMetadataAlbum( input_file, &value) && value )
99         {
100             strncpy( title->metadata->album, value, 255);
101             MP4Free(value);
102             value = NULL;
103         }
104         
105         if( MP4GetMetadataGenre( input_file, &value) && value )
106         {
107             strncpy( title->metadata->genre, value, 255);
108             MP4Free(value);
109             value = NULL;
110         }
111         
112         if( MP4GetMetadataCoverArt( input_file, &cover_art, &size, 0) && 
113             cover_art )
114         {
115             title->metadata->coverart = cover_art; 
116             title->metadata->coverart_size = size;
117             identify_art_type( title->metadata );
118             hb_deep_log( 2, "Got some cover art of type %d, size %d", 
119                          title->metadata->coverart_type,
120                          title->metadata->coverart_size);
121         }
122         
123         /*
124          * Handle the chapters. 
125          */
126         MP4Chapter_t *chapter_list = NULL;
127         uint32_t      chapter_count;
128         
129         MP4GetChapters( input_file, &chapter_list, &chapter_count, 
130                         MP4ChapterTypeQt );
131
132         if( chapter_list && ( hb_list_count( title->list_chapter ) == 0 ) ) {
133             uint i = 1;
134             while( i <= chapter_count )
135             {
136                 hb_chapter_t * chapter;
137                 chapter = calloc( sizeof( hb_chapter_t ), 1 );
138                 chapter->index = i;
139                 chapter->duration = chapter_list[i-1].duration * 90;
140                 chapter->hours    = chapter->duration / 90000 / 3600;
141                 chapter->minutes  = ( ( chapter->duration / 90000 ) % 3600 ) / 60;
142                 chapter->seconds  = ( chapter->duration / 90000 ) % 60;
143                 strcpy( chapter->title, chapter_list[i-1].title );
144                 hb_deep_log( 2, "Added chapter %i, name='%s', dur=%lld, (%02i:%02i:%02i)", chapter->index, chapter->title, 
145                        chapter->duration, chapter->hours, 
146                        chapter->minutes, chapter->seconds);
147                 hb_list_add( title->list_chapter, chapter );
148                 i++;
149             }
150         }
151
152         MP4Close( input_file );
153     }
154 }
155
156 /*
157  * decmetadata()
158  *
159  * Look at the title and extract whatever metadata we can from that title.
160  */
161 void decmetadata( hb_title_t *title )
162 {
163     if( !title ) 
164     {
165         return;
166     }
167     
168     if( title->metadata )
169     {
170         free( title->metadata );
171         title->metadata = NULL;
172     }
173
174     title->metadata = calloc( sizeof(hb_metadata_t), 1);
175
176     if( !title->metadata )
177     {
178         return;
179     }
180
181     /*
182      * Hacky way of figuring out if this is an MP4, in which case read the data using libmp4v2
183      */
184     if( title->container_name && strcmp(title->container_name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 ) 
185     {
186         decmp4metadata( title );
187     } else {
188         free( title->metadata );
189         title->metadata = NULL;
190     }
191 }