mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-26 01:02:33 +00:00
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>
This commit is contained in:
parent
e096283ea5
commit
70b922f371
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user