mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-22 15:18:21 +00:00
codecs: h264decoder: ref pic lists as decode_slice parameters
Pass reference picture lists to decode_slice() vmethods Change gstv4l2codech264dec and gstnvh264dec accordingly. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1238>
This commit is contained in:
parent
990392d595
commit
d2aae6bb96
5 changed files with 58 additions and 35 deletions
|
@ -137,6 +137,10 @@ struct _GstH264DecoderPrivate
|
|||
GArray *ref_pic_list_b0;
|
||||
GArray *ref_pic_list_b1;
|
||||
|
||||
/* Reference picture lists, constructed for each slice */
|
||||
GArray *ref_pic_list0;
|
||||
GArray *ref_pic_list1;
|
||||
|
||||
/* Cached array to handle pictures to be outputed */
|
||||
GArray *to_output;
|
||||
};
|
||||
|
@ -178,9 +182,8 @@ static gboolean gst_h264_decoder_finish_current_picture (GstH264Decoder * self);
|
|||
static gboolean gst_h264_decoder_finish_picture (GstH264Decoder * self,
|
||||
GstH264Picture * picture);
|
||||
static void gst_h264_decoder_prepare_ref_pic_lists (GstH264Decoder * self);
|
||||
static gboolean gst_h264_decoder_modify_ref_pic_lists (GstH264Decoder * self,
|
||||
GPtrArray * ref_pic_l0, GPtrArray * ref_pic_l1);
|
||||
static void gst_h264_decoder_clear_ref_pic_lists (GstH264Decoder * self);
|
||||
static gboolean gst_h264_decoder_modify_ref_pic_lists (GstH264Decoder * self);
|
||||
|
||||
static void
|
||||
gst_h264_decoder_class_init (GstH264DecoderClass * klass)
|
||||
|
@ -224,6 +227,11 @@ gst_h264_decoder_init (GstH264Decoder * self)
|
|||
g_array_set_clear_func (priv->ref_pic_list_b1,
|
||||
(GDestroyNotify) gst_h264_picture_clear);
|
||||
|
||||
priv->ref_pic_list0 = g_array_sized_new (FALSE, TRUE,
|
||||
sizeof (GstH264Picture *), 32);
|
||||
priv->ref_pic_list1 = g_array_sized_new (FALSE, TRUE,
|
||||
sizeof (GstH264Picture *), 32);
|
||||
|
||||
priv->to_output = g_array_sized_new (FALSE, TRUE,
|
||||
sizeof (GstH264Picture *), 16);
|
||||
g_array_set_clear_func (priv->to_output,
|
||||
|
@ -239,6 +247,8 @@ gst_h264_decoder_finalize (GObject * object)
|
|||
g_array_unref (priv->ref_pic_list_p0);
|
||||
g_array_unref (priv->ref_pic_list_b0);
|
||||
g_array_unref (priv->ref_pic_list_b1);
|
||||
g_array_unref (priv->ref_pic_list0);
|
||||
g_array_unref (priv->ref_pic_list1);
|
||||
g_array_unref (priv->to_output);
|
||||
}
|
||||
|
||||
|
@ -1924,7 +1934,8 @@ gst_h264_decoder_decode_slice (GstH264Decoder * self)
|
|||
|
||||
g_assert (klass->decode_slice);
|
||||
|
||||
ret = klass->decode_slice (self, picture, slice);
|
||||
ret = klass->decode_slice (self, picture, slice, ref_pic_list0,
|
||||
ref_pic_list1);
|
||||
if (!ret) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"Subclass didn't want to decode picture %p (frame_num %d, poc %d)",
|
||||
|
@ -2162,24 +2173,25 @@ pic_num_f (GstH264Decoder * self, const GstH264Picture * picture)
|
|||
/* shift elements on the |array| starting from |from| to |to|,
|
||||
* inclusive, one position to the right and insert pic at |from| */
|
||||
static void
|
||||
shift_right_and_insert (GPtrArray * array, gint from, gint to,
|
||||
shift_right_and_insert (GArray * array, gint from, gint to,
|
||||
GstH264Picture * picture)
|
||||
{
|
||||
g_return_if_fail (from <= to);
|
||||
g_return_if_fail (array && picture);
|
||||
|
||||
g_ptr_array_set_size (array, to + 2);
|
||||
g_ptr_array_insert (array, from, picture);
|
||||
g_array_set_size (array, to + 2);
|
||||
g_array_insert_val (array, from, picture);
|
||||
}
|
||||
|
||||
/* This can process either ref_pic_list0 or ref_pic_list1, depending
|
||||
* on the list argument. Set up pointers to proper list to be
|
||||
* processed here. */
|
||||
static gboolean
|
||||
modify_ref_pic_list (GstH264Decoder * self, int list, GPtrArray * ref_pic_listx)
|
||||
modify_ref_pic_list (GstH264Decoder * self, int list)
|
||||
{
|
||||
GstH264DecoderPrivate *priv = self->priv;
|
||||
GstH264Picture *picture = priv->current_picture;
|
||||
GArray *ref_pic_listx;
|
||||
const GstH264SliceHdr *slice_hdr = &priv->current_slice.header;
|
||||
const GstH264RefPicListModification *list_mod;
|
||||
gboolean ref_pic_list_modification_flag_lX;
|
||||
|
@ -2194,12 +2206,14 @@ modify_ref_pic_list (GstH264Decoder * self, int list, GPtrArray * ref_pic_listx)
|
|||
GstH264Picture *pic;
|
||||
|
||||
if (list == 0) {
|
||||
ref_pic_listx = priv->ref_pic_list0;
|
||||
ref_pic_list_modification_flag_lX =
|
||||
slice_hdr->ref_pic_list_modification_flag_l0;
|
||||
num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l0;
|
||||
num_ref_idx_lX_active_minus1 = slice_hdr->num_ref_idx_l0_active_minus1;
|
||||
list_mod = slice_hdr->ref_pic_list_modification_l0;
|
||||
} else {
|
||||
ref_pic_listx = priv->ref_pic_list1;
|
||||
ref_pic_list_modification_flag_lX =
|
||||
slice_hdr->ref_pic_list_modification_flag_l1;
|
||||
num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l1;
|
||||
|
@ -2216,7 +2230,7 @@ modify_ref_pic_list (GstH264Decoder * self, int list, GPtrArray * ref_pic_listx)
|
|||
* which must be handled by clients */
|
||||
g_assert (num_ref_idx_lX_active_minus1 >= 0);
|
||||
if (ref_pic_listx->len > num_ref_idx_lX_active_minus1 + 1)
|
||||
g_ptr_array_set_size (ref_pic_listx, num_ref_idx_lX_active_minus1 + 1);
|
||||
g_array_set_size (ref_pic_listx, num_ref_idx_lX_active_minus1 + 1);
|
||||
|
||||
if (!ref_pic_list_modification_flag_lX)
|
||||
return TRUE;
|
||||
|
@ -2270,10 +2284,11 @@ modify_ref_pic_list (GstH264Decoder * self, int list, GPtrArray * ref_pic_listx)
|
|||
|
||||
for (src = ref_idx_lx, dst = ref_idx_lx;
|
||||
src <= num_ref_idx_lX_active_minus1 + 1; src++) {
|
||||
GstH264Picture *src_pic = g_ptr_array_index (ref_pic_listx, src);
|
||||
GstH264Picture *src_pic =
|
||||
g_array_index (ref_pic_listx, GstH264Picture *, src);
|
||||
gint src_pic_num_lx = src_pic ? pic_num_f (self, src_pic) : -1;
|
||||
if (src_pic_num_lx != pic_num_lx)
|
||||
g_ptr_array_index (ref_pic_listx, dst++) = src_pic;
|
||||
g_array_index (ref_pic_listx, GstH264Picture *, dst++) = src_pic;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2295,10 +2310,11 @@ modify_ref_pic_list (GstH264Decoder * self, int list, GPtrArray * ref_pic_listx)
|
|||
|
||||
for (src = ref_idx_lx, dst = ref_idx_lx;
|
||||
src <= num_ref_idx_lX_active_minus1 + 1; src++) {
|
||||
GstH264Picture *src_pic = g_ptr_array_index (ref_pic_listx, src);
|
||||
GstH264Picture *src_pic =
|
||||
g_array_index (ref_pic_listx, GstH264Picture *, src);
|
||||
if (long_term_pic_num_f (self, src_pic) !=
|
||||
list_mod->value.long_term_pic_num)
|
||||
g_ptr_array_index (ref_pic_listx, dst++) = src_pic;
|
||||
g_array_index (ref_pic_listx, GstH264Picture *, dst++) = src_pic;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2322,39 +2338,36 @@ modify_ref_pic_list (GstH264Decoder * self, int list, GPtrArray * ref_pic_listx)
|
|||
* temporarily made one element longer than the required final list.
|
||||
* Resize the list back to its required size. */
|
||||
if (ref_pic_listx->len > num_ref_idx_lX_active_minus1 + 1)
|
||||
g_ptr_array_set_size (ref_pic_listx, num_ref_idx_lX_active_minus1 + 1);
|
||||
g_array_set_size (ref_pic_listx, num_ref_idx_lX_active_minus1 + 1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
from_list_to_array (GPtrArray * array, GList * list)
|
||||
copy_pic_list_into (GArray * dest, GArray * src)
|
||||
{
|
||||
GList *l;
|
||||
gint i;
|
||||
g_array_set_size (dest, 0);
|
||||
|
||||
for (l = list; l; l = g_list_next (l))
|
||||
g_ptr_array_add (array, l->data);
|
||||
for (i = 0; i < src->len; i++)
|
||||
g_array_append_val (dest, g_array_index (src, gpointer, i));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h264_decoder_modify_ref_pic_lists (GstH264Decoder * self,
|
||||
GPtrArray * ref_pic_list0, GPtrArray * ref_pic_list1)
|
||||
gst_h264_decoder_modify_ref_pic_lists (GstH264Decoder * self)
|
||||
{
|
||||
GstH264DecoderPrivate *priv = self->priv;
|
||||
GstH264SliceHdr *slice_hdr = &priv->current_slice.header;
|
||||
|
||||
g_ptr_array_set_size (ref_pic_list0, 0);
|
||||
g_ptr_array_set_size (ref_pic_list1, 0);
|
||||
|
||||
/* fill reference picture lists for B and S/SP slices */
|
||||
if (GST_H264_IS_P_SLICE (slice_hdr) || GST_H264_IS_SP_SLICE (slice_hdr)) {
|
||||
from_list_to_array (ref_pic_list0, priv->ref_pic_list_p0);
|
||||
return modify_ref_pic_list (self, 0, ref_pic_list0);
|
||||
copy_pic_list_into (priv->ref_pic_list0, priv->ref_pic_list_p0);
|
||||
return modify_ref_pic_list (self, 0);
|
||||
} else {
|
||||
from_list_to_array (ref_pic_list0, priv->ref_pic_list_b0);
|
||||
from_list_to_array (ref_pic_list1, priv->ref_pic_list_b1);
|
||||
return modify_ref_pic_list (self, 0, ref_pic_list0)
|
||||
&& modify_ref_pic_list (self, 1, ref_pic_list1);
|
||||
copy_pic_list_into (priv->ref_pic_list0, priv->ref_pic_list_b0);
|
||||
copy_pic_list_into (priv->ref_pic_list1, priv->ref_pic_list_b1);
|
||||
return modify_ref_pic_list (self, 0)
|
||||
&& modify_ref_pic_list (self, 1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -69,7 +69,10 @@ struct _GstH264Decoder
|
|||
* Called per one #GstH264Picture to notify subclass to prepare
|
||||
* decoding process for the #GstH264Picture
|
||||
* @decode_slice: Provides per slice data with parsed slice header and
|
||||
* required raw bitstream for subclass to decode it
|
||||
* required raw bitstream for subclass to decode it.
|
||||
* if gst_h264_decoder_set_process_ref_pic_lists() is called
|
||||
* with %TRUE by the subclass, @ref_pic_list0 and @ref_pic_list1
|
||||
* are non-%NULL.
|
||||
* @end_picture: Optional.
|
||||
* Called per one #GstH264Picture to notify subclass to finish
|
||||
* decoding process for the #GstH264Picture
|
||||
|
@ -97,7 +100,9 @@ struct _GstH264DecoderClass
|
|||
|
||||
gboolean (*decode_slice) (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture,
|
||||
GstH264Slice * slice);
|
||||
GstH264Slice * slice,
|
||||
GArray * ref_pic_list0,
|
||||
GArray * ref_pic_list1);
|
||||
|
||||
gboolean (*end_picture) (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture);
|
||||
|
|
|
@ -157,7 +157,8 @@ static GstFlowReturn gst_d3d11_h264_dec_output_picture (GstH264Decoder *
|
|||
static gboolean gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb);
|
||||
static gboolean gst_d3d11_h264_dec_decode_slice (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice);
|
||||
GstH264Picture * picture, GstH264Slice * slice, GArray * ref_pic_list0,
|
||||
GArray * ref_pic_list1);
|
||||
static gboolean gst_d3d11_h264_dec_end_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture);
|
||||
|
||||
|
@ -912,7 +913,8 @@ gst_d3d11_h264_dec_fill_picture_params (GstD3D11H264Dec * self,
|
|||
|
||||
static gboolean
|
||||
gst_d3d11_h264_dec_decode_slice (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice)
|
||||
GstH264Picture * picture, GstH264Slice * slice, GArray * ref_pic_list0,
|
||||
GArray * ref_pic_list1)
|
||||
{
|
||||
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
|
||||
GstH264SPS *sps;
|
||||
|
|
|
@ -162,7 +162,8 @@ static GstFlowReturn gst_nv_h264_dec_output_picture (GstH264Decoder *
|
|||
static gboolean gst_nv_h264_dec_start_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb);
|
||||
static gboolean gst_nv_h264_dec_decode_slice (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice);
|
||||
GstH264Picture * picture, GstH264Slice * slice, GArray * ref_pic_list0,
|
||||
GArray * ref_pic_list1);
|
||||
static gboolean gst_nv_h264_dec_end_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture);
|
||||
|
||||
|
@ -907,7 +908,8 @@ gst_nv_h264_dec_start_picture (GstH264Decoder * decoder,
|
|||
|
||||
static gboolean
|
||||
gst_nv_h264_dec_decode_slice (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice)
|
||||
GstH264Picture * picture, GstH264Slice * slice, GArray * ref_pic_list0,
|
||||
GArray * ref_pic_list1)
|
||||
{
|
||||
GstNvH264Dec *self = GST_NV_H264_DEC (decoder);
|
||||
gsize new_size;
|
||||
|
|
|
@ -789,7 +789,8 @@ fail:
|
|||
|
||||
static gboolean
|
||||
gst_v4l2_codec_h264_dec_decode_slice (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture, GstH264Slice * slice)
|
||||
GstH264Picture * picture, GstH264Slice * slice, GArray * ref_pic_list0,
|
||||
GArray * ref_pic_list1)
|
||||
{
|
||||
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
||||
|
||||
|
|
Loading…
Reference in a new issue