[FFmpeg-devel] [HACK] parse m4a metadata

Reimar Döffinger Reimar.Doeffinger
Wed Jun 11 20:45:28 CEST 2008


Hello,
with attached patch FFmpeg can read the metadata from
http://samples.mplayerhq.hu/A-codecs/lossless/luckynight.m4a
It is still quite ugly, and I do not want to spend any time on it, so
cleaning up is something that someone else must do.
There is also a problem that the existing metadata code probably has,
too: The strings might contain linebreaks, which are coded mac-style as
\r whereas IMO FFmpeg should use \n instead.

Greetings,
Reimar D?ffinger
-------------- next part --------------
Index: libavformat/mov.c
===================================================================
--- libavformat/mov.c	(revision 13651)
+++ libavformat/mov.c	(working copy)
@@ -1334,6 +1334,71 @@
     get_buffer(pb, str, FFMIN(size, str_size));
 }
 
+static void mov_parse_ilst_string(ByteIOContext *pb, char *str, int size)
+{
+    uint32_t tag_size = get_be32(pb);
+    uint32_t tag      = get_le32(pb);
+    url_fskip(pb, 8);
+    if (tag != MKTAG('d','a','t','a') || tag_size < 16) return;
+    tag_size -= 16;
+    get_buffer(pb, str, FFMIN(size, tag_size));
+}
+
+static void mov_read_ilst(MOVContext *c, ByteIOContext *pb, uint64_t end)
+{
+    while (url_ftell(pb) + 8 < end) {
+        uint32_t tag_size = get_be32(pb);
+        uint32_t tag      = get_le32(pb);
+        uint64_t next     = url_ftell(pb) + tag_size - 8;
+
+        if (next > end) // stop if tag_size is wrong
+            break;
+
+        switch (tag) {
+        case MKTAG(0xa9,'n','a','m'):
+            mov_parse_ilst_string(pb, c->fc->title,     sizeof(c->fc->title));
+            break;
+        case MKTAG(0xa9,'A','R','T'):
+            mov_parse_ilst_string(pb, c->fc->author,    sizeof(c->fc->author));
+            break;
+        case MKTAG(0xa9,'c','m','t'):
+            mov_parse_ilst_string(pb, c->fc->comment,   sizeof(c->fc->comment));
+            break;
+        case MKTAG(0xa9,'a','l','b'):
+            mov_parse_ilst_string(pb, c->fc->album,     sizeof(c->fc->album));
+            break;
+        case MKTAG('t','r','k','n'):
+            get_be32(pb); // length
+            get_be32(pb); // "data"
+            url_fskip(pb, 8);
+            c->fc->track = get_be32(pb);
+            break;
+        default:
+            break;
+        }
+
+        url_fseek(pb, next, SEEK_SET);
+    }
+}
+
+static void mov_read_meta(MOVContext *c, ByteIOContext *pb, uint64_t end)
+{
+    url_fskip(pb, 4);
+    while (url_ftell(pb) + 8 < end) {
+        uint32_t tag_size = get_be32(pb);
+        uint32_t tag      = get_le32(pb);
+        uint64_t next     = url_ftell(pb) + tag_size - 8;
+
+        if (next > end) // stop if tag_size is wrong
+            break;
+
+        if (tag == MKTAG('i','l','s','t'))
+            mov_read_ilst(c, pb, next);
+
+        url_fseek(pb, next, SEEK_SET);
+    }
+}
+
 static int mov_read_udta(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
 {
     uint64_t end = url_ftell(pb) + atom.size;
@@ -1359,6 +1424,9 @@
         case MKTAG(0xa9,'i','n','f'):
             mov_parse_udta_string(pb, c->fc->comment,   sizeof(c->fc->comment));
             break;
+        case MKTAG('m','e','t','a'):
+            mov_read_meta(c, pb, next);
+            break;
         default:
             break;
         }



More information about the ffmpeg-devel mailing list