audioencoder: refactor getcaps proxy function to be reusable
authorThiago Santos <thiagoss@osg.samsung.com>
Tue, 16 Dec 2014 14:13:40 +0000 (11:13 -0300)
committerThiago Santos <thiagoss@osg.samsung.com>
Wed, 17 Dec 2014 22:15:23 +0000 (19:15 -0300)
Makes the audioencoder's getcaps function that proxies downstream
restriction available to other elements in the audio module to use it

gst-libs/gst/audio/Makefile.am
gst-libs/gst/audio/gstaudioencoder.c
gst-libs/gst/audio/gstaudioutilsprivate.c [new file with mode: 0644]
gst-libs/gst/audio/gstaudioutilsprivate.h [new file with mode: 0644]

index 0e67b9b..696e814 100644 (file)
@@ -38,6 +38,7 @@ libgstaudio_@GST_API_VERSION@_la_SOURCES = \
        gstaudiometa.c \
        gstaudiosink.c \
        gstaudiosrc.c \
+       gstaudioutilsprivate.c \
        streamvolume.c \
        gstaudioiec61937.c
 
@@ -64,7 +65,8 @@ libgstaudio_@GST_API_VERSION@include_HEADERS = \
        gstaudioiec61937.h
 
 nodist_libgstaudio_@GST_API_VERSION@include_HEADERS = \
-       audio-enumtypes.h
+       audio-enumtypes.h \
+       gstaudioutilsprivate.h
 
 libgstaudio_@GST_API_VERSION@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) \
                $(ORC_CFLAGS)
index 25d0dec..c6a6a23 100644 (file)
 #endif
 
 #include "gstaudioencoder.h"
+#include "gstaudioutilsprivate.h"
 #include <gst/base/gstadapter.h>
 #include <gst/audio/audio.h>
 #include <gst/pbutils/descriptions.h>
@@ -1359,70 +1360,9 @@ GstCaps *
 gst_audio_encoder_proxy_getcaps (GstAudioEncoder * enc, GstCaps * caps,
     GstCaps * filter)
 {
-  GstCaps *templ_caps = NULL;
-  GstCaps *allowed = NULL;
-  GstCaps *fcaps, *filter_caps;
-  gint i, j;
-
-  /* we want to be able to communicate to upstream elements like audioconvert
-   * and audioresample any rate/channel restrictions downstream (e.g. muxer
-   * only accepting certain sample rates) */
-  templ_caps =
-      caps ? gst_caps_ref (caps) : gst_pad_get_pad_template_caps (enc->sinkpad);
-  allowed = gst_pad_get_allowed_caps (enc->srcpad);
-  if (!allowed || gst_caps_is_empty (allowed) || gst_caps_is_any (allowed)) {
-    fcaps = templ_caps;
-    goto done;
-  }
-
-  GST_LOG_OBJECT (enc, "template caps %" GST_PTR_FORMAT, templ_caps);
-  GST_LOG_OBJECT (enc, "allowed caps %" GST_PTR_FORMAT, allowed);
-
-  filter_caps = gst_caps_new_empty ();
-
-  for (i = 0; i < gst_caps_get_size (templ_caps); i++) {
-    GQuark q_name;
-
-    q_name = gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i));
-
-    /* pick rate + channel fields from allowed caps */
-    for (j = 0; j < gst_caps_get_size (allowed); j++) {
-      const GstStructure *allowed_s = gst_caps_get_structure (allowed, j);
-      const GValue *val;
-      GstStructure *s;
-
-      s = gst_structure_new_id_empty (q_name);
-      if ((val = gst_structure_get_value (allowed_s, "rate")))
-        gst_structure_set_value (s, "rate", val);
-      if ((val = gst_structure_get_value (allowed_s, "channels")))
-        gst_structure_set_value (s, "channels", val);
-      /* following might also make sense for some encoded formats,
-       * e.g. wavpack */
-      if ((val = gst_structure_get_value (allowed_s, "channel-mask")))
-        gst_structure_set_value (s, "channel-mask", val);
-
-      filter_caps = gst_caps_merge_structure (filter_caps, s);
-    }
-  }
-
-  fcaps = gst_caps_intersect (filter_caps, templ_caps);
-  gst_caps_unref (filter_caps);
-  gst_caps_unref (templ_caps);
-
-  if (filter) {
-    GST_LOG_OBJECT (enc, "intersecting with %" GST_PTR_FORMAT, filter);
-    filter_caps = gst_caps_intersect_full (filter, fcaps,
-        GST_CAPS_INTERSECT_FIRST);
-    gst_caps_unref (fcaps);
-    fcaps = filter_caps;
-  }
-
-done:
-  gst_caps_replace (&allowed, NULL);
-
-  GST_LOG_OBJECT (enc, "proxy caps %" GST_PTR_FORMAT, fcaps);
-
-  return fcaps;
+  return __gst_audio_element_proxy_getcaps (GST_ELEMENT_CAST (enc),
+      GST_AUDIO_ENCODER_SINK_PAD (enc), GST_AUDIO_ENCODER_SRC_PAD (enc),
+      caps, filter);
 }
 
 static GstCaps *
diff --git a/gst-libs/gst/audio/gstaudioutilsprivate.c b/gst-libs/gst/audio/gstaudioutilsprivate.c
new file mode 100644 (file)
index 0000000..5d0676b
--- /dev/null
@@ -0,0 +1,140 @@
+/* GStreamer
+ * Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
+ * Copyright (C) 2011 Nokia Corporation. All rights reserved.
+ *   Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/audio/audio.h>
+#include "gstaudioutilsprivate.h"
+
+/*
+ * Takes caps and copies its audio fields to tmpl_caps
+ */
+static GstCaps *
+__gst_audio_element_proxy_caps (GstElement * element, GstCaps * templ_caps,
+    GstCaps * caps)
+{
+  GstCaps *result = gst_caps_new_empty ();
+  gint i, j;
+  gint templ_caps_size = gst_caps_get_size (templ_caps);
+  gint caps_size = gst_caps_get_size (caps);
+
+  for (i = 0; i < templ_caps_size; i++) {
+    GQuark q_name =
+        gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i));
+
+    for (j = 0; j < caps_size; j++) {
+      const GstStructure *caps_s = gst_caps_get_structure (caps, j);
+      const GValue *val;
+      GstStructure *s;
+
+      s = gst_structure_new_id_empty (q_name);
+      if ((val = gst_structure_get_value (caps_s, "rate")))
+        gst_structure_set_value (s, "rate", val);
+      if ((val = gst_structure_get_value (caps_s, "channels")))
+        gst_structure_set_value (s, "channels", val);
+      if ((val = gst_structure_get_value (caps_s, "channels-mask")))
+        gst_structure_set_value (s, "channels-mask", val);
+
+      result = gst_caps_merge_structure (result, s);
+    }
+  }
+
+  return result;
+}
+
+/**
+ * __gst_audio_element_proxy_getcaps:
+ * @element: a #GstElement
+ * @sinkpad: the element's sink #GstPad
+ * @srcpad: the element's source #GstPad
+ * @initial_caps: initial caps
+ * @filter: filter caps
+ *
+ * Returns caps that express @initial_caps (or sink template caps if
+ * @initial_caps == NULL) restricted to rate/channels/...
+ * combinations supported by downstream elements (e.g. muxers).
+ *
+ * Returns: a #GstCaps owned by caller
+ */
+GstCaps *
+__gst_audio_element_proxy_getcaps (GstElement * element, GstPad * sinkpad,
+    GstPad * srcpad, GstCaps * initial_caps, GstCaps * filter)
+{
+  GstCaps *templ_caps, *src_templ_caps;
+  GstCaps *peer_caps;
+  GstCaps *allowed;
+  GstCaps *fcaps, *filter_caps;
+
+  /* Allow downstream to specify rate/channels constraints
+   * and forward them upstream for audio converters to handle
+   */
+  templ_caps = initial_caps ? gst_caps_ref (initial_caps) :
+      gst_pad_get_pad_template_caps (sinkpad);
+  src_templ_caps = gst_pad_get_pad_template_caps (srcpad);
+  if (filter && !gst_caps_is_any (filter)) {
+    GstCaps *proxy_filter =
+        __gst_audio_element_proxy_caps (element, src_templ_caps, filter);
+
+    peer_caps = gst_pad_peer_query_caps (srcpad, proxy_filter);
+    gst_caps_unref (proxy_filter);
+  } else {
+    peer_caps = gst_pad_peer_query_caps (srcpad, NULL);
+  }
+
+  allowed = gst_caps_intersect_full (peer_caps, src_templ_caps,
+      GST_CAPS_INTERSECT_FIRST);
+
+  gst_caps_unref (src_templ_caps);
+  gst_caps_unref (peer_caps);
+
+  if (!allowed || gst_caps_is_any (allowed)) {
+    fcaps = templ_caps;
+    goto done;
+  } else if (gst_caps_is_empty (allowed)) {
+    fcaps = gst_caps_ref (allowed);
+    goto done;
+  }
+
+  GST_LOG_OBJECT (element, "template caps %" GST_PTR_FORMAT, templ_caps);
+  GST_LOG_OBJECT (element, "allowed caps %" GST_PTR_FORMAT, allowed);
+
+  filter_caps = __gst_audio_element_proxy_caps (element, templ_caps, allowed);
+
+  fcaps = gst_caps_intersect (filter_caps, templ_caps);
+  gst_caps_unref (filter_caps);
+  gst_caps_unref (templ_caps);
+
+  if (filter) {
+    GST_LOG_OBJECT (element, "intersecting with %" GST_PTR_FORMAT, filter);
+    filter_caps = gst_caps_intersect (fcaps, filter);
+    gst_caps_unref (fcaps);
+    fcaps = filter_caps;
+  }
+
+done:
+  gst_caps_replace (&allowed, NULL);
+
+  GST_LOG_OBJECT (element, "proxy caps %" GST_PTR_FORMAT, fcaps);
+
+  return fcaps;
+}
diff --git a/gst-libs/gst/audio/gstaudioutilsprivate.h b/gst-libs/gst/audio/gstaudioutilsprivate.h
new file mode 100644 (file)
index 0000000..553af0a
--- /dev/null
@@ -0,0 +1,40 @@
+/* GStreamer
+ * Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
+ * Copyright (C) 2011 Nokia Corporation. All rights reserved.
+ *   Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_AUDIO_H__
+#include <gst/audio/audio.h>
+#endif
+
+#ifndef _GST_AUDIO_UTILS_PRIVATE_H_
+#define _GST_AUDIO_UTILS_PRIVATE_H_
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+/* Element utility functions */
+GstCaps *__gst_audio_element_proxy_getcaps (GstElement * element, GstPad * sinkpad,
+                                            GstPad * srcpad, GstCaps * initial_caps,
+                                            GstCaps * filter);
+
+G_END_DECLS
+
+#endif