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)