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.
This commit is contained in:
Gwenole Beauchesne 2013-01-30 16:33:48 +01:00
parent 41dcd82e2f
commit 2305b0db46
2 changed files with 35 additions and 0 deletions

View file

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

View file

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