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>
This commit is contained in:
Seungha Yang 2020-04-23 19:47:09 +09:00 committed by GStreamer Merge Bot
parent ed6236f551
commit 00ad871628

View file

@ -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);