[FFmpeg-cvslog] id3v2: read TXXX frames with two calls to decode_str() instead of one.

Anton Khirnov git at videolan.org
Tue Oct 4 03:47:41 CEST 2011


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Sun Oct  2 09:06:34 2011 +0200| [d2961e4ebfbb78af0f066760eb0ffb8a8567e529] | committer: Anton Khirnov

id3v2: read TXXX frames with two calls to decode_str() instead of one.

Read the key in the first, value in the second.

This allows to avoid pointless strdups and simplify decode_str() by
dropping two of its parameters.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=d2961e4ebfbb78af0f066760eb0ffb8a8567e529
---

 libavformat/id3v2.c |   60 +++++++++++++++++++++++---------------------------
 1 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index a3d7ae6..48443e1 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -73,23 +73,20 @@ static void free_geobtag(ID3v2ExtraMetaGEOB *geob)
 
 /**
  * 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;
@@ -104,7 +101,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--;
@@ -133,7 +130,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);)
         }
@@ -142,7 +139,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--;
@@ -155,10 +152,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, (uint8_t **)dst);
     *maxread = left;
 
     return 0;
@@ -170,38 +164,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;
-
-    if (val)
-        av_dict_set(&s->metadata, key, val, AV_DICT_DONT_OVERWRITE);
+        dict_flags |= AV_DICT_DONT_STRDUP_VAL;
 
-    av_free(dst);
+    if (dst)
+        av_dict_set(&s->metadata, key, dst, dict_flags);
 }
 
 /**
@@ -234,17 +230,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;
 



More information about the ffmpeg-cvslog mailing list