mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 18:50:48 +00:00
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:
parent
8018fa2526
commit
48a6641717
2 changed files with 32 additions and 1 deletions
|
@ -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");
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue