Commit ebfc9497f7 for ffmpeg
commit ebfc9497f7d6d71460feb70133fbf2439ee212b9
Author: Mark Thompson <sw@jkqxz.net>
Date: Mon May 4 12:30:08 2026 +0100
apv_metadata: Add delete_filler option
Deletes all filler bytes in the stream:
- Filler PBUs.
- Filler at end of frame PBUs.
- Dummy bytes trailing in tile data.
- Filler at end of AU info PBUs.
- Filler at end of metadata PBUs.
- Filler metadata payloads.
diff --git a/libavcodec/bsf/apv_metadata.c b/libavcodec/bsf/apv_metadata.c
index 5342a593e6..d49552eee2 100644
--- a/libavcodec/bsf/apv_metadata.c
+++ b/libavcodec/bsf/apv_metadata.c
@@ -32,6 +32,8 @@ typedef struct APVMetadataContext {
int transfer_characteristics;
int matrix_coefficients;
int full_range_flag;
+
+ int delete_filler;
} APVMetadataContext;
@@ -62,6 +64,8 @@ static int apv_metadata_update_frame_header(AVBSFContext *bsf,
static int apv_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt,
CodedBitstreamFragment *frag)
{
+ APVMetadataContext *ctx = bsf->priv_data;
+ const CodedBitstreamAPVContext *priv = ctx->common.input->priv_data;
int err, i;
for (i = 0; i < frag->nb_units; i++) {
@@ -73,6 +77,72 @@ static int apv_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt,
}
}
+ if (ctx->delete_filler) {
+ // Types of filler to delete:
+ // - Filler PBUs.
+ // - Filler at end of frame PBUs.
+ // - Dummy bytes trailing in tile data.
+ // - Filler at end of AU info PBUs.
+ // - Filler at end of metadata PBUs.
+ // - Filler metadata payloads.
+
+ for (i = frag->nb_units - 1; i >= 0; i--) {
+ switch (frag->units[i].type) {
+ case APV_PBU_FILLER:
+ ff_cbs_delete_unit(frag, i);
+ break;
+ case APV_PBU_PRIMARY_FRAME:
+ case APV_PBU_NON_PRIMARY_FRAME:
+ case APV_PBU_PREVIEW_FRAME:
+ case APV_PBU_DEPTH_FRAME:
+ case APV_PBU_ALPHA_FRAME:
+ {
+ APVRawFrame *frame = frag->units[i].content;
+ frame->filler.filler_size = 0;
+ for (int t = 0; t < priv->num_tiles; t++)
+ frame->tile[t].tile_dummy_byte_size = 0;
+ // tile_size[t] may be wrong here, but are
+ // recalculated during CBS write.
+ }
+ break;
+ case APV_PBU_ACCESS_UNIT_INFORMATION:
+ {
+ APVRawAUInfo *au_info = frag->units[i].content;
+ au_info->filler.filler_size = 0;
+ }
+ break;
+ case APV_PBU_METADATA:
+ {
+ APVRawMetadata *md = frag->units[i].content;
+ int k = 0;
+ md->filler.filler_size = 0;
+ for (int j = 0; j < md->metadata_count; j++) {
+ APVRawMetadataPayload *pl = &md->payloads[j];
+ if (pl->payload_type == APV_METADATA_FILLER) {
+ // Drop this payload.
+ } else {
+ if (k < j)
+ md->payloads[k] = md->payloads[j];
+ ++k;
+ }
+ }
+ if (k == 0) {
+ // This metadata PBU contained only a filler
+ // payload, so now we have to delete the whole
+ // thing because a metadata PBU must contain at
+ // least one payload.
+ ff_cbs_delete_unit(frag, i);
+ } else {
+ md->metadata_count = k;
+ // metadata_size may be wrong here, but is
+ // recalculated during CBS write.
+ }
+ }
+ break;
+ }
+ }
+ }
+
return 0;
}
@@ -109,6 +179,9 @@ static const AVOption apv_metadata_options[] = {
{ "pc", "PC (full) range", 0, AV_OPT_TYPE_CONST,
{ .i64 = 1 }, .flags = FLAGS, .unit = "cr" },
+ { "delete_filler", "Delete all filler in the stream",
+ OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS },
+
{ NULL }
};