-
Notifications
You must be signed in to change notification settings - Fork 4
h264: fix "Missing reference picture" decode errors after IDR when max_reference_frames > 1 #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
936c5da
4f50beb
111710b
4742df4
3e90f05
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| output.* | ||
| /target/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,7 +96,9 @@ impl H264Encoder { | |
| _bitfield_align_1: [], | ||
| _bitfield_1: ash::vk::native::StdVideoEncodeH264SliceHeaderFlags::new_bitfield_1( | ||
| 0, // direct_spatial_mv_pred_flag | ||
| 0, // num_ref_idx_active_override_flag | ||
| // Always override the PPS default so decoders use the per-slice active count, | ||
| // preventing "Missing reference picture" errors when the DPB is not yet full. | ||
| 1, // num_ref_idx_active_override_flag | ||
| 0, // reserved | ||
| ), | ||
| }; | ||
|
|
@@ -173,38 +175,28 @@ impl H264Encoder { | |
| (0, 0) | ||
| } | ||
| } else if !is_idr && !self.l0_references.is_empty() { | ||
| // P-frame: L0 reference list. | ||
| // WE MUST FILL THE LIST UP TO THE PPS DEFAULT COUNT using duplicates if needed. | ||
|
|
||
| // Use negotiated active count. | ||
| let target_count = self.active_reference_count as usize; | ||
| let count = self.l0_references.len(); | ||
|
|
||
| // 1. Fill actual references | ||
| for (i, ref_info) in self.l0_references.iter().enumerate() { | ||
| // P-frame: L0 reference list using actual available references. | ||
| // Clamp to the negotiated active count maximum. | ||
| let actual_count = self | ||
| .l0_references | ||
| .len() | ||
| .min(self.active_reference_count as usize); | ||
|
|
||
| for (i, ref_info) in self.l0_references.iter().take(actual_count).enumerate() { | ||
| if i < 32 { | ||
| ref_list0[i] = ref_info.dpb_slot; | ||
| } | ||
|
||
| } | ||
|
|
||
| // 2. Pad with duplicates of the last reference if needed to reach target_count | ||
| if count < target_count && count > 0 { | ||
| let last_slot = ref_list0[count - 1]; | ||
| let end = target_count.min(32); | ||
| ref_list0[count..end].fill(last_slot); | ||
| } | ||
|
|
||
| // We provide target_count entries if we have at least 1, otherwise 0. | ||
| (target_count.min(32), 0) | ||
| (actual_count.min(32), 0) | ||
| } else { | ||
| // IDR: no references. | ||
| (0, 0) | ||
| }; | ||
|
|
||
| // Note: num_ref_idx_l0_active_minus1 in ReferenceListsInfo tells the driver/hardware | ||
| // how many entries in our RefPicList0 array are valid. | ||
| // Since we ensure 3 entries are valid (by duplicating), we set this to 2. | ||
|
|
||
| // num_ref_idx_l0_active_minus1 tells the driver how many entries in RefPicList0 | ||
| // are valid and is encoded into the slice header (because we set | ||
| // num_ref_idx_active_override_flag=1 above). | ||
| let ref_lists_info = ash::vk::native::StdVideoEncodeH264ReferenceListsInfo { | ||
| flags: ref_lists_info_flags, | ||
| num_ref_idx_l0_active_minus1: if num_ref_l0 > 0 { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
num_ref_idx_active_override_flagis set to 1 unconditionally, but in H.264 this syntax element is only present for P/B/SP slices. For IDR/I slices (and any case wherepicture_info.pRefListsis NULL), forcing this flag risks generating a non-conformant slice header or a driver-side mismatch between the slice header and provided reference list info. Consider setting it conditionally based onslice_type(e.g., only when references are actually signaled) and keeping it 0 for IDR/I slices.