deinterleave: implement accept-caps
authorThiago Santos <thiagoss@osg.samsung.com>
Wed, 30 Sep 2015 20:35:33 +0000 (17:35 -0300)
committerThiago Santos <thiagoss@osg.samsung.com>
Wed, 30 Sep 2015 20:35:33 +0000 (17:35 -0300)
Avoid using default accept-caps handler that will query downstream
and is more expensive. Just check if the caps is compatible with
the template and check if the channels are the same.

gst/interleave/deinterleave.c
tests/check/elements/deinterleave.c

index 345829f..cdf71f9 100644 (file)
@@ -361,6 +361,56 @@ gst_deinterleave_set_process_function (GstDeinterleave * self)
 }
 
 static gboolean
+gst_deinterleave_check_caps_change (GstDeinterleave * self,
+    GstAudioInfo * old_info, GstAudioInfo * new_info)
+{
+  gint i;
+  gboolean same_layout = TRUE;
+  gboolean was_unpositioned;
+  gboolean is_unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (new_info);
+  gint new_channels = GST_AUDIO_INFO_CHANNELS (new_info);
+  gint old_channels;
+
+  was_unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (old_info);
+  old_channels = GST_AUDIO_INFO_CHANNELS (old_info);
+
+  /* We allow caps changes as long as the number of channels doesn't change
+   * and the channel positions stay the same. _getcaps() should've cared
+   * for this already but better be safe.
+   */
+  if (new_channels != old_channels)
+    goto cannot_change_caps;
+
+  /* Now check the channel positions. If we had no channel positions
+   * and get them or the other way around things have changed.
+   * If we had channel positions and get different ones things have
+   * changed too of course
+   */
+  if ((!was_unpositioned && is_unpositioned) || (was_unpositioned
+          && !is_unpositioned))
+    goto cannot_change_caps;
+
+  if (!is_unpositioned) {
+    if (GST_AUDIO_INFO_CHANNELS (old_info) !=
+        GST_AUDIO_INFO_CHANNELS (new_info))
+      goto cannot_change_caps;
+    for (i = 0; i < GST_AUDIO_INFO_CHANNELS (old_info); i++) {
+      if (new_info->position[i] != old_info->position[i]) {
+        same_layout = FALSE;
+        break;
+      }
+    }
+    if (!same_layout)
+      goto cannot_change_caps;
+  }
+
+  return TRUE;
+
+cannot_change_caps:
+  return FALSE;
+}
+
+static gboolean
 gst_deinterleave_sink_setcaps (GstDeinterleave * self, GstCaps * caps)
 {
   GstCaps *srccaps;
@@ -375,51 +425,17 @@ gst_deinterleave_sink_setcaps (GstDeinterleave * self, GstCaps * caps)
     goto unsupported_caps;
 
   if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) {
-    gint i;
-    gboolean same_layout = TRUE;
-    gboolean was_unpositioned;
-    gboolean is_unpositioned =
-        GST_AUDIO_INFO_IS_UNPOSITIONED (&self->audio_info);
-    gint new_channels = GST_AUDIO_INFO_CHANNELS (&self->audio_info);
-    gint old_channels;
     GstAudioInfo old_info;
 
     gst_audio_info_init (&old_info);
     if (!gst_audio_info_from_caps (&old_info, self->sinkcaps))
       goto info_from_caps_failed;
-    was_unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (&old_info);
-    old_channels = GST_AUDIO_INFO_CHANNELS (&old_info);
 
-    /* We allow caps changes as long as the number of channels doesn't change
-     * and the channel positions stay the same. _getcaps() should've cared
-     * for this already but better be safe.
-     */
-    if (new_channels != old_channels ||
-        !gst_deinterleave_set_process_function (self))
-      goto cannot_change_caps;
-
-    /* Now check the channel positions. If we had no channel positions
-     * and get them or the other way around things have changed.
-     * If we had channel positions and get different ones things have
-     * changed too of course
-     */
-    if ((!was_unpositioned && is_unpositioned) || (was_unpositioned
-            && !is_unpositioned))
-      goto cannot_change_caps;
-
-    if (!is_unpositioned) {
-      if (GST_AUDIO_INFO_CHANNELS (&old_info) !=
-          GST_AUDIO_INFO_CHANNELS (&self->audio_info))
-        goto cannot_change_caps;
-      for (i = 0; i < GST_AUDIO_INFO_CHANNELS (&old_info); i++) {
-        if (self->audio_info.position[i] != old_info.position[i]) {
-          same_layout = FALSE;
-          break;
-        }
-      }
-      if (!same_layout)
+    if (gst_deinterleave_check_caps_change (self, &old_info, &self->audio_info)) {
+      if (!gst_deinterleave_set_process_function (self))
         goto cannot_change_caps;
-    }
+    } else
+      goto cannot_change_caps;
 
   }
 
@@ -504,6 +520,35 @@ __set_channels (GstCaps * caps, gint channels)
   }
 }
 
+static gboolean
+gst_deinterleave_sink_acceptcaps (GstPad * pad, GstObject * parent,
+    GstCaps * caps)
+{
+  GstDeinterleave *self = GST_DEINTERLEAVE (parent);
+  GstCaps *templ_caps = gst_pad_get_pad_template_caps (pad);
+  gboolean ret;
+
+  ret = gst_caps_can_intersect (templ_caps, caps);
+  gst_caps_unref (templ_caps);
+  if (ret && self->sinkcaps) {
+    GstAudioInfo new_info;
+
+    gst_audio_info_init (&new_info);
+    if (!gst_audio_info_from_caps (&new_info, caps))
+      goto info_from_caps_failed;
+    ret =
+        gst_deinterleave_check_caps_change (self, &self->audio_info, &new_info);
+  }
+
+  return ret;
+
+info_from_caps_failed:
+  {
+    GST_ERROR_OBJECT (self, "coud not get info from caps");
+    return FALSE;
+  }
+}
+
 static GstCaps *
 gst_deinterleave_getcaps (GstPad * pad, GstObject * parent, GstCaps * filter)
 {
@@ -642,6 +687,16 @@ gst_deinterleave_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
       res = TRUE;
       break;
     }
+    case GST_QUERY_ACCEPT_CAPS:{
+      GstCaps *caps;
+      gboolean ret;
+
+      gst_query_parse_accept_caps (query, &caps);
+      ret = gst_deinterleave_sink_acceptcaps (pad, parent, caps);
+      gst_query_set_accept_caps_result (query, ret);
+      res = TRUE;
+      break;
+    }
     default:
       res = gst_pad_query_default (pad, parent, query);
       break;
index 658a90b..f81fddb 100644 (file)
@@ -306,6 +306,7 @@ GST_START_TEST (test_2_channels_caps_change)
 
   ret_caps = gst_pad_peer_query_caps (mysrcpad, caps);
   fail_if (gst_caps_is_empty (ret_caps));
+  fail_unless (gst_pad_peer_query_accept_caps (mysrcpad, caps));
   gst_caps_unref (ret_caps);
   gst_check_setup_events (mysrcpad, deinterleave, caps, GST_FORMAT_TIME);
 
@@ -340,6 +341,7 @@ GST_START_TEST (test_2_channels_caps_change)
       NULL);
   ret_caps = gst_pad_peer_query_caps (mysrcpad, caps2);
   fail_if (gst_caps_is_empty (ret_caps));
+  fail_unless (gst_pad_peer_query_accept_caps (mysrcpad, caps2));
   gst_caps_unref (ret_caps);
   gst_pad_set_caps (mysrcpad, caps2);
 
@@ -371,6 +373,7 @@ GST_START_TEST (test_2_channels_caps_change)
   ret_caps = gst_pad_peer_query_caps (mysrcpad, caps2);
   fail_unless (gst_caps_is_empty (ret_caps));
   gst_caps_unref (ret_caps);
+  fail_if (gst_pad_peer_query_accept_caps (mysrcpad, caps2));
   gst_pad_set_caps (mysrcpad, caps2);
 
   inbuf = gst_buffer_new_and_alloc (3 * 48000 * sizeof (gfloat));