This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 98c766ec19 avcodec/hevc_mp4toannexb: handle packet-side hvcC extradata
98c766ec19 is described below
commit 98c766ec190b10c2f4ec36dfc7eeb0bc9450a10b
Author: jiangjie <[email protected]>
AuthorDate: Wed Jun 17 11:35:19 2026 +0800
Commit: James Almer <[email protected]>
CommitDate: Mon Jun 29 14:06:29 2026 +0000
avcodec/hevc_mp4toannexb: handle packet-side hvcC extradata
Do not overwrite the output codecpar extradata after init(). Keep the
currently active HEVC parameter sets in HEVCBSFContext instead.
When AV_PKT_DATA_NEW_EXTRADATA on an input packet carries hvcC extradata,
convert it to Annex B, update the runtime extradata state, and remove the
packet side data.
Also add a FATE test covering extradata reloads with
hevc_mp4toannexb,hevc_metadata.
---
libavcodec/bsf/hevc_mp4toannexb.c | 70 ++++++++++++++++++-----
tests/fate/hevc.mak | 3 +
tests/ref/fate/hevc-bsf-mp4toannexb-new-extradata | 9 +++
3 files changed, 69 insertions(+), 13 deletions(-)
diff --git a/libavcodec/bsf/hevc_mp4toannexb.c
b/libavcodec/bsf/hevc_mp4toannexb.c
index 120cc14c13..79633499b4 100644
--- a/libavcodec/bsf/hevc_mp4toannexb.c
+++ b/libavcodec/bsf/hevc_mp4toannexb.c
@@ -34,12 +34,17 @@
#define MIN_HEVCC_LENGTH 23
typedef struct HEVCBSFContext {
+ uint8_t *extradata;
+ size_t extradata_size;
uint8_t length_size;
int extradata_parsed;
} HEVCBSFContext;
-static int hevc_extradata_to_annexb(AVBSFContext *ctx)
+static int hevc_extradata_to_annexb(AVBSFContext *ctx,
+ const uint8_t *extradata, int
extradata_size,
+ uint8_t **out_extradata, int
*out_extradata_size)
{
+ HEVCBSFContext *s = ctx->priv_data;
GetByteContext gb;
int length_size, num_arrays, i, j;
int ret = 0;
@@ -47,7 +52,7 @@ static int hevc_extradata_to_annexb(AVBSFContext *ctx)
uint8_t *new_extradata = NULL;
size_t new_extradata_size = 0;
- bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size);
+ bytestream2_init(&gb, extradata, extradata_size);
bytestream2_skip(&gb, 21);
length_size = (bytestream2_get_byte(&gb) & 3) + 1;
@@ -85,14 +90,30 @@ static int hevc_extradata_to_annexb(AVBSFContext *ctx)
}
}
- av_freep(&ctx->par_out->extradata);
- ctx->par_out->extradata = new_extradata;
- ctx->par_out->extradata_size = new_extradata_size;
-
if (!new_extradata_size)
av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
- return length_size;
+ if (out_extradata && out_extradata_size) {
+ av_freep(out_extradata);
+ *out_extradata =
+ av_malloc(new_extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!(*out_extradata)) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ *out_extradata_size = new_extradata_size;
+ memcpy(*out_extradata, new_extradata, new_extradata_size);
+ memset(*out_extradata + new_extradata_size, 0,
+ AV_INPUT_BUFFER_PADDING_SIZE);
+ }
+
+ av_freep(&s->extradata);
+ s->extradata = new_extradata;
+ s->extradata_size = new_extradata_size;
+
+ s->length_size = length_size;
+ s->extradata_parsed = 1;
+ return 0;
fail:
av_freep(&new_extradata);
return ret;
@@ -100,7 +121,6 @@ fail:
static int hevc_mp4toannexb_init(AVBSFContext *ctx)
{
- HEVCBSFContext *s = ctx->priv_data;
int ret;
if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
@@ -109,11 +129,13 @@ static int hevc_mp4toannexb_init(AVBSFContext *ctx)
av_log(ctx, AV_LOG_VERBOSE,
"The input looks like it is Annex B already\n");
} else {
- ret = hevc_extradata_to_annexb(ctx);
+ ret = hevc_extradata_to_annexb(ctx,
+ ctx->par_in->extradata,
+ ctx->par_in->extradata_size,
+ &ctx->par_out->extradata,
+ &ctx->par_out->extradata_size);
if (ret < 0)
return ret;
- s->length_size = ret;
- s->extradata_parsed = 1;
}
return 0;
@@ -128,11 +150,26 @@ static int hevc_mp4toannexb_filter(AVBSFContext *ctx,
AVPacket *out)
int got_irap = 0;
int got_ps = 0, seen_irap_ps = 0;
int i, ret = 0;
+ size_t extradata_size = 0;
+ uint8_t *extradata = NULL;
ret = ff_bsf_get_packet(ctx, &in);
if (ret < 0)
return ret;
+ extradata =
+ av_packet_get_side_data(in, AV_PKT_DATA_NEW_EXTRADATA,
&extradata_size);
+ if (extradata && extradata_size >= MIN_HEVCC_LENGTH &&
+ ((extradata[0] == 1) ||
+ (extradata[0] == 0 && (extradata[1] || extradata[2] > 1)))) {
+ ret = hevc_extradata_to_annexb(ctx, extradata, extradata_size,
+ NULL, NULL);
+ if (ret < 0)
+ goto fail;
+ av_packet_side_data_remove(in->side_data, &in->side_data_elems,
+ AV_PKT_DATA_NEW_EXTRADATA);
+ }
+
if (!s->extradata_parsed) {
av_packet_move_ref(out, in);
av_packet_free(&in);
@@ -192,7 +229,7 @@ static int hevc_mp4toannexb_filter(AVBSFContext *ctx,
AVPacket *out)
nalu_type <= HEVC_NAL_RSV_IRAP_VCL23;
is_ps = nalu_type >= HEVC_NAL_VPS && nalu_type <= HEVC_NAL_PPS &&
seen_irap_ps;
add_extradata = (is_ps || is_irap) && !got_ps && !got_irap;
- extra_size = add_extradata * ctx->par_out->extradata_size;
+ extra_size = add_extradata * s->extradata_size;
got_irap |= is_irap;
got_ps |= is_ps;
@@ -208,7 +245,7 @@ static int hevc_mp4toannexb_filter(AVBSFContext *ctx,
AVPacket *out)
goto fail;
if (extra_size)
- memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size);
+ memcpy(out->data + prev_size, s->extradata, extra_size);
AV_WB32(out->data + prev_size + extra_size, 1);
bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size,
nalu_size);
}
@@ -225,6 +262,12 @@ fail:
return ret;
}
+static void hevc_mp4toannexb_close(AVBSFContext *ctx)
+{
+ HEVCBSFContext *s = ctx->priv_data;
+ av_freep(&s->extradata);
+}
+
static const enum AVCodecID codec_ids[] = {
AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE,
};
@@ -235,4 +278,5 @@ const FFBitStreamFilter ff_hevc_mp4toannexb_bsf = {
.priv_data_size = sizeof(HEVCBSFContext),
.init = hevc_mp4toannexb_init,
.filter = hevc_mp4toannexb_filter,
+ .close = hevc_mp4toannexb_close,
};
diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak
index 7ce9ff403b..413ee5c049 100644
--- a/tests/fate/hevc.mak
+++ b/tests/fate/hevc.mak
@@ -235,6 +235,9 @@ fate-hevc-bsf-mp4toannexb: CMD = md5 -i
$(TARGET_PATH)/tests/data/hevc-mp4.mov -
fate-hevc-bsf-mp4toannexb: CMP = oneline
fate-hevc-bsf-mp4toannexb: REF = 73019329ed7f81c24f9af67c34c640c0
+FATE_HEVC-$(call DEMMUX, HEVC MOV, MOV HEVC, HEVC_PARSER HEVC_MP4TOANNEXB_BSF
EXTRACT_EXTRADATA_BSF HEVC_METADATA_BSF) +=
fate-hevc-bsf-mp4toannexb-new-extradata
+fate-hevc-bsf-mp4toannexb-new-extradata: CMD = stream_remux mov
$(TARGET_SAMPLES)/hevc/extradata-reload-multi-stsd.mov "" hevc "-bsf:v
hevc_mp4toannexb,hevc_metadata -map 0:v"
+
# Start with IDR, POC < 0 after the second IDR
FATE_HEVC-$(call FRAMECRC, MOV HEVC,, HEVC_PARSER MOV_MUXER DTS2PTS_BSF) +=
fate-hevc-bsf-dts2pts-idr
fate-hevc-bsf-dts2pts-idr: CMD = transcode "hevc"
$(TARGET_SAMPLES)/hevc-conformance/SLIST_B_Sony_8.bit mov "-c:v copy -bsf:v
dts2pts" "-c:v copy"
diff --git a/tests/ref/fate/hevc-bsf-mp4toannexb-new-extradata
b/tests/ref/fate/hevc-bsf-mp4toannexb-new-extradata
new file mode 100644
index 0000000000..9644359d98
--- /dev/null
+++ b/tests/ref/fate/hevc-bsf-mp4toannexb-new-extradata
@@ -0,0 +1,9 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 1/1
+0, 0, 0, 1, 24576, 0x76a8158f
+0, 1, 1, 1, 24576, 0x804e162a
+0, 2, 2, 1, 24576, 0xc1d05bea
+0, 3, 3, 1, 24576, 0xd84f5c77
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]