d3d11decoder: Move zero-copy decision logic into decoder object

Get rid of all duplicated code for zero-copy decision and output buffer
allocation

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2117>
This commit is contained in:
Seungha Yang 2021-03-28 16:06:55 +09:00
parent 03f1ff2042
commit bcdd2c4984
7 changed files with 130 additions and 298 deletions

View file

@ -137,12 +137,16 @@ struct _GstD3D11Decoder
ID3D11VideoDecoder *decoder_handle;
GstVideoInfo info;
GstVideoInfo output_info;
GstD3D11Codec codec;
gint coded_width;
gint coded_height;
DXGI_FORMAT decoder_format;
gboolean downstream_supports_d3d11;
GstVideoCodecState *input_state;
GstVideoCodecState *output_state;
GstBufferPool *internal_pool;
/* Internal pool params */
gint aligned_width;
@ -176,6 +180,9 @@ static void gst_d3d11_decoder_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void gst_d3d11_decoder_dispose (GObject * obj);
static void gst_d3d11_decoder_finalize (GObject * obj);
static gboolean gst_d3d11_decoder_can_direct_render (GstD3D11Decoder * decoder,
GstVideoDecoder * videodec, GstBuffer * view_buffer,
gint display_width, gint display_height);
#define parent_class gst_d3d11_decoder_parent_class
G_DEFINE_TYPE (GstD3D11Decoder, gst_d3d11_decoder, GST_TYPE_OBJECT);
@ -301,6 +308,9 @@ gst_d3d11_decoder_reset (GstD3D11Decoder * self)
self->use_array_of_texture = FALSE;
self->downstream_supports_d3d11 = FALSE;
g_clear_pointer (&self->output_state, gst_video_codec_state_unref);
g_clear_pointer (&self->input_state, gst_video_codec_state_unref);
}
static void
@ -645,7 +655,8 @@ gst_d3d11_decoder_get_supported_decoder_profile (GstD3D11Decoder * decoder,
gboolean
gst_d3d11_decoder_configure (GstD3D11Decoder * decoder, GstD3D11Codec codec,
GstVideoInfo * info, gint coded_width, gint coded_height, guint dpb_size)
GstVideoCodecState * input_state, GstVideoInfo * info, gint coded_width,
gint coded_height, guint dpb_size)
{
const GstD3D11Format *d3d11_format;
@ -653,6 +664,7 @@ gst_d3d11_decoder_configure (GstD3D11Decoder * decoder, GstD3D11Codec codec,
g_return_val_if_fail (codec > GST_D3D11_CODEC_NONE, FALSE);
g_return_val_if_fail (codec < GST_D3D11_CODEC_LAST, FALSE);
g_return_val_if_fail (info != NULL, FALSE);
g_return_val_if_fail (input_state != NULL, FALSE);
g_return_val_if_fail (coded_width >= GST_VIDEO_INFO_WIDTH (info), FALSE);
g_return_val_if_fail (coded_height >= GST_VIDEO_INFO_HEIGHT (info), FALSE);
g_return_val_if_fail (dpb_size > 0, FALSE);
@ -668,7 +680,8 @@ gst_d3d11_decoder_configure (GstD3D11Decoder * decoder, GstD3D11Codec codec,
}
decoder->codec = codec;
decoder->info = *info;
decoder->input_state = gst_video_codec_state_ref (input_state);
decoder->info = decoder->output_info = *info;
decoder->coded_width = coded_width;
decoder->coded_height = coded_height;
decoder->dpb_size = dpb_size;
@ -1192,10 +1205,11 @@ gst_d3d11_decoder_get_output_view_from_buffer (GstD3D11Decoder * decoder,
}
static gboolean
copy_to_system (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width,
gint display_height, GstBuffer * decoder_buffer, GstBuffer * output)
copy_to_system (GstD3D11Decoder * self, GstBuffer * decoder_buffer,
GstBuffer * output)
{
GstVideoFrame out_frame;
GstVideoInfo *info = &self->output_info;
guint i;
GstD3D11Memory *in_mem;
D3D11_MAPPED_SUBRESOURCE map;
@ -1272,9 +1286,10 @@ copy_to_system (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width,
}
static gboolean
copy_to_d3d11 (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width,
gint display_height, GstBuffer * decoder_buffer, GstBuffer * output)
copy_to_d3d11 (GstD3D11Decoder * self, GstBuffer * decoder_buffer,
GstBuffer * output)
{
GstVideoInfo *info = &self->output_info;
GstD3D11Memory *in_mem;
GstD3D11Memory *out_mem;
GstMapInfo out_map;
@ -1302,8 +1317,8 @@ copy_to_d3d11 (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width,
src_box.front = 0;
src_box.back = 1;
src_box.right = GST_ROUND_UP_2 (GST_VIDEO_INFO_WIDTH (&self->info));
src_box.bottom = GST_ROUND_UP_2 (GST_VIDEO_INFO_HEIGHT (&self->info));
src_box.right = GST_ROUND_UP_2 (GST_VIDEO_INFO_WIDTH (info));
src_box.bottom = GST_ROUND_UP_2 (GST_VIDEO_INFO_HEIGHT (info));
out_subresource_index = gst_d3d11_memory_get_subresource_index (out_mem);
device_context->CopySubresourceRegion ((ID3D11Resource *) out_map.data,
@ -1318,26 +1333,57 @@ copy_to_d3d11 (GstD3D11Decoder * self, GstVideoInfo * info, gint display_width,
gboolean
gst_d3d11_decoder_process_output (GstD3D11Decoder * decoder,
GstVideoInfo * info, gint display_width, gint display_height,
GstBuffer * decoder_buffer, GstBuffer * output)
GstVideoDecoder * videodec, gint display_width, gint display_height,
GstBuffer * decoder_buffer, GstBuffer ** output)
{
gboolean can_device_copy = TRUE;
g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
g_return_val_if_fail (GST_IS_VIDEO_DECODER (videodec), FALSE);
g_return_val_if_fail (GST_IS_BUFFER (decoder_buffer), FALSE);
g_return_val_if_fail (GST_IS_BUFFER (output), FALSE);
g_return_val_if_fail (output != NULL, FALSE);
if (display_width != GST_VIDEO_INFO_WIDTH (&decoder->output_info) ||
display_height != GST_VIDEO_INFO_HEIGHT (&decoder->output_info)) {
GST_INFO_OBJECT (videodec, "Frame size changed, do renegotiate");
gst_video_info_set_format (&decoder->output_info,
GST_VIDEO_INFO_FORMAT (&decoder->info),
display_width, display_height);
GST_VIDEO_INFO_INTERLACE_MODE (&decoder->output_info) =
GST_VIDEO_INFO_INTERLACE_MODE (&decoder->info);
if (!gst_video_decoder_negotiate (videodec)) {
GST_ERROR_OBJECT (videodec, "Failed to re-negotiate with new frame size");
return FALSE;
}
}
if (gst_d3d11_decoder_can_direct_render (decoder, videodec, decoder_buffer,
display_width, display_height)) {
GstMemory *mem;
mem = gst_buffer_peek_memory (decoder_buffer, 0);
GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
*output = gst_buffer_ref (decoder_buffer);
/* if decoder buffer is intended to be outputted and we don't need to
* do post processing, do nothing here */
if (decoder_buffer == output)
return TRUE;
}
*output = gst_video_decoder_allocate_output_buffer (videodec);
if (*output == NULL) {
GST_ERROR_OBJECT (videodec, "Couldn't allocate output buffer");
return FALSE;
}
/* decoder buffer must have single memory */
if (gst_buffer_n_memory (decoder_buffer) == gst_buffer_n_memory (output)) {
if (gst_buffer_n_memory (decoder_buffer) == gst_buffer_n_memory (*output)) {
GstMemory *mem;
GstD3D11Memory *dmem;
mem = gst_buffer_peek_memory (output, 0);
mem = gst_buffer_peek_memory (*output, 0);
if (!gst_is_d3d11_memory (mem)) {
can_device_copy = FALSE;
goto do_process;
@ -1352,32 +1398,29 @@ gst_d3d11_decoder_process_output (GstD3D11Decoder * decoder,
do_process:
if (can_device_copy) {
return copy_to_d3d11 (decoder, info, display_width, display_height,
decoder_buffer, output);
return copy_to_d3d11 (decoder, decoder_buffer, *output);
}
return copy_to_system (decoder, info, display_width, display_height,
decoder_buffer, output);
return copy_to_system (decoder, decoder_buffer, *output);
}
gboolean
gst_d3d11_decoder_negotiate (GstD3D11Decoder * decoder,
GstVideoDecoder * videodec, GstVideoCodecState * input_state,
GstVideoCodecState ** output_state)
GstVideoDecoder * videodec)
{
GstVideoInfo *info;
GstCaps *peer_caps;
GstVideoCodecState *state = NULL;
gboolean alternate_interlaced;
gboolean alternate_supported = FALSE;
gboolean d3d11_supported = FALSE;
GstVideoInfo *info;
GstVideoCodecState *input_state;
g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
g_return_val_if_fail (GST_IS_VIDEO_DECODER (videodec), FALSE);
g_return_val_if_fail (input_state != NULL, FALSE);
g_return_val_if_fail (output_state != NULL, FALSE);
info = &decoder->info;
info = &decoder->output_info;
input_state = decoder->input_state;
alternate_interlaced =
(GST_VIDEO_INFO_INTERLACE_MODE (info) ==
@ -1463,9 +1506,8 @@ gst_d3d11_decoder_negotiate (GstD3D11Decoder * decoder,
state->caps = gst_video_info_to_caps (&state->info);
if (*output_state)
gst_video_codec_state_unref (*output_state);
*output_state = state;
g_clear_pointer (&decoder->output_state, gst_video_codec_state_unref);
decoder->output_state = state;
if (d3d11_supported) {
gst_caps_set_features (state->caps, 0,
@ -1632,20 +1674,28 @@ gst_d3d11_decoder_flush (GstD3D11Decoder * decoder, GstVideoDecoder * videodec)
return TRUE;
}
gboolean
static gboolean
gst_d3d11_decoder_can_direct_render (GstD3D11Decoder * decoder,
GstBuffer * view_buffer, GstMiniObject * picture)
GstVideoDecoder * videodec, GstBuffer * view_buffer,
gint display_width, gint display_height)
{
GstMemory *mem;
GstD3D11PoolAllocator *alloc;
guint max_size = 0, outstanding_size = 0;
g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
g_return_val_if_fail (GST_IS_BUFFER (view_buffer), FALSE);
/* We don't support direct render for reverse playback */
if (videodec->input_segment.rate < 0)
return FALSE;
if (!decoder->can_direct_rendering || !decoder->downstream_supports_d3d11)
return FALSE;
/* different size, need copy */
/* TODO: crop meta */
if (display_width != GST_VIDEO_INFO_WIDTH (&decoder->info) ||
display_height != GST_VIDEO_INFO_HEIGHT (&decoder->info))
return FALSE;
/* we can do direct render in this case, since there is no DPB pool size
* limit */
if (decoder->use_array_of_texture)

View file

@ -61,6 +61,7 @@ gboolean gst_d3d11_decoder_is_configured (GstD3D11Decoder * decoder);
gboolean gst_d3d11_decoder_configure (GstD3D11Decoder * decoder,
GstD3D11Codec codec,
GstVideoCodecState * input_state,
GstVideoInfo * info,
gint coded_width,
gint coded_height,
@ -93,16 +94,14 @@ ID3D11VideoDecoderOutputView * gst_d3d11_decoder_get_output_view_from_buffer (Gs
guint8 * view_id);
gboolean gst_d3d11_decoder_process_output (GstD3D11Decoder * decoder,
GstVideoInfo * info,
GstVideoDecoder * videodec,
gint display_width,
gint display_height,
GstBuffer * decoder_buffer,
GstBuffer * output);
GstBuffer ** output);
gboolean gst_d3d11_decoder_negotiate (GstD3D11Decoder * decoder,
GstVideoDecoder * videodec,
GstVideoCodecState * input_state,
GstVideoCodecState ** output_state);
GstVideoDecoder * videodec);
gboolean gst_d3d11_decoder_decide_allocation (GstD3D11Decoder * decoder,
GstVideoDecoder * videodec,
@ -111,10 +110,6 @@ gboolean gst_d3d11_decoder_decide_allocation (GstD3D11Decoder * decod
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);

View file

@ -100,8 +100,6 @@ typedef struct _GstD3D11H264Dec
{
GstH264Decoder parent;
GstVideoCodecState *output_state;
GstD3D11Device *device;
gint width, height;
@ -352,10 +350,6 @@ gst_d3d11_h264_dec_close (GstVideoDecoder * decoder)
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
if (self->output_state)
gst_video_codec_state_unref (self->output_state);
self->output_state = NULL;
gst_clear_object (&self->d3d11_decoder);
gst_clear_object (&self->device);
@ -366,12 +360,9 @@ static gboolean
gst_d3d11_h264_dec_negotiate (GstVideoDecoder * decoder)
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
GstH264Decoder *h264dec = GST_H264_DECODER (decoder);
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder, decoder,
h264dec->input_state, &self->output_state)) {
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder, decoder))
return FALSE;
}
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
@ -506,7 +497,7 @@ gst_d3d11_h264_dec_new_sequence (GstH264Decoder * decoder,
*/
self->max_dpb_size = max_dpb_size;
if (!gst_d3d11_decoder_configure (self->d3d11_decoder, GST_D3D11_CODEC_H264,
&info, self->coded_width, self->coded_height,
decoder->input_state, &info, self->coded_width, self->coded_height,
/* Additional 4 views margin for zero-copy rendering */
max_dpb_size + 4)) {
GST_ERROR_OBJECT (self, "Failed to create decoder");
@ -825,9 +816,7 @@ gst_d3d11_h264_dec_output_picture (GstH264Decoder * decoder,
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
GstBuffer *output_buffer = NULL;
GstBuffer *view_buffer;
gboolean direct_rendering = FALSE;
GST_LOG_OBJECT (self,
"Outputting picture %p (poc %d)", picture, picture->pic_order_cnt);
@ -839,37 +828,8 @@ gst_d3d11_h264_dec_output_picture (GstH264Decoder * decoder,
goto error;
}
/* if downstream is d3d11 element and forward playback case,
* expose our decoder view without copy. In case of reverse playback, however,
* we cannot do that since baseclass will store the decoded buffer
* up to gop size but our dpb pool cannot be increased */
if (GST_VIDEO_DECODER (self)->input_segment.rate > 0
&& gst_d3d11_decoder_can_direct_render (self->d3d11_decoder, view_buffer,
GST_MINI_OBJECT_CAST (picture))) {
direct_rendering = TRUE;
}
if (direct_rendering) {
GstMemory *mem;
output_buffer = gst_buffer_ref (view_buffer);
mem = gst_buffer_peek_memory (output_buffer, 0);
GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
} else {
output_buffer = gst_video_decoder_allocate_output_buffer (vdec);
}
if (!output_buffer) {
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
goto error;
}
frame->output_buffer = output_buffer;
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder,
&self->output_state->info,
GST_VIDEO_INFO_WIDTH (&self->output_state->info),
GST_VIDEO_INFO_HEIGHT (&self->output_state->info),
view_buffer, output_buffer)) {
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder, vdec,
self->width, self->height, view_buffer, &frame->output_buffer)) {
GST_ERROR_OBJECT (self, "Failed to copy buffer");
goto error;
}

View file

@ -70,8 +70,6 @@ typedef struct _GstD3D11H265Dec
{
GstH265Decoder parent;
GstVideoCodecState *output_state;
GstD3D11Device *device;
gint width, height;
@ -307,10 +305,6 @@ gst_d3d11_h265_dec_close (GstVideoDecoder * decoder)
{
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
if (self->output_state)
gst_video_codec_state_unref (self->output_state);
self->output_state = NULL;
gst_clear_object (&self->d3d11_decoder);
gst_clear_object (&self->device);
@ -321,12 +315,9 @@ static gboolean
gst_d3d11_h265_dec_negotiate (GstVideoDecoder * decoder)
{
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
GstH265Decoder *h265dec = GST_H265_DECODER (decoder);
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder, decoder,
h265dec->input_state, &self->output_state)) {
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder, decoder))
return FALSE;
}
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
@ -466,7 +457,7 @@ gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder,
GST_VIDEO_INFO_INTERLACE_MODE (&info) = self->interlace_mode;
if (!gst_d3d11_decoder_configure (self->d3d11_decoder, GST_D3D11_CODEC_H265,
&info, self->coded_width, self->coded_height,
decoder->input_state, &info, self->coded_width, self->coded_height,
/* Additional 4 views margin for zero-copy rendering */
max_dpb_size + 4)) {
GST_ERROR_OBJECT (self, "Failed to create decoder");
@ -799,9 +790,7 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
{
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
GstBuffer *output_buffer = NULL;
GstBuffer *view_buffer;
gboolean direct_rendering = FALSE;
GST_LOG_OBJECT (self, "Outputting picture %p, poc %d, picture_struct %d, "
"buffer flags 0x%x", picture, picture->pic_order_cnt, picture->pic_struct,
@ -814,41 +803,9 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
goto error;
}
/* if downstream is d3d11 element and forward playback case,
* expose our decoder view without copy. In case of reverse playback, however,
* we cannot do that since baseclass will store the decoded buffer
* up to gop size but our dpb pool cannot be increased */
if (GST_VIDEO_DECODER (self)->input_segment.rate > 0
&& gst_d3d11_decoder_can_direct_render (self->d3d11_decoder, view_buffer,
GST_MINI_OBJECT_CAST (picture))) {
direct_rendering = TRUE;
}
if (direct_rendering) {
GstMemory *mem;
output_buffer = gst_buffer_ref (view_buffer);
mem = gst_buffer_peek_memory (output_buffer, 0);
GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
} else {
output_buffer =
gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
}
if (!output_buffer) {
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
goto error;
}
frame->output_buffer = output_buffer;
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder,
&self->output_state->info,
GST_VIDEO_INFO_WIDTH (&self->output_state->info),
GST_VIDEO_INFO_HEIGHT (&self->output_state->info),
view_buffer, output_buffer)) {
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder, vdec,
self->width, self->height, view_buffer, &frame->output_buffer)) {
GST_ERROR_OBJECT (self, "Failed to copy buffer");
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
goto error;
}

View file

@ -73,7 +73,6 @@ typedef struct _GstD3D11Mpeg2Dec
{
GstMpeg2Decoder parent;
GstVideoCodecState *output_state;
GstD3D11Device *device;
GstD3D11Decoder *d3d11_decoder;
@ -308,12 +307,9 @@ static gboolean
gst_d3d11_mpeg2_dec_negotiate (GstVideoDecoder * decoder)
{
GstD3D11Mpeg2Dec *self = GST_D3D11_MPEG2_DEC (decoder);
GstMpeg2Decoder *mpeg2dec = GST_MPEG2_DECODER (decoder);
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder, decoder,
mpeg2dec->input_state, &self->output_state)) {
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder, decoder))
return FALSE;
}
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
@ -431,8 +427,8 @@ gst_d3d11_mpeg2_dec_new_sequence (GstMpeg2Decoder * decoder,
GST_VIDEO_INFO_INTERLACE_MODE (&info) = GST_VIDEO_INTERLACE_MODE_MIXED;
if (!gst_d3d11_decoder_configure (self->d3d11_decoder,
GST_D3D11_CODEC_MPEG2, &info, self->width, self->height,
NUM_OUTPUT_VIEW)) {
GST_D3D11_CODEC_MPEG2, decoder->input_state, &info,
self->width, self->height, NUM_OUTPUT_VIEW)) {
GST_ERROR_OBJECT (self, "Failed to create decoder");
return FALSE;
}
@ -886,9 +882,7 @@ gst_d3d11_mpeg2_dec_output_picture (GstMpeg2Decoder * decoder,
{
GstD3D11Mpeg2Dec *self = GST_D3D11_MPEG2_DEC (decoder);
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
GstBuffer *output_buffer = NULL;
GstBuffer *view_buffer;
gboolean direct_rendering = FALSE;
GST_LOG_OBJECT (self, "Outputting picture %p", picture);
@ -899,38 +893,8 @@ gst_d3d11_mpeg2_dec_output_picture (GstMpeg2Decoder * decoder,
goto error;
}
/* if downstream is d3d11 element and forward playback case,
* expose our decoder view without copy. In case of reverse playback, however,
* we cannot do that since baseclass will store the decoded buffer
* up to gop size but our dpb pool cannot be increased */
if (GST_VIDEO_DECODER (self)->input_segment.rate > 0
&& gst_d3d11_decoder_can_direct_render (self->d3d11_decoder, view_buffer,
GST_MINI_OBJECT_CAST (picture))) {
direct_rendering = TRUE;
}
if (direct_rendering) {
GstMemory *mem;
output_buffer = gst_buffer_ref (view_buffer);
mem = gst_buffer_peek_memory (output_buffer, 0);
GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
} else {
output_buffer = gst_video_decoder_allocate_output_buffer (vdec);
}
if (!output_buffer) {
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
goto error;
}
frame->output_buffer = output_buffer;
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder,
&self->output_state->info,
GST_VIDEO_INFO_WIDTH (&self->output_state->info),
GST_VIDEO_INFO_HEIGHT (&self->output_state->info),
view_buffer, output_buffer)) {
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder, vdec,
self->width, self->height, view_buffer, &frame->output_buffer)) {
GST_ERROR_OBJECT (self, "Failed to copy buffer");
goto error;
}

View file

@ -73,7 +73,6 @@ typedef struct _GstD3D11Vp8Dec
{
GstVp8Decoder parent;
GstVideoCodecState *output_state;
GstD3D11Device *device;
GstD3D11Decoder *d3d11_decoder;
@ -272,12 +271,9 @@ static gboolean
gst_d3d11_vp8_dec_negotiate (GstVideoDecoder * decoder)
{
GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder);
GstVp8Decoder *vp8dec = GST_VP8_DECODER (decoder);
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder,
decoder, vp8dec->input_state, &self->output_state)) {
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder, decoder))
return FALSE;
}
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
@ -345,7 +341,8 @@ gst_d3d11_vp8_dec_new_sequence (GstVp8Decoder * decoder,
self->out_format, self->width, self->height);
if (!gst_d3d11_decoder_configure (self->d3d11_decoder, GST_D3D11_CODEC_VP8,
&info, self->width, self->height, NUM_OUTPUT_VIEW)) {
decoder->input_state, &info, self->width, self->height,
NUM_OUTPUT_VIEW)) {
GST_ERROR_OBJECT (self, "Failed to create decoder");
return FALSE;
}
@ -388,9 +385,7 @@ gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder,
{
GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder);
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
GstBuffer *output_buffer = NULL;
GstBuffer *view_buffer;
gboolean direct_rendering = FALSE;
g_assert (picture->frame_hdr.show_frame);
@ -403,37 +398,8 @@ gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder,
goto error;
}
/* if downstream is d3d11 element and forward playback case,
* expose our decoder view without copy. In case of reverse playback, however,
* we cannot do that since baseclass will store the decoded buffer
* up to gop size but our dpb pool cannot be increased */
if (GST_VIDEO_DECODER (self)->input_segment.rate > 0
&& gst_d3d11_decoder_can_direct_render (self->d3d11_decoder, view_buffer,
GST_MINI_OBJECT_CAST (picture))) {
direct_rendering = TRUE;
}
if (direct_rendering) {
GstMemory *mem;
output_buffer = gst_buffer_ref (view_buffer);
mem = gst_buffer_peek_memory (output_buffer, 0);
GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
} else {
output_buffer = gst_video_decoder_allocate_output_buffer (vdec);
}
if (!output_buffer) {
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
goto error;
}
frame->output_buffer = output_buffer;
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder,
&self->output_state->info,
picture->frame_hdr.width, picture->frame_hdr.height,
view_buffer, output_buffer)) {
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder, vdec,
self->width, self->height, view_buffer, &frame->output_buffer)) {
GST_ERROR_OBJECT (self, "Failed to copy buffer");
goto error;
}

View file

@ -103,16 +103,8 @@ typedef struct _GstD3D11Vp9Dec
{
GstVp9Decoder parent;
GstVideoCodecState *output_state;
GstD3D11Device *device;
GstD3D11Decoder *d3d11_decoder;
guint width, height;
GstVP9Profile profile;
GstVideoFormat out_format;
} GstD3D11Vp9Dec;
typedef struct _GstD3D11Vp9DecClass
@ -310,12 +302,9 @@ static gboolean
gst_d3d11_vp9_dec_negotiate (GstVideoDecoder * decoder)
{
GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder);
GstVp9Decoder *vp9dec = GST_VP9_DECODER (decoder);
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder,
decoder, vp9dec->input_state, &self->output_state)) {
if (!gst_d3d11_decoder_negotiate (self->d3d11_decoder, decoder))
return FALSE;
}
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
@ -370,53 +359,34 @@ gst_d3d11_vp9_dec_new_sequence (GstVp9Decoder * decoder,
const GstVp9Parser * parser, const GstVp9FrameHdr * frame_hdr)
{
GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder);
gboolean modified = FALSE;
GstVideoInfo info;
GstVideoFormat out_format = GST_VIDEO_FORMAT_UNKNOWN;
GST_LOG_OBJECT (self, "new sequence");
if (self->width < frame_hdr->width || self->height < frame_hdr->height) {
self->width = frame_hdr->width;
self->height = frame_hdr->height;
GST_INFO_OBJECT (self, "resolution changed %dx%d",
self->width, self->height);
modified = TRUE;
if (frame_hdr->profile == GST_VP9_PROFILE_0)
out_format = GST_VIDEO_FORMAT_NV12;
else if (frame_hdr->profile == GST_VP9_PROFILE_2)
out_format = GST_VIDEO_FORMAT_P010_10LE;
if (out_format == GST_VIDEO_FORMAT_UNKNOWN) {
GST_ERROR_OBJECT (self, "Could not support profile %d", frame_hdr->profile);
return FALSE;
}
if (self->profile != frame_hdr->profile) {
self->profile = (GstVP9Profile) frame_hdr->profile;
GST_INFO_OBJECT (self, "profile changed %d", self->profile);
modified = TRUE;
gst_video_info_set_format (&info,
out_format, frame_hdr->width, frame_hdr->height);
if (!gst_d3d11_decoder_configure (self->d3d11_decoder, GST_D3D11_CODEC_VP9,
decoder->input_state, &info, (gint) frame_hdr->width,
(gint) frame_hdr->height, NUM_OUTPUT_VIEW)) {
GST_ERROR_OBJECT (self, "Failed to create decoder");
return FALSE;
}
if (modified || !gst_d3d11_decoder_is_configured (self->d3d11_decoder)) {
GstVideoInfo info;
self->out_format = GST_VIDEO_FORMAT_UNKNOWN;
if (self->profile == GST_VP9_PROFILE_0) {
self->out_format = GST_VIDEO_FORMAT_NV12;
} else if (self->profile == GST_VP9_PROFILE_2) {
self->out_format = GST_VIDEO_FORMAT_P010_10LE;
}
if (self->out_format == GST_VIDEO_FORMAT_UNKNOWN) {
GST_ERROR_OBJECT (self, "Could not support profile %d", self->profile);
return FALSE;
}
gst_video_info_set_format (&info,
self->out_format, self->width, self->height);
if (!gst_d3d11_decoder_configure (self->d3d11_decoder, GST_D3D11_CODEC_VP9,
&info, self->width, self->height, NUM_OUTPUT_VIEW)) {
GST_ERROR_OBJECT (self, "Failed to create decoder");
return FALSE;
}
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
return FALSE;
}
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
return FALSE;
}
return TRUE;
@ -479,9 +449,7 @@ gst_d3d11_vp9_dec_output_picture (GstVp9Decoder * decoder,
{
GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder);
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
GstBuffer *output_buffer = NULL;
GstBuffer *view_buffer;
gboolean direct_rendering = FALSE;
GST_LOG_OBJECT (self, "Outputting picture %p", picture);
@ -492,37 +460,9 @@ gst_d3d11_vp9_dec_output_picture (GstVp9Decoder * decoder,
goto error;
}
/* if downstream is d3d11 element and forward playback case,
* expose our decoder view without copy. In case of reverse playback, however,
* we cannot do that since baseclass will store the decoded buffer
* up to gop size but our dpb pool cannot be increased */
if (GST_VIDEO_DECODER (self)->input_segment.rate > 0
&& gst_d3d11_decoder_can_direct_render (self->d3d11_decoder, view_buffer,
GST_MINI_OBJECT_CAST (picture))) {
direct_rendering = TRUE;
}
if (direct_rendering) {
GstMemory *mem;
output_buffer = gst_buffer_ref (view_buffer);
mem = gst_buffer_peek_memory (output_buffer, 0);
GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
} else {
output_buffer = gst_video_decoder_allocate_output_buffer (vdec);
}
if (!output_buffer) {
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
goto error;
}
frame->output_buffer = output_buffer;
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder,
&self->output_state->info,
picture->frame_hdr.width, picture->frame_hdr.height,
view_buffer, output_buffer)) {
if (!gst_d3d11_decoder_process_output (self->d3d11_decoder, vdec,
picture->frame_hdr.width, picture->frame_hdr.height, view_buffer,
&frame->output_buffer)) {
GST_ERROR_OBJECT (self, "Failed to copy buffer");
goto error;
}