vulkan_encode_av1: set primary_ref_frame to a reference name, not a slot

primary_ref_frame is an index into the seven reference names, but the
code assigned it the reference's DPB slot. The two coincide only while
the reference sits in slot 0; once it rotates to slot 1,
referenceNameSlotIndices[primary_ref_frame] is -1, which is invalid,
and NVIDIA drivers lose the device. Inherited from vaapi_encode_av1,
where the same confusion is harmless as the raw frame header maps
every reference name to the same slot.

Have set_name_slot() return the name it picked and use that.

Fixes #20540.
This commit is contained in:
Lynne
2026-08-02 06:30:59 +09:00
parent ac16cfb86e
commit 0da8f2f4ee

View File

@@ -159,7 +159,7 @@ static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
return 0;
}
static void set_name_slot(int slot, int *slot_indices, uint32_t allowed_idx, int group)
static int set_name_slot(int slot, int *slot_indices, uint32_t allowed_idx, int group)
{
int from = group ? AV1_REF_FRAME_GOLDEN : 0;
int to = group ? AV1_REFS_PER_FRAME : AV1_REF_FRAME_GOLDEN;
@@ -167,7 +167,7 @@ static void set_name_slot(int slot, int *slot_indices, uint32_t allowed_idx, int
for (int i = from; i < to; i++) {
if ((slot_indices[i] == -1) && (allowed_idx & (1 << i))) {
slot_indices[i] = slot;
return;
return i;
}
}
@@ -377,12 +377,12 @@ static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
for (int i = 0; i < AV1_REFS_PER_FRAME; i++)
ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
ap->av1pic_info.primary_ref_frame = ap_ref->slot;
ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_PREDICTIVE_KHR;
pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_SINGLE_REFERENCE_KHR;
ref_name_mask = enc->caps.singleReferenceNameMask;
set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
ap->av1pic_info.primary_ref_frame =
set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
// vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
@@ -422,11 +422,11 @@ static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
ref = pic->refs[0][pic->nb_refs[0] - 1];
ap_ref = ref->codec_priv;
ap->last_idr_frame = ap_ref->last_idr_frame;
ap->av1pic_info.primary_ref_frame = ap_ref->slot;
ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
for (int i = 0; i < AV1_REF_FRAME_GOLDEN; i++)
ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
ap->av1pic_info.primary_ref_frame =
set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
ref = pic->refs[1][pic->nb_refs[1] - 1];
ap_ref = ref->codec_priv;