summaryrefslogtreecommitdiff
path: root/gst-libs
diff options
context:
space:
mode:
authorSeungha Yang <seungha@centricular.com>2020-04-23 19:47:09 +0900
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>2020-04-28 13:23:53 +0000
commit00ad8716289eb438425956d8d5d529d31e5a4a25 (patch)
tree372d7b25f6d2f504bddb5a02da4e6292f86079ff /gst-libs
parented6236f5513c65d6b5220443ed0f3d4c8a812712 (diff)
downloadgstreamer-plugins-bad-00ad8716289eb438425956d8d5d529d31e5a4a25.tar.gz
h264decoder: Output decoded pictures as soon as possible
In case of IDR, any previously decoded pictures must be drained before the IDR and POC of IDR should be zero. So we can output IDR immediately. Also, when POC of current picture is expected to be the next output POC, decoder can output the picture as well without waiting. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1211>
Diffstat (limited to 'gst-libs')
-rw-r--r--gst-libs/gst/codecs/gsth264decoder.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/gst-libs/gst/codecs/gsth264decoder.c b/gst-libs/gst/codecs/gsth264decoder.c
index 39eb17b19..a240b81ba 100644
--- a/gst-libs/gst/codecs/gsth264decoder.c
+++ b/gst-libs/gst/codecs/gsth264decoder.c
@@ -875,6 +875,7 @@ gst_h264_decoder_fill_picture_from_slice (GstH264Decoder * self,
}
picture->idr = slice->nalu.idr_pic_flag;
+ picture->dec_ref_pic_marking = slice_hdr->dec_ref_pic_marking;
if (picture->idr)
picture->idr_pic_id = slice_hdr->idr_pic_id;
@@ -1571,6 +1572,47 @@ gst_h264_decoder_finish_picture (GstH264Decoder * self,
gst_h264_dpb_add (priv->dpb, gst_h264_picture_ref (picture));
}
+ /* C.4.5.3 "Bumping" process for non-DPB full case, DPB full cases should be
+ * covered above */
+ /* FIXME: should cover interlaced streams */
+ if (!picture->outputted && picture->field == GST_H264_PICTURE_FIELD_FRAME) {
+ gboolean do_output = TRUE;
+ if (picture->idr &&
+ !picture->dec_ref_pic_marking.no_output_of_prior_pics_flag) {
+ /* The current picture is an IDR picture and no_output_of_prior_pics_flag
+ * is not equal to 1 and is not inferred to be equal to 1, as specified
+ * in clause C.4.4 */
+ GST_TRACE_OBJECT (self, "Output IDR picture");
+ } else if (picture->mem_mgmt_5) {
+ /* The current picture has memory_management_control_operation equal to 5,
+ * as specified in clause C.4.4 */
+ GST_TRACE_OBJECT (self, "Output mem_mgmt_5 picture");
+ } else if (priv->last_output_poc >= 0 &&
+ picture->pic_order_cnt > priv->last_output_poc &&
+ (picture->pic_order_cnt - priv->last_output_poc) <= 2) {
+ /* NOTE: this condition is not specified by spec but we can output
+ * this picture based on calculated POC and last outputted POC */
+
+ /* NOTE: The assumption here is, every POC of frame will have step of two.
+ * however, if the assumption is wrong, (i.e., POC step is one, not two),
+ * this would break output order. If this assumption is wrong,
+ * please remove this condition.
+ */
+ GST_LOG_OBJECT (self,
+ "Forcing output picture %p (frame num %d, poc %d, last poc %d)",
+ picture, picture->frame_num, picture->pic_order_cnt,
+ priv->last_output_poc);
+ } else {
+ do_output = FALSE;
+ GST_TRACE_OBJECT (self, "Current picture %p (frame num %d, poc %d) "
+ "is not ready to be output picture",
+ picture, picture->frame_num, picture->pic_order_cnt);
+ }
+
+ if (do_output)
+ gst_h264_decoder_do_output_picture (self, picture);
+ }
+
if (not_outputted)
g_list_free_full (not_outputted, (GDestroyNotify) gst_h264_picture_unref);