nvdec: Fix video stuttering issue with VP9

Address nvidia driver specific behavior to avoid unexpected frame mismatch
between GStreamer and NVDEC.
This commit is contained in:
Seungha Yang 2019-07-19 01:07:38 +09:00
parent 8018fa2526
commit 48a6641717
2 changed files with 32 additions and 1 deletions

View file

@ -445,18 +445,36 @@ parser_decode_callback (GstNvDec * nvdec, CUVIDPICPARAMS * params)
}
pending_frames = gst_video_decoder_get_frames (GST_VIDEO_DECODER (nvdec));
/* NOTE: this decode callback could be invoked multiple times for
* one cuvidParseVideoData() call. Most likely it can be related to "decode only"
* frame of VPX codec but no document available.
* In that case, the last decoded frame seems to be displayed */
for (iter = pending_frames; iter; iter = g_list_next (iter)) {
guint id;
GstVideoCodecFrame *frame = (GstVideoCodecFrame *) iter->data;
gboolean set_data = FALSE;
id = GPOINTER_TO_UINT (gst_video_codec_frame_get_user_data (frame));
if (!id) {
if (G_UNLIKELY (nvdec->state == GST_NVDEC_STATE_DECODE)) {
if (id) {
GST_LOG_OBJECT (nvdec, "reset the last user data");
set_data = TRUE;
}
} else if (!id) {
set_data = TRUE;
}
if (set_data) {
gst_video_codec_frame_set_user_data (frame,
GUINT_TO_POINTER (params->CurrPicIdx + 1), NULL);
break;
}
}
nvdec->state = GST_NVDEC_STATE_DECODE;
g_list_free_full (pending_frames,
(GDestroyNotify) gst_video_codec_frame_unref);
@ -586,6 +604,7 @@ gst_nvdec_start (GstVideoDecoder * decoder)
{
GstNvDec *nvdec = GST_NVDEC (decoder);
nvdec->state = GST_NVDEC_STATE_INIT;
GST_DEBUG_OBJECT (nvdec, "creating CUDA context");
nvdec->cuda_context = g_object_new (gst_nvdec_cuda_context_get_type (), NULL);
@ -851,6 +870,8 @@ gst_nvdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
if (GST_BUFFER_IS_DISCONT (frame->input_buffer))
packet.flags |= CUVID_PKT_DISCONTINUITY;
nvdec->state = GST_NVDEC_STATE_PARSE;
if (!cuda_OK (CuvidParseVideoData (nvdec->parser, &packet)))
GST_WARNING_OBJECT (nvdec, "parser failed");
@ -872,6 +893,8 @@ gst_nvdec_flush (GstVideoDecoder * decoder)
packet.payload = NULL;
packet.flags = CUVID_PKT_ENDOFSTREAM;
nvdec->state = GST_NVDEC_STATE_PARSE;
if (!cuda_OK (CuvidParseVideoData (nvdec->parser, &packet)))
GST_WARNING_OBJECT (nvdec, "parser failed");

View file

@ -64,6 +64,13 @@ GType gst_nvdec_cuda_context_get_type (void);
typedef struct _GstNvDec GstNvDec;
typedef struct _GstNvDecClass GstNvDecClass;
typedef enum
{
GST_NVDEC_STATE_INIT = 0,
GST_NVDEC_STATE_PARSE,
GST_NVDEC_STATE_DECODE,
} GstNvDecState;
struct _GstNvDec
{
GstVideoDecoder parent;
@ -84,6 +91,7 @@ struct _GstNvDec
GstVideoCodecState *input_state;
GstFlowReturn last_ret;
GstNvDecState state;
};
struct _GstNvDecClass