rtpopuspay: Forward stereo preferences from caps upstream
authorOlivier Crête <olivier.crete@collabora.com>
Tue, 24 Mar 2015 17:57:54 +0000 (13:57 -0400)
committerOlivier Crête <olivier.crete@collabora.com>
Wed, 25 Mar 2015 19:26:55 +0000 (15:26 -0400)
https://bugzilla.gnome.org/show_bug.cgi?id=746617

ext/opus/gstrtpopuspay.c

index 7a36dce..057c8d0 100644 (file)
@@ -54,6 +54,8 @@ GST_STATIC_PAD_TEMPLATE ("src",
 
 static gboolean gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload,
     GstCaps * caps);
+static GstCaps *gst_rtp_opus_pay_getcaps (GstRTPBasePayload * payload,
+    GstPad * pad, GstCaps * filter);
 static GstFlowReturn gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload *
     payload, GstBuffer * buffer);
 
@@ -69,6 +71,7 @@ gst_rtp_opus_pay_class_init (GstRtpOPUSPayClass * klass)
   element_class = GST_ELEMENT_CLASS (klass);
 
   gstbasertppayload_class->set_caps = gst_rtp_opus_pay_setcaps;
+  gstbasertppayload_class->get_caps = gst_rtp_opus_pay_getcaps;
   gstbasertppayload_class->handle_buffer = gst_rtp_opus_pay_handle_buffer;
 
   gst_element_class_add_pad_template (element_class,
@@ -117,7 +120,8 @@ gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
   s = gst_caps_get_structure (caps, 0);
   if (gst_structure_get_int (s, "channels", &channels)) {
     if (channels > 2) {
-      GST_ERROR_OBJECT (payload, "More than 2 channels are not supported yet");
+      GST_ERROR_OBJECT (payload,
+          "More than 2 channels with multistream=FALSE is invalid");
       return FALSE;
     } else if (channels == 2) {
       sprop_stereo = "1";
@@ -177,3 +181,62 @@ gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * basepayload,
   /* Push out */
   return gst_rtp_base_payload_push (basepayload, outbuf);
 }
+
+static GstCaps *
+gst_rtp_opus_pay_getcaps (GstRTPBasePayload * payload,
+    GstPad * pad, GstCaps * filter)
+{
+  GstCaps *caps, *peercaps, *tcaps;
+  GstStructure *s;
+  const gchar *stereo;
+
+  if (pad == GST_RTP_BASE_PAYLOAD_SRCPAD (payload))
+    return
+        GST_RTP_BASE_PAYLOAD_CLASS (gst_rtp_opus_pay_parent_class)->get_caps
+        (payload, pad, filter);
+
+  tcaps = gst_pad_get_pad_template_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload));
+  peercaps = gst_pad_peer_query_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload),
+      tcaps);
+  gst_caps_unref (tcaps);
+  if (!peercaps)
+    return
+        GST_RTP_BASE_PAYLOAD_CLASS (gst_rtp_opus_pay_parent_class)->get_caps
+        (payload, pad, filter);
+
+  if (gst_caps_is_empty (peercaps))
+    return peercaps;
+
+  caps = gst_pad_get_pad_template_caps (GST_RTP_BASE_PAYLOAD_SINKPAD (payload));
+
+  s = gst_caps_get_structure (peercaps, 0);
+  stereo = gst_structure_get_string (s, "stereo");
+  if (stereo != NULL) {
+    caps = gst_caps_make_writable (caps);
+
+    if (!strcmp (stereo, "1")) {
+      GstCaps *caps2 = gst_caps_copy (caps);
+
+      gst_caps_set_simple (caps, "channels", G_TYPE_INT, 2, NULL);
+      gst_caps_set_simple (caps2, "channels", G_TYPE_INT, 1, NULL);
+      caps = gst_caps_merge (caps, caps2);
+    } else if (!strcmp (stereo, "0")) {
+      GstCaps *caps2 = gst_caps_copy (caps);
+
+      gst_caps_set_simple (caps, "channels", G_TYPE_INT, 1, NULL);
+      gst_caps_set_simple (caps2, "channels", G_TYPE_INT, 2, NULL);
+      caps = gst_caps_merge (caps, caps2);
+    }
+  }
+  gst_caps_unref (peercaps);
+
+  if (filter) {
+    GstCaps *tmp = gst_caps_intersect_full (caps, filter,
+        GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (caps);
+    caps = tmp;
+  }
+
+  GST_DEBUG_OBJECT (payload, "Returning caps: %" GST_PTR_FORMAT, caps);
+  return caps;
+}