mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 15:08:53 +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_b0;
|
||||||
GArray *ref_pic_list_b1;
|
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 */
|
/* Cached array to handle pictures to be outputed */
|
||||||
GArray *to_output;
|
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,
|
static gboolean gst_h264_decoder_finish_picture (GstH264Decoder * self,
|
||||||
GstH264Picture * picture);
|
GstH264Picture * picture);
|
||||||
static void gst_h264_decoder_prepare_ref_pic_lists (GstH264Decoder * self);
|
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 void gst_h264_decoder_clear_ref_pic_lists (GstH264Decoder * self);
|
||||||
|
static gboolean gst_h264_decoder_modify_ref_pic_lists (GstH264Decoder * self);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_h264_decoder_class_init (GstH264DecoderClass * klass)
|
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,
|
g_array_set_clear_func (priv->ref_pic_list_b1,
|
||||||
(GDestroyNotify) gst_h264_picture_clear);
|
(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,
|
priv->to_output = g_array_sized_new (FALSE, TRUE,
|
||||||
sizeof (GstH264Picture *), 16);
|
sizeof (GstH264Picture *), 16);
|
||||||
g_array_set_clear_func (priv->to_output,
|
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_p0);
|
||||||
g_array_unref (priv->ref_pic_list_b0);
|
g_array_unref (priv->ref_pic_list_b0);
|
||||||
g_array_unref (priv->ref_pic_list_b1);
|
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);
|
g_array_unref (priv->to_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1924,7 +1934,8 @@ gst_h264_decoder_decode_slice (GstH264Decoder * self)
|
||||||
|
|
||||||
g_assert (klass->decode_slice);
|
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) {
|
if (!ret) {
|
||||||
GST_WARNING_OBJECT (self,
|
GST_WARNING_OBJECT (self,
|
||||||
"Subclass didn't want to decode picture %p (frame_num %d, poc %d)",
|
"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|,
|
/* shift elements on the |array| starting from |from| to |to|,
|
||||||
* inclusive, one position to the right and insert pic at |from| */
|
* inclusive, one position to the right and insert pic at |from| */
|
||||||
static void
|
static void
|
||||||
shift_right_and_insert (GPtrArray * array, gint from, gint to,
|
shift_right_and_insert (GArray * array, gint from, gint to,
|
||||||
GstH264Picture * picture)
|
GstH264Picture * picture)
|
||||||
{
|
{
|
||||||
g_return_if_fail (from <= to);
|
g_return_if_fail (from <= to);
|
||||||
g_return_if_fail (array && picture);
|
g_return_if_fail (array && picture);
|
||||||
|
|
||||||
g_ptr_array_set_size (array, to + 2);
|
g_array_set_size (array, to + 2);
|
||||||
g_ptr_array_insert (array, from, picture);
|
g_array_insert_val (array, from, picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This can process either ref_pic_list0 or ref_pic_list1, depending
|
/* This can process either ref_pic_list0 or ref_pic_list1, depending
|
||||||
* on the list argument. Set up pointers to proper list to be
|
* on the list argument. Set up pointers to proper list to be
|
||||||
* processed here. */
|
* processed here. */
|
||||||
static gboolean
|
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;
|
GstH264DecoderPrivate *priv = self->priv;
|
||||||
GstH264Picture *picture = priv->current_picture;
|
GstH264Picture *picture = priv->current_picture;
|
||||||
|
GArray *ref_pic_listx;
|
||||||
const GstH264SliceHdr *slice_hdr = &priv->current_slice.header;
|
const GstH264SliceHdr *slice_hdr = &priv->current_slice.header;
|
||||||
const GstH264RefPicListModification *list_mod;
|
const GstH264RefPicListModification *list_mod;
|
||||||
gboolean ref_pic_list_modification_flag_lX;
|
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;
|
GstH264Picture *pic;
|
||||||
|
|
||||||
if (list == 0) {
|
if (list == 0) {
|
||||||
|
ref_pic_listx = priv->ref_pic_list0;
|
||||||
ref_pic_list_modification_flag_lX =
|
ref_pic_list_modification_flag_lX =
|
||||||
slice_hdr->ref_pic_list_modification_flag_l0;
|
slice_hdr->ref_pic_list_modification_flag_l0;
|
||||||
num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_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;
|
num_ref_idx_lX_active_minus1 = slice_hdr->num_ref_idx_l0_active_minus1;
|
||||||
list_mod = slice_hdr->ref_pic_list_modification_l0;
|
list_mod = slice_hdr->ref_pic_list_modification_l0;
|
||||||
} else {
|
} else {
|
||||||
|
ref_pic_listx = priv->ref_pic_list1;
|
||||||
ref_pic_list_modification_flag_lX =
|
ref_pic_list_modification_flag_lX =
|
||||||
slice_hdr->ref_pic_list_modification_flag_l1;
|
slice_hdr->ref_pic_list_modification_flag_l1;
|
||||||
num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_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 */
|
* which must be handled by clients */
|
||||||
g_assert (num_ref_idx_lX_active_minus1 >= 0);
|
g_assert (num_ref_idx_lX_active_minus1 >= 0);
|
||||||
if (ref_pic_listx->len > num_ref_idx_lX_active_minus1 + 1)
|
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)
|
if (!ref_pic_list_modification_flag_lX)
|
||||||
return TRUE;
|
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;
|
for (src = ref_idx_lx, dst = ref_idx_lx;
|
||||||
src <= num_ref_idx_lX_active_minus1 + 1; src++) {
|
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;
|
gint src_pic_num_lx = src_pic ? pic_num_f (self, src_pic) : -1;
|
||||||
if (src_pic_num_lx != pic_num_lx)
|
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;
|
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;
|
for (src = ref_idx_lx, dst = ref_idx_lx;
|
||||||
src <= num_ref_idx_lX_active_minus1 + 1; src++) {
|
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) !=
|
if (long_term_pic_num_f (self, src_pic) !=
|
||||||
list_mod->value.long_term_pic_num)
|
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;
|
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.
|
* temporarily made one element longer than the required final list.
|
||||||
* Resize the list back to its required size. */
|
* Resize the list back to its required size. */
|
||||||
if (ref_pic_listx->len > num_ref_idx_lX_active_minus1 + 1)
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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))
|
for (i = 0; i < src->len; i++)
|
||||||
g_ptr_array_add (array, l->data);
|
g_array_append_val (dest, g_array_index (src, gpointer, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_h264_decoder_modify_ref_pic_lists (GstH264Decoder * self,
|
gst_h264_decoder_modify_ref_pic_lists (GstH264Decoder * self)
|
||||||
GPtrArray * ref_pic_list0, GPtrArray * ref_pic_list1)
|
|
||||||
{
|
{
|
||||||
GstH264DecoderPrivate *priv = self->priv;
|
GstH264DecoderPrivate *priv = self->priv;
|
||||||
GstH264SliceHdr *slice_hdr = &priv->current_slice.header;
|
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 */
|
/* 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)) {
|
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);
|
copy_pic_list_into (priv->ref_pic_list0, priv->ref_pic_list_p0);
|
||||||
return modify_ref_pic_list (self, 0, ref_pic_list0);
|
return modify_ref_pic_list (self, 0);
|
||||||
} else {
|
} else {
|
||||||
from_list_to_array (ref_pic_list0, priv->ref_pic_list_b0);
|
copy_pic_list_into (priv->ref_pic_list0, priv->ref_pic_list_b0);
|
||||||
from_list_to_array (ref_pic_list1, priv->ref_pic_list_b1);
|
copy_pic_list_into (priv->ref_pic_list1, priv->ref_pic_list_b1);
|
||||||
return modify_ref_pic_list (self, 0, ref_pic_list0)
|
return modify_ref_pic_list (self, 0)
|
||||||
&& modify_ref_pic_list (self, 1, ref_pic_list1);
|
&& modify_ref_pic_list (self, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -69,7 +69,10 @@ struct _GstH264Decoder
|
||||||
* Called per one #GstH264Picture to notify subclass to prepare
|
* Called per one #GstH264Picture to notify subclass to prepare
|
||||||
* decoding process for the #GstH264Picture
|
* decoding process for the #GstH264Picture
|
||||||
* @decode_slice: Provides per slice data with parsed slice header and
|
* @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.
|
* @end_picture: Optional.
|
||||||
* Called per one #GstH264Picture to notify subclass to finish
|
* Called per one #GstH264Picture to notify subclass to finish
|
||||||
* decoding process for the #GstH264Picture
|
* decoding process for the #GstH264Picture
|
||||||
|
@ -97,7 +100,9 @@ struct _GstH264DecoderClass
|
||||||
|
|
||||||
gboolean (*decode_slice) (GstH264Decoder * decoder,
|
gboolean (*decode_slice) (GstH264Decoder * decoder,
|
||||||
GstH264Picture * picture,
|
GstH264Picture * picture,
|
||||||
GstH264Slice * slice);
|
GstH264Slice * slice,
|
||||||
|
GArray * ref_pic_list0,
|
||||||
|
GArray * ref_pic_list1);
|
||||||
|
|
||||||
gboolean (*end_picture) (GstH264Decoder * decoder,
|
gboolean (*end_picture) (GstH264Decoder * decoder,
|
||||||
GstH264Picture * picture);
|
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,
|
static gboolean gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
|
||||||
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb);
|
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb);
|
||||||
static gboolean gst_d3d11_h264_dec_decode_slice (GstH264Decoder * decoder,
|
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,
|
static gboolean gst_d3d11_h264_dec_end_picture (GstH264Decoder * decoder,
|
||||||
GstH264Picture * picture);
|
GstH264Picture * picture);
|
||||||
|
|
||||||
|
@ -912,7 +913,8 @@ gst_d3d11_h264_dec_fill_picture_params (GstD3D11H264Dec * self,
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_d3d11_h264_dec_decode_slice (GstH264Decoder * decoder,
|
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);
|
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
|
||||||
GstH264SPS *sps;
|
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,
|
static gboolean gst_nv_h264_dec_start_picture (GstH264Decoder * decoder,
|
||||||
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb);
|
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb);
|
||||||
static gboolean gst_nv_h264_dec_decode_slice (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);
|
||||||
static gboolean gst_nv_h264_dec_end_picture (GstH264Decoder * decoder,
|
static gboolean gst_nv_h264_dec_end_picture (GstH264Decoder * decoder,
|
||||||
GstH264Picture * picture);
|
GstH264Picture * picture);
|
||||||
|
|
||||||
|
@ -907,7 +908,8 @@ gst_nv_h264_dec_start_picture (GstH264Decoder * decoder,
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nv_h264_dec_decode_slice (GstH264Decoder * decoder,
|
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);
|
GstNvH264Dec *self = GST_NV_H264_DEC (decoder);
|
||||||
gsize new_size;
|
gsize new_size;
|
||||||
|
|
|
@ -789,7 +789,8 @@ fail:
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_v4l2_codec_h264_dec_decode_slice (GstH264Decoder * decoder,
|
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);
|
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue