From 309a9406141089548ec0783e9f76b396fdb2607d Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Mon, 15 Mar 2021 18:26:03 +0900 Subject: [PATCH] d3d11decoder: Do negotiation again per forward/reverse playback mode change For reverse playback, we are always copying decoded frame to downstream buffer. So the pool size can be and need to be large enough. In case that forward playback, however, we need to restrict the max pool size for performance reason. Otherwise decoder will keep copying decoded texture to downstream buffer pool if decoding is faster than downstream throughput performance and also there are queue element between them. Part-of: --- sys/d3d11/gstd3d11decoder.cpp | 60 ++++++++++++++++++++++++++++++---- sys/d3d11/gstd3d11decoder.h | 4 ++- sys/d3d11/gstd3d11h264dec.cpp | 13 ++++++++ sys/d3d11/gstd3d11h265dec.cpp | 13 ++++++++ sys/d3d11/gstd3d11mpeg2dec.cpp | 13 ++++++++ sys/d3d11/gstd3d11vp8dec.cpp | 13 ++++++++ sys/d3d11/gstd3d11vp9dec.cpp | 13 ++++++++ 7 files changed, 122 insertions(+), 7 deletions(-) diff --git a/sys/d3d11/gstd3d11decoder.cpp b/sys/d3d11/gstd3d11decoder.cpp index 197affef27..b4ab233d41 100644 --- a/sys/d3d11/gstd3d11decoder.cpp +++ b/sys/d3d11/gstd3d11decoder.cpp @@ -125,6 +125,8 @@ struct _GstD3D11Decoder gboolean configured; gboolean opened; + gboolean reverse_playback; + GstD3D11Device *device; ID3D11VideoDevice *video_device; @@ -989,26 +991,43 @@ gst_d3d11_decoder_get_output_view_buffer (GstD3D11Decoder * decoder, { GstBuffer *buf = NULL; GstFlowReturn ret; + gboolean reverse_playback = FALSE; + gboolean rate_changed = FALSE; g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE); - if (!decoder->internal_pool) { + if (videodec->input_segment.rate < 0) + reverse_playback = TRUE; + + if (reverse_playback != decoder->reverse_playback) { + GST_DEBUG_OBJECT (videodec, "Rate was changed, need re-negotiation"); + rate_changed = TRUE; + } + + if (!decoder->internal_pool || rate_changed) { + gboolean reconfigured; + /* Replicate gst_video_decoder_allocate_output_buffer(). * In case of zero-copy playback, this is the last chance for querying * required min-buffer size by downstream and take account of * the min-buffer size into our internel pool size */ GST_VIDEO_DECODER_STREAM_LOCK (videodec); - if (gst_pad_check_reconfigure (GST_VIDEO_DECODER_SRC_PAD (videodec))) { - GST_DEBUG_OBJECT (videodec, - "Downstream was reconfigured, negotiating again"); - gst_video_decoder_negotiate (videodec); - } + reconfigured = + gst_pad_check_reconfigure (GST_VIDEO_DECODER_SRC_PAD (videodec)); + GST_DEBUG_OBJECT (videodec, + "Downstream was reconfigured, negotiating again"); GST_VIDEO_DECODER_STREAM_UNLOCK (videodec); + if (reconfigured || rate_changed) + gst_video_decoder_negotiate (videodec); + if (!gst_d3d11_decoder_prepare_output_view_pool (decoder)) { GST_ERROR_OBJECT (videodec, "Failed to setup internal pool"); return NULL; } + } else if (!gst_buffer_pool_set_active (decoder->internal_pool, TRUE)) { + GST_ERROR_OBJECT (videodec, "Couldn't set active internal pool"); + return NULL; } ret = gst_buffer_pool_acquire_buffer (decoder->internal_pool, &buf, NULL); @@ -1408,6 +1427,22 @@ gst_d3d11_decoder_decide_allocation (GstD3D11Decoder * decoder, size = (guint) vinfo.size; } + if (videodec->input_segment.rate >= 0) { + decoder->reverse_playback = FALSE; + + /* Don't allow too large pool size */ + if (use_d3d11_pool) { + guint prev_max = max; + + max = MAX (4, max); + max = MAX (max, min); + + GST_DEBUG_OBJECT (videodec, "Update max size %d -> %d", prev_max, max); + } + } else { + decoder->reverse_playback = TRUE; + } + config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, outcaps, size, min, max); gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); @@ -1464,6 +1499,19 @@ gst_d3d11_decoder_decide_allocation (GstD3D11Decoder * decoder, return TRUE; } +gboolean +gst_d3d11_decoder_flush (GstD3D11Decoder * decoder, GstVideoDecoder * videodec) +{ + g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE); + + /* Set active FALSE so that other thread which is waiting DPB texture buffer + * to be able to wakeup */ + if (decoder->internal_pool) + gst_buffer_pool_set_active (decoder->internal_pool, FALSE); + + return TRUE; +} + gboolean gst_d3d11_decoder_can_direct_render (GstD3D11Decoder * decoder, GstBuffer * view_buffer, GstMiniObject * picture) diff --git a/sys/d3d11/gstd3d11decoder.h b/sys/d3d11/gstd3d11decoder.h index 132c09dc4b..1a85ca4ea4 100644 --- a/sys/d3d11/gstd3d11decoder.h +++ b/sys/d3d11/gstd3d11decoder.h @@ -109,11 +109,13 @@ gboolean gst_d3d11_decoder_decide_allocation (GstD3D11Decoder * decod GstVideoDecoder * videodec, GstQuery * query); +gboolean gst_d3d11_decoder_flush (GstD3D11Decoder * decoder, + GstVideoDecoder * videodec); + gboolean gst_d3d11_decoder_can_direct_render (GstD3D11Decoder * decoder, GstBuffer * view_buffer, GstMiniObject * picture); - /* Utils for class registration */ gboolean gst_d3d11_decoder_util_is_legacy_device (GstD3D11Device * device); diff --git a/sys/d3d11/gstd3d11h264dec.cpp b/sys/d3d11/gstd3d11h264dec.cpp index 66ceede7da..d35e8f162c 100644 --- a/sys/d3d11/gstd3d11h264dec.cpp +++ b/sys/d3d11/gstd3d11h264dec.cpp @@ -157,6 +157,7 @@ static gboolean gst_d3d11_h264_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query); static gboolean gst_d3d11_h264_dec_src_query (GstVideoDecoder * decoder, GstQuery * query); +static gboolean gst_d3d11_h264_dec_flush (GstVideoDecoder * decoder); /* GstH264Decoder */ static gboolean gst_d3d11_h264_dec_new_sequence (GstH264Decoder * decoder, @@ -235,6 +236,7 @@ gst_d3d11_h264_dec_class_init (GstD3D11H264DecClass * klass, gpointer data) decoder_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_d3d11_h264_dec_decide_allocation); decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d11_h264_dec_src_query); + decoder_class->flush = GST_DEBUG_FUNCPTR (gst_d3d11_h264_dec_flush); h264decoder_class->new_sequence = GST_DEBUG_FUNCPTR (gst_d3d11_h264_dec_new_sequence); @@ -408,6 +410,17 @@ gst_d3d11_h264_dec_src_query (GstVideoDecoder * decoder, GstQuery * query) return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query); } +static gboolean +gst_d3d11_h264_dec_flush (GstVideoDecoder * decoder) +{ + GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder); + + if (self->d3d11_decoder) + gst_d3d11_decoder_flush (self->d3d11_decoder, decoder); + + return GST_VIDEO_DECODER_CLASS (parent_class)->flush (decoder); +} + static gboolean gst_d3d11_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps, gint max_dpb_size) diff --git a/sys/d3d11/gstd3d11h265dec.cpp b/sys/d3d11/gstd3d11h265dec.cpp index 0c8914e504..b520106a46 100644 --- a/sys/d3d11/gstd3d11h265dec.cpp +++ b/sys/d3d11/gstd3d11h265dec.cpp @@ -127,6 +127,7 @@ static gboolean gst_d3d11_h265_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query); static gboolean gst_d3d11_h265_dec_src_query (GstVideoDecoder * decoder, GstQuery * query); +static gboolean gst_d3d11_h265_dec_flush (GstVideoDecoder * decoder); /* GstH265Decoder */ static gboolean gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder, @@ -209,6 +210,7 @@ gst_d3d11_h265_dec_class_init (GstD3D11H265DecClass * klass, gpointer data) decoder_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_decide_allocation); decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_src_query); + decoder_class->flush = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_flush); h265decoder_class->new_sequence = GST_DEBUG_FUNCPTR (gst_d3d11_h265_dec_new_sequence); @@ -363,6 +365,17 @@ gst_d3d11_h265_dec_src_query (GstVideoDecoder * decoder, GstQuery * query) return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query); } +static gboolean +gst_d3d11_h265_dec_flush (GstVideoDecoder * decoder) +{ + GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder); + + if (self->d3d11_decoder) + gst_d3d11_decoder_flush (self->d3d11_decoder, decoder); + + return GST_VIDEO_DECODER_CLASS (parent_class)->flush (decoder); +} + static gboolean gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps, gint max_dpb_size) diff --git a/sys/d3d11/gstd3d11mpeg2dec.cpp b/sys/d3d11/gstd3d11mpeg2dec.cpp index 1c2cbc9784..7d5a2c1c1c 100644 --- a/sys/d3d11/gstd3d11mpeg2dec.cpp +++ b/sys/d3d11/gstd3d11mpeg2dec.cpp @@ -121,6 +121,7 @@ static gboolean gst_d3d11_mpeg2_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query); static gboolean gst_d3d11_mpeg2_dec_src_query (GstVideoDecoder * decoder, GstQuery * query); +static gboolean gst_d3d11_mpeg2_dec_flush (GstVideoDecoder * decoder); /* GstMpeg2Decoder */ static gboolean gst_d3d11_mpeg2_dec_new_sequence (GstMpeg2Decoder * decoder, @@ -200,6 +201,7 @@ gst_d3d11_mpeg2_dec_class_init (GstD3D11Mpeg2DecClass * klass, gpointer data) decoder_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_d3d11_mpeg2_dec_decide_allocation); decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d11_mpeg2_dec_src_query); + decoder_class->flush = GST_DEBUG_FUNCPTR (gst_d3d11_mpeg2_dec_flush); mpeg2decoder_class->new_sequence = GST_DEBUG_FUNCPTR (gst_d3d11_mpeg2_dec_new_sequence); @@ -350,6 +352,17 @@ gst_d3d11_mpeg2_dec_src_query (GstVideoDecoder * decoder, GstQuery * query) return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query); } +static gboolean +gst_d3d11_mpeg2_dec_flush (GstVideoDecoder * decoder) +{ + GstD3D11Mpeg2Dec *self = GST_D3D11_MPEG2_DEC (decoder); + + if (self->d3d11_decoder) + gst_d3d11_decoder_flush (self->d3d11_decoder, decoder); + + return GST_VIDEO_DECODER_CLASS (parent_class)->flush (decoder); +} + static gboolean gst_d3d11_mpeg2_dec_new_sequence (GstMpeg2Decoder * decoder, const GstMpegVideoSequenceHdr * seq, diff --git a/sys/d3d11/gstd3d11vp8dec.cpp b/sys/d3d11/gstd3d11vp8dec.cpp index e65d0e515e..a81405f41c 100644 --- a/sys/d3d11/gstd3d11vp8dec.cpp +++ b/sys/d3d11/gstd3d11vp8dec.cpp @@ -107,6 +107,7 @@ static gboolean gst_d3d11_vp8_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query); static gboolean gst_d3d11_vp8_dec_src_query (GstVideoDecoder * decoder, GstQuery * query); +static gboolean gst_d3d11_vp8_dec_flush (GstVideoDecoder * decoder); /* GstVp8Decoder */ static gboolean gst_d3d11_vp8_dec_new_sequence (GstVp8Decoder * decoder, @@ -178,6 +179,7 @@ gst_d3d11_vp8_dec_class_init (GstD3D11Vp8DecClass * klass, gpointer data) decoder_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_d3d11_vp8_dec_decide_allocation); decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d11_vp8_dec_src_query); + decoder_class->flush = GST_DEBUG_FUNCPTR (gst_d3d11_vp8_dec_flush); vp8decoder_class->new_sequence = GST_DEBUG_FUNCPTR (gst_d3d11_vp8_dec_new_sequence); @@ -314,6 +316,17 @@ gst_d3d11_vp8_dec_src_query (GstVideoDecoder * decoder, GstQuery * query) return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query); } +static gboolean +gst_d3d11_vp8_dec_flush (GstVideoDecoder * decoder) +{ + GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder); + + if (self->d3d11_decoder) + gst_d3d11_decoder_flush (self->d3d11_decoder, decoder); + + return GST_VIDEO_DECODER_CLASS (parent_class)->flush (decoder); +} + static gboolean gst_d3d11_vp8_dec_new_sequence (GstVp8Decoder * decoder, const GstVp8FrameHdr * frame_hdr) diff --git a/sys/d3d11/gstd3d11vp9dec.cpp b/sys/d3d11/gstd3d11vp9dec.cpp index 23aa23c089..0e06a1fc89 100644 --- a/sys/d3d11/gstd3d11vp9dec.cpp +++ b/sys/d3d11/gstd3d11vp9dec.cpp @@ -141,6 +141,7 @@ static gboolean gst_d3d11_vp9_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query); static gboolean gst_d3d11_vp9_dec_src_query (GstVideoDecoder * decoder, GstQuery * query); +static gboolean gst_d3d11_vp9_dec_flush (GstVideoDecoder * decoder); /* GstVp9Decoder */ static gboolean gst_d3d11_vp9_dec_new_sequence (GstVp9Decoder * decoder, @@ -214,6 +215,7 @@ gst_d3d11_vp9_dec_class_init (GstD3D11Vp9DecClass * klass, gpointer data) decoder_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_d3d11_vp9_dec_decide_allocation); decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d11_vp9_dec_src_query); + decoder_class->flush = GST_DEBUG_FUNCPTR (gst_d3d11_vp9_dec_flush); vp9decoder_class->new_sequence = GST_DEBUG_FUNCPTR (gst_d3d11_vp9_dec_new_sequence); @@ -352,6 +354,17 @@ gst_d3d11_vp9_dec_src_query (GstVideoDecoder * decoder, GstQuery * query) return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query); } +static gboolean +gst_d3d11_vp9_dec_flush (GstVideoDecoder * decoder) +{ + GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder); + + if (self->d3d11_decoder) + gst_d3d11_decoder_flush (self->d3d11_decoder, decoder); + + return GST_VIDEO_DECODER_CLASS (parent_class)->flush (decoder); +} + static gboolean gst_d3d11_vp9_dec_new_sequence (GstVp9Decoder * decoder, const GstVp9Parser * parser, const GstVp9FrameHdr * frame_hdr)