From f40ccb381166fc86eec1fe8003992b41a814a16c Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 9 Dec 2011 17:25:41 +0000 Subject: [PATCH] opusenc: add upstream negotiation for multistream ability This will help elements that cannot deal with multistream, such as the RTP payloader. The caps now do not include a "streams" field anymore, but a "multistream" boolean, since we have no real use for knowing the exact amount of streams. https://bugzilla.gnome.org/show_bug.cgi?id=665078 --- ext/opus/gstopusenc.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++- ext/opus/gstopusheader.c | 7 ++--- ext/opus/gstopusparse.c | 2 +- ext/opus/gstrtpopuspay.c | 2 +- 4 files changed, 71 insertions(+), 6 deletions(-) diff --git a/ext/opus/gstopusenc.c b/ext/opus/gstopusenc.c index 502f4a9..0ccbbeb 100644 --- a/ext/opus/gstopusenc.c +++ b/ext/opus/gstopusenc.c @@ -126,7 +126,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-opus, streams = (int) [1, 255 ]") + GST_STATIC_CAPS ("audio/x-opus") ); #define DEFAULT_AUDIO TRUE @@ -161,6 +161,7 @@ static void gst_opus_enc_finalize (GObject * object); static gboolean gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event); +static GstCaps *gst_opus_enc_sink_getcaps (GstAudioEncoder * benc); static gboolean gst_opus_enc_setup (GstOpusEnc * enc); static void gst_opus_enc_get_property (GObject * object, guint prop_id, @@ -229,6 +230,7 @@ gst_opus_enc_class_init (GstOpusEncClass * klass) base_class->set_format = GST_DEBUG_FUNCPTR (gst_opus_enc_set_format); base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_opus_enc_handle_frame); base_class->event = GST_DEBUG_FUNCPTR (gst_opus_enc_sink_event); + base_class->getcaps = GST_DEBUG_FUNCPTR (gst_opus_enc_sink_getcaps); g_object_class_install_property (gobject_class, PROP_AUDIO, g_param_spec_boolean ("audio", "Audio or voice", @@ -721,6 +723,68 @@ gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event) return FALSE; } +static GstCaps * +gst_opus_enc_sink_getcaps (GstAudioEncoder * benc) +{ + GstOpusEnc *enc; + GstCaps *caps; + GstCaps *peercaps = NULL; + GstCaps *intersect = NULL; + guint i; + gboolean allow_multistream; + + enc = GST_OPUS_ENC (benc); + + GST_DEBUG_OBJECT (enc, "sink getcaps"); + + peercaps = gst_pad_peer_get_caps (GST_AUDIO_ENCODER_SRC_PAD (benc)); + if (!peercaps) { + GST_DEBUG_OBJECT (benc, "No peercaps, returning template sink caps"); + return + gst_caps_copy (gst_pad_get_pad_template_caps + (GST_AUDIO_ENCODER_SINK_PAD (benc))); + } + + intersect = gst_caps_intersect (peercaps, + gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (benc))); + gst_caps_unref (peercaps); + + if (gst_caps_is_empty (intersect)) + return intersect; + + allow_multistream = FALSE; + for (i = 0; i < gst_caps_get_size (intersect); i++) { + GstStructure *s = gst_caps_get_structure (intersect, i); + gboolean multistream; + if (gst_structure_get_boolean (s, "multistream", &multistream)) { + if (multistream) { + allow_multistream = TRUE; + } + } else { + allow_multistream = TRUE; + } + } + + gst_caps_unref (intersect); + + caps = + gst_caps_copy (gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SINK_PAD + (benc))); + if (!allow_multistream) { + GValue range = { 0 }; + g_value_init (&range, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&range, 1, 2); + for (i = 0; i < gst_caps_get_size (caps); i++) { + GstStructure *s = gst_caps_get_structure (caps, i); + gst_structure_set_value (s, "channels", &range); + } + g_value_unset (&range); + } + + GST_DEBUG_OBJECT (enc, "Returning caps: %" GST_PTR_FORMAT, caps); + return caps; +} + static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf) { diff --git a/ext/opus/gstopusheader.c b/ext/opus/gstopusheader.c index 185c85e..d3d631f 100644 --- a/ext/opus/gstopusheader.c +++ b/ext/opus/gstopusheader.c @@ -151,6 +151,7 @@ gst_opus_header_create_caps_from_headers (GstCaps ** caps, GSList ** headers, GstBuffer * buf1, GstBuffer * buf2) { int n_streams, family; + gboolean multistream; g_return_if_fail (caps); g_return_if_fail (headers && !*headers); @@ -167,9 +168,9 @@ gst_opus_header_create_caps_from_headers (GstCaps ** caps, GSList ** headers, } /* mark and put on caps */ - *caps = - gst_caps_new_simple ("audio/x-opus", "streams", G_TYPE_INT, n_streams, - NULL); + multistream = n_streams > 1; + *caps = gst_caps_new_simple ("audio/x-opus", + "multistream", G_TYPE_BOOLEAN, multistream, NULL); *caps = _gst_caps_set_buffer_array (*caps, "streamheader", buf1, buf2, NULL); *headers = g_slist_prepend (*headers, buf2); diff --git a/ext/opus/gstopusparse.c b/ext/opus/gstopusparse.c index 542031f..f3706cb 100644 --- a/ext/opus/gstopusparse.c +++ b/ext/opus/gstopusparse.c @@ -58,7 +58,7 @@ static GstStaticPadTemplate opus_parse_sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-opus, streams = (int) [ 1, 255 ]") + GST_STATIC_CAPS ("audio/x-opus") ); G_DEFINE_TYPE (GstOpusParse, gst_opus_parse, GST_TYPE_BASE_PARSE); diff --git a/ext/opus/gstrtpopuspay.c b/ext/opus/gstrtpopuspay.c index 9724e62..cdd7ee0 100644 --- a/ext/opus/gstrtpopuspay.c +++ b/ext/opus/gstrtpopuspay.c @@ -37,7 +37,7 @@ static GstStaticPadTemplate gst_rtp_opus_pay_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-opus") + GST_STATIC_CAPS ("audio/x-opus, multistream = (boolean) FALSE") ); static GstStaticPadTemplate gst_rtp_opus_pay_src_template = -- 2.7.4