[FFmpeg-devel] [PATCH] avformat/mov: read stream bitrates from isml manifest

Alexandre Sicard alexandre.sicard at smartjog.com
Wed Jun 19 18:44:48 CEST 2013


This allows to read a live isml movie and segment it using the smoothstreaming
muxer, which requires the bitrates to be known for each stream.

Signed-off-by: Alexandre Sicard <alexandre.sicard at smartjog.com>
---
 libavformat/isom.h |  2 ++
 libavformat/mov.c  | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 220b2df..b0fa453 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -162,6 +162,8 @@ typedef struct MOVContext {
     int use_absolute_path;
     int ignore_editlist;
     int64_t next_root_atom; ///< offset of the next root atom
+    int *bitrates;          ///< bitrates read before streams creation
+    int bitrates_count;
 } MOVContext;
 
 int ff_mp4_read_descr_len(AVIOContext *pb);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 5c61f6c..f27e4e5 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -24,6 +24,7 @@
  */
 
 #include <limits.h>
+#include <regex.h>
 
 //#define MOV_EXPORT_ALL_METADATA
 
@@ -2730,6 +2731,74 @@ static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     return 0;
 }
 
+static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    int ret;
+    uint8_t uuid[16];
+    const uint8_t uuid_isml_manifest[] = {
+        0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
+        0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
+    };
+
+    if (atom.size < sizeof(uuid) || atom.size == INT64_MAX)
+        return AVERROR_INVALIDDATA;
+
+    ret = avio_read(pb, uuid, sizeof(uuid));
+    if (ret < 0) {
+        return ret;
+    }
+    if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) {
+        uint8_t *buffer, *ptr;
+        regex_t preg;
+        regmatch_t *pmatch;
+
+        avio_skip(pb, 4); // zeroes
+
+        buffer = av_mallocz(atom.size - sizeof(uuid) - 4 + 1);
+        if (!buffer) {
+            return AVERROR(ENOMEM);
+        }
+        ret = avio_read(pb, buffer, atom.size - sizeof(uuid) - 4);
+        if (ret < 0) {
+            return ret;
+        }
+
+        pmatch = av_mallocz(sizeof(regmatch_t) * 3);
+        if (!pmatch) {
+            av_free(buffer);
+            return AVERROR(ENOMEM);
+        }
+        if (regcomp(&preg, "systemBitrate=\"([0-9]+)\"", REG_EXTENDED|REG_ICASE)) {
+            av_free(buffer);
+            av_free(pmatch);
+            return AVERROR_EXTERNAL;
+        }
+
+        ptr = buffer;
+        while (!regexec(&preg, ptr, 3, pmatch, 0)) {
+            c->bitrates_count++;
+            c->bitrates = av_realloc(c->bitrates, sizeof(int) * c->bitrates_count);
+            if (!c->bitrates) {
+                regfree(&preg);
+                av_free(buffer);
+                av_free(pmatch);
+                return AVERROR(ENOMEM);
+            }
+            errno = 0;
+            c->bitrates[c->bitrates_count - 1] = strtol(ptr + pmatch[1].rm_so, NULL, 10);
+            if (errno) {
+                c->bitrates[c->bitrates_count - 1] = 0;
+            }
+            ptr += pmatch[0].rm_eo;
+        }
+
+        regfree(&preg);
+        av_free(pmatch);
+        av_free(buffer);
+    }
+    return 0;
+}
+
 static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('A','C','L','R'), mov_read_avid },
 { MKTAG('A','P','R','G'), mov_read_avid },
@@ -2793,6 +2862,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */
 { MKTAG('d','v','c','1'), mov_read_dvc1 },
 { MKTAG('s','b','g','p'), mov_read_sbgp },
+{ MKTAG('u','u','i','d'), mov_read_uuid },
 { 0, NULL }
 };
 
@@ -3109,6 +3179,7 @@ static int mov_read_close(AVFormatContext *s)
     }
 
     av_freep(&mov->trex_data);
+    av_freep(&mov->bitrates);
 
     return 0;
 }
@@ -3221,6 +3292,14 @@ static int mov_read_header(AVFormatContext *s)
         }
     }
 
+    if (mov->bitrates_count) {
+        for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
+            if (mov->bitrates[i] > 0) {
+                s->streams[i]->codec->bit_rate = mov->bitrates[i];
+            }
+        }
+    }
+
     return 0;
 }
 
-- 
1.8.3



More information about the ffmpeg-devel mailing list