mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-01-13 02:41:37 +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 use_absolute_path;
|
||||||
int ignore_editlist;
|
int ignore_editlist;
|
||||||
int64_t next_root_atom; ///< offset of the next root atom
|
int64_t next_root_atom; ///< offset of the next root atom
|
||||||
|
int *bitrates; ///< bitrates read before streams creation
|
||||||
|
int bitrates_count;
|
||||||
} MOVContext;
|
} MOVContext;
|
||||||
|
|
||||||
int ff_mp4_read_descr_len(AVIOContext *pb);
|
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;
|
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[] = {
|
static const MOVParseTableEntry mov_default_parse_table[] = {
|
||||||
{ MKTAG('A','C','L','R'), mov_read_avid },
|
{ MKTAG('A','C','L','R'), mov_read_avid },
|
||||||
{ MKTAG('A','P','R','G'), 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('c','h','a','n'), mov_read_chan }, /* channel layout */
|
||||||
{ MKTAG('d','v','c','1'), mov_read_dvc1 },
|
{ MKTAG('d','v','c','1'), mov_read_dvc1 },
|
||||||
{ MKTAG('s','b','g','p'), mov_read_sbgp },
|
{ MKTAG('s','b','g','p'), mov_read_sbgp },
|
||||||
|
{ MKTAG('u','u','i','d'), mov_read_uuid },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3110,6 +3177,7 @@ static int mov_read_close(AVFormatContext *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
av_freep(&mov->trex_data);
|
av_freep(&mov->trex_data);
|
||||||
|
av_freep(&mov->bitrates);
|
||||||
|
|
||||||
return 0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user