It is commonly stored in a vorbiscomment block in codec private data.
Anton Khirnov authored on 2014/05/26 19:48:56... | ... |
@@ -166,7 +166,8 @@ OBJS-$(CONFIG_LXF_DEMUXER) += lxfdec.o |
166 | 166 |
OBJS-$(CONFIG_M4V_DEMUXER) += m4vdec.o rawdec.o |
167 | 167 |
OBJS-$(CONFIG_M4V_MUXER) += rawenc.o |
168 | 168 |
OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ |
169 |
- isom.o rmsipr.o |
|
169 |
+ isom.o rmsipr.o \ |
|
170 |
+ oggparsevorbis.o vorbiscomment.o |
|
170 | 171 |
OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ |
171 | 172 |
isom.o avc.o hevc.o \ |
172 | 173 |
flacenc_header.o avlanguage.o wv.o |
... | ... |
@@ -141,7 +141,7 @@ static int flac_read_header(AVFormatContext *s) |
141 | 141 |
if (metadata_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) { |
142 | 142 |
AVDictionaryEntry *chmask; |
143 | 143 |
|
144 |
- if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size)) { |
|
144 |
+ if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size, 1)) { |
|
145 | 145 |
av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n"); |
146 | 146 |
} |
147 | 147 |
|
... | ... |
@@ -55,6 +55,7 @@ |
55 | 55 |
#include "internal.h" |
56 | 56 |
#include "isom.h" |
57 | 57 |
#include "matroska.h" |
58 |
+#include "oggdec.h" |
|
58 | 59 |
/* For ff_codec_get_id(). */ |
59 | 60 |
#include "riff.h" |
60 | 61 |
#include "rmsipr.h" |
... | ... |
@@ -1443,6 +1444,7 @@ static int matroska_parse_flac(AVFormatContext *s, |
1443 | 1443 |
MatroskaTrack *track, |
1444 | 1444 |
int *offset) |
1445 | 1445 |
{ |
1446 |
+ AVStream *st = track->stream; |
|
1446 | 1447 |
uint8_t *p = track->codec_priv.data; |
1447 | 1448 |
int size = track->codec_priv.size; |
1448 | 1449 |
|
... | ... |
@@ -1454,6 +1456,42 @@ static int matroska_parse_flac(AVFormatContext *s, |
1454 | 1454 |
*offset = 8; |
1455 | 1455 |
track->codec_priv.size = 8 + FLAC_STREAMINFO_SIZE; |
1456 | 1456 |
|
1457 |
+ p += track->codec_priv.size; |
|
1458 |
+ size -= track->codec_priv.size; |
|
1459 |
+ |
|
1460 |
+ /* parse the remaining metadata blocks if present */ |
|
1461 |
+ while (size >= 4) { |
|
1462 |
+ int block_last, block_type, block_size; |
|
1463 |
+ |
|
1464 |
+ flac_parse_block_header(p, &block_last, &block_type, &block_size); |
|
1465 |
+ |
|
1466 |
+ p += 4; |
|
1467 |
+ size -= 4; |
|
1468 |
+ if (block_size > size) |
|
1469 |
+ return 0; |
|
1470 |
+ |
|
1471 |
+ /* check for the channel mask */ |
|
1472 |
+ if (block_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) { |
|
1473 |
+ AVDictionary *dict = NULL; |
|
1474 |
+ AVDictionaryEntry *chmask; |
|
1475 |
+ |
|
1476 |
+ ff_vorbis_comment(s, &dict, p, block_size, 0); |
|
1477 |
+ chmask = av_dict_get(dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); |
|
1478 |
+ if (chmask) { |
|
1479 |
+ uint64_t mask = strtol(chmask->value, NULL, 0); |
|
1480 |
+ if (!mask || mask & ~0x3ffffULL) { |
|
1481 |
+ av_log(s, AV_LOG_WARNING, |
|
1482 |
+ "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); |
|
1483 |
+ } else |
|
1484 |
+ st->codec->channel_layout = mask; |
|
1485 |
+ } |
|
1486 |
+ av_dict_free(&dict); |
|
1487 |
+ } |
|
1488 |
+ |
|
1489 |
+ p += block_size; |
|
1490 |
+ size -= block_size; |
|
1491 |
+ } |
|
1492 |
+ |
|
1457 | 1493 |
return 0; |
1458 | 1494 |
} |
1459 | 1495 |
|
... | ... |
@@ -122,7 +122,8 @@ extern const struct ogg_codec ff_speex_codec; |
122 | 122 |
extern const struct ogg_codec ff_theora_codec; |
123 | 123 |
extern const struct ogg_codec ff_vorbis_codec; |
124 | 124 |
|
125 |
-int ff_vorbis_comment(AVFormatContext *ms, AVDictionary **m, const uint8_t *buf, int size); |
|
125 |
+int ff_vorbis_comment(AVFormatContext *ms, AVDictionary **m, |
|
126 |
+ const uint8_t *buf, int size, int parse_picture); |
|
126 | 127 |
|
127 | 128 |
static inline int |
128 | 129 |
ogg_find_stream (struct ogg * ogg, int serial) |
... | ... |
@@ -81,7 +81,7 @@ static int celt_header(AVFormatContext *s, int idx) |
81 | 81 |
} else if (priv && priv->extra_headers_left) { |
82 | 82 |
/* Extra headers (vorbiscomment) */ |
83 | 83 |
|
84 |
- ff_vorbis_comment(s, &st->metadata, p, os->psize); |
|
84 |
+ ff_vorbis_comment(s, &st->metadata, p, os->psize, 1); |
|
85 | 85 |
priv->extra_headers_left--; |
86 | 86 |
return 1; |
87 | 87 |
} else { |
... | ... |
@@ -69,7 +69,7 @@ flac_header (AVFormatContext * s, int idx) |
69 | 69 |
|
70 | 70 |
avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); |
71 | 71 |
} else if (mdt == FLAC_METADATA_TYPE_VORBIS_COMMENT) { |
72 |
- ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 4, os->psize - 4); |
|
72 |
+ ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 4, os->psize - 4, 1); |
|
73 | 73 |
} |
74 | 74 |
|
75 | 75 |
return 1; |
... | ... |
@@ -97,7 +97,7 @@ ogm_header(AVFormatContext *s, int idx) |
97 | 97 |
} else if (bytestream2_peek_byte(&p) == 3) { |
98 | 98 |
bytestream2_skip(&p, 7); |
99 | 99 |
if (bytestream2_get_bytes_left(&p) > 1) |
100 |
- ff_vorbis_comment(s, &st->metadata, p.buffer, bytestream2_get_bytes_left(&p) - 1); |
|
100 |
+ ff_vorbis_comment(s, &st->metadata, p.buffer, bytestream2_get_bytes_left(&p) - 1, 1); |
|
101 | 101 |
} |
102 | 102 |
|
103 | 103 |
return 1; |
... | ... |
@@ -74,7 +74,7 @@ static int opus_header(AVFormatContext *avf, int idx) |
74 | 74 |
if (priv->need_comments) { |
75 | 75 |
if (os->psize < 8 || memcmp(packet, "OpusTags", 8)) |
76 | 76 |
return AVERROR_INVALIDDATA; |
77 |
- ff_vorbis_comment(avf, &st->metadata, packet + 8, os->psize - 8); |
|
77 |
+ ff_vorbis_comment(avf, &st->metadata, packet + 8, os->psize - 8, 1); |
|
78 | 78 |
priv->need_comments--; |
79 | 79 |
return 1; |
80 | 80 |
} |
... | ... |
@@ -79,7 +79,7 @@ static int speex_header(AVFormatContext *s, int idx) { |
79 | 79 |
|
80 | 80 |
avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); |
81 | 81 |
} else |
82 |
- ff_vorbis_comment(s, &st->metadata, p, os->psize); |
|
82 |
+ ff_vorbis_comment(s, &st->metadata, p, os->psize, 1); |
|
83 | 83 |
|
84 | 84 |
spxp->seq++; |
85 | 85 |
return 1; |
... | ... |
@@ -116,7 +116,7 @@ static int theora_header(AVFormatContext *s, int idx) |
116 | 116 |
} |
117 | 117 |
break; |
118 | 118 |
case 0x81: |
119 |
- ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 7); |
|
119 |
+ ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 7, 1); |
|
120 | 120 |
case 0x82: |
121 | 121 |
if (!thp->version) |
122 | 122 |
return AVERROR_INVALIDDATA; |
... | ... |
@@ -72,7 +72,8 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val) |
72 | 72 |
} |
73 | 73 |
|
74 | 74 |
int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m, |
75 |
- const uint8_t *buf, int size) |
|
75 |
+ const uint8_t *buf, int size, |
|
76 |
+ int parse_picture) |
|
76 | 77 |
{ |
77 | 78 |
const uint8_t *p = buf; |
78 | 79 |
const uint8_t *end = buf + size; |
... | ... |
@@ -137,7 +138,7 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m, |
137 | 137 |
* 'METADATA_BLOCK_PICTURE'. This is the preferred and |
138 | 138 |
* recommended way of embedding cover art within VorbisComments." |
139 | 139 |
*/ |
140 |
- if (!strcmp(tt, "METADATA_BLOCK_PICTURE")) { |
|
140 |
+ if (!strcmp(tt, "METADATA_BLOCK_PICTURE") && parse_picture) { |
|
141 | 141 |
int ret; |
142 | 142 |
char *pict = av_malloc(vl); |
143 | 143 |
|
... | ... |
@@ -305,7 +306,7 @@ static int vorbis_header(AVFormatContext *s, int idx) |
305 | 305 |
} else if (os->buf[os->pstart] == 3) { |
306 | 306 |
if (os->psize > 8 && |
307 | 307 |
ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, |
308 |
- os->psize - 8) >= 0) { |
|
308 |
+ os->psize - 8, 1) >= 0) { |
|
309 | 309 |
unsigned new_len; |
310 | 310 |
|
311 | 311 |
int ret = ff_replaygain_export(st, st->metadata); |