mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 20:42:30 +00:00
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:
parent
41dcd82e2f
commit
2305b0db46
2 changed files with 35 additions and 0 deletions
|
@ -48,6 +48,9 @@ enum {
|
||||||
|
|
||||||
static GParamSpec *g_properties[N_PROPERTIES] = { NULL, };
|
static GParamSpec *g_properties[N_PROPERTIES] = { NULL, };
|
||||||
|
|
||||||
|
static void
|
||||||
|
drop_frame(GstVaapiDecoder *decoder, GstVideoCodecFrame *frame);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parser_state_finalize(GstVaapiParserState *ps)
|
parser_state_finalize(GstVaapiParserState *ps)
|
||||||
{
|
{
|
||||||
|
@ -246,6 +249,10 @@ do_decode_1(GstVaapiDecoder *decoder, GstVaapiDecoderFrame *frame)
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
return status;
|
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;
|
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +268,13 @@ do_decode(GstVaapiDecoder *decoder, GstVideoCodecFrame *base_frame)
|
||||||
gst_vaapi_decoder_frame_ref(frame);
|
gst_vaapi_decoder_frame_ref(frame);
|
||||||
status = do_decode_1(decoder, frame);
|
status = do_decode_1(decoder, frame);
|
||||||
gst_vaapi_decoder_frame_unref(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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,6 +365,23 @@ decode_step(GstVaapiDecoder *decoder)
|
||||||
return status;
|
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
|
static inline void
|
||||||
push_frame(GstVaapiDecoder *decoder, GstVideoCodecFrame *frame)
|
push_frame(GstVaapiDecoder *decoder, GstVideoCodecFrame *frame)
|
||||||
{
|
{
|
||||||
|
|
|
@ -145,6 +145,10 @@ G_BEGIN_DECLS
|
||||||
GST_VAAPI_TYPE_DECODER, \
|
GST_VAAPI_TYPE_DECODER, \
|
||||||
GstVaapiDecoderPrivate))
|
GstVaapiDecoderPrivate))
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GST_VAAPI_DECODER_STATUS_DROP_FRAME = -2
|
||||||
|
} GstVaapiDecoderStatusPrivate;
|
||||||
|
|
||||||
typedef struct _GstVaapiParserState GstVaapiParserState;
|
typedef struct _GstVaapiParserState GstVaapiParserState;
|
||||||
struct _GstVaapiParserState {
|
struct _GstVaapiParserState {
|
||||||
GstVideoCodecFrame *current_frame;
|
GstVideoCodecFrame *current_frame;
|
||||||
|
|
Loading…
Reference in a new issue