d3d11decoder: Move zero-copy decision logic into decoder object
authorSeungha Yang <seungha@centricular.com>
Sun, 28 Mar 2021 07:06:55 +0000 (16:06 +0900)
committerSeungha Yang <seungha@centricular.com>
Sun, 28 Mar 2021 09:00:28 +0000 (18:00 +0900)
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>

sys/d3d11/gstd3d11decoder.cpp
sys/d3d11/gstd3d11decoder.h
sys/d3d11/gstd3d11h264dec.cpp
sys/d3d11/gstd3d11h265dec.cpp
sys/d3d11/gstd3d11mpeg2dec.cpp
sys/d3d11/gstd3d11vp8dec.cpp
sys/d3d11/gstd3d11vp9dec.cpp

index c629543..636c71c 100644 (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)
index abb4db7..f88a377 100644 (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);
 
index c089718..f68a517 100644 (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;
   }
index bf2d5ec..18fba71 100644 (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;
   }
 
index 87d9224..2bb91d0 100644 (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;
   }
index 126d1ea..04356f2 100644 (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;
   }
index 60c4b1a..4a56458 100644 (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 (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;
@@ -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;
   }