From d59abf5257ce900d02205cfea179f92fae66c082 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Tue, 19 Jul 2022 18:19:48 +0800
Subject: [PATCH 3/4] HACK: caps: Consider dmabuf subset of system memory

Note, this is only true when the dmabuf is mmapable.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 gst/gstcaps.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/gst/gstcaps.c b/gst/gstcaps.c
index 28a7dfe..4e2b862 100644
--- a/gst/gstcaps.c
+++ b/gst/gstcaps.c
@@ -125,6 +125,23 @@ typedef struct _GstCapsImpl
 /* lock to protect multiple invocations of static caps to caps conversion */
 G_LOCK_DEFINE_STATIC (static_caps_lock);
 
+#ifndef GST_CAPS_FEATURE_MEMORY_DMABUF
+#define GST_CAPS_FEATURE_MEMORY_DMABUF "memory:DMABuf"
+#endif
+
+/* HACK: dma memory would likely provide system memory through mmap */
+static gboolean
+gst_caps_features_drop_dma (GstCapsFeatures * features)
+{
+  if (gst_caps_features_is_any (features) ||
+      !gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF))
+    return FALSE;
+
+  gst_caps_features_remove (features, GST_CAPS_FEATURE_MEMORY_DMABUF);
+  gst_caps_features_add (features, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
+  return TRUE;
+}
+
 static void gst_caps_transform_to_string (const GValue * src_value,
     GValue * dest_value);
 static gboolean gst_caps_from_string_inplace (GstCaps * caps,
@@ -1340,6 +1357,8 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
     if (!f1)
       f1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
 
+    f1 = gst_caps_features_copy (f1);
+retry:
     for (j = GST_CAPS_LEN (superset) - 1; j >= 0; j--) {
       s2 = gst_caps_get_structure_unchecked (superset, j);
       f2 = gst_caps_get_features_unchecked (superset, j);
@@ -1354,6 +1373,11 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
       }
     }
 
+    if (j == -1 && gst_caps_features_drop_dma (f1))
+      goto retry;
+
+    gst_caps_features_free (f1);
+
     /* If we found no superset for this subset structure
      * we return FALSE immediately */
     if (j == -1) {
@@ -1596,10 +1620,26 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
       features2 = gst_caps_get_features_unchecked (caps2, k);
       if (!features2)
         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
+
+      features1 = gst_caps_features_copy (features1);
+      features2 = gst_caps_features_copy (features2);
+retry:
       if (gst_caps_features_is_equal (features1, features2) &&
           gst_structure_can_intersect (struct1, struct2)) {
+        gst_caps_features_free (features1);
+        gst_caps_features_free (features2);
         return TRUE;
+      } else {
+        if (gst_caps_features_drop_dma (features1))
+          goto retry;
+
+        if (gst_caps_features_drop_dma (features2))
+          goto retry;
       }
+
+      gst_caps_features_free (features1);
+      gst_caps_features_free (features2);
+
       /* move down left */
       k++;
       if (G_UNLIKELY (j == 0))
@@ -1622,6 +1662,7 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
   GstCapsFeatures *features2;
   GstCaps *dest;
   GstStructure *istruct;
+  gboolean drop_dma = FALSE;
 
   dest = gst_caps_new_empty ();
   /* run zigzag on top line then right line, this preserves the caps order
@@ -1642,6 +1683,8 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
    */
   len1 = GST_CAPS_LEN (caps1);
   len2 = GST_CAPS_LEN (caps2);
+
+retry:
   for (i = 0; i < len1 + len2 - 1; i++) {
     /* caps1 index goes from 0 to GST_CAPS_LEN (caps1)-1 */
     j = MIN (i, len1 - 1);
@@ -1659,6 +1702,15 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
       features2 = gst_caps_get_features_unchecked (caps2, k);
       if (!features2)
         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
+
+      features1 = gst_caps_features_copy (features1);
+      features2 = gst_caps_features_copy (features2);
+
+      if (drop_dma) {
+        gst_caps_features_drop_dma (features1);
+        gst_caps_features_drop_dma (features2);
+      }
+
       if (gst_caps_features_is_equal (features1, features2)) {
         istruct = gst_structure_intersect (struct1, struct2);
         if (istruct) {
@@ -1672,6 +1724,10 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
                 gst_caps_features_copy_conditional (features1));
         }
       }
+
+      gst_caps_features_free (features1);
+      gst_caps_features_free (features2);
+
       /* move down left */
       k++;
       if (G_UNLIKELY (j == 0))
@@ -1679,6 +1735,13 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
       j--;
     }
   }
+
+  /* try without DMA */
+  if (CAPS_IS_EMPTY (dest) && !drop_dma) {
+    drop_dma = TRUE;
+    goto retry;
+  }
+
   return dest;
 }
 
@@ -1706,20 +1769,34 @@ gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2)
   GstCapsFeatures *features2;
   GstCaps *dest;
   GstStructure *istruct;
+  gboolean drop_dma = FALSE;
 
   dest = gst_caps_new_empty ();
   len1 = GST_CAPS_LEN (caps1);
   len2 = GST_CAPS_LEN (caps2);
+
+retry:
   for (i = 0; i < len1; i++) {
     struct1 = gst_caps_get_structure_unchecked (caps1, i);
     features1 = gst_caps_get_features_unchecked (caps1, i);
     if (!features1)
       features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
+
+    features1 = gst_caps_features_copy (features1);
+
     for (j = 0; j < len2; j++) {
       struct2 = gst_caps_get_structure_unchecked (caps2, j);
       features2 = gst_caps_get_features_unchecked (caps2, j);
       if (!features2)
         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
+
+      features2 = gst_caps_features_copy (features2);
+
+      if (drop_dma) {
+        gst_caps_features_drop_dma (features1);
+        gst_caps_features_drop_dma (features2);
+      }
+
       if (gst_caps_features_is_equal (features1, features2)) {
         istruct = gst_structure_intersect (struct1, struct2);
         if (istruct) {
@@ -1733,7 +1810,17 @@ gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2)
                 gst_caps_features_copy_conditional (features1));
         }
       }
+
+      gst_caps_features_free (features2);
     }
+
+    gst_caps_features_free (features1);
+  }
+
+  /* try without DMA */
+  if (CAPS_IS_EMPTY (dest) && !drop_dma) {
+    drop_dma = TRUE;
+    goto retry;
   }
 
   return dest;
-- 
2.20.1

