d3d11decoder: Add hardcoded minimum resolution values to caps for NVIDIA
authorSeungha Yang <seungha@centricular.com>
Wed, 11 May 2022 20:13:08 +0000 (05:13 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 12 May 2022 18:20:26 +0000 (18:20 +0000)
NVIDIA GPUs have undocumented limitation regarding minimum resolution
and it can be queried via a NVDEC API. However, since we don't want to
bring CUDA/NVDEC API into D3D11, use hardcoded values for now
until we find a nice way for capability check.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2406>

subprojects/gst-plugins-bad/sys/d3d11/gstd3d11av1dec.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11decoder.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11decoder.h
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11h264dec.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11h265dec.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11mpeg2dec.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11vp8dec.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11vp9dec.cpp

index d6ffe8e..09adb42 100644 (file)
@@ -1338,16 +1338,10 @@ gst_d3d11_av1_dec_register (GstPlugin * plugin, GstD3D11Device * device,
 
   /* To cover both landscape and portrait, select max value */
   resolution = MAX (max_width, max_height);
-  gst_caps_set_simple (sink_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
-  gst_caps_set_simple (src_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
 
   type_info.class_data =
       gst_d3d11_decoder_class_data_new (device, GST_DXVA_CODEC_AV1,
-      sink_caps, src_caps);
+      sink_caps, src_caps, resolution);
 
   type_name = g_strdup ("GstD3D11AV1Dec");
   feature_name = g_strdup ("d3d11av1dec");
index cc5845a..77d6469 100644 (file)
@@ -1979,6 +1979,7 @@ struct _GstD3D11DecoderClassData
  * @device: (transfer none): a #GstD3D11Device
  * @sink_caps: (transfer full): a #GstCaps
  * @src_caps: (transfer full): a #GstCaps
+ * @max_resolution: maximum supported resolution
  *
  * Create new #GstD3D11DecoderClassData
  *
@@ -1986,16 +1987,51 @@ struct _GstD3D11DecoderClassData
  */
 GstD3D11DecoderClassData *
 gst_d3d11_decoder_class_data_new (GstD3D11Device * device, GstDXVACodec codec,
-    GstCaps * sink_caps, GstCaps * src_caps)
+    GstCaps * sink_caps, GstCaps * src_caps, guint max_resolution)
 {
   GstD3D11DecoderClassData *ret;
+  guint min_width = 1;
+  guint min_height = 1;
 
   g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
   g_return_val_if_fail (sink_caps != NULL, NULL);
   g_return_val_if_fail (src_caps != NULL, NULL);
 
+  /* FIXME: D3D11/DXVA does not have an API for querying minimum resolution
+   * capability. Might need to find a nice way for testing minimum resolution.
+   *
+   * Below hardcoded values were checked on RTX 2080/3060 GPUs via NVDEC API
+   * (VP8 decoding is not supported by those GPUs via D3D11/DXVA) */
+  if (gst_d3d11_get_device_vendor (device) == GST_D3D11_DEVICE_VENDOR_NVIDIA) {
+    switch (codec) {
+      case GST_DXVA_CODEC_MPEG2:
+      case GST_DXVA_CODEC_H264:
+      case GST_DXVA_CODEC_VP8:
+        min_width = 48;
+        min_height = 16;
+        break;
+      case GST_DXVA_CODEC_H265:
+        min_width = min_height = 144;
+        break;
+      case GST_DXVA_CODEC_VP9:
+      case GST_DXVA_CODEC_AV1:
+        min_width = min_height = 128;
+        break;
+      default:
+        g_assert_not_reached ();
+        return nullptr;
+    }
+  }
+
   ret = g_new0 (GstD3D11DecoderClassData, 1);
 
+  gst_caps_set_simple (sink_caps,
+      "width", GST_TYPE_INT_RANGE, min_width, max_resolution,
+      "height", GST_TYPE_INT_RANGE, min_height, max_resolution, nullptr);
+  gst_caps_set_simple (src_caps,
+      "width", GST_TYPE_INT_RANGE, min_width, max_resolution,
+      "height", GST_TYPE_INT_RANGE, min_height, max_resolution, nullptr);
+
   /* class data will be leaked if the element never gets instantiated */
   GST_MINI_OBJECT_FLAG_SET (sink_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
   GST_MINI_OBJECT_FLAG_SET (src_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
index f07028b..5981bf9 100644 (file)
@@ -143,7 +143,8 @@ gboolean          gst_d3d11_decoder_supports_resolution (GstD3D11Device * device
 GstD3D11DecoderClassData *  gst_d3d11_decoder_class_data_new  (GstD3D11Device * device,
                                                                GstDXVACodec codec,
                                                                GstCaps * sink_caps,
-                                                               GstCaps * src_caps);
+                                                               GstCaps * src_caps,
+                                                               guint max_resolution);
 
 void  gst_d3d11_decoder_class_data_fill_subclass_data (GstD3D11DecoderClassData * data,
                                                        GstD3D11DecoderSubClassData * subclass_data);
index 10a63c3..ea5b286 100644 (file)
@@ -989,16 +989,10 @@ gst_d3d11_h264_dec_register (GstPlugin * plugin, GstD3D11Device * device,
 
   /* To cover both landscape and portrait, select max value */
   resolution = MAX (max_width, max_height);
-  gst_caps_set_simple (sink_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
-  gst_caps_set_simple (src_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
 
   type_info.class_data =
       gst_d3d11_decoder_class_data_new (device, GST_DXVA_CODEC_H264,
-      sink_caps, src_caps);
+      sink_caps, src_caps, resolution);
 
   type_name = g_strdup ("GstD3D11H264Dec");
   feature_name = g_strdup ("d3d11h264dec");
index 64c03dd..a8d7c4d 100644 (file)
@@ -1083,12 +1083,6 @@ gst_d3d11_h265_dec_register (GstPlugin * plugin, GstD3D11Device * device,
 
   /* To cover both landscape and portrait, select max value */
   resolution = MAX (max_width, max_height);
-  gst_caps_set_simple (sink_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
-  gst_caps_set_simple (src_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
 
   /* Copy src caps to append other capsfeatures */
   src_caps_copy = gst_caps_copy (src_caps);
@@ -1124,7 +1118,7 @@ gst_d3d11_h265_dec_register (GstPlugin * plugin, GstD3D11Device * device,
 
   type_info.class_data =
       gst_d3d11_decoder_class_data_new (device, GST_DXVA_CODEC_H265,
-      sink_caps, src_caps);
+      sink_caps, src_caps, resolution);
 
   type_name = g_strdup ("GstD3D11H265Dec");
   feature_name = g_strdup ("d3d11h265dec");
index 58102fd..59f3c6b 100644 (file)
@@ -814,16 +814,9 @@ gst_d3d11_mpeg2_dec_register (GstPlugin * plugin, GstD3D11Device * device,
   /* NOTE: We are supporting only 4:2:0, main or simple profiles */
   gst_caps_set_simple (src_caps, "format", G_TYPE_STRING, "NV12", NULL);
 
-  gst_caps_set_simple (sink_caps,
-      "width", GST_TYPE_INT_RANGE, 1, 1920,
-      "height", GST_TYPE_INT_RANGE, 1, 1920, NULL);
-  gst_caps_set_simple (src_caps,
-      "width", GST_TYPE_INT_RANGE, 1, 1920,
-      "height", GST_TYPE_INT_RANGE, 1, 1920, NULL);
-
   type_info.class_data =
       gst_d3d11_decoder_class_data_new (device, GST_DXVA_CODEC_MPEG2,
-      sink_caps, src_caps);
+      sink_caps, src_caps, 1920);
 
   type_name = g_strdup ("GstD3D11Mpeg2Dec");
   feature_name = g_strdup ("d3d11mpeg2dec");
index d54980c..8e56658 100644 (file)
@@ -724,16 +724,10 @@ gst_d3d11_vp8_dec_register (GstPlugin * plugin, GstD3D11Device * device,
 
   /* To cover both landscape and portrait, select max value */
   resolution = MAX (max_width, max_height);
-  gst_caps_set_simple (sink_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
-  gst_caps_set_simple (src_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
 
   type_info.class_data =
       gst_d3d11_decoder_class_data_new (device, GST_DXVA_CODEC_VP8,
-      sink_caps, src_caps);
+      sink_caps, src_caps, resolution);
 
   type_name = g_strdup ("GstD3D11Vp8Dec");
   feature_name = g_strdup ("d3d11vp8dec");
index 90b1bb3..85ce5d4 100644 (file)
@@ -936,16 +936,10 @@ gst_d3d11_vp9_dec_register (GstPlugin * plugin, GstD3D11Device * device,
 
   /* To cover both landscape and portrait, select max value */
   resolution = MAX (max_width, max_height);
-  gst_caps_set_simple (sink_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
-  gst_caps_set_simple (src_caps,
-      "width", GST_TYPE_INT_RANGE, 1, resolution,
-      "height", GST_TYPE_INT_RANGE, 1, resolution, NULL);
 
   type_info.class_data =
       gst_d3d11_decoder_class_data_new (device, GST_DXVA_CODEC_VP9,
-      sink_caps, src_caps);
+      sink_caps, src_caps, resolution);
 
   type_name = g_strdup ("GstD3D11Vp9Dec");
   feature_name = g_strdup ("d3d11vp9dec");