diff options
author | Alexandre Sicard <alexandre.sicard@smartjog.com> | 2013-07-08 11:56:40 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-07-08 17:36:45 +0200 |
commit | 70b922f371e27440a51ee1e9cc1c7db0e042ebd1 (patch) | |
tree | fb7aef979a1f2c6a406e612e25176817ae943a25 | |
parent | e096283ea55bc36a637b47329e19ddb26fb1440b (diff) | |
download | ffmpeg-70b922f371e27440a51ee1e9cc1c7db0e042ebd1.tar.gz |
avformat/mov: read stream bitrates from isml manifest
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@smartjog.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/isom.h | 2 | ||||
-rw-r--r-- | libavformat/mov.c | 74 |
2 files changed, 76 insertions, 0 deletions
diff --git a/libavformat/isom.h b/libavformat/isom.h index 220b2df4e1..b0fa453de6 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 9833d7badd..99c396e296 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2731,6 +2731,72 @@ 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]; + static 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; + } else if (ret != sizeof(uuid)) { + return AVERROR_INVALIDDATA; + } + if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) { + uint8_t *buffer, *ptr; + char *endptr; + size_t len = atom.size - sizeof(uuid); + + if (len < 4) { + return AVERROR_INVALIDDATA; + } + ret = avio_skip(pb, 4); // zeroes + len -= 4; + + buffer = av_mallocz(len + 1); + if (!buffer) { + return AVERROR(ENOMEM); + } + ret = avio_read(pb, buffer, len); + if (ret < 0) { + av_free(buffer); + return ret; + } else if (ret != len) { + av_free(buffer); + return AVERROR_INVALIDDATA; + } + + ptr = buffer; + while ((ptr = av_stristr(ptr, "systemBitrate=\"")) != NULL) { + ptr += sizeof("systemBitrate=\"") - 1; + c->bitrates_count++; + c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates)); + if (!c->bitrates) { + c->bitrates_count = 0; + av_free(buffer); + return AVERROR(ENOMEM); + } + errno = 0; + ret = strtol(ptr, &endptr, 10); + if (ret < 0 || errno || *endptr != '"') { + c->bitrates[c->bitrates_count - 1] = 0; + } else { + c->bitrates[c->bitrates_count - 1] = ret; + } + } + + 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 }, @@ -2794,6 +2860,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 } }; @@ -3110,6 +3177,7 @@ static int mov_read_close(AVFormatContext *s) } av_freep(&mov->trex_data); + av_freep(&mov->bitrates); return 0; } @@ -3222,6 +3290,12 @@ static int mov_read_header(AVFormatContext *s) } } + for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) { + if (mov->bitrates[i]) { + s->streams[i]->codec->bit_rate = mov->bitrates[i]; + } + } + return 0; } |