[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