diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-10-04 03:21:14 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-10-04 03:24:59 +0200 |
commit | 2f9d6ffda78725e11b351a7a5d69414a32010810 (patch) | |
tree | b9bf0e40ad2b85a35af8b5c0b9b6d50c19ad5303 /libavformat/id3v2.c | |
parent | 98df93c9fe2dd4698cd7b4d699b248cbfd1427b4 (diff) | |
parent | 60df6b004858dcab96fc96c6dd32484780a8d7c3 (diff) | |
download | ffmpeg-2f9d6ffda78725e11b351a7a5d69414a32010810.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
id3v2: remove pointless casts
id3v2: read TXXX frames with two calls to decode_str() instead of one.
id3v2: don't discard the whole tag when encountering empty frames.
libvpx: fix build with older libvpx versions.
ARM: check for inline asm 'y' operand modifier support
Conflicts:
libavcodec/libvpxenc.c
libavformat/id3v2.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/id3v2.c')
-rw-r--r-- | libavformat/id3v2.c | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 9d7ceef5a4..48124cee84 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -81,23 +81,20 @@ static void free_geobtag(void *obj) /** * Decode characters to UTF-8 according to encoding type. The decoded buffer is - * always null terminated. + * always null terminated. Stop reading when either *maxread bytes are read from + * pb or U+0000 character is found. * * @param dst Pointer where the address of the buffer with the decoded bytes is * stored. Buffer must be freed by caller. - * @param dstlen Pointer to an int where the length of the decoded string - * is stored (in bytes, incl. null termination) * @param maxread Pointer to maximum number of characters to read from the * AVIOContext. After execution the value is decremented by the number of bytes * actually read. - * @seeknull If true, decoding stops after the first U+0000 character found, if - * there is any before maxread is reached * @returns 0 if no error occured, dst is uninitialized on error */ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, - uint8_t **dst, int *dstlen, int *maxread, const int seeknull) + uint8_t **dst, int *maxread) { - int len, ret; + int ret; uint8_t tmp; uint32_t ch = 1; int left = *maxread; @@ -112,7 +109,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, switch (encoding) { case ID3v2_ENCODING_ISO8859: - while (left && (!seeknull || ch)) { + while (left && ch) { ch = avio_r8(pb); PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);) left--; @@ -122,7 +119,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, case ID3v2_ENCODING_UTF16BOM: if ((left -= 2) < 0) { av_log(s, AV_LOG_ERROR, "Cannot read BOM value, input too short\n"); - avio_close_dyn_buf(dynbuf, (uint8_t **)dst); + avio_close_dyn_buf(dynbuf, dst); av_freep(dst); return AVERROR_INVALIDDATA; } @@ -133,7 +130,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, break; default: av_log(s, AV_LOG_ERROR, "Incorrect BOM value\n"); - avio_close_dyn_buf(dynbuf, (uint8_t **)dst); + avio_close_dyn_buf(dynbuf, dst); av_freep(dst); *maxread = left; return AVERROR_INVALIDDATA; @@ -141,7 +138,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, // fall-through case ID3v2_ENCODING_UTF16BE: - while ((left > 1) && (!seeknull || ch)) { + while ((left > 1) && ch) { GET_UTF16(ch, ((left -= 2) >= 0 ? get(pb) : 0), break;) PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);) } @@ -150,7 +147,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, break; case ID3v2_ENCODING_UTF8: - while (left && (!seeknull || ch)) { + while (left && ch) { ch = avio_r8(pb); avio_w8(dynbuf, ch); left--; @@ -163,10 +160,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, if (ch) avio_w8(dynbuf, 0); - len = avio_close_dyn_buf(dynbuf, (uint8_t **)dst); - if (dstlen) - *dstlen = len; - + avio_close_dyn_buf(dynbuf, dst); *maxread = left; return 0; @@ -178,38 +172,40 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key) { uint8_t *dst; - const char *val = NULL; - int len, dstlen; + int encoding, dict_flags = AV_DICT_DONT_OVERWRITE; unsigned genre; if (taglen < 1) return; + encoding = avio_r8(pb); taglen--; /* account for encoding type byte */ - if (decode_str(s, pb, avio_r8(pb), &dst, &dstlen, &taglen, 0) < 0) { + if (decode_str(s, pb, encoding, &dst, &taglen) < 0) { av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key); return; } if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1) - && genre <= ID3v1_GENRE_MAX) - val = ff_id3v1_genre_str[genre]; - else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) { - /* dst now contains two 0-terminated strings */ - dst[dstlen] = 0; - len = strlen(dst); + && genre <= ID3v1_GENRE_MAX) { + av_freep(&dst); + dst = ff_id3v1_genre_str[genre]; + } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) { + /* dst now contains the key, need to get value */ key = dst; - val = dst + FFMIN(len + 1, dstlen); + if (decode_str(s, pb, encoding, &dst, &taglen) < 0) { + av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key); + av_freep(&key); + return; + } + dict_flags |= AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_STRDUP_KEY; } else if (*dst) - val = dst; + dict_flags |= AV_DICT_DONT_STRDUP_VAL; - if (val) - av_dict_set(&s->metadata, key, val, AV_DICT_DONT_OVERWRITE); - - av_free(dst); + if (dst) + av_dict_set(&s->metadata, key, dst, dict_flags); } /** @@ -242,17 +238,17 @@ static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, char * taglen--; /* read MIME type (always ISO-8859) */ - if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type, NULL, &taglen, 1) < 0 + if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type, &taglen) < 0 || taglen <= 0) goto fail; /* read file name */ - if (decode_str(s, pb, encoding, &geob_data->file_name, NULL, &taglen, 1) < 0 + if (decode_str(s, pb, encoding, &geob_data->file_name, &taglen) < 0 || taglen <= 0) goto fail; /* read content description */ - if (decode_str(s, pb, encoding, &geob_data->description, NULL, &taglen, 1) < 0 + if (decode_str(s, pb, encoding, &geob_data->description, &taglen) < 0 || taglen < 0) goto fail; @@ -410,7 +406,7 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t tag[3] = 0; tlen = avio_rb24(s->pb); } - if (tlen > (1<<28) || !tlen) + if (tlen > (1<<28)) break; len -= taghdrlen + tlen; @@ -419,6 +415,12 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t next = avio_tell(s->pb) + tlen; + if (!tlen) { + if (tag[0]) + av_log(s, AV_LOG_DEBUG, "Invalid empty frame %s, skipping.\n", tag); + continue; + } + if (tflags & ID3v2_FLAG_DATALEN) { if (tlen < 4) break; |