mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
avformat/matroskadec: support parsing more than one BlockMore element
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
parent
2244722f1f
commit
44513156e3
@ -349,13 +349,17 @@ typedef struct MatroskaLevel {
|
||||
uint64_t length;
|
||||
} MatroskaLevel;
|
||||
|
||||
typedef struct MatroskaBlockMore {
|
||||
uint64_t additional_id;
|
||||
EbmlBin additional;
|
||||
} MatroskaBlockMore;
|
||||
|
||||
typedef struct MatroskaBlock {
|
||||
uint64_t duration;
|
||||
CountedElement reference;
|
||||
uint64_t non_simple;
|
||||
EbmlBin bin;
|
||||
uint64_t additional_id;
|
||||
EbmlBin additional;
|
||||
EbmlList blockmore;
|
||||
int64_t discard_padding;
|
||||
} MatroskaBlock;
|
||||
|
||||
@ -759,13 +763,13 @@ static EbmlSyntax matroska_segments[] = {
|
||||
};
|
||||
|
||||
static EbmlSyntax matroska_blockmore[] = {
|
||||
{ MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlock,additional_id), { .u = 1 } },
|
||||
{ MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlock,additional) },
|
||||
{ MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlockMore,additional_id), { .u = 1 } },
|
||||
{ MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlockMore,additional) },
|
||||
CHILD_OF(matroska_blockadditions)
|
||||
};
|
||||
|
||||
static EbmlSyntax matroska_blockadditions[] = {
|
||||
{ MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, 0, {.n = matroska_blockmore} },
|
||||
{ MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, sizeof(MatroskaBlockMore), offsetof(MatroskaBlock, blockmore), { .n = matroska_blockmore } },
|
||||
CHILD_OF(matroska_blockgroup)
|
||||
};
|
||||
|
||||
@ -3610,12 +3614,28 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int matroska_parse_block_additional(MatroskaDemuxContext *matroska,
|
||||
AVPacket *pkt,
|
||||
const uint8_t *data, int size, uint64_t id)
|
||||
{
|
||||
uint8_t *side_data = av_packet_new_side_data(pkt,
|
||||
AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
|
||||
size + (size_t)8);
|
||||
if (!side_data)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
AV_WB64(side_data, id);
|
||||
memcpy(side_data + 8, data, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int matroska_parse_frame(MatroskaDemuxContext *matroska,
|
||||
MatroskaTrack *track, AVStream *st,
|
||||
AVBufferRef *buf, uint8_t *data, int pkt_size,
|
||||
uint64_t timecode, uint64_t lace_duration,
|
||||
int64_t pos, int is_keyframe,
|
||||
uint8_t *additional, uint64_t additional_id, int additional_size,
|
||||
MatroskaBlockMore *blockmore, int nb_blockmore,
|
||||
int64_t discard_padding)
|
||||
{
|
||||
uint8_t *pkt_data = data;
|
||||
@ -3647,7 +3667,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (!pkt_size && !additional_size)
|
||||
if (!pkt_size && !nb_blockmore)
|
||||
goto no_output;
|
||||
|
||||
if (!buf)
|
||||
@ -3666,16 +3686,18 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
|
||||
pkt->flags = is_keyframe;
|
||||
pkt->stream_index = st->index;
|
||||
|
||||
if (additional_size > 0) {
|
||||
uint8_t *side_data = av_packet_new_side_data(pkt,
|
||||
AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
|
||||
additional_size + 8);
|
||||
if (!side_data) {
|
||||
for (int i = 0; i < nb_blockmore; i++) {
|
||||
MatroskaBlockMore *more = &blockmore[i];
|
||||
|
||||
if (!more->additional.size)
|
||||
continue;
|
||||
|
||||
res = matroska_parse_block_additional(matroska, pkt, more->additional.data,
|
||||
more->additional.size, more->additional_id);
|
||||
if (res < 0) {
|
||||
av_packet_unref(pkt);
|
||||
return AVERROR(ENOMEM);
|
||||
return res;
|
||||
}
|
||||
AV_WB64(side_data, additional_id);
|
||||
memcpy(side_data + 8, additional, additional_size);
|
||||
}
|
||||
|
||||
if (discard_padding) {
|
||||
@ -3721,7 +3743,7 @@ fail:
|
||||
static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf, uint8_t *data,
|
||||
int size, int64_t pos, uint64_t cluster_time,
|
||||
uint64_t block_duration, int is_keyframe,
|
||||
uint8_t *additional, uint64_t additional_id, int additional_size,
|
||||
MatroskaBlockMore *blockmore, int nb_blockmore,
|
||||
int64_t cluster_pos, int64_t discard_padding)
|
||||
{
|
||||
uint64_t timecode = AV_NOPTS_VALUE;
|
||||
@ -3856,7 +3878,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf
|
||||
res = matroska_parse_frame(matroska, track, st, buf, out_data,
|
||||
out_size, timecode, lace_duration,
|
||||
pos, !n ? is_keyframe : 0,
|
||||
additional, additional_id, additional_size,
|
||||
blockmore, nb_blockmore,
|
||||
discard_padding);
|
||||
if (res)
|
||||
return res;
|
||||
@ -3897,14 +3919,12 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
|
||||
|
||||
if (res >= 0 && block->bin.size > 0) {
|
||||
int is_keyframe = block->non_simple ? block->reference.count == 0 : -1;
|
||||
uint8_t* additional = block->additional.size > 0 ?
|
||||
block->additional.data : NULL;
|
||||
|
||||
res = matroska_parse_block(matroska, block->bin.buf, block->bin.data,
|
||||
block->bin.size, block->bin.pos,
|
||||
cluster->timecode, block->duration,
|
||||
is_keyframe, additional, block->additional_id,
|
||||
block->additional.size, cluster->pos,
|
||||
is_keyframe, block->blockmore.elem,
|
||||
block->blockmore.nb_elem, cluster->pos,
|
||||
block->discard_padding);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user