vkh264dec: enhance interlaced content support
- Use frame_num instead of pic_num to set the long_term_pic_num fixing 10 interlaced tests in fluster test suite: JVT-AVC_V1 - Send the slice offset only once in case of interlaced content. Fixing 5 interlaced tests in fluster test suite: JVT-AVC_V1. - The default value for top and bottom field flag should be 0 in the case of a progressive content. - Use short and long term refs helper getter method to retrieve the reference frames according its none existing and interlaced state - Reorganize the find_next_slot_idx code to be easier to read. Co-authored-by: Daniel Almeida <daniel.almeida@collabora.com> Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7854>
This commit is contained in:
parent
3090cefbc5
commit
ee7d41f76b
@ -1013,13 +1013,10 @@ _find_next_slot_idx (GstH264Picture * picture, GArray * dpb)
|
|||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
GstH264Picture *pic = g_array_index (dpb, GstH264Picture *, i);
|
GstH264Picture *pic = g_array_index (dpb, GstH264Picture *, i);
|
||||||
if (!pic->nonexisting) {
|
GstVulkanH264Picture *h264_pic = gst_h264_picture_get_user_data (pic);
|
||||||
if (pic->second_field)
|
if (pic->nonexisting || pic->second_field)
|
||||||
continue;
|
continue;
|
||||||
GstVulkanH264Picture *h264_pic = gst_h264_picture_get_user_data (pic);
|
arr[h264_pic->slot_idx] = pic;
|
||||||
if (h264_pic)
|
|
||||||
arr[h264_pic->slot_idx] = pic;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* let's return the smallest available / not ref index */
|
/* let's return the smallest available / not ref index */
|
||||||
@ -1047,7 +1044,7 @@ _fill_h264_slot (GstH264Picture * picture,
|
|||||||
GST_H264_PICTURE_IS_LONG_TERM_REF (picture),
|
GST_H264_PICTURE_IS_LONG_TERM_REF (picture),
|
||||||
},
|
},
|
||||||
.FrameNum = GST_H264_PICTURE_IS_LONG_TERM_REF (picture) ?
|
.FrameNum = GST_H264_PICTURE_IS_LONG_TERM_REF (picture) ?
|
||||||
picture->long_term_pic_num : picture->pic_num,
|
picture->long_term_pic_num : picture->frame_num,
|
||||||
/* .reserved = */
|
/* .reserved = */
|
||||||
/* .PicOrderCnt = */
|
/* .PicOrderCnt = */
|
||||||
};
|
};
|
||||||
@ -1055,8 +1052,6 @@ _fill_h264_slot (GstH264Picture * picture,
|
|||||||
|
|
||||||
switch (picture->field) {
|
switch (picture->field) {
|
||||||
case GST_H264_PICTURE_FIELD_FRAME:
|
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[0] = picture->top_field_order_cnt;
|
||||||
stdh264_ref->PicOrderCnt[1] = picture->bottom_field_order_cnt;
|
stdh264_ref->PicOrderCnt[1] = picture->bottom_field_order_cnt;
|
||||||
break;
|
break;
|
||||||
@ -1148,61 +1143,58 @@ gst_vulkan_h264_decoder_start_picture (GstH264Decoder * decoder,
|
|||||||
GstVulkanH264Picture *pic;
|
GstVulkanH264Picture *pic;
|
||||||
GArray *refs;
|
GArray *refs;
|
||||||
guint i, j;
|
guint i, j;
|
||||||
gboolean interlaced;
|
|
||||||
|
|
||||||
GST_TRACE_OBJECT (self, "Start picture");
|
GST_TRACE_OBJECT (self, "Start picture");
|
||||||
|
|
||||||
|
|
||||||
ret = _update_parameters (self, self->need_sps_update ? sps : NULL, pps);
|
ret = _update_parameters (self, self->need_sps_update ? sps : NULL, pps);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
if (self->need_sps_update)
|
if (self->need_sps_update)
|
||||||
self->need_sps_update = FALSE;
|
self->need_sps_update = FALSE;
|
||||||
|
|
||||||
|
|
||||||
refs = gst_h264_dpb_get_pictures_all (dpb);
|
refs = gst_h264_dpb_get_pictures_all (dpb);
|
||||||
|
|
||||||
pic = gst_h264_picture_get_user_data (picture);
|
pic = gst_h264_picture_get_user_data (picture);
|
||||||
g_assert (pic);
|
g_assert (pic);
|
||||||
|
|
||||||
_fill_h264_pic (picture, slice, &pic->vk_h264pic, &pic->std_h264pic);
|
_fill_h264_pic (picture, slice, &pic->vk_h264pic, &pic->std_h264pic);
|
||||||
|
/* Search for the next slot index in all available refs */
|
||||||
pic->slot_idx = _find_next_slot_idx (picture, refs);
|
pic->slot_idx = _find_next_slot_idx (picture, refs);
|
||||||
|
|
||||||
|
g_array_unref (refs);
|
||||||
|
/* Create a new refs array to retrieve short-term and long term refs */
|
||||||
|
refs = g_array_sized_new (FALSE, TRUE, sizeof (GstH264Picture *), 16);
|
||||||
|
g_array_set_clear_func (refs, (GDestroyNotify) gst_clear_h264_picture);
|
||||||
|
|
||||||
/* fill main slot */
|
/* fill main slot */
|
||||||
_fill_ref_slot (self, picture, &pic->base.slot,
|
_fill_ref_slot (self, picture, &pic->base.slot,
|
||||||
&pic->base.pic_res, &pic->vk_slot, &pic->std_ref, NULL);
|
&pic->base.pic_res, &pic->vk_slot, &pic->std_ref, NULL);
|
||||||
|
|
||||||
interlaced = GST_VIDEO_INFO_INTERLACE_MODE (&self->output_state->info)
|
gst_h264_dpb_get_pictures_short_term_ref (dpb, FALSE, FALSE, refs);
|
||||||
!= GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
|
|
||||||
j = 0;
|
|
||||||
|
|
||||||
/* Fill in short-term references */
|
/* Fill in short-term references */
|
||||||
|
j = 0;
|
||||||
for (i = 0; i < refs->len; i++) {
|
for (i = 0; i < refs->len; i++) {
|
||||||
GstH264Picture *picture = g_array_index (refs, GstH264Picture *, i);
|
GstH264Picture *picture = g_array_index (refs, GstH264Picture *, i);
|
||||||
/* XXX: shall we add second fields? */
|
|
||||||
if (!picture->nonexisting && GST_H264_PICTURE_IS_SHORT_TERM_REF (picture)) {
|
_fill_ref_slot (self, picture, &pic->base.slots[j],
|
||||||
_fill_ref_slot (self, picture, &pic->base.slots[j],
|
&pic->base.pics_res[j], &pic->vk_slots[j], &pic->std_refs[j],
|
||||||
&pic->base.pics_res[j], &pic->vk_slots[j], &pic->std_refs[j],
|
&pic->base.refs[j]);
|
||||||
&pic->base.refs[j]);
|
j++;
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_array_set_size (refs, 0);
|
||||||
|
gst_h264_dpb_get_pictures_long_term_ref (dpb, FALSE, refs);
|
||||||
/* Fill in long-term refs */
|
/* Fill in long-term refs */
|
||||||
for (i = 0; i < refs->len; i++) {
|
for (i = 0; i < refs->len; i++) {
|
||||||
GstH264Picture *picture = g_array_index (refs, GstH264Picture *, i);
|
GstH264Picture *picture = g_array_index (refs, GstH264Picture *, i);
|
||||||
|
|
||||||
if (picture->second_field || (interlaced && !picture->other_field))
|
_fill_ref_slot (self, picture, &pic->base.slots[j],
|
||||||
continue;
|
&pic->base.pics_res[j], &pic->vk_slots[j], &pic->std_refs[j],
|
||||||
|
&pic->base.refs[j]);
|
||||||
|
j++;
|
||||||
|
|
||||||
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],
|
|
||||||
&pic->base.refs[j]);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
g_array_set_size (refs, 0);
|
||||||
g_array_unref (refs);
|
g_array_unref (refs);
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
@ -1290,6 +1282,9 @@ gst_vulkan_h264_decoder_end_picture (GstH264Decoder * decoder,
|
|||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do not send the same slice data again */
|
||||||
|
g_clear_pointer (&pic->base.slice_offs, g_array_unref);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user