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;
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);
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
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;
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);
}
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;
}
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;
}
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;
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,
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;
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) ==
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,
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)
gboolean gst_d3d11_decoder_configure (GstD3D11Decoder * decoder,
GstD3D11Codec codec,
+ GstVideoCodecState * input_state,
GstVideoInfo * info,
gint coded_width,
gint coded_height,
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,
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);
{
GstH264Decoder parent;
- GstVideoCodecState *output_state;
-
GstD3D11Device *device;
gint width, height;
{
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);
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);
}
*/
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");
{
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);
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;
}
{
GstH265Decoder parent;
- GstVideoCodecState *output_state;
-
GstD3D11Device *device;
gint width, height;
{
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);
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);
}
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");
{
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,
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;
}
{
GstMpeg2Decoder parent;
- GstVideoCodecState *output_state;
GstD3D11Device *device;
GstD3D11Decoder *d3d11_decoder;
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);
}
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;
}
{
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);
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;
}
{
GstVp8Decoder parent;
- GstVideoCodecState *output_state;
GstD3D11Device *device;
GstD3D11Decoder *d3d11_decoder;
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);
}
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;
}
{
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);
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;
}
{
GstVp9Decoder parent;
- GstVideoCodecState *output_state;
-
GstD3D11Device *device;
-
GstD3D11Decoder *d3d11_decoder;
-
- guint width, height;
- GstVP9Profile profile;
-
- GstVideoFormat out_format;
} GstD3D11Vp9Dec;
typedef struct _GstD3D11Vp9DecClass
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);
}
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 (self->profile != frame_hdr->profile) {
- self->profile = (GstVP9Profile) frame_hdr->profile;
- GST_INFO_OBJECT (self, "profile changed %d", self->profile);
- modified = TRUE;
+ if (out_format == GST_VIDEO_FORMAT_UNKNOWN) {
+ GST_ERROR_OBJECT (self, "Could not support profile %d", frame_hdr->profile);
+ return FALSE;
}
- if (modified || !gst_d3d11_decoder_is_configured (self->d3d11_decoder)) {
- GstVideoInfo info;
+ gst_video_info_set_format (&info,
+ out_format, frame_hdr->width, frame_hdr->height);
- 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_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 (!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;
{
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);
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;
}