PR #24032 opened by Steven Xiao (younengxiao)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24032
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24032.patch
This commit adds AV1 B-frame support.
- Enable B-frame scheduling for the D3D12VA AV1 encoder by setting the
ref_l0/ref_l1 capability.
- Stash hidden (non-independent) anchor frames coded data and prepend it to
the next visible frame packet (show_existing_frame handling).
- Add FF_HW_FLAG_TIMESTAMP_NO_DELAY to avoiding non-monotonic DTS warnings
at higher B-frame reorder depths.
- Set 2 B-frames as default(align with D3D12VA H.264 and HEVC encoder)
Example usage:
- default (2 B-frames will be applied):
ffmpeg -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4
-c:v av1_d3d12va output.mp4
- 3 B-frames:
ffmpeg -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4
-c:v av1_d3d12va -bf 3 output.mp4
From 2730cf27f0338ede0149f465160c653940ea7f85 Mon Sep 17 00:00:00 2001
From: younengxiao <[email protected]>
Date: Thu, 16 Jul 2026 15:13:31 -0400
Subject: [PATCH] avcodec/d3d12va_encode_av1: add AV1 B-frame (compound
prediction) support
This commit adds AV1 B-frame support.
- Enable B-frame scheduling for the D3D12VA AV1 encoder by setting the
ref_l0/ref_l1 capability.
- Stash hidden (non-independent) anchor frames coded data and prepend
it to the next visible frame packet (show_existing_frame handling).
- Add FF_HW_FLAG_TIMESTAMP_NO_DELAY to avoiding non-monotonic DTS warnings
at higher B-frame reorder depths.
- Set 2 B-frames as default(align with D3D12VA H.264 and HEVC encoder)
Example usage:
- default (2 B-frames will be applied):
ffmpeg -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v
av1_d3d12va output.mp4
- 3 B-frames:
ffmpeg -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v
av1_d3d12va -bf 3 output.mp4
Signed-off-by: younengxiao <[email protected]>
---
libavcodec/d3d12va_encode.c | 30 ++++-
libavcodec/d3d12va_encode.h | 5 +
libavcodec/d3d12va_encode_av1.c | 194 ++++++++++++++++++++++++++------
libavcodec/hw_base_encode.h | 3 +
4 files changed, 192 insertions(+), 40 deletions(-)
diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c
index 442dbc6a4a..4151c554ee 100644
--- a/libavcodec/d3d12va_encode.c
+++ b/libavcodec/d3d12va_encode.c
@@ -911,13 +911,31 @@ static int d3d12va_encode_output(AVCodecContext *avctx,
if (err < 0)
return err;
+ if (pic->non_independent_frame) {
+ if (pic->tail_size) {
+ if (base_ctx->tail_pkt->size) {
+ err = AVERROR_BUG;
+ goto end;
+ }
+ err = ff_get_encode_buffer(avctx, base_ctx->tail_pkt,
pic->tail_size, 0);
+ if (err < 0)
+ goto end;
+ memcpy(base_ctx->tail_pkt->data, pic->tail_data, pic->tail_size);
+ pkt_ptr = base_ctx->tail_pkt;
+ }
+ }
+
av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
base_pic->display_order, base_pic->encode_order);
+ /* FF_HW_FLAG_TIMESTAMP_NO_DELAY: DTS = PTS for codecs whose output is
+ * already in display order (e.g. AV1 with show_existing_frame). */
ff_hw_base_encode_set_output_property(base_ctx, avctx,
(FFHWBaseEncodePicture *)base_pic,
- pkt_ptr, 0);
+ pkt_ptr,
+ ctx->codec->flags &
FF_HW_FLAG_TIMESTAMP_NO_DELAY);
- return 0;
+end:
+ return err;
}
static int d3d12va_encode_set_profile(AVCodecContext *avctx)
@@ -1350,8 +1368,12 @@ static int
d3d12va_encode_init_gop_structure(AVCodecContext *avctx)
#if CONFIG_AV1_D3D12VA_ENCODER
case D3D12_VIDEO_ENCODER_CODEC_AV1:
ref_l0 =
support.PictureSupport.pAV1Support->MaxUniqueReferencesPerFrame;
- // AV1 doesn't use traditional L1 references like H.264/HEVC
- ref_l1 = 0;
+ if (support.PictureSupport.pAV1Support->PredictionMode ==
+
D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_COMPOUND_REFERENCE ||
+ ref_l0 >= 2)
+ ref_l1 = 1;
+ else
+ ref_l1 = 0;
break;
#endif
default:
diff --git a/libavcodec/d3d12va_encode.h b/libavcodec/d3d12va_encode.h
index f2e97da7d2..bfc5dd5578 100644
--- a/libavcodec/d3d12va_encode.h
+++ b/libavcodec/d3d12va_encode.h
@@ -61,6 +61,11 @@ typedef struct D3D12VAEncodePicture {
// ROI delta QP map (void* to support both INT8 for H.264/HEVC and INT16
for AV1)
void *qp_map;
int qp_map_size;
+
+ // Hidden-frame (AV1 show_existing_frame) support
+ int non_independent_frame;
+ char tail_data[MAX_PARAM_BUFFER_SIZE];
+ size_t tail_size;
} D3D12VAEncodePicture;
typedef struct D3D12VAEncodeProfile {
diff --git a/libavcodec/d3d12va_encode_av1.c b/libavcodec/d3d12va_encode_av1.c
index 89b727ca33..6165eceafd 100644
--- a/libavcodec/d3d12va_encode_av1.c
+++ b/libavcodec/d3d12va_encode_av1.c
@@ -104,6 +104,7 @@ typedef struct D3D12VAEncodeAV1Context {
uint8_t q_idx_idr;
uint8_t q_idx_p;
+ uint8_t q_idx_b;
// Writer structures.
D3D12VAHWBaseEncodeAV1 units;
@@ -123,6 +124,10 @@ typedef struct D3D12VAEncodeAV1Context {
uint16_t context_update_tile_id;
uint8_t width_in_sbs_minus_1[AV1_MAX_TILE_COLS];
uint8_t height_in_sbs_minus_1[AV1_MAX_TILE_ROWS];
+
+ // Stash for hidden (non-independent) anchor frame coded bytes
+ uint8_t *stash_data;
+ size_t stash_size;
} D3D12VAEncodeAV1Context;
typedef struct D3D12VAEncodeAV1Level {
@@ -325,17 +330,29 @@ static int
d3d12va_encode_av1_write_picture_header(AVCodecContext *avctx,
char *data, size_t
*data_len)
{
D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+ D3D12VAEncodeContext *ctx = avctx->priv_data;
+ CodedBitstreamAV1Context *cbctx = priv->cbc->priv_data;
CodedBitstreamFragment *obu = &priv->current_obu;
AV1RawOBU *frameheader_obu = av_mallocz(sizeof(AV1RawOBU));
+ int show_slot = 0;
int err = 0;
+ if (!frameheader_obu)
+ return AVERROR(ENOMEM);
+
av_fifo_read(priv->picture_header_list, frameheader_obu, 1);
err = d3d12va_encode_av1_update_current_frame_picture_header(avctx,
pic,frameheader_obu);
if (err < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed to update current frame picture
header: %d.\n", err);
+ av_freep(&frameheader_obu);
return err;
}
+ // The DPB slot this frame refreshes (single bit for anchor P frames)
+ if (frameheader_obu->obu.frame_header.refresh_frame_flags) {
+ show_slot =
ff_ctz(frameheader_obu->obu.frame_header.refresh_frame_flags);
+ }
+
// Add the frame header OBU
frameheader_obu->header.obu_has_size_field = 1;
@@ -343,6 +360,38 @@ static int
d3d12va_encode_av1_write_picture_header(AVCodecContext *avctx,
if (err < 0)
goto fail;
err = d3d12va_encode_av1_write_obu(avctx, data, data_len, obu);
+ if (err < 0)
+ goto fail;
+
+ // For hidden anchor frames, build the show_existing_frame tail OBU now
+ pic->tail_size = 0;
+ if (pic->non_independent_frame) {
+ AV1RawOBU rep_obu = { 0 };
+ AV1RawFrameHeader *rep_fh = &rep_obu.obu.frame_header;
+ size_t tail_bit_len = 0;
+
+ ff_cbs_fragment_reset(obu);
+
+ rep_obu.header.obu_type = AV1_OBU_FRAME_HEADER;
+ rep_obu.header.obu_has_size_field = 1;
+ rep_fh->show_existing_frame = 1;
+ rep_fh->frame_to_show_map_idx = show_slot;
+ rep_fh->frame_type = AV1_FRAME_INTER;
+ rep_fh->frame_width_minus_1 = ctx->resolution.Width - 1;
+ rep_fh->frame_height_minus_1 = ctx->resolution.Height - 1;
+ rep_fh->render_width_minus_1 = rep_fh->frame_width_minus_1;
+ rep_fh->render_height_minus_1 = rep_fh->frame_height_minus_1;
+
+ cbctx->seen_frame_header = 0;
+
+ err = d3d12va_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER,
&rep_obu);
+ if (err < 0)
+ goto fail;
+ err = d3d12va_encode_av1_write_obu(avctx, pic->tail_data,
&tail_bit_len, obu);
+ if (err < 0)
+ goto fail;
+ pic->tail_size = tail_bit_len / 8;
+ }
fail:
ff_cbs_fragment_reset(obu);
@@ -460,6 +509,7 @@ static int d3d12va_encode_av1_get_coded_data(AVCodecContext
*avctx,
size_t obu_size = 0;
size_t tile_payload_size = 0;
size_t total_size = 0;
+ size_t prev_stash_sz = 0;
uint64_t nb_subregions = 0;
int output_buffer_mapped = 0;
@@ -525,10 +575,34 @@ static int
d3d12va_encode_av1_get_coded_data(AVCodecContext *avctx,
obu_size = bit_len / 8;
total_size = pic->header_size + av1_pic_hd_size + obu_size;
- err = ff_get_encode_buffer(avctx, pkt, total_size, 0);
- if (err < 0)
- goto end;
- ptr = pkt->data;
+
+ /*
+ * Hidden anchor frame: stash its coded bytes so they will be prepended
+ * to the next visible frame's packet. Visible frame: allocate a packet
+ * large enough for any stashed hidden frame bytes followed by this
+ * frame's coded data.
+ */
+ if (pic->non_independent_frame) {
+ uint8_t *new_stash = av_realloc(priv->stash_data,
+ priv->stash_size + total_size);
+ if (!new_stash) {
+ err = AVERROR(ENOMEM);
+ goto end;
+ }
+ priv->stash_data = new_stash;
+ ptr = priv->stash_data + priv->stash_size;
+ } else {
+ prev_stash_sz = priv->stash_size;
+ err = ff_get_encode_buffer(avctx, pkt, prev_stash_sz + total_size, 0);
+ if (err < 0)
+ goto end;
+ if (prev_stash_sz) {
+ memcpy(pkt->data, priv->stash_data, prev_stash_sz);
+ av_freep(&priv->stash_data);
+ priv->stash_size = 0;
+ }
+ ptr = pkt->data + prev_stash_sz;
+ }
memcpy(ptr, mapped_data, pic->header_size);
ptr += pic->header_size;
@@ -538,6 +612,9 @@ static int d3d12va_encode_av1_get_coded_data(AVCodecContext
*avctx,
memcpy(ptr, obu_buf, obu_size);
+ if (pic->non_independent_frame)
+ priv->stash_size += total_size;
+
av_log(avctx, AV_LOG_DEBUG, "AV1 packet: %"PRIu64" tiles, header %d, "
"pic header %zu, tile group %zu, total %zu bytes.\n",
nb_subregions, pic->header_size, av1_pic_hd_size, obu_size,
total_size);
@@ -734,8 +811,8 @@ static int
d3d12va_encode_av1_init_sequence_params(AVCodecContext *avctx)
seq->max_frame_width_minus_1 = ctx->resolution.Width - 1;
seq->max_frame_height_minus_1 = ctx->resolution.Height - 1;
- seq->frame_width_bits_minus_1 = av_log2(ctx->resolution.Width);
- seq->frame_height_bits_minus_1 = av_log2(ctx->resolution.Height);
+ seq->frame_width_bits_minus_1 = av_log2(ctx->resolution.Width - 1);
+ seq->frame_height_bits_minus_1 = av_log2(ctx->resolution.Height - 1);
seqheader_obu->header.obu_type = AV1_OBU_SEQUENCE_HEADER;
@@ -1037,6 +1114,7 @@ static int d3d12va_encode_av1_configure(AVCodecContext
*avctx)
if (ctx->rc.Mode == D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP) {
D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP *cqp_ctl;
+ int fixed_qp_b;
fixed_qp_inter = av_clip_uintp2(ctx->rc_quality, 8);
if (avctx->i_quant_factor > 0.0)
@@ -1045,9 +1123,15 @@ static int d3d12va_encode_av1_configure(AVCodecContext
*avctx)
else
fixed_qp_key = fixed_qp_inter;
+ if (avctx->b_quant_factor > 0.0)
+ fixed_qp_b = av_clip_uintp2((avctx->b_quant_factor *
fixed_qp_inter +
+ avctx->b_quant_offset) + 0.5, 8);
+ else
+ fixed_qp_b = fixed_qp_inter;
+
av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
- "%d / %d for Key / Inter frames.\n",
- fixed_qp_key, fixed_qp_inter);
+ "%d / %d / %d for Key / Inter / B frames.\n",
+ fixed_qp_key, fixed_qp_inter, fixed_qp_b);
ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP);
cqp_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
@@ -1056,12 +1140,13 @@ static int d3d12va_encode_av1_configure(AVCodecContext
*avctx)
cqp_ctl->ConstantQP_FullIntracodedFrame =
fixed_qp_key;
cqp_ctl->ConstantQP_InterPredictedFrame_PrevRefOnly =
fixed_qp_inter;
- cqp_ctl->ConstantQP_InterPredictedFrame_BiDirectionalRef =
fixed_qp_inter;
+ cqp_ctl->ConstantQP_InterPredictedFrame_BiDirectionalRef = fixed_qp_b;
ctx->rc.ConfigParams.pConfiguration_CQP = cqp_ctl;
priv->q_idx_idr = fixed_qp_key;
priv->q_idx_p = fixed_qp_inter;
+ priv->q_idx_b = fixed_qp_b;
}
@@ -1148,8 +1233,8 @@ static int
d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx,
AV1RawFrameHeader *fh =
&frameheader_obu->obu.frame_header;
FFHWBaseEncodePicture *ref;
- D3D12VAEncodeAV1Picture *href;
- int i;
+ D3D12VAEncodeAV1Picture *href, *href_l0, *href_l1;
+ int i, phys;
static const int8_t
default_loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME] =
{ 1, 0, 0, 0, -1, 0, -1, -1 };
@@ -1163,6 +1248,11 @@ static int
d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx,
if (!d3d12va_pic->pic_ctl.pAV1PicData)
return AVERROR(ENOMEM);
+ for (i = 0; i < AV1_NUM_REF_FRAMES; i++) {
+
d3d12va_pic->pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[i]
+ .ReconstructedPictureResourceIndex =
D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX;
+ }
+
// Initialize frame type and reference frame management
switch(pic->type) {
case FF_HW_PICTURE_TYPE_IDR:
@@ -1172,6 +1262,8 @@ static int
d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx,
hpic->slot = 0;
hpic->last_idr_frame = pic->display_order;
fh->tx_mode = AV1_TX_MODE_LARGEST;
+ d3d12va_pic->pic_ctl.pAV1PicData->CompoundPredictionType =
+ D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_SINGLE_REFERENCE;
break;
case FF_HW_PICTURE_TYPE_P:
@@ -1182,6 +1274,9 @@ static int
d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx,
ref = pic->refs[0][pic->nb_refs[0] - 1];
href = ref->codec_priv;
+ d3d12va_pic->pic_ctl.pAV1PicData->CompoundPredictionType =
+ D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_SINGLE_REFERENCE;
+
/**
* The encoder uses a simple alternating reference frame strategy:
* - For P-frames, it uses the last reconstructed frame as a
reference.
@@ -1212,18 +1307,58 @@ static int
d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx,
fh->ref_frame_idx[3] = href->slot;
fh->ref_order_hint[href->slot] = ref->display_order -
href->last_idr_frame;
} else if (base_ctx->ref_l0 == 1) {
+ // Keep the other slot's order hint consistent
+ href = pic->refs[0][0]->codec_priv;
fh->ref_order_hint[!href->slot] =
cbctx->ref[!href->slot].order_hint;
}
break;
case FF_HW_PICTURE_TYPE_B:
- av_log(avctx, AV_LOG_ERROR, "D3D12 AV1 video encode on this device
requires B-frame support, "
- "but it's not implemented.\n");
- return AVERROR_PATCHWELCOME;
+ fh->frame_type = AV1_FRAME_INTER;
+ fh->base_q_idx = priv->q_idx_b;
+ fh->tx_mode = AV1_TX_MODE_SELECT;
+ fh->refresh_frame_flags = 0x0; // B-frames don't refresh any DPB
slot
+ fh->reference_select = 1; // compound prediction
+
+ d3d12va_pic->pic_ctl.pAV1PicData->CompoundPredictionType =
+
D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_COMPOUND_REFERENCE;
+
+ assert(pic->nb_refs[0] >= 1 && pic->nb_refs[1] >= 1);
+
+ // L0 reference (LAST = previous anchor)
+ ref = pic->refs[0][pic->nb_refs[0] - 1];
+ href_l0 = ref->codec_priv;
+ hpic->last_idr_frame = href_l0->last_idr_frame;
+ fh->primary_ref_frame = href_l0->slot;
+ fh->ref_order_hint[href_l0->slot] = ref->display_order -
href_l0->last_idr_frame;
+
+ // LAST, LAST2, LAST3, GOLDEN → L0 slot
+ for (i = 0; i < AV1_REF_FRAME_GOLDEN; i++)
+ fh->ref_frame_idx[i] = href_l0->slot;
+
+ // L1 reference (BWDREF = future anchor)
+ ref = pic->refs[1][pic->nb_refs[1] - 1];
+ href_l1 = ref->codec_priv;
+ fh->ref_order_hint[href_l1->slot] = ref->display_order -
href_l1->last_idr_frame;
+
+ // BWDREF, ALTREF2, ALTREF → L1 slot
+ for (i = AV1_REF_FRAME_GOLDEN; i < AV1_REFS_PER_FRAME; i++)
+ fh->ref_frame_idx[i] = href_l1->slot;
+ break;
+
default:
av_log(avctx, AV_LOG_ERROR, "Unsupported picture type %d.\n",
pic->type);
+ return AVERROR(EINVAL);
}
+ // Assign ppTexture2Ds indices in list order (L0 first, then L1).
+ for (phys = 0, i = 0; i < 2; i++) {
+ for (int j = 0; j < pic->nb_refs[i]; j++) {
+ D3D12VAEncodeAV1Picture *hr = pic->refs[i][j]->codec_priv;
+
d3d12va_pic->pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[hr->slot]
+ .ReconstructedPictureResourceIndex = phys++;
+ }
+ }
cbctx->seen_frame_header = 0;
@@ -1264,30 +1399,14 @@ static int
d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx,
d3d12va_pic->pic_ctl.pAV1PicData->TemporalLayerIndexPlus1 =
hpic->temporal_id + 1;
d3d12va_pic->pic_ctl.pAV1PicData->SpatialLayerIndexPlus1 =
hpic->spatial_id + 1;
d3d12va_pic->pic_ctl.pAV1PicData->PictureIndex = pic->display_order;
+ d3d12va_pic->pic_ctl.pAV1PicData->OrderHint = fh->order_hint;
d3d12va_pic->pic_ctl.pAV1PicData->InterpolationFilter =
D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_SWITCHABLE;
d3d12va_pic->pic_ctl.pAV1PicData->PrimaryRefFrame = fh->primary_ref_frame;
if (fh->error_resilient_mode)
d3d12va_pic->pic_ctl.pAV1PicData->Flags |=
D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_FLAG_ENABLE_ERROR_RESILIENT_MODE;
- if (pic->type == FF_HW_PICTURE_TYPE_IDR)
- {
- for (int i = 0; i < AV1_NUM_REF_FRAMES; i++) {
-
d3d12va_pic->pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[i].ReconstructedPictureResourceIndex
=
- D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX;
- }
- } else if (pic->type == FF_HW_PICTURE_TYPE_P) {
- for (i = 0; i < pic->nb_refs[0]; i++) {
- FFHWBaseEncodePicture *ref_pic = pic->refs[0][i];
-
d3d12va_pic->pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[i].ReconstructedPictureResourceIndex
=
- ((D3D12VAEncodeAV1Picture*)ref_pic->codec_priv)->slot;
- }
- }
- // Set reference frame management
- memset(d3d12va_pic->pic_ctl.pAV1PicData->ReferenceIndices, 0, sizeof(UINT)
* AV1_REFS_PER_FRAME);
- if (pic->type == FF_HW_PICTURE_TYPE_P) {
- for (i = 0; i < AV1_REFS_PER_FRAME; i++)
- d3d12va_pic->pic_ctl.pAV1PicData->ReferenceIndices[i] =
fh->ref_frame_idx[i];
- }
+ for (i = 0; i < AV1_REFS_PER_FRAME; i++)
+ d3d12va_pic->pic_ctl.pAV1PicData->ReferenceIndices[i] =
fh->ref_frame_idx[i];
// Process ROI side data if present and supported
if (base_ctx->roi_allowed && d3d12va_pic->qp_map &&
d3d12va_pic->qp_map_size > 0) {
@@ -1295,6 +1414,8 @@ static int
d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx,
d3d12va_pic->pic_ctl.pAV1PicData->pRateControlQPMap = (INT16
*)d3d12va_pic->qp_map;
}
+ d3d12va_pic->non_independent_frame = (pic->display_order >
pic->encode_order);
+
return av_fifo_write(priv->picture_header_list,
&priv->units.raw_frame_header, 1);
}
@@ -1305,8 +1426,8 @@ static const D3D12VAEncodeType d3d12va_encode_type_av1 = {
.d3d12_codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
.flags = FF_HW_FLAG_B_PICTURES |
- FF_HW_FLAG_B_PICTURE_REFERENCES |
- FF_HW_FLAG_NON_IDR_KEY_PICTURES,
+ FF_HW_FLAG_NON_IDR_KEY_PICTURES |
+ FF_HW_FLAG_TIMESTAMP_NO_DELAY,
.default_quality = 25,
@@ -1372,6 +1493,7 @@ static int d3d12va_encode_av1_close(AVCodecContext *avctx)
av_freep(&priv->common.subregions_layout.pTilesPartition_AV1);
av_fifo_freep2(&priv->picture_header_list);
+ av_freep(&priv->stash_data);
return ff_d3d12va_encode_close(avctx);
}
@@ -1446,7 +1568,7 @@ static const AVOption d3d12va_encode_av1_options[] = {
static const FFCodecDefault d3d12va_encode_av1_defaults[] = {
{ "b", "0" },
- { "bf", "0" },
+ { "bf", "2" },
{ "g", "120" },
{ "i_qfactor", "1" },
{ "i_qoffset", "0" },
diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h
index e768579722..e026679c1d 100644
--- a/libavcodec/hw_base_encode.h
+++ b/libavcodec/hw_base_encode.h
@@ -56,6 +56,9 @@ enum {
// Codec supports non-IDR key pictures (that is, key pictures do
// not necessarily empty the DPB).
FF_HW_FLAG_NON_IDR_KEY_PICTURES = 1 << 5,
+ // Output is in display order; set DTS = PTS on every packet
+ // (e.g. AV1 hidden anchor frames with show_existing_frame).
+ FF_HW_FLAG_TIMESTAMP_NO_DELAY = 1 << 6,
};
typedef struct FFHWBaseEncodePicture {
--
2.52.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]