From 4e422bec4fa7be03f7540c2c1d939b36305d0fb3 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Fri, 17 Nov 2017 17:09:22 +1100 Subject: [PATCH] nvdec: implement flush/drain Fixes outputted frame sequence when performing a seek i.e. when seeking backwards, the first frame after the seek was a frame from the future. This would result in GstVideoDecoder essentially marking all the timestamps as essentially bogus and the base class would attempt to compensate. A visible indication of this was 'decreasing timestamp' warning after a seek. https://bugzilla.gnome.org/show_bug.cgi?id=790478 --- sys/nvdec/gstnvdec.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/sys/nvdec/gstnvdec.c b/sys/nvdec/gstnvdec.c index 618c990..841a701 100644 --- a/sys/nvdec/gstnvdec.c +++ b/sys/nvdec/gstnvdec.c @@ -216,6 +216,8 @@ static gboolean gst_nvdec_decide_allocation (GstVideoDecoder * decoder, static void gst_nvdec_set_context (GstElement * element, GstContext * context); static gboolean gst_nvdec_src_query (GstVideoDecoder * decoder, GstQuery * query); +static gboolean gst_nvdec_flush (GstVideoDecoder * decoder); +static GstFlowReturn gst_nvdec_drain (GstVideoDecoder * decoder); static GstStaticPadTemplate gst_nvdec_sink_template = GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME, @@ -260,6 +262,8 @@ gst_nvdec_class_init (GstNvDecClass * klass) video_decoder_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_nvdec_decide_allocation); video_decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_nvdec_src_query); + video_decoder_class->drain = GST_DEBUG_FUNCPTR (gst_nvdec_drain); + video_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_nvdec_flush); element_class->set_context = GST_DEBUG_FUNCPTR (gst_nvdec_set_context); } @@ -857,6 +861,44 @@ gst_nvdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) } static gboolean +gst_nvdec_flush (GstVideoDecoder * decoder) +{ + GstNvDec *nvdec = GST_NVDEC (decoder); + CUVIDSOURCEDATAPACKET packet = { 0, }; + + GST_DEBUG_OBJECT (nvdec, "flush"); + + packet.payload_size = 0; + packet.payload = NULL; + packet.flags = CUVID_PKT_ENDOFSTREAM; + + if (!cuda_OK (cuvidParseVideoData (nvdec->parser, &packet))) + GST_WARNING_OBJECT (nvdec, "parser failed"); + + handle_pending_frames (nvdec); + + return TRUE; +} + +static GstFlowReturn +gst_nvdec_drain (GstVideoDecoder * decoder) +{ + GstNvDec *nvdec = GST_NVDEC (decoder); + CUVIDSOURCEDATAPACKET packet = { 0, }; + + GST_DEBUG_OBJECT (nvdec, "draining decoder"); + + packet.payload_size = 0; + packet.payload = NULL; + packet.flags = CUVID_PKT_ENDOFSTREAM; + + if (!cuda_OK (cuvidParseVideoData (nvdec->parser, &packet))) + GST_WARNING_OBJECT (nvdec, "parser failed"); + + return handle_pending_frames (nvdec); +} + +static gboolean gst_nvdec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) { GstNvDec *nvdec = GST_NVDEC (decoder); -- 2.7.4