avformat/oggparsevorbis: Factor parsing a single VorbisComment out

This is in preparation for further commits.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2021-08-23 10:03:47 +02:00
parent 033105a739
commit f1d89d6dd0

View File

@@ -84,52 +84,23 @@ int ff_vorbis_stream_comment(AVFormatContext *as, AVStream *st,
return updates; return updates;
} }
int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m, static int vorbis_parse_single_comment(AVFormatContext *as, AVDictionary **m,
const uint8_t *buf, int size, const uint8_t *buf, uint32_t size,
int parse_picture) int *updates, int parse_picture)
{ {
const uint8_t *p = buf; const char *t = buf, *v = memchr(t, '=', size);
const uint8_t *end = buf + size; char *tt, *ct;
int updates = 0;
unsigned n;
int s;
/* must have vendor_length and user_comment_list_length */
if (size < 8)
return AVERROR_INVALIDDATA;
s = bytestream_get_le32(&p);
if (end - p - 4 < s || s < 0)
return AVERROR_INVALIDDATA;
p += s;
n = bytestream_get_le32(&p);
while (end - p >= 4 && n > 0) {
const char *t, *v;
int tl, vl; int tl, vl;
s = bytestream_get_le32(&p);
if (end - p < s || s < 0)
break;
t = p;
p += s;
n--;
v = memchr(t, '=', s);
if (!v) if (!v)
continue; return 0;
tl = v - t; tl = v - t;
vl = s - tl - 1; vl = size - tl - 1;
v++; v++;
if (tl && vl) { if (!tl || !vl)
char *tt, *ct; return 0;
tt = av_malloc(tl + 1); tt = av_malloc(tl + 1);
ct = av_malloc(vl + 1); ct = av_malloc(vl + 1);
@@ -153,13 +124,13 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
*/ */
if (!av_strcasecmp(tt, "METADATA_BLOCK_PICTURE") && parse_picture) { if (!av_strcasecmp(tt, "METADATA_BLOCK_PICTURE") && parse_picture) {
int ret, len = AV_BASE64_DECODE_SIZE(vl); int ret, len = AV_BASE64_DECODE_SIZE(vl);
char *pict = av_malloc(len); uint8_t *pict = av_malloc(len);
if (!pict) { if (!pict) {
av_log(as, AV_LOG_WARNING, "out-of-memory error. Skipping cover art block.\n"); av_log(as, AV_LOG_WARNING, "out-of-memory error. Skipping cover art block.\n");
av_freep(&tt); av_freep(&tt);
av_freep(&ct); av_freep(&ct);
continue; return 0;
} }
ret = av_base64_decode(pict, ct, len); ret = av_base64_decode(pict, ct, len);
av_freep(&tt); av_freep(&tt);
@@ -169,10 +140,10 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
av_freep(&pict); av_freep(&pict);
if (ret < 0) { if (ret < 0) {
av_log(as, AV_LOG_WARNING, "Failed to parse cover art block.\n"); av_log(as, AV_LOG_WARNING, "Failed to parse cover art block.\n");
continue; return 0;
} }
} else if (!ogm_chapter(as, tt, ct)) { } else if (!ogm_chapter(as, tt, ct)) {
updates++; (*updates)++;
if (av_dict_get(*m, tt, NULL, 0)) { if (av_dict_get(*m, tt, NULL, 0)) {
av_dict_set(m, tt, ";", AV_DICT_APPEND); av_dict_set(m, tt, ";", AV_DICT_APPEND);
} }
@@ -180,7 +151,44 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL |
AV_DICT_APPEND); AV_DICT_APPEND);
} }
}
return 0;
}
int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
const uint8_t *buf, int size,
int parse_picture)
{
const uint8_t *p = buf;
const uint8_t *end = buf + size;
int updates = 0;
unsigned n;
int s, ret;
/* must have vendor_length and user_comment_list_length */
if (size < 8)
return AVERROR_INVALIDDATA;
s = bytestream_get_le32(&p);
if (end - p - 4 < s || s < 0)
return AVERROR_INVALIDDATA;
p += s;
n = bytestream_get_le32(&p);
while (end - p >= 4 && n > 0) {
s = bytestream_get_le32(&p);
if (end - p < s || s < 0)
break;
ret = vorbis_parse_single_comment(as, m, p, s, &updates, parse_picture);
if (ret < 0)
return ret;
p += s;
n--;
} }
if (p != end) if (p != end)