[FFmpeg-devel] [PATCH v3 1/7] avformat/matroskadec: support parsing more than one BlockMore element
James Almer
jamrial at gmail.com
Thu Mar 30 05:04:42 EEST 2023
Signed-off-by: James Almer <jamrial at gmail.com>
---
Changes since v2: Cast 8 to size_t and fixed a return value.
libavformat/matroskadec.c | 62 ++++++++++++++++++++++++++-------------
1 file changed, 41 insertions(+), 21 deletions(-)
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 3a888e3ada..b7f9870f3d 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -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);
}
--
2.40.0
More information about the ffmpeg-devel
mailing list