mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
h264decoder: Add ability to lookup by system_frame_number
This is to avoid having to create a reference chain in decoders from GstVideoCodecFrame to GstH264PIcture to implementation wrapper. So this change introduces: - gst_h264_dpb_remove_outputed (dpb) - gst_h264_dpb_get_picture(dpb, system_frame_num) - gst_h264_decoder_get_picture (dec, system_frame_num) In order to ensure that frames can be looked up during the draining process, we now first remove all (including reference) frames that have been outputed but are still in the DPB. Then for each remaining buffers, we remove it from the DPB to reach reference 1 and output it. Previously we could take all not outputed outside of the DPB which would prevent lookup by the base class. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1449>
This commit is contained in:
parent
82fb55bdff
commit
6523c5bcb6
4 changed files with 78 additions and 1 deletions
|
@ -1320,15 +1320,20 @@ gst_h264_decoder_drain_internal (GstH264Decoder * self)
|
|||
GstH264DecoderPrivate *priv = self->priv;
|
||||
GArray *to_output = priv->to_output;
|
||||
|
||||
/* We are around to drain, so we can get rist of everything that has been
|
||||
* outputed already */
|
||||
gst_h264_dpb_delete_outputed (priv->dpb);
|
||||
gst_h264_dpb_get_pictures_not_outputted (priv->dpb, to_output);
|
||||
g_array_sort (to_output, (GCompareFunc) poc_asc_compare);
|
||||
gst_h264_dpb_clear (priv->dpb);
|
||||
|
||||
while (to_output->len) {
|
||||
GstH264Picture *picture = g_array_index (to_output, GstH264Picture *, 0);
|
||||
|
||||
/* We want the last reference when outputing so take a ref and then remove
|
||||
* from both arrays. */
|
||||
gst_h264_picture_ref (picture);
|
||||
g_array_remove_index (to_output, 0);
|
||||
gst_h264_dpb_delete_by_poc (priv->dpb, picture->pic_order_cnt);
|
||||
|
||||
GST_LOG_OBJECT (self, "Output picture %p (frame num %d, poc %d)", picture,
|
||||
picture->frame_num, picture->pic_order_cnt);
|
||||
|
@ -1336,6 +1341,8 @@ gst_h264_decoder_drain_internal (GstH264Decoder * self)
|
|||
}
|
||||
|
||||
g_array_set_size (to_output, 0);
|
||||
gst_h264_dpb_clear (priv->dpb);
|
||||
priv->last_output_poc = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2456,3 +2463,10 @@ gst_h264_decoder_set_process_ref_pic_lists (GstH264Decoder * self,
|
|||
{
|
||||
self->priv->process_ref_pic_lists = process;
|
||||
}
|
||||
|
||||
GstH264Picture *
|
||||
gst_h264_decoder_get_picture (GstH264Decoder * self,
|
||||
guint32 system_frame_number)
|
||||
{
|
||||
return gst_h264_dpb_get_picture (self->priv->dpb, system_frame_number);
|
||||
}
|
||||
|
|
|
@ -139,6 +139,10 @@ GST_CODECS_API
|
|||
void gst_h264_decoder_set_process_ref_pic_lists (GstH264Decoder * self,
|
||||
gboolean process);
|
||||
|
||||
GST_CODECS_API
|
||||
GstH264Picture * gst_h264_decoder_get_picture (GstH264Decoder * self,
|
||||
guint32 system_frame_number);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_H264_DECODER_H__ */
|
||||
|
|
|
@ -233,6 +233,32 @@ gst_h264_dpb_delete_unused (GstH264Dpb * dpb)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h264_dpb_delete_outputed:
|
||||
* @dpb: a #GstH264Dpb
|
||||
*
|
||||
* Delete already outputted picture, even if they are referenced.
|
||||
*/
|
||||
void
|
||||
gst_h264_dpb_delete_outputed (GstH264Dpb * dpb)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (dpb != NULL);
|
||||
|
||||
for (i = 0; i < dpb->pic_list->len; i++) {
|
||||
GstH264Picture *picture =
|
||||
g_array_index (dpb->pic_list, GstH264Picture *, i);
|
||||
|
||||
if (picture->outputted) {
|
||||
GST_TRACE ("remove picture %p (frame num %d) from dpb",
|
||||
picture, picture->frame_num);
|
||||
g_array_remove_index_fast (dpb->pic_list, i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h264_dpb_delete_by_poc:
|
||||
* @dpb: a #GstH264Dpb
|
||||
|
@ -523,3 +549,29 @@ gst_h264_dpb_is_full (GstH264Dpb * dpb)
|
|||
|
||||
return dpb->pic_list->len >= dpb->max_num_pics;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h264_dpb_get_picture:
|
||||
* @system_frame_number The system frame number
|
||||
*
|
||||
* Returns: the picture identitifed with the specified @system_frame_number.
|
||||
*/
|
||||
GstH264Picture *
|
||||
gst_h264_dpb_get_picture (GstH264Dpb * dpb, guint32 system_frame_number)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (dpb != NULL, NULL);
|
||||
|
||||
for (i = 0; i < dpb->pic_list->len; i++) {
|
||||
GstH264Picture *picture =
|
||||
g_array_index (dpb->pic_list, GstH264Picture *, i);
|
||||
|
||||
if (picture->system_frame_number == system_frame_number) {
|
||||
gst_h264_picture_ref (picture);
|
||||
return picture;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -169,6 +169,9 @@ void gst_h264_dpb_add (GstH264Dpb * dpb,
|
|||
GST_CODECS_API
|
||||
void gst_h264_dpb_delete_unused (GstH264Dpb * dpb);
|
||||
|
||||
GST_CODECS_API
|
||||
void gst_h264_dpb_delete_outputed (GstH264Dpb * dpb);
|
||||
|
||||
GST_CODECS_API
|
||||
void gst_h264_dpb_delete_by_poc (GstH264Dpb * dpb,
|
||||
gint poc);
|
||||
|
@ -205,6 +208,10 @@ void gst_h264_dpb_get_pictures_long_term_ref (GstH264Dpb * dpb,
|
|||
GST_CODECS_API
|
||||
GArray * gst_h264_dpb_get_pictures_all (GstH264Dpb * dpb);
|
||||
|
||||
GST_CODECS_API
|
||||
GstH264Picture * gst_h264_dpb_get_picture (GstH264Dpb * dpb,
|
||||
guint32 system_frame_number);
|
||||
|
||||
GST_CODECS_API
|
||||
gint gst_h264_dpb_get_size (GstH264Dpb * dpb);
|
||||
|
||||
|
|
Loading…
Reference in a new issue