vkh264dec: enable h264 interlaced decoding

First the slot_index shall have the same value for the first and second
fields.

Also, the reference frames are only those with both fields.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7854>
This commit is contained in:
Víctor Manuel Jáquez Leal 2024-06-21 16:55:05 +02:00 committed by GStreamer Marge Bot
parent f5f20ce85e
commit 3090cefbc5

View file

@ -1001,7 +1001,7 @@ _fill_h264_pic (const GstH264Picture * picture, const GstH264Slice * slice,
}
static gint32
_find_next_slot_idx (GArray * dpb)
_find_next_slot_idx (GstH264Picture * picture, GArray * dpb)
{
gint32 i;
guint len;
@ -1014,6 +1014,8 @@ _find_next_slot_idx (GArray * dpb)
for (i = 0; i < len; i++) {
GstH264Picture *pic = g_array_index (dpb, GstH264Picture *, i);
if (!pic->nonexisting) {
if (pic->second_field)
continue;
GstVulkanH264Picture *h264_pic = gst_h264_picture_get_user_data (pic);
if (h264_pic)
arr[h264_pic->slot_idx] = pic;
@ -1022,7 +1024,8 @@ _find_next_slot_idx (GArray * dpb)
/* let's return the smallest available / not ref index */
for (i = 0; i < len; i++) {
if (!arr[i])
if (!arr[i]
|| (picture->second_field && picture->other_field == arr[i]))
return i;
}
@ -1037,10 +1040,8 @@ _fill_h264_slot (GstH264Picture * picture,
/* *INDENT-OFF* */
*stdh264_ref = (StdVideoDecodeH264ReferenceInfo) {
.flags = {
.top_field_flag =
(picture->field == GST_H264_PICTURE_FIELD_TOP_FIELD),
.bottom_field_flag =
(picture->field == GST_H264_PICTURE_FIELD_BOTTOM_FIELD),
.top_field_flag = 0,
.bottom_field_flag = 0,
.is_non_existing = picture->nonexisting,
.used_for_long_term_reference =
GST_H264_PICTURE_IS_LONG_TERM_REF (picture),
@ -1054,19 +1055,25 @@ _fill_h264_slot (GstH264Picture * picture,
switch (picture->field) {
case GST_H264_PICTURE_FIELD_FRAME:
stdh264_ref->flags.top_field_flag = 1;
stdh264_ref->flags.bottom_field_flag = 1;
stdh264_ref->PicOrderCnt[0] = picture->top_field_order_cnt;
stdh264_ref->PicOrderCnt[1] = picture->bottom_field_order_cnt;
break;
case GST_H264_PICTURE_FIELD_BOTTOM_FIELD:
if (picture->other_field)
stdh264_ref->flags.bottom_field_flag = 1;
if (picture->other_field) {
stdh264_ref->PicOrderCnt[0] = picture->other_field->top_field_order_cnt;
else
stdh264_ref->flags.top_field_flag = 1;
} else
stdh264_ref->PicOrderCnt[0] = 0;
stdh264_ref->PicOrderCnt[1] = picture->bottom_field_order_cnt;
break;
case GST_H264_PICTURE_FIELD_TOP_FIELD:
stdh264_ref->PicOrderCnt[0] = picture->top_field_order_cnt;
stdh264_ref->flags.top_field_flag = 1;
if (picture->other_field) {
stdh264_ref->flags.bottom_field_flag = 1;
stdh264_ref->PicOrderCnt[1] =
picture->other_field->bottom_field_order_cnt;
} else {
@ -1141,6 +1148,7 @@ gst_vulkan_h264_decoder_start_picture (GstH264Decoder * decoder,
GstVulkanH264Picture *pic;
GArray *refs;
guint i, j;
gboolean interlaced;
GST_TRACE_OBJECT (self, "Start picture");
@ -1158,12 +1166,14 @@ gst_vulkan_h264_decoder_start_picture (GstH264Decoder * decoder,
g_assert (pic);
_fill_h264_pic (picture, slice, &pic->vk_h264pic, &pic->std_h264pic);
pic->slot_idx = _find_next_slot_idx (refs);
pic->slot_idx = _find_next_slot_idx (picture, refs);
/* fill main slot */
_fill_ref_slot (self, picture, &pic->base.slot,
&pic->base.pic_res, &pic->vk_slot, &pic->std_ref, NULL);
interlaced = GST_VIDEO_INFO_INTERLACE_MODE (&self->output_state->info)
!= GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
j = 0;
/* Fill in short-term references */
@ -1176,13 +1186,15 @@ gst_vulkan_h264_decoder_start_picture (GstH264Decoder * decoder,
&pic->base.refs[j]);
j++;
}
/* FIXME: do it in O(n) rather O(2n) */
}
/* Fill in long-term refs */
for (i = 0; i < refs->len; i++) {
GstH264Picture *picture = g_array_index (refs, GstH264Picture *, i);
/* XXX: shall we add non existing and second fields? */
if (picture->second_field || (interlaced && !picture->other_field))
continue;
if (GST_H264_PICTURE_IS_LONG_TERM_REF (picture)) {
_fill_ref_slot (self, picture, &pic->base.slots[j],
&pic->base.pics_res[j], &pic->vk_slots[j], &pic->std_refs[j],