diff --git a/gst-libs/gst/codecs/gsth264decoder.c b/gst-libs/gst/codecs/gsth264decoder.c index d490adb842..bf48a60193 100644 --- a/gst-libs/gst/codecs/gsth264decoder.c +++ b/gst-libs/gst/codecs/gsth264decoder.c @@ -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); +} diff --git a/gst-libs/gst/codecs/gsth264decoder.h b/gst-libs/gst/codecs/gsth264decoder.h index c562d13625..aa0915390f 100644 --- a/gst-libs/gst/codecs/gsth264decoder.h +++ b/gst-libs/gst/codecs/gsth264decoder.h @@ -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__ */ diff --git a/gst-libs/gst/codecs/gsth264picture.c b/gst-libs/gst/codecs/gsth264picture.c index 90f4003940..45c28d671e 100644 --- a/gst-libs/gst/codecs/gsth264picture.c +++ b/gst-libs/gst/codecs/gsth264picture.c @@ -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; +} diff --git a/gst-libs/gst/codecs/gsth264picture.h b/gst-libs/gst/codecs/gsth264picture.h index 697ff994c1..27d237dd26 100644 --- a/gst-libs/gst/codecs/gsth264picture.h +++ b/gst-libs/gst/codecs/gsth264picture.h @@ -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);