From c207bdf1e7ac5ea4010a9268c6683796fa385d0e Mon Sep 17 00:00:00 2001 From: Danilo Cesar Lemes de Paula Date: Wed, 7 Dec 2011 15:13:11 -0200 Subject: [PATCH 01/20] Adding opus RTP payloader/depayloader element Adding OPUS RTP module based on the current draft: http://tools.ietf.org/id/draft-spittka-payload-rtp-opus-00.txt https://bugzilla.gnome.org/show_bug.cgi?id=664817 --- gst/rtp/gstrtpopusdepay.c | 123 +++++++++++++++++++++++++++++++++ gst/rtp/gstrtpopusdepay.h | 57 ++++++++++++++++ gst/rtp/gstrtpopuspay.c | 140 ++++++++++++++++++++++++++++++++++++++ gst/rtp/gstrtpopuspay.h | 58 ++++++++++++++++ 4 files changed, 378 insertions(+) create mode 100644 gst/rtp/gstrtpopusdepay.c create mode 100644 gst/rtp/gstrtpopusdepay.h create mode 100644 gst/rtp/gstrtpopuspay.c create mode 100644 gst/rtp/gstrtpopuspay.h diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c new file mode 100644 index 0000000000..0f1869ed56 --- /dev/null +++ b/gst/rtp/gstrtpopusdepay.c @@ -0,0 +1,123 @@ +/* + * Opus Depayloader Gst Element + * + * @author: Danilo Cesar Lemes de Paula + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include "gstrtpopusdepay.h" + +GST_DEBUG_CATEGORY_STATIC (rtpopusdepay_debug); +#define GST_CAT_DEFAULT (rtpopusdepay_debug) + + + +static GstStaticPadTemplate gst_rtp_opus_depay_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING "," + "clock-rate = (int) 48000, " + "encoding-name = (string) \"X-GST-OPUS-DRAFT-SPITTKA-00\"") + ); + +static GstStaticPadTemplate gst_rtp_opus_depay_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-opus") + ); + +static GstBuffer *gst_rtp_opus_depay_process (GstBaseRTPDepayload * depayload, + GstBuffer * buf); +static gboolean gst_rtp_opus_depay_setcaps (GstBaseRTPDepayload * depayload, + GstCaps * caps); + +GST_BOILERPLATE (GstRTPOpusDepay, gst_rtp_opus_depay, GstBaseRTPDepayload, + GST_TYPE_BASE_RTP_DEPAYLOAD); + +static void +gst_rtp_opus_depay_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_opus_depay_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_opus_depay_sink_template)); + gst_element_class_set_details_simple (element_class, + "RTP Opus packet depayloader", "Codec/Depayloader/Network/RTP", + "Extracts Opus audio from RTP packets", + "Danilo Cesar Lemes de Paula "); +} + +static void +gst_rtp_opus_depay_class_init (GstRTPOpusDepayClass * klass) +{ + GstBaseRTPDepayloadClass *gstbasertpdepayload_class; + + gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; + + gstbasertpdepayload_class->process = gst_rtp_opus_depay_process; + gstbasertpdepayload_class->set_caps = gst_rtp_opus_depay_setcaps; + + GST_DEBUG_CATEGORY_INIT (rtpopusdepay_debug, "rtpopusdepay", 0, + "Opus RTP Depayloader"); +} + +static void +gst_rtp_opus_depay_init (GstRTPOpusDepay * rtpopusdepay, + GstRTPOpusDepayClass * klass) +{ + +} + +static gboolean +gst_rtp_opus_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) +{ + GstCaps *srccaps; + gboolean ret; + + srccaps = gst_caps_new_simple ("audio/x-opus", NULL); + ret = gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps); + + GST_DEBUG_OBJECT (depayload, + "set caps on source: %" GST_PTR_FORMAT " (ret=%d)", srccaps, ret); + gst_caps_unref (srccaps); + + depayload->clock_rate = 48000; + + return ret; +} + +static GstBuffer * +gst_rtp_opus_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) +{ + GstBuffer *outbuf; + outbuf = gst_rtp_buffer_get_payload_buffer (buf); + + return outbuf; +} diff --git a/gst/rtp/gstrtpopusdepay.h b/gst/rtp/gstrtpopusdepay.h new file mode 100644 index 0000000000..ba217e0e8f --- /dev/null +++ b/gst/rtp/gstrtpopusdepay.h @@ -0,0 +1,57 @@ +/* + * Opus Depayloader Gst Element + * + * @author: Danilo Cesar Lemes de Paula + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_OPUS_DEPAY_H__ +#define __GST_RTP_OPUS_DEPAY_H__ + +#include +#include + +G_BEGIN_DECLS typedef struct _GstRTPOpusDepay GstRTPOpusDepay; +typedef struct _GstRTPOpusDepayClass GstRTPOpusDepayClass; + +#define GST_TYPE_RTP_OPUS_DEPAY \ + (gst_rtp_opus_depay_get_type()) +#define GST_RTP_OPUS_DEPAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_OPUS_DEPAY,GstRTPOpusDepay)) +#define GST_RTP_OPUS_DEPAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_OPUS_DEPAY,GstRTPOpusDepayClass)) +#define GST_IS_RTP_OPUS_DEPAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_OPUS_DEPAY)) +#define GST_IS_RTP_OPUS_DEPAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_OPUS_DEPAY)) + + +struct _GstRTPOpusDepay +{ + GstBaseRTPDepayload depayload; + +}; + +struct _GstRTPOpusDepayClass +{ + GstBaseRTPDepayloadClass parent_class; +}; + +GType gst_rtp_opus_depay_get_type (void); + +G_END_DECLS +#endif /* __GST_RTP_OPUS_DEPAY_H__ */ diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c new file mode 100644 index 0000000000..9724e6276a --- /dev/null +++ b/gst/rtp/gstrtpopuspay.c @@ -0,0 +1,140 @@ +/* + * Opus Payloader Gst Element + * + * @author: Danilo Cesar Lemes de Paula + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#include "gstrtpopuspay.h" + +GST_DEBUG_CATEGORY_STATIC (rtpopuspay_debug); +#define GST_CAT_DEFAULT (rtpopuspay_debug) + + +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") + ); + +static GstStaticPadTemplate gst_rtp_opus_pay_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp, " + "media = (string) \"audio\", " + "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " + "clock-rate = (int) 48000, " + "encoding-name = (string) \"X-GST-OPUS-DRAFT-SPITTKA-00\"") + ); + +static gboolean gst_rtp_opus_pay_setcaps (GstBaseRTPPayload * payload, + GstCaps * caps); +static GstFlowReturn gst_rtp_opus_pay_handle_buffer (GstBaseRTPPayload * + payload, GstBuffer * buffer); + +GST_BOILERPLATE (GstRtpOPUSPay, gst_rtp_opus_pay, GstBaseRTPPayload, + GST_TYPE_BASE_RTP_PAYLOAD); + +static void +gst_rtp_opus_pay_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_opus_pay_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_opus_pay_sink_template)); + + gst_element_class_set_details_simple (element_class, + "RTP Opus payloader", + "Codec/Payloader/Network/RTP", + "Puts Opus audio in RTP packets", + "Danilo Cesar Lemes de Paula "); +} + +static void +gst_rtp_opus_pay_class_init (GstRtpOPUSPayClass * klass) +{ + GstBaseRTPPayloadClass *gstbasertppayload_class; + + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; + + gstbasertppayload_class->set_caps = gst_rtp_opus_pay_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtp_opus_pay_handle_buffer; + + GST_DEBUG_CATEGORY_INIT (rtpopuspay_debug, "rtpopuspay", 0, + "Opus RTP Payloader"); +} + +static void +gst_rtp_opus_pay_init (GstRtpOPUSPay * rtpopuspay, GstRtpOPUSPayClass * klass) +{ +} + +static gboolean +gst_rtp_opus_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + gboolean res; + gchar *capsstr; + + capsstr = gst_caps_to_string (caps); + + gst_basertppayload_set_options (payload, "audio", FALSE, + "X-GST-OPUS-DRAFT-SPITTKA-00", 48000); + res = + gst_basertppayload_set_outcaps (payload, "caps", G_TYPE_STRING, capsstr, + NULL); + g_free (capsstr); + + return res; +} + +static GstFlowReturn +gst_rtp_opus_pay_handle_buffer (GstBaseRTPPayload * basepayload, + GstBuffer * buffer) +{ + GstBuffer *outbuf; + GstClockTime timestamp; + + guint size; + guint8 *data; + guint8 *payload; + + size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); + timestamp = GST_BUFFER_TIMESTAMP (buffer); + + outbuf = gst_rtp_buffer_new_allocate (size, 0, 0); + payload = gst_rtp_buffer_get_payload (outbuf); + + memcpy (payload, data, size); + + gst_rtp_buffer_set_marker (outbuf, FALSE); + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + + return gst_basertppayload_push (basepayload, outbuf); +} diff --git a/gst/rtp/gstrtpopuspay.h b/gst/rtp/gstrtpopuspay.h new file mode 100644 index 0000000000..23abd0dabf --- /dev/null +++ b/gst/rtp/gstrtpopuspay.h @@ -0,0 +1,58 @@ +/* + * Opus Payloader Gst Element + * + * @author: Danilo Cesar Lemes de Paula + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RTP_OPUS_PAY_H__ +#define __GST_RTP_OPUS_PAY_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_RTP_OPUS_PAY \ + (gst_rtp_opus_pay_get_type()) +#define GST_RTP_OPUS_PAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_OPUS_PAY,GstRtpOPUSPay)) +#define GST_RTP_OPUS_PAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_OPUS_PAY,GstRtpOPUSPayClass)) +#define GST_IS_RTP_OPUS_PAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_OPUS_PAY)) +#define GST_IS_RTP_OPUS_PAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_OPUS_PAY)) + +typedef struct _GstRtpOPUSPay GstRtpOPUSPay; +typedef struct _GstRtpOPUSPayClass GstRtpOPUSPayClass; + +struct _GstRtpOPUSPay +{ + GstBaseRTPPayload payload; +}; + +struct _GstRtpOPUSPayClass +{ + GstBaseRTPPayloadClass parent_class; +}; + +GType gst_rtp_opus_pay_get_type (void); + +G_END_DECLS + +#endif /* __GST_RTP_OPUS_PAY_H__ */ From 8df374108ad1d36945977ccf759767ca9e9409c9 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 9 Dec 2011 17:25:41 +0000 Subject: [PATCH 02/20] 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 --- gst/rtp/gstrtpopuspay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 9724e6276a..cdd7ee00c3 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/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 = From 77ea437507a4db3e1b6630958cfafba941a55597 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Fri, 30 Dec 2011 11:41:17 +0100 Subject: [PATCH 03/20] Merge remote-tracking branch 'origin/master' into 0.11-premerge Conflicts: docs/libs/Makefile.am ext/kate/gstkatetiger.c ext/opus/gstopusdec.c ext/xvid/gstxvidenc.c gst-libs/gst/basecamerabinsrc/Makefile.am gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h gst-libs/gst/video/gstbasevideocodec.c gst-libs/gst/video/gstbasevideocodec.h gst-libs/gst/video/gstbasevideodecoder.c gst-libs/gst/video/gstbasevideoencoder.c gst/asfmux/gstasfmux.c gst/audiovisualizers/gstwavescope.c gst/camerabin2/gstcamerabin2.c gst/debugutils/gstcompare.c gst/frei0r/gstfrei0rmixer.c gst/mpegpsmux/mpegpsmux.c gst/mpegtsmux/mpegtsmux.c gst/mxf/mxfmux.c gst/videomeasure/gstvideomeasure_ssim.c gst/videoparsers/gsth264parse.c gst/videoparsers/gstmpeg4videoparse.c --- gst/rtp/gstrtpopusdepay.c | 43 +++++++++++------------- gst/rtp/gstrtpopusdepay.h | 6 ++-- gst/rtp/gstrtpopuspay.c | 71 +++++++++++++++++++-------------------- gst/rtp/gstrtpopuspay.h | 6 ++-- 4 files changed, 60 insertions(+), 66 deletions(-) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index 0f1869ed56..f8effbb6c7 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -31,8 +31,6 @@ GST_DEBUG_CATEGORY_STATIC (rtpopusdepay_debug); #define GST_CAT_DEFAULT (rtpopusdepay_debug) - - static GstStaticPadTemplate gst_rtp_opus_depay_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -51,18 +49,22 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS ("audio/x-opus") ); -static GstBuffer *gst_rtp_opus_depay_process (GstBaseRTPDepayload * depayload, +static GstBuffer *gst_rtp_opus_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf); -static gboolean gst_rtp_opus_depay_setcaps (GstBaseRTPDepayload * depayload, +static gboolean gst_rtp_opus_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps); -GST_BOILERPLATE (GstRTPOpusDepay, gst_rtp_opus_depay, GstBaseRTPDepayload, - GST_TYPE_BASE_RTP_DEPAYLOAD); +G_DEFINE_TYPE (GstRTPOpusDepay, gst_rtp_opus_depay, + GST_TYPE_RTP_BASE_DEPAYLOAD); static void -gst_rtp_opus_depay_base_init (gpointer klass) +gst_rtp_opus_depay_class_init (GstRTPOpusDepayClass * klass) { - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstRTPBaseDepayloadClass *gstbasertpdepayload_class; + GstElementClass *element_class; + + element_class = GST_ELEMENT_CLASS (klass); + gstbasertpdepayload_class = (GstRTPBaseDepayloadClass *) klass; gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_opus_depay_src_template)); @@ -72,14 +74,6 @@ gst_rtp_opus_depay_base_init (gpointer klass) "RTP Opus packet depayloader", "Codec/Depayloader/Network/RTP", "Extracts Opus audio from RTP packets", "Danilo Cesar Lemes de Paula "); -} - -static void -gst_rtp_opus_depay_class_init (GstRTPOpusDepayClass * klass) -{ - GstBaseRTPDepayloadClass *gstbasertpdepayload_class; - - gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass; gstbasertpdepayload_class->process = gst_rtp_opus_depay_process; gstbasertpdepayload_class->set_caps = gst_rtp_opus_depay_setcaps; @@ -89,20 +83,19 @@ gst_rtp_opus_depay_class_init (GstRTPOpusDepayClass * klass) } static void -gst_rtp_opus_depay_init (GstRTPOpusDepay * rtpopusdepay, - GstRTPOpusDepayClass * klass) +gst_rtp_opus_depay_init (GstRTPOpusDepay * rtpopusdepay) { } static gboolean -gst_rtp_opus_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) +gst_rtp_opus_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { GstCaps *srccaps; gboolean ret; - srccaps = gst_caps_new_simple ("audio/x-opus", NULL); - ret = gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps); + srccaps = gst_caps_new_empty_simple ("audio/x-opus"); + ret = gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depayload), srccaps); GST_DEBUG_OBJECT (depayload, "set caps on source: %" GST_PTR_FORMAT " (ret=%d)", srccaps, ret); @@ -114,10 +107,14 @@ gst_rtp_opus_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) } static GstBuffer * -gst_rtp_opus_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf) +gst_rtp_opus_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstBuffer *outbuf; - outbuf = gst_rtp_buffer_get_payload_buffer (buf); + GstRTPBuffer rtpbuf = { NULL, }; + + gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuf); + outbuf = gst_rtp_buffer_get_payload_buffer (&rtpbuf); + gst_rtp_buffer_unmap (&rtpbuf); return outbuf; } diff --git a/gst/rtp/gstrtpopusdepay.h b/gst/rtp/gstrtpopusdepay.h index ba217e0e8f..968ae52ae8 100644 --- a/gst/rtp/gstrtpopusdepay.h +++ b/gst/rtp/gstrtpopusdepay.h @@ -23,7 +23,7 @@ #define __GST_RTP_OPUS_DEPAY_H__ #include -#include +#include G_BEGIN_DECLS typedef struct _GstRTPOpusDepay GstRTPOpusDepay; typedef struct _GstRTPOpusDepayClass GstRTPOpusDepayClass; @@ -42,13 +42,13 @@ typedef struct _GstRTPOpusDepayClass GstRTPOpusDepayClass; struct _GstRTPOpusDepay { - GstBaseRTPDepayload depayload; + GstRTPBaseDepayload depayload; }; struct _GstRTPOpusDepayClass { - GstBaseRTPDepayloadClass parent_class; + GstRTPBaseDepayloadClass parent_class; }; GType gst_rtp_opus_depay_get_type (void); diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index cdd7ee00c3..5003c739f9 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -51,18 +51,24 @@ GST_STATIC_PAD_TEMPLATE ("src", "encoding-name = (string) \"X-GST-OPUS-DRAFT-SPITTKA-00\"") ); -static gboolean gst_rtp_opus_pay_setcaps (GstBaseRTPPayload * payload, +static gboolean gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps); -static GstFlowReturn gst_rtp_opus_pay_handle_buffer (GstBaseRTPPayload * +static GstFlowReturn gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * payload, GstBuffer * buffer); -GST_BOILERPLATE (GstRtpOPUSPay, gst_rtp_opus_pay, GstBaseRTPPayload, - GST_TYPE_BASE_RTP_PAYLOAD); +G_DEFINE_TYPE (GstRtpOPUSPay, gst_rtp_opus_pay, GST_TYPE_RTP_BASE_PAYLOAD); static void -gst_rtp_opus_pay_base_init (gpointer klass) +gst_rtp_opus_pay_class_init (GstRtpOPUSPayClass * klass) { - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstRTPBasePayloadClass *gstbasertppayload_class; + GstElementClass *element_class; + + gstbasertppayload_class = (GstRTPBasePayloadClass *) klass; + element_class = GST_ELEMENT_CLASS (klass); + + gstbasertppayload_class->set_caps = gst_rtp_opus_pay_setcaps; + gstbasertppayload_class->handle_buffer = gst_rtp_opus_pay_handle_buffer; gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_opus_pay_src_template)); @@ -74,39 +80,28 @@ gst_rtp_opus_pay_base_init (gpointer klass) "Codec/Payloader/Network/RTP", "Puts Opus audio in RTP packets", "Danilo Cesar Lemes de Paula "); -} - -static void -gst_rtp_opus_pay_class_init (GstRtpOPUSPayClass * klass) -{ - GstBaseRTPPayloadClass *gstbasertppayload_class; - - gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; - - gstbasertppayload_class->set_caps = gst_rtp_opus_pay_setcaps; - gstbasertppayload_class->handle_buffer = gst_rtp_opus_pay_handle_buffer; GST_DEBUG_CATEGORY_INIT (rtpopuspay_debug, "rtpopuspay", 0, "Opus RTP Payloader"); } static void -gst_rtp_opus_pay_init (GstRtpOPUSPay * rtpopuspay, GstRtpOPUSPayClass * klass) +gst_rtp_opus_pay_init (GstRtpOPUSPay * rtpopuspay) { } static gboolean -gst_rtp_opus_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) +gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) { gboolean res; gchar *capsstr; capsstr = gst_caps_to_string (caps); - gst_basertppayload_set_options (payload, "audio", FALSE, + gst_rtp_base_payload_set_options (payload, "audio", FALSE, "X-GST-OPUS-DRAFT-SPITTKA-00", 48000); res = - gst_basertppayload_set_outcaps (payload, "caps", G_TYPE_STRING, capsstr, + gst_rtp_base_payload_set_outcaps (payload, "caps", G_TYPE_STRING, capsstr, NULL); g_free (capsstr); @@ -114,27 +109,29 @@ gst_rtp_opus_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps) } static GstFlowReturn -gst_rtp_opus_pay_handle_buffer (GstBaseRTPPayload * basepayload, +gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buffer) { + GstRTPBuffer rtpbuf = { NULL, }; GstBuffer *outbuf; - GstClockTime timestamp; + gsize size; + gpointer *data; - guint size; - guint8 *data; - guint8 *payload; + /* Copy data and timestamp to a new output buffer + * FIXME : Don't we have a convenience function for this ? */ + data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ); + outbuf = gst_rtp_buffer_new_copy_data (data, size); + GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer); - size = GST_BUFFER_SIZE (buffer); - data = GST_BUFFER_DATA (buffer); - timestamp = GST_BUFFER_TIMESTAMP (buffer); + /* Unmap and free input buffer */ + gst_buffer_unmap (buffer, data, size); + gst_buffer_unref (buffer); - outbuf = gst_rtp_buffer_new_allocate (size, 0, 0); - payload = gst_rtp_buffer_get_payload (outbuf); + /* Remove marker from RTP buffer */ + gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtpbuf); + gst_rtp_buffer_set_marker (&rtpbuf, FALSE); + gst_rtp_buffer_unmap (&rtpbuf); - memcpy (payload, data, size); - - gst_rtp_buffer_set_marker (outbuf, FALSE); - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - - return gst_basertppayload_push (basepayload, outbuf); + /* Push out */ + return gst_rtp_base_payload_push (basepayload, outbuf); } diff --git a/gst/rtp/gstrtpopuspay.h b/gst/rtp/gstrtpopuspay.h index 23abd0dabf..81160fe2ad 100644 --- a/gst/rtp/gstrtpopuspay.h +++ b/gst/rtp/gstrtpopuspay.h @@ -23,7 +23,7 @@ #define __GST_RTP_OPUS_PAY_H__ #include -#include +#include G_BEGIN_DECLS @@ -43,12 +43,12 @@ typedef struct _GstRtpOPUSPayClass GstRtpOPUSPayClass; struct _GstRtpOPUSPay { - GstBaseRTPPayload payload; + GstRTPBasePayload payload; }; struct _GstRtpOPUSPayClass { - GstBaseRTPPayloadClass parent_class; + GstRTPBasePayloadClass parent_class; }; GType gst_rtp_opus_pay_get_type (void); From d1965627559894d6429a0962eee9ce0e8a1d0760 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 7 Mar 2012 17:14:29 +0100 Subject: [PATCH 04/20] opus: port to updated 0.11 --- gst/rtp/gstrtpopuspay.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 5003c739f9..0a8fd36516 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -114,17 +114,16 @@ gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * basepayload, { GstRTPBuffer rtpbuf = { NULL, }; GstBuffer *outbuf; - gsize size; - gpointer *data; + GstMapInfo map; /* Copy data and timestamp to a new output buffer * FIXME : Don't we have a convenience function for this ? */ - data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ); - outbuf = gst_rtp_buffer_new_copy_data (data, size); + gst_buffer_map (buffer, &map, GST_MAP_READ); + outbuf = gst_rtp_buffer_new_copy_data (map.data, map.size); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer); /* Unmap and free input buffer */ - gst_buffer_unmap (buffer, data, size); + gst_buffer_unmap (buffer, &map); gst_buffer_unref (buffer); /* Remove marker from RTP buffer */ From ad261f64c39550545104c67824b704716cb9cb57 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 14 Sep 2012 17:08:49 +0200 Subject: [PATCH 05/20] replace gst_element_class_set_details_simple with gst_element_class_set_metadata --- gst/rtp/gstrtpopusdepay.c | 2 +- gst/rtp/gstrtpopuspay.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index f8effbb6c7..dba1c14560 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -70,7 +70,7 @@ gst_rtp_opus_depay_class_init (GstRTPOpusDepayClass * klass) gst_static_pad_template_get (&gst_rtp_opus_depay_src_template)); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_opus_depay_sink_template)); - gst_element_class_set_details_simple (element_class, + gst_element_class_set_metadata (element_class, "RTP Opus packet depayloader", "Codec/Depayloader/Network/RTP", "Extracts Opus audio from RTP packets", "Danilo Cesar Lemes de Paula "); diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 0a8fd36516..9eee960663 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -75,7 +75,7 @@ gst_rtp_opus_pay_class_init (GstRtpOPUSPayClass * klass) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_opus_pay_sink_template)); - gst_element_class_set_details_simple (element_class, + gst_element_class_set_metadata (element_class, "RTP Opus payloader", "Codec/Payloader/Network/RTP", "Puts Opus audio in RTP packets", From 18638c9c4e8e199caf399f53e79c7e4c0693bc80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 20 Sep 2012 18:41:24 -0400 Subject: [PATCH 06/20] rtpopuspay: Allocate the rtp buffer correctly Use the right functions to allocate the rtp buffer --- gst/rtp/gstrtpopuspay.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 9eee960663..e1781e1b0b 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -112,24 +112,10 @@ static GstFlowReturn gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buffer) { - GstRTPBuffer rtpbuf = { NULL, }; GstBuffer *outbuf; - GstMapInfo map; - /* Copy data and timestamp to a new output buffer - * FIXME : Don't we have a convenience function for this ? */ - gst_buffer_map (buffer, &map, GST_MAP_READ); - outbuf = gst_rtp_buffer_new_copy_data (map.data, map.size); - GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer); - - /* Unmap and free input buffer */ - gst_buffer_unmap (buffer, &map); - gst_buffer_unref (buffer); - - /* Remove marker from RTP buffer */ - gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtpbuf); - gst_rtp_buffer_set_marker (&rtpbuf, FALSE); - gst_rtp_buffer_unmap (&rtpbuf); + outbuf = gst_rtp_buffer_new_allocate (0, 0, 0); + outbuf = gst_buffer_append (outbuf, gst_buffer_ref (buffer)); /* Push out */ return gst_rtp_base_payload_push (basepayload, outbuf); From 17742d234797811dfcdfec54fb009c30799d2e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 17 Oct 2012 17:34:26 +0100 Subject: [PATCH 07/20] Use gst_element_class_set_static_metadata() where possible. Avoids some string copies. Also re-indent some stuff. Also some indent fixes here and there. --- gst/rtp/gstrtpopusdepay.c | 2 +- gst/rtp/gstrtpopuspay.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index dba1c14560..8d89e282a4 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -70,7 +70,7 @@ gst_rtp_opus_depay_class_init (GstRTPOpusDepayClass * klass) gst_static_pad_template_get (&gst_rtp_opus_depay_src_template)); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_opus_depay_sink_template)); - gst_element_class_set_metadata (element_class, + gst_element_class_set_static_metadata (element_class, "RTP Opus packet depayloader", "Codec/Depayloader/Network/RTP", "Extracts Opus audio from RTP packets", "Danilo Cesar Lemes de Paula "); diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index e1781e1b0b..cb3279c2a3 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -75,7 +75,7 @@ gst_rtp_opus_pay_class_init (GstRtpOPUSPayClass * klass) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_rtp_opus_pay_sink_template)); - gst_element_class_set_metadata (element_class, + gst_element_class_set_static_metadata (element_class, "RTP Opus payloader", "Codec/Payloader/Network/RTP", "Puts Opus audio in RTP packets", From 5d893c7ea23389df06c5ca00014ac0c89225a719 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 22 Oct 2012 12:08:41 +0200 Subject: [PATCH 08/20] opuspay: remove pointless caps serialization Remove the caps serialization in the rtp caps. the spec nor the receiver does anything with it. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=686547 --- gst/rtp/gstrtpopuspay.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index cb3279c2a3..5ba3217cde 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -94,16 +94,10 @@ static gboolean gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) { gboolean res; - gchar *capsstr; - - capsstr = gst_caps_to_string (caps); gst_rtp_base_payload_set_options (payload, "audio", FALSE, "X-GST-OPUS-DRAFT-SPITTKA-00", 48000); - res = - gst_rtp_base_payload_set_outcaps (payload, "caps", G_TYPE_STRING, capsstr, - NULL); - g_free (capsstr); + res = gst_rtp_base_payload_set_outcaps (payload, NULL); return res; } From 117e30c47e7241f1acf4b95b751ce2c8fb78a833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 3 Nov 2012 20:38:00 +0000 Subject: [PATCH 09/20] Fix FSF address https://bugzilla.gnome.org/show_bug.cgi?id=687520 --- gst/rtp/gstrtpopusdepay.c | 4 ++-- gst/rtp/gstrtpopusdepay.h | 4 ++-- gst/rtp/gstrtpopuspay.c | 4 ++-- gst/rtp/gstrtpopuspay.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index 8d89e282a4..da6d51eabc 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -15,8 +15,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H diff --git a/gst/rtp/gstrtpopusdepay.h b/gst/rtp/gstrtpopusdepay.h index 968ae52ae8..7890eb19d5 100644 --- a/gst/rtp/gstrtpopusdepay.h +++ b/gst/rtp/gstrtpopusdepay.h @@ -15,8 +15,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifndef __GST_RTP_OPUS_DEPAY_H__ diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 5ba3217cde..acebc8d9c2 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -15,8 +15,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H diff --git a/gst/rtp/gstrtpopuspay.h b/gst/rtp/gstrtpopuspay.h index 81160fe2ad..e21bbe3c38 100644 --- a/gst/rtp/gstrtpopuspay.h +++ b/gst/rtp/gstrtpopuspay.h @@ -15,8 +15,8 @@ * * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ #ifndef __GST_RTP_OPUS_PAY_H__ From b310393916467e0a24d04c1372132773c371a2ed Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 31 Jan 2013 12:30:49 +0100 Subject: [PATCH 10/20] opuspay: fix timestamps Copy timestamps to payloaded buffer. Avoid input buffer memory leak. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=692929 --- gst/rtp/gstrtpopuspay.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index acebc8d9c2..69ad51ec6f 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -107,9 +107,18 @@ gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buffer) { GstBuffer *outbuf; + GstClockTime pts, dts, duration; + + pts = GST_BUFFER_PTS (buffer); + dts = GST_BUFFER_DTS (buffer); + duration = GST_BUFFER_DURATION (buffer); outbuf = gst_rtp_buffer_new_allocate (0, 0, 0); - outbuf = gst_buffer_append (outbuf, gst_buffer_ref (buffer)); + outbuf = gst_buffer_append (outbuf, buffer); + + GST_BUFFER_PTS (outbuf) = pts; + GST_BUFFER_DTS (outbuf) = dts; + GST_BUFFER_DURATION (outbuf) = duration; /* Push out */ return gst_rtp_base_payload_push (basepayload, outbuf); From 9e4511edf4b20736ecafc137a6eaa11ddb638826 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Sat, 1 Nov 2014 10:10:27 -0400 Subject: [PATCH 11/20] rtpopus: Use OPUS encoding name Both Firefox and Chrome uses OPUS as the encoding in their SDP. Adding this now defacto standard name remove the need for special case in SDP parsing code. https://bugzilla.gnome.org/show_bug.cgi?id=737810 --- gst/rtp/gstrtpopusdepay.c | 2 +- gst/rtp/gstrtpopuspay.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index da6d51eabc..6bcdd12627 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -39,7 +39,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", "media = (string) \"audio\", " "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING "," "clock-rate = (int) 48000, " - "encoding-name = (string) \"X-GST-OPUS-DRAFT-SPITTKA-00\"") + "encoding-name = (string) { \"OPUS\", \"X-GST-OPUS-DRAFT-SPITTKA-00\" }") ); static GstStaticPadTemplate gst_rtp_opus_depay_src_template = diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 69ad51ec6f..8cfd79def7 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -48,7 +48,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "media = (string) \"audio\", " "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " "clock-rate = (int) 48000, " - "encoding-name = (string) \"X-GST-OPUS-DRAFT-SPITTKA-00\"") + "encoding-name = (string) { \"OPUS\", \"X-GST-OPUS-DRAFT-SPITTKA-00\" }") ); static gboolean gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, From e427369840e30477e6791543795264f884569ad6 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 5 Feb 2015 10:27:51 +0000 Subject: [PATCH 12/20] rtpopuspay: negotiate the encoding name Chrome uses a different encoding name that gstreamer. https://bugzilla.gnome.org/show_bug.cgi?id=737810 --- gst/rtp/gstrtpopuspay.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 8cfd79def7..7cd90eff63 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -94,9 +94,26 @@ static gboolean gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) { gboolean res; + GstCaps *src_caps; + GstStructure *s; + char *encoding_name; + + src_caps = gst_pad_get_allowed_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload)); + if (src_caps) { + src_caps = gst_caps_truncate (src_caps); + src_caps = gst_caps_make_writable (src_caps); + s = gst_caps_get_structure (src_caps, 0); + gst_structure_fixate_field_string (s, "encoding-name", + "X-GST-OPUS-DRAFT-SPITTKA-00"); + encoding_name = g_strdup (gst_structure_get_string (s, "encoding-name")); + gst_caps_unref (src_caps); + } else { + encoding_name = g_strdup ("X-GST-OPUS-DRAFT-SPITTKA-00"); + } gst_rtp_base_payload_set_options (payload, "audio", FALSE, - "X-GST-OPUS-DRAFT-SPITTKA-00", 48000); + encoding_name, 48000); + g_free (encoding_name); res = gst_rtp_base_payload_set_outcaps (payload, NULL); return res; From 755289ed0ceefe35d5ef14b39886389ecf2e47a7 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 19 Feb 2015 14:05:06 +0000 Subject: [PATCH 13/20] rtpopuspay: make caps writable before truncating them https://bugzilla.gnome.org/show_bug.cgi?id=737810 --- gst/rtp/gstrtpopuspay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 7cd90eff63..eebbdee766 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -100,8 +100,8 @@ gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) src_caps = gst_pad_get_allowed_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload)); if (src_caps) { - src_caps = gst_caps_truncate (src_caps); src_caps = gst_caps_make_writable (src_caps); + src_caps = gst_caps_truncate (src_caps); s = gst_caps_get_structure (src_caps, 0); gst_structure_fixate_field_string (s, "encoding-name", "X-GST-OPUS-DRAFT-SPITTKA-00"); From 4b5ad70924f3c86b6cdeff2d75068daad80a584b Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 19 Feb 2015 14:30:10 +0000 Subject: [PATCH 14/20] rtpopuspay: default encoding name to OPUS https://bugzilla.gnome.org/show_bug.cgi?id=737810 --- gst/rtp/gstrtpopuspay.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index eebbdee766..d0f7b10c54 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -103,8 +103,7 @@ gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) src_caps = gst_caps_make_writable (src_caps); src_caps = gst_caps_truncate (src_caps); s = gst_caps_get_structure (src_caps, 0); - gst_structure_fixate_field_string (s, "encoding-name", - "X-GST-OPUS-DRAFT-SPITTKA-00"); + gst_structure_fixate_field_string (s, "encoding-name", "OPUS"); encoding_name = g_strdup (gst_structure_get_string (s, "encoding-name")); gst_caps_unref (src_caps); } else { From bbb1143ca36f9e201a6236dcfed384d44b26b4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 23 Mar 2015 12:24:55 +0100 Subject: [PATCH 15/20] opus: Handle sprop-stereo and sprop-maxcapturerate RTP caps fields https://bugzilla.gnome.org/show_bug.cgi?id=746617 --- gst/rtp/gstrtpopusdepay.c | 29 +++++++++++++++++++++++++++++ gst/rtp/gstrtpopuspay.c | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index 6bcdd12627..f58259ff8a 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -92,9 +92,38 @@ static gboolean gst_rtp_opus_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) { GstCaps *srccaps; + GstStructure *s; gboolean ret; + const gchar *sprop_stereo, *sprop_maxcapturerate; srccaps = gst_caps_new_empty_simple ("audio/x-opus"); + + s = gst_caps_get_structure (caps, 0); + if ((sprop_stereo = gst_structure_get_string (s, "sprop-stereo"))) { + if (strcmp (sprop_stereo, "0") == 0) + gst_caps_set_simple (srccaps, "channels", G_TYPE_INT, 1, NULL); + else if (strcmp (sprop_stereo, "1") == 0) + gst_caps_set_simple (srccaps, "channels", G_TYPE_INT, 2, NULL); + else + GST_WARNING_OBJECT (depayload, "Unknown sprop-stereo value '%s'", + sprop_stereo); + } + + if ((sprop_maxcapturerate = + gst_structure_get_string (s, "sprop-maxcapturerate"))) { + gulong rate; + gchar *tailptr; + + rate = strtoul (sprop_maxcapturerate, &tailptr, 10); + if (rate > INT_MAX || *tailptr != '\0') { + GST_WARNING_OBJECT (depayload, + "Failed to parse sprop-maxcapturerate value '%s'", + sprop_maxcapturerate); + } else { + gst_caps_set_simple (srccaps, "rate", G_TYPE_INT, rate, NULL); + } + } + ret = gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depayload), srccaps); GST_DEBUG_OBJECT (depayload, diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index d0f7b10c54..a5a69569e4 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -97,6 +97,9 @@ gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) GstCaps *src_caps; GstStructure *s; char *encoding_name; + gint channels, rate; + const char *sprop_stereo = NULL; + char *sprop_maxcapturerate = NULL; src_caps = gst_pad_get_allowed_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload)); if (src_caps) { @@ -110,10 +113,44 @@ gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) encoding_name = g_strdup ("X-GST-OPUS-DRAFT-SPITTKA-00"); } + 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"); + return FALSE; + } else if (channels == 2) { + sprop_stereo = "1"; + } else { + sprop_stereo = "0"; + } + } + + if (gst_structure_get_int (s, "rate", &rate)) { + sprop_maxcapturerate = g_strdup_printf ("%d", rate); + } + gst_rtp_base_payload_set_options (payload, "audio", FALSE, encoding_name, 48000); g_free (encoding_name); - res = gst_rtp_base_payload_set_outcaps (payload, NULL); + + if (sprop_maxcapturerate && sprop_stereo) { + res = + gst_rtp_base_payload_set_outcaps (payload, "sprop-maxcapturerate", + G_TYPE_STRING, sprop_maxcapturerate, "sprop-stereo", G_TYPE_STRING, + sprop_stereo, NULL); + } else if (sprop_maxcapturerate) { + res = + gst_rtp_base_payload_set_outcaps (payload, "sprop-maxcapturerate", + G_TYPE_STRING, sprop_maxcapturerate, NULL); + } else if (sprop_stereo) { + res = + gst_rtp_base_payload_set_outcaps (payload, "sprop-stereo", + G_TYPE_STRING, sprop_stereo, NULL); + } else { + res = gst_rtp_base_payload_set_outcaps (payload, NULL); + } + + g_free (sprop_maxcapturerate); return res; } From 4df223f3257f29a14086b17c7904b13b71d5ab80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 24 Mar 2015 13:56:21 -0400 Subject: [PATCH 16/20] rtpopuspay: Set the number of channels to 2 as per RFC draft https://bugzilla.gnome.org/show_bug.cgi?id=746617 --- gst/rtp/gstrtpopuspay.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index a5a69569e4..7a36dceaaf 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -48,6 +48,7 @@ GST_STATIC_PAD_TEMPLATE ("src", "media = (string) \"audio\", " "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", " "clock-rate = (int) 48000, " + "encoding-params = (string) \"2\", " "encoding-name = (string) { \"OPUS\", \"X-GST-OPUS-DRAFT-SPITTKA-00\" }") ); From 89b172b3ed43a5e43dd12b70611e3fd627a35b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 24 Mar 2015 13:57:54 -0400 Subject: [PATCH 17/20] rtpopuspay: Forward stereo preferences from caps upstream https://bugzilla.gnome.org/show_bug.cgi?id=746617 --- gst/rtp/gstrtpopuspay.c | 65 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 7a36dceaaf..057c8d0cc3 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -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; +} From ff51629c9aba8dac99c393512776e57719081879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 4 May 2015 11:23:16 +0200 Subject: [PATCH 18/20] opusdepay: Set multistream=FALSE on the Opus caps The RTP Opus mapping only allows mono/stereo, and not multistream Opus streams. --- gst/rtp/gstrtpopusdepay.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index f58259ff8a..af3237bebb 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -46,7 +46,7 @@ static GstStaticPadTemplate gst_rtp_opus_depay_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-opus") + GST_STATIC_CAPS ("audio/x-opus, multistream = (boolean) FALSE") ); static GstBuffer *gst_rtp_opus_depay_process (GstRTPBaseDepayload * depayload, @@ -96,7 +96,9 @@ gst_rtp_opus_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) gboolean ret; const gchar *sprop_stereo, *sprop_maxcapturerate; - srccaps = gst_caps_new_empty_simple ("audio/x-opus"); + srccaps = + gst_caps_new_simple ("audio/x-opus", "multistream", G_TYPE_BOOLEAN, FALSE, + NULL); s = gst_caps_get_structure (caps, 0); if ((sprop_stereo = gst_structure_get_string (s, "sprop-stereo"))) { From 0472d9f8b238ff5ad99b88eafd556469e116796b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 30 Jun 2015 13:51:33 +0200 Subject: [PATCH 19/20] opus: Copy metadata in the (de)payloader, but only the relevant ones The payloader didn't copy anything so far, the depayloader copied every possible meta. Let's make it consistent and just copy all metas without tags or with only the audio tag. https://bugzilla.gnome.org/show_bug.cgi?id=751774 --- gst/rtp/gstrtpopusdepay.c | 24 ++++++++++++++++++++++++ gst/rtp/gstrtpopuspay.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index af3237bebb..abb7218e03 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "gstrtpopusdepay.h" GST_DEBUG_CATEGORY_STATIC (rtpopusdepay_debug); @@ -137,6 +138,25 @@ gst_rtp_opus_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) return ret; } +static gboolean +foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data) +{ + GstRTPOpusDepay *depay = user_data; + const GstMetaInfo *info = (*meta)->info; + const gchar *const *tags = gst_meta_api_type_get_tags (info->api); + + if (!tags || (g_strv_length ((gchar **) tags) == 1 + && gst_meta_api_type_has_tag (info->api, + g_quark_from_string (GST_META_TAG_AUDIO_STR)))) { + GST_DEBUG_OBJECT (depay, "keeping metadata %s", g_type_name (info->api)); + } else { + GST_DEBUG_OBJECT (depay, "dropping metadata %s", g_type_name (info->api)); + *meta = NULL; + } + + return TRUE; +} + static GstBuffer * gst_rtp_opus_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { @@ -147,5 +167,9 @@ gst_rtp_opus_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) outbuf = gst_rtp_buffer_get_payload_buffer (&rtpbuf); gst_rtp_buffer_unmap (&rtpbuf); + outbuf = gst_buffer_make_writable (outbuf); + /* Filter away all metas that are not sensible to copy */ + gst_buffer_foreach_meta (outbuf, foreach_metadata, depayload); + return outbuf; } diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index 057c8d0cc3..ead49a58a6 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -26,6 +26,7 @@ #include #include +#include #include "gstrtpopuspay.h" @@ -160,18 +161,52 @@ gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) return res; } +typedef struct +{ + GstRtpOPUSPay *pay; + GstBuffer *outbuf; +} CopyMetaData; + +static gboolean +foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data) +{ + CopyMetaData *data = user_data; + GstRtpOPUSPay *pay = data->pay; + GstBuffer *outbuf = data->outbuf; + const GstMetaInfo *info = (*meta)->info; + const gchar *const *tags = gst_meta_api_type_get_tags (info->api); + + if (!tags || (g_strv_length ((gchar **) tags) == 1 + && gst_meta_api_type_has_tag (info->api, + g_quark_from_string (GST_META_TAG_AUDIO_STR)))) { + GstMetaTransformCopy copy_data = { FALSE, 0, -1 }; + GST_DEBUG_OBJECT (pay, "copy metadata %s", g_type_name (info->api)); + /* simply copy then */ + info->transform_func (outbuf, *meta, inbuf, + _gst_meta_transform_copy, ©_data); + } else { + GST_DEBUG_OBJECT (pay, "not copying metadata %s", g_type_name (info->api)); + } + + return TRUE; +} + static GstFlowReturn gst_rtp_opus_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buffer) { GstBuffer *outbuf; GstClockTime pts, dts, duration; + CopyMetaData data; pts = GST_BUFFER_PTS (buffer); dts = GST_BUFFER_DTS (buffer); duration = GST_BUFFER_DURATION (buffer); outbuf = gst_rtp_buffer_new_allocate (0, 0, 0); + data.pay = GST_RTP_OPUS_PAY (basepayload); + data.outbuf = outbuf; + gst_buffer_foreach_meta (buffer, foreach_metadata, &data); outbuf = gst_buffer_append (outbuf, buffer); GST_BUFFER_PTS (outbuf) = pts; From 01342378b56fe7445ae8292139aba93bab65cec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 3 Nov 2015 14:50:53 +0200 Subject: [PATCH 20/20] opus: Add proper support for multichannel audio https://bugzilla.gnome.org/show_bug.cgi?id=757152 --- gst/rtp/gstrtpopusdepay.c | 6 +++--- gst/rtp/gstrtpopuspay.c | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/gst/rtp/gstrtpopusdepay.c b/gst/rtp/gstrtpopusdepay.c index abb7218e03..8152cd57fa 100644 --- a/gst/rtp/gstrtpopusdepay.c +++ b/gst/rtp/gstrtpopusdepay.c @@ -47,7 +47,7 @@ static GstStaticPadTemplate gst_rtp_opus_depay_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-opus, multistream = (boolean) FALSE") + GST_STATIC_CAPS ("audio/x-opus, channel-mapping-family = (int) 0") ); static GstBuffer *gst_rtp_opus_depay_process (GstRTPBaseDepayload * depayload, @@ -98,8 +98,8 @@ gst_rtp_opus_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps) const gchar *sprop_stereo, *sprop_maxcapturerate; srccaps = - gst_caps_new_simple ("audio/x-opus", "multistream", G_TYPE_BOOLEAN, FALSE, - NULL); + gst_caps_new_simple ("audio/x-opus", "channel-mapping-family", G_TYPE_INT, + 0, NULL); s = gst_caps_get_structure (caps, 0); if ((sprop_stereo = gst_structure_get_string (s, "sprop-stereo"))) { diff --git a/gst/rtp/gstrtpopuspay.c b/gst/rtp/gstrtpopuspay.c index ead49a58a6..5038028b12 100644 --- a/gst/rtp/gstrtpopuspay.c +++ b/gst/rtp/gstrtpopuspay.c @@ -38,7 +38,8 @@ 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, multistream = (boolean) FALSE") + GST_STATIC_CAPS + ("audio/x-opus, channels = (int) [1, 2], channel-mapping-family = (int) 0") ); static GstStaticPadTemplate gst_rtp_opus_pay_src_template = @@ -122,7 +123,7 @@ gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) if (gst_structure_get_int (s, "channels", &channels)) { if (channels > 2) { GST_ERROR_OBJECT (payload, - "More than 2 channels with multistream=FALSE is invalid"); + "More than 2 channels with channel-mapping-family=0 is invalid"); return FALSE; } else if (channels == 2) { sprop_stereo = "1";