From f0204d43ff5c4ae0fd3117bccebd4b05440eba07 Mon Sep 17 00:00:00 2001
From: lishixu <lishixu@allwinnertech.com>
Date: Fri, 15 Nov 2024 16:12:03 +0800
Subject: [PATCH] support intersect caps with dmafeature

ignore difference in DMA type and SYSTEM type
---
 gst/gstcaps.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/gst/gstcaps.c b/gst/gstcaps.c
index bbb9211..580fafc 100644
--- a/gst/gstcaps.c
+++ b/gst/gstcaps.c
@@ -73,6 +73,10 @@
 
 #define DEBUG_REFCOUNT
 
+#ifndef GST_CAPS_FEATURE_MEMORY_DMABUF
+#define GST_CAPS_FEATURE_MEMORY_DMABUF "memory:DMABuf"
+#endif
+
 typedef struct _GstCapsArrayElement
 {
   GstStructure *structure;
@@ -125,6 +129,18 @@ typedef struct _GstCapsImpl
 /* lock to protect multiple invocations of static caps to caps conversion */
 G_LOCK_DEFINE_STATIC (static_caps_lock);
 
+static gboolean
+gst_caps_features_remove_dma_feature (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,
@@ -1330,6 +1346,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);
@@ -1344,6 +1362,11 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
       }
     }
 
+    if (j == -1 && gst_caps_features_remove_dma_feature (f1))
+      goto retry;
+
+    gst_caps_features_free (f1);
+
     /* If we found no superset for this subset structure
      * we return FALSE immediately */
     if (j == -1) {
@@ -1586,10 +1609,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_remove_dma_feature (features1))
+          goto retry;
+
+        if (gst_caps_features_remove_dma_feature (features2))
+          goto retry;
       }
+
+      gst_caps_features_free (features1);
+      gst_caps_features_free (features2);
+
       /* move down left */
       k++;
       if (G_UNLIKELY (j == 0))
@@ -1612,6 +1651,7 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
   GstCapsFeatures *features2;
   GstCaps *dest;
   GstStructure *istruct;
+  gboolean remove_dma_feature = FALSE;
 
   dest = gst_caps_new_empty ();
   /* run zigzag on top line then right line, this preserves the caps order
@@ -1632,6 +1672,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);
@@ -1649,6 +1691,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 (remove_dma_feature) {
+        gst_caps_features_remove_dma_feature (features1);
+        gst_caps_features_remove_dma_feature (features2);
+      }
+
       if (gst_caps_features_is_equal (features1, features2)) {
         istruct = gst_structure_intersect (struct1, struct2);
         if (istruct) {
@@ -1662,6 +1713,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))
@@ -1669,6 +1724,13 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
       j--;
     }
   }
+
+  /* try without DMA */
+  if (CAPS_IS_EMPTY (dest) && !remove_dma_feature) {
+    remove_dma_feature = TRUE;
+    goto retry;
+  }
+
   return dest;
 }
 
@@ -1696,20 +1758,34 @@ gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2)
   GstCapsFeatures *features2;
   GstCaps *dest;
   GstStructure *istruct;
+  gboolean remove_dma_feature = 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 (remove_dma_feature) {
+        gst_caps_features_remove_dma_feature (features1);
+        gst_caps_features_remove_dma_feature (features2);
+      }
+
       if (gst_caps_features_is_equal (features1, features2)) {
         istruct = gst_structure_intersect (struct1, struct2);
         if (istruct) {
@@ -1723,7 +1799,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) && !remove_dma_feature) {
+    remove_dma_feature = TRUE;
+    goto retry;
   }
 
   return dest;
-- 
2.37.1

