Mercurial > libavformat.hg
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 { |