From 2305b0db461753c756fe60b4ad60d5497f642ab0 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Wed, 30 Jan 2013 16:33:48 +0100 Subject: [PATCH] decoder: allow frames to be dropped. If the decoder was not able to decode a frame because insufficient information was available, e.g. missing sequence or picture header, then allow the frame to be gracefully dropped without generating any error. It is also possible that a frame is not meant to be displayed but only used as a reference, so dropping that frame is also a valid operation since GstVideoDecoder base class has extra references to that GstVideoCodecFrame that needs to be released. --- gst-libs/gst/vaapi/gstvaapidecoder.c | 31 +++++++++++++++++++++++ gst-libs/gst/vaapi/gstvaapidecoder_priv.h | 4 +++ 2 files changed, 35 insertions(+) diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.c b/gst-libs/gst/vaapi/gstvaapidecoder.c index 97baec2d1b..1f346e682e 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder.c @@ -48,6 +48,9 @@ enum { static GParamSpec *g_properties[N_PROPERTIES] = { NULL, }; +static void +drop_frame(GstVaapiDecoder *decoder, GstVideoCodecFrame *frame); + static void parser_state_finalize(GstVaapiParserState *ps) { @@ -246,6 +249,10 @@ do_decode_1(GstVaapiDecoder *decoder, GstVaapiDecoderFrame *frame) if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status; } + + /* Drop frame if there is no slice data unit in there */ + if (G_UNLIKELY(frame->units->len == 0)) + return GST_VAAPI_DECODER_STATUS_DROP_FRAME; return GST_VAAPI_DECODER_STATUS_SUCCESS; } @@ -261,6 +268,13 @@ do_decode(GstVaapiDecoder *decoder, GstVideoCodecFrame *base_frame) gst_vaapi_decoder_frame_ref(frame); status = do_decode_1(decoder, frame); gst_vaapi_decoder_frame_unref(frame); + + switch ((guint)status) { + case GST_VAAPI_DECODER_STATUS_DROP_FRAME: + drop_frame(decoder, base_frame); + status = GST_VAAPI_DECODER_STATUS_SUCCESS; + break; + } return status; } @@ -351,6 +365,23 @@ decode_step(GstVaapiDecoder *decoder) return status; } +static void +drop_frame(GstVaapiDecoder *decoder, GstVideoCodecFrame *frame) +{ + GstVaapiDecoderPrivate * const priv = decoder->priv; + + GST_DEBUG("drop frame %d", frame->system_frame_number); + + /* no surface proxy */ + gst_video_codec_frame_set_user_data(frame, NULL, NULL); + + frame->pts = GST_CLOCK_TIME_NONE; + GST_VIDEO_CODEC_FRAME_FLAG_SET(frame, + GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY); + + g_queue_push_tail(priv->frames, gst_video_codec_frame_ref(frame)); +} + static inline void push_frame(GstVaapiDecoder *decoder, GstVideoCodecFrame *frame) { diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h index 9b0867d4ab..bb4e02ba08 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h +++ b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h @@ -145,6 +145,10 @@ G_BEGIN_DECLS GST_VAAPI_TYPE_DECODER, \ GstVaapiDecoderPrivate)) +typedef enum { + GST_VAAPI_DECODER_STATUS_DROP_FRAME = -2 +} GstVaapiDecoderStatusPrivate; + typedef struct _GstVaapiParserState GstVaapiParserState; struct _GstVaapiParserState { GstVideoCodecFrame *current_frame;