comparison mov.c @ 4726:1ce512298dbd libavformat

more generic metadata handling
author bcoudurier
date Mon, 16 Mar 2009 06:03:29 +0000
parents f2d519837d2d
children 245cabbfa676
comparison
equal deleted inserted replaced
4725:f2d519837d2d 4726:1ce512298dbd
21 */ 21 */
22 22
23 #include <limits.h> 23 #include <limits.h>
24 24
25 //#define DEBUG 25 //#define DEBUG
26 //#define DEBUG_METADATA
27 //#define MOV_EXPORT_ALL_METADATA
26 28
27 #include "libavutil/intreadwrite.h" 29 #include "libavutil/intreadwrite.h"
28 #include "libavutil/avstring.h" 30 #include "libavutil/avstring.h"
29 #include "avformat.h" 31 #include "avformat.h"
30 #include "riff.h" 32 #include "riff.h"
75 int (*parse)(MOVContext *ctx, ByteIOContext *pb, MOVAtom atom); 77 int (*parse)(MOVContext *ctx, ByteIOContext *pb, MOVAtom atom);
76 } MOVParseTableEntry; 78 } MOVParseTableEntry;
77 79
78 static const MOVParseTableEntry mov_default_parse_table[]; 80 static const MOVParseTableEntry mov_default_parse_table[];
79 81
82 static int mov_read_udta_string(MOVContext *c, ByteIOContext *pb, MOVAtom atom);
83
80 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOVAtom atom) 84 static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
81 { 85 {
82 int64_t total_size = 0; 86 int64_t total_size = 0;
83 MOVAtom a; 87 MOVAtom a;
84 int i; 88 int i;
87 a.offset = atom.offset; 91 a.offset = atom.offset;
88 92
89 if (atom.size < 0) 93 if (atom.size < 0)
90 atom.size = INT64_MAX; 94 atom.size = INT64_MAX;
91 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) { 95 while(((total_size + 8) < atom.size) && !url_feof(pb) && !err) {
96 int (*parse)(MOVContext*, ByteIOContext*, MOVAtom) = NULL;
92 a.size = atom.size; 97 a.size = atom.size;
93 a.type=0; 98 a.type=0;
94 if(atom.size >= 8) { 99 if(atom.size >= 8) {
95 a.size = get_be32(pb); 100 a.size = get_be32(pb);
96 a.type = get_le32(pb); 101 a.type = get_le32(pb);
112 a.size -= 8; 117 a.size -= 8;
113 if(a.size < 0) 118 if(a.size < 0)
114 break; 119 break;
115 a.size = FFMIN(a.size, atom.size - total_size); 120 a.size = FFMIN(a.size, atom.size - total_size);
116 121
117 for (i = 0; mov_default_parse_table[i].type != 0 122 for (i = 0; mov_default_parse_table[i].type; i++)
118 && mov_default_parse_table[i].type != a.type; i++) 123 if (mov_default_parse_table[i].type == a.type) {
119 /* empty */; 124 parse = mov_default_parse_table[i].parse;
120 125 break;
121 if (mov_default_parse_table[i].type == 0) { /* skip leaf atoms data */ 126 }
127
128 // container is user data
129 if (!parse && (atom.type == MKTAG('u','d','t','a') ||
130 atom.type == MKTAG('i','l','s','t')))
131 parse = mov_read_udta_string;
132
133 if (!parse) { /* skip leaf atoms data */
122 url_fskip(pb, a.size); 134 url_fskip(pb, a.size);
123 } else { 135 } else {
124 int64_t start_pos = url_ftell(pb); 136 int64_t start_pos = url_ftell(pb);
125 int64_t left; 137 int64_t left;
126 err = mov_default_parse_table[i].parse(c, pb, a); 138 err = parse(c, pb, a);
127 if (url_is_streamed(pb) && c->found_moov && c->found_mdat) 139 if (url_is_streamed(pb) && c->found_moov && c->found_mdat)
128 break; 140 break;
129 left = a.size - url_ftell(pb) + start_pos; 141 left = a.size - url_ftell(pb) + start_pos;
130 if (left > 0) /* skip garbage at atom end */ 142 if (left > 0) /* skip garbage at atom end */
131 url_fskip(pb, left); 143 url_fskip(pb, left);
1360 return 0; 1372 return 0;
1361 } 1373 }
1362 1374
1363 static int mov_read_udta_string(MOVContext *c, ByteIOContext *pb, MOVAtom atom) 1375 static int mov_read_udta_string(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
1364 { 1376 {
1377 #ifdef MOV_EXPORT_ALL_METADATA
1378 char tmp_key[5];
1379 #endif
1365 char str[1024], key2[16], language[4] = {0}; 1380 char str[1024], key2[16], language[4] = {0};
1366 const char *key = NULL; 1381 const char *key = NULL;
1367 uint16_t str_size; 1382 uint16_t str_size;
1368 1383
1369 if (c->itunes_metadata) {
1370 int data_size = get_be32(pb);
1371 int tag = get_le32(pb);
1372 if (tag == MKTAG('d','a','t','a')) {
1373 get_be32(pb); // type
1374 get_be32(pb); // unknown
1375 str_size = data_size - 16;
1376 atom.size -= 16;
1377 } else return 0;
1378 } else {
1379 str_size = get_be16(pb); // string length
1380 ff_mov_lang_to_iso639(get_be16(pb), language);
1381 atom.size -= 4;
1382 }
1383 switch (atom.type) { 1384 switch (atom.type) {
1384 case MKTAG(0xa9,'n','a','m'): key = "title"; break; 1385 case MKTAG(0xa9,'n','a','m'): key = "title"; break;
1385 case MKTAG(0xa9,'a','u','t'): 1386 case MKTAG(0xa9,'a','u','t'):
1386 case MKTAG(0xa9,'A','R','T'): 1387 case MKTAG(0xa9,'A','R','T'):
1387 case MKTAG(0xa9,'w','r','t'): key = "author"; break; 1388 case MKTAG(0xa9,'w','r','t'): key = "author"; break;
1392 case MKTAG(0xa9,'d','a','y'): key = "year"; break; 1393 case MKTAG(0xa9,'d','a','y'): key = "year"; break;
1393 case MKTAG(0xa9,'g','e','n'): key = "genre"; break; 1394 case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
1394 case MKTAG(0xa9,'t','o','o'): 1395 case MKTAG(0xa9,'t','o','o'):
1395 case MKTAG(0xa9,'e','n','c'): key = "muxer"; break; 1396 case MKTAG(0xa9,'e','n','c'): key = "muxer"; break;
1396 } 1397 }
1398
1399 if (c->itunes_metadata && atom.size > 8) {
1400 int data_size = get_be32(pb);
1401 int tag = get_le32(pb);
1402 if (tag == MKTAG('d','a','t','a')) {
1403 get_be32(pb); // type
1404 get_be32(pb); // unknown
1405 str_size = data_size - 16;
1406 atom.size -= 16;
1407 } else return 0;
1408 } else if (atom.size > 4 && key && !c->itunes_metadata) {
1409 str_size = get_be16(pb); // string length
1410 ff_mov_lang_to_iso639(get_be16(pb), language);
1411 atom.size -= 4;
1412 } else
1413 str_size = atom.size;
1414
1415 #ifdef MOV_EXPORT_ALL_METADATA
1416 if (!key) {
1417 snprintf(tmp_key, 5, "%.4s", (char*)&atom.type);
1418 key = tmp_key;
1419 }
1420 #endif
1421
1397 if (!key) 1422 if (!key)
1398 return 0; 1423 return 0;
1399 if (atom.size < 0) 1424 if (atom.size < 0)
1400 return -1; 1425 return -1;
1401 1426
1405 av_metadata_set(&c->fc->metadata, key, str); 1430 av_metadata_set(&c->fc->metadata, key, str);
1406 if (*language && strcmp(language, "und")) { 1431 if (*language && strcmp(language, "und")) {
1407 snprintf(key2, sizeof(key2), "%s-%s", key, language); 1432 snprintf(key2, sizeof(key2), "%s-%s", key, language);
1408 av_metadata_set(&c->fc->metadata, key2, str); 1433 av_metadata_set(&c->fc->metadata, key2, str);
1409 } 1434 }
1410 dprintf(c->fc, "%.4s %s %d %lld\n", (char*)&atom.type, str, str_size, atom.size); 1435 #ifdef DEBUG_METADATA
1436 av_log(c->fc, AV_LOG_DEBUG, "lang \"%3s\" ", language);
1437 av_log(c->fc, AV_LOG_DEBUG, "tag \"%s\" value \"%s\" atom \"%.4s\" %d %lld\n",
1438 key, str, (char*)&atom.type, str_size, atom.size);
1439 #endif
1440
1411 return 0; 1441 return 0;
1412 } 1442 }
1413 1443
1414 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOVAtom atom) 1444 static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
1415 { 1445 {
1767 { MKTAG('u','d','t','a'), mov_read_default }, 1797 { MKTAG('u','d','t','a'), mov_read_default },
1768 { MKTAG('w','a','v','e'), mov_read_wave }, 1798 { MKTAG('w','a','v','e'), mov_read_wave },
1769 { MKTAG('e','s','d','s'), mov_read_esds }, 1799 { MKTAG('e','s','d','s'), mov_read_esds },
1770 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */ 1800 { MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
1771 { MKTAG('c','m','o','v'), mov_read_cmov }, 1801 { MKTAG('c','m','o','v'), mov_read_cmov },
1772 { MKTAG(0xa9,'n','a','m'), mov_read_udta_string },
1773 { MKTAG(0xa9,'w','r','t'), mov_read_udta_string },
1774 { MKTAG(0xa9,'c','p','y'), mov_read_udta_string },
1775 { MKTAG(0xa9,'i','n','f'), mov_read_udta_string },
1776 { MKTAG(0xa9,'i','n','f'), mov_read_udta_string },
1777 { MKTAG(0xa9,'A','R','T'), mov_read_udta_string },
1778 { MKTAG(0xa9,'a','l','b'), mov_read_udta_string },
1779 { MKTAG(0xa9,'c','m','t'), mov_read_udta_string },
1780 { MKTAG(0xa9,'a','u','t'), mov_read_udta_string },
1781 { MKTAG(0xa9,'d','a','y'), mov_read_udta_string },
1782 { MKTAG(0xa9,'g','e','n'), mov_read_udta_string },
1783 { MKTAG(0xa9,'e','n','c'), mov_read_udta_string },
1784 { MKTAG(0xa9,'t','o','o'), mov_read_udta_string },
1785 { 0, NULL } 1802 { 0, NULL }
1786 }; 1803 };
1787 1804
1788 static int mov_probe(AVProbeData *p) 1805 static int mov_probe(AVProbeData *p)
1789 { 1806 {