summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVíctor Manuel Jáquez Leal <vjaquez@igalia.com>2019-11-03 17:59:01 +0100
committerTim-Philipp Müller <tim@centricular.com>2019-11-29 16:32:36 +0000
commit42f844e75cf7cc86054f005f307aac3004304eac (patch)
tree77abf1ade200982cffbc9be4d1ff4106590d6f09
parent73035433d1119556849907a23465f626a1ce0c78 (diff)
libs: decoder: h265: skip all pictures prior the first I-frame
Don't try to decode until the first I-frame is received within the currently active sequence. i965 H265 decoder don't show any artifact but it crashes. Fixes: #98
-rw-r--r--gst-libs/gst/vaapi/gstvaapidecoder_h265.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h265.c b/gst-libs/gst/vaapi/gstvaapidecoder_h265.c
index 61f508ab..edc06be3 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder_h265.c
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_h265.c
@@ -343,6 +343,8 @@ typedef enum
GST_H265_VIDEO_STATE_GOT_SPS = 1 << 1,
GST_H265_VIDEO_STATE_GOT_PPS = 1 << 2,
GST_H265_VIDEO_STATE_GOT_SLICE = 1 << 3,
+ GST_H265_VIDEO_STATE_GOT_I_FRAME = 1 << 4, /* persistent across SPS */
+ GST_H265_VIDEO_STATE_GOT_P_SLICE = 1 << 5, /* predictive (all non-intra) */
GST_H265_VIDEO_STATE_VALID_PICTURE_HEADERS =
(GST_H265_VIDEO_STATE_GOT_SPS | GST_H265_VIDEO_STATE_GOT_PPS),
@@ -562,6 +564,11 @@ ensure_sps (GstVaapiDecoderH265 * decoder, GstH265SPS * sps)
GstVaapiDecoderH265Private *const priv = &decoder->priv;
GstVaapiParserInfoH265 *const pi = priv->sps[sps->id];
+ /* Propagate "got I-frame" state to the next SPS unit if the current
+ * sequence was not ended */
+ if (pi && priv->active_sps)
+ pi->state |= (priv->active_sps->state & GST_H265_VIDEO_STATE_GOT_I_FRAME);
+
gst_vaapi_parser_info_h265_replace (&priv->active_sps, pi);
return pi ? &pi->data.sps : NULL;
}
@@ -1299,12 +1306,20 @@ static GstVaapiDecoderStatus
decode_current_picture (GstVaapiDecoderH265 * decoder)
{
GstVaapiDecoderH265Private *const priv = &decoder->priv;
+ GstVaapiParserInfoH265 *const sps_pi = decoder->priv.active_sps;
GstVaapiPictureH265 *const picture = priv->current_picture;
if (!is_valid_state (priv->decoder_state, GST_H265_VIDEO_STATE_VALID_PICTURE)) {
goto drop_frame;
}
+ priv->decoder_state |= sps_pi->state;
+ if (!(priv->decoder_state & GST_H265_VIDEO_STATE_GOT_I_FRAME)) {
+ if (priv->decoder_state & GST_H265_VIDEO_STATE_GOT_P_SLICE)
+ goto drop_frame;
+ sps_pi->state |= GST_H265_VIDEO_STATE_GOT_I_FRAME;
+ }
+
priv->decoder_state = 0;
/* FIXME: Use SEI header values */
priv->pic_structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
@@ -1441,6 +1456,8 @@ parse_slice (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
return get_status (result);
priv->parser_state |= GST_H265_VIDEO_STATE_GOT_SLICE;
+ if (!GST_H265_IS_I_SLICE (slice_hdr))
+ priv->parser_state |= GST_H265_VIDEO_STATE_GOT_P_SLICE;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
@@ -1530,9 +1547,15 @@ static GstVaapiDecoderStatus
decode_sequence_end (GstVaapiDecoderH265 * decoder)
{
GstVaapiDecoderStatus status;
+ GstVaapiParserInfoH265 *const sps_pi = decoder->priv.active_sps;
GST_DEBUG ("decode sequence-end");
+ /* Sequence ended, don't try to propagate "got I-frame" state beyond
+ * this point */
+ if (sps_pi)
+ sps_pi->state &= ~GST_H265_VIDEO_STATE_GOT_I_FRAME;
+
status = decode_current_picture (decoder);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
@@ -2572,7 +2595,6 @@ decode_slice (GstVaapiDecoderH265 * decoder, GstVaapiDecoderUnit * unit)
gst_vaapi_picture_add_slice (GST_VAAPI_PICTURE_CAST (picture), slice);
picture->last_slice_hdr = slice_hdr;
- priv->decoder_state |= GST_H265_VIDEO_STATE_GOT_SLICE;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}