opusenc: Reverse channel order in template caps
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-base / ext / opus / gstopusenc.c
1 /* GStreamer Opus Encoder
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2008> Sebastian Dröge <sebastian.droege@collabora.co.uk>
4  * Copyright (C) <2011> Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 /*
23  * Based on the speexenc element
24  */
25
26 /**
27  * SECTION:element-opusenc
28  * @title: opusenc
29  * @see_also: opusdec, oggmux
30  *
31  * This element encodes raw audio to OPUS.
32  *
33  * ## Example pipelines
34  * |[
35  * gst-launch-1.0 -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! opusenc ! oggmux ! filesink location=sine.ogg
36  * ]|
37  * Encode a test sine signal to Ogg/OPUS.
38  *
39  */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47 #include <math.h>
48 #include <opus.h>
49
50 #include <gst/gsttagsetter.h>
51 #include <gst/audio/audio.h>
52 #include <gst/pbutils/pbutils.h>
53 #include <gst/tag/tag.h>
54 #include <gst/glib-compat-private.h>
55
56 #include "gstopuselements.h"
57 #include "gstopusheader.h"
58 #include "gstopuscommon.h"
59 #include "gstopusenc.h"
60
61 GST_DEBUG_CATEGORY_STATIC (opusenc_debug);
62 #define GST_CAT_DEFAULT opusenc_debug
63
64 /* Some arbitrary bounds beyond which it really doesn't make sense.
65    The spec mentions 6 kb/s to 510 kb/s, so 4000 and 650000 ought to be
66    safe as property bounds. */
67 #define LOWEST_BITRATE 4000
68 #define HIGHEST_BITRATE 650000
69
70 #define GST_OPUS_ENC_TYPE_BANDWIDTH (gst_opus_enc_bandwidth_get_type())
71 static GType
72 gst_opus_enc_bandwidth_get_type (void)
73 {
74   static const GEnumValue values[] = {
75     {OPUS_BANDWIDTH_NARROWBAND, "Narrow band", "narrowband"},
76     {OPUS_BANDWIDTH_MEDIUMBAND, "Medium band", "mediumband"},
77     {OPUS_BANDWIDTH_WIDEBAND, "Wide band", "wideband"},
78     {OPUS_BANDWIDTH_SUPERWIDEBAND, "Super wide band", "superwideband"},
79     {OPUS_BANDWIDTH_FULLBAND, "Full band", "fullband"},
80     {OPUS_AUTO, "Auto", "auto"},
81     {0, NULL, NULL}
82   };
83   static GType id = 0;
84
85   if (g_once_init_enter ((gsize *) & id)) {
86     GType _id;
87
88     _id = g_enum_register_static ("GstOpusEncBandwidth", values);
89
90     g_once_init_leave ((gsize *) & id, _id);
91   }
92
93   return id;
94 }
95
96 #define GST_OPUS_ENC_TYPE_FRAME_SIZE (gst_opus_enc_frame_size_get_type())
97 static GType
98 gst_opus_enc_frame_size_get_type (void)
99 {
100   static const GEnumValue values[] = {
101     {2, "2.5", "2.5"},
102     {5, "5", "5"},
103     {10, "10", "10"},
104     {20, "20", "20"},
105     {40, "40", "40"},
106     {60, "60", "60"},
107     {0, NULL, NULL}
108   };
109   static GType id = 0;
110
111   if (g_once_init_enter ((gsize *) & id)) {
112     GType _id;
113
114     _id = g_enum_register_static ("GstOpusEncFrameSize", values);
115
116     g_once_init_leave ((gsize *) & id, _id);
117   }
118
119   return id;
120 }
121
122 #define GST_OPUS_ENC_TYPE_AUDIO_TYPE (gst_opus_enc_audio_type_get_type())
123 static GType
124 gst_opus_enc_audio_type_get_type (void)
125 {
126   static const GEnumValue values[] = {
127     {OPUS_APPLICATION_AUDIO, "Generic audio", "generic"},
128     {OPUS_APPLICATION_VOIP, "Voice", "voice"},
129     {OPUS_APPLICATION_RESTRICTED_LOWDELAY, "Restricted low delay",
130         "restricted-lowdelay"},
131     {0, NULL, NULL}
132   };
133   static GType id = 0;
134
135   if (g_once_init_enter ((gsize *) & id)) {
136     GType _id;
137
138     _id = g_enum_register_static ("GstOpusEncAudioType", values);
139
140     g_once_init_leave ((gsize *) & id, _id);
141   }
142
143   return id;
144 }
145
146 #define GST_OPUS_ENC_TYPE_BITRATE_TYPE (gst_opus_enc_bitrate_type_get_type())
147 static GType
148 gst_opus_enc_bitrate_type_get_type (void)
149 {
150   static const GEnumValue values[] = {
151     {BITRATE_TYPE_CBR, "CBR", "cbr"},
152     {BITRATE_TYPE_VBR, "VBR", "vbr"},
153     {BITRATE_TYPE_CONSTRAINED_VBR, "Constrained VBR", "constrained-vbr"},
154     {0, NULL, NULL}
155   };
156   static GType id = 0;
157
158   if (g_once_init_enter ((gsize *) & id)) {
159     GType _id;
160
161     _id = g_enum_register_static ("GstOpusEncBitrateType", values);
162
163     g_once_init_leave ((gsize *) & id, _id);
164   }
165
166   return id;
167 }
168
169 #define FORMAT_STR GST_AUDIO_NE(S16)
170 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
171     GST_PAD_SINK,
172     GST_PAD_ALWAYS,
173     GST_STATIC_CAPS ("audio/x-raw, "
174         "format = (string) " FORMAT_STR ", "
175         "layout = (string) interleaved, "
176         "rate = (int) 48000, "
177         "channels = (int) [ 1, 8 ]; "
178         "audio/x-raw, "
179         "format = (string) " FORMAT_STR ", "
180         "layout = (string) interleaved, "
181         "rate = (int) { 8000, 12000, 16000, 24000 }, "
182         "channels = (int) [ 1, 8 ] ")
183     );
184
185 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
186     GST_PAD_SRC,
187     GST_PAD_ALWAYS,
188     GST_STATIC_CAPS ("audio/x-opus")
189     );
190
191 #define DEFAULT_AUDIO           TRUE
192 #define DEFAULT_AUDIO_TYPE      OPUS_APPLICATION_AUDIO
193 #define DEFAULT_BITRATE         64000
194 #define DEFAULT_BANDWIDTH       OPUS_BANDWIDTH_FULLBAND
195 #define DEFAULT_FRAMESIZE       20
196 #define DEFAULT_CBR             TRUE
197 #define DEFAULT_CONSTRAINED_VBR TRUE
198 #define DEFAULT_BITRATE_TYPE    BITRATE_TYPE_CONSTRAINED_VBR
199 #define DEFAULT_COMPLEXITY      10
200 #define DEFAULT_INBAND_FEC      FALSE
201 #define DEFAULT_DTX             FALSE
202 #define DEFAULT_PACKET_LOSS_PERCENT 0
203 #define DEFAULT_MAX_PAYLOAD_SIZE 4000
204
205 enum
206 {
207   PROP_0,
208   PROP_AUDIO_TYPE,
209   PROP_BITRATE,
210   PROP_BANDWIDTH,
211   PROP_FRAME_SIZE,
212   PROP_BITRATE_TYPE,
213   PROP_COMPLEXITY,
214   PROP_INBAND_FEC,
215   PROP_DTX,
216   PROP_PACKET_LOSS_PERCENT,
217   PROP_MAX_PAYLOAD_SIZE
218 };
219
220 static void gst_opus_enc_finalize (GObject * object);
221
222 static gboolean gst_opus_enc_sink_event (GstAudioEncoder * benc,
223     GstEvent * event);
224 static GstCaps *gst_opus_enc_sink_getcaps (GstAudioEncoder * benc,
225     GstCaps * filter);
226 static gboolean gst_opus_enc_setup (GstOpusEnc * enc);
227
228 static void gst_opus_enc_get_property (GObject * object, guint prop_id,
229     GValue * value, GParamSpec * pspec);
230 static void gst_opus_enc_set_property (GObject * object, guint prop_id,
231     const GValue * value, GParamSpec * pspec);
232
233 static void gst_opus_enc_set_tags (GstOpusEnc * enc);
234 static gboolean gst_opus_enc_start (GstAudioEncoder * benc);
235 static gboolean gst_opus_enc_stop (GstAudioEncoder * benc);
236 static gboolean gst_opus_enc_set_format (GstAudioEncoder * benc,
237     GstAudioInfo * info);
238 static GstFlowReturn gst_opus_enc_handle_frame (GstAudioEncoder * benc,
239     GstBuffer * buf);
240 static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
241
242 static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buffer);
243
244 #define gst_opus_enc_parent_class parent_class
245 G_DEFINE_TYPE_WITH_CODE (GstOpusEnc, gst_opus_enc, GST_TYPE_AUDIO_ENCODER,
246     G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
247     G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
248 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (opusenc, "opusenc",
249     GST_RANK_PRIMARY, GST_TYPE_OPUS_ENC, opus_element_init (plugin));
250
251 static void
252 gst_opus_enc_set_tags (GstOpusEnc * enc)
253 {
254   GstTagList *taglist;
255
256   /* create a taglist and add a bitrate tag to it */
257   taglist = gst_tag_list_new_empty ();
258   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
259       GST_TAG_BITRATE, enc->bitrate, NULL);
260
261   gst_audio_encoder_merge_tags (GST_AUDIO_ENCODER (enc), taglist,
262       GST_TAG_MERGE_REPLACE);
263
264   gst_tag_list_unref (taglist);
265 }
266
267 static void
268 gst_opus_enc_class_init (GstOpusEncClass * klass)
269 {
270   GObjectClass *gobject_class;
271   GstAudioEncoderClass *base_class;
272   GstElementClass *gstelement_class;
273
274   gobject_class = (GObjectClass *) klass;
275   base_class = (GstAudioEncoderClass *) klass;
276   gstelement_class = (GstElementClass *) klass;
277
278   gobject_class->set_property = gst_opus_enc_set_property;
279   gobject_class->get_property = gst_opus_enc_get_property;
280
281   gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
282   gst_element_class_add_static_pad_template (gstelement_class, &sink_factory);
283   gst_element_class_set_static_metadata (gstelement_class, "Opus audio encoder",
284       "Codec/Encoder/Audio",
285       "Encodes audio in Opus format",
286       "Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>");
287
288   base_class->start = GST_DEBUG_FUNCPTR (gst_opus_enc_start);
289   base_class->stop = GST_DEBUG_FUNCPTR (gst_opus_enc_stop);
290   base_class->set_format = GST_DEBUG_FUNCPTR (gst_opus_enc_set_format);
291   base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_opus_enc_handle_frame);
292   base_class->sink_event = GST_DEBUG_FUNCPTR (gst_opus_enc_sink_event);
293   base_class->getcaps = GST_DEBUG_FUNCPTR (gst_opus_enc_sink_getcaps);
294
295   g_object_class_install_property (gobject_class, PROP_AUDIO_TYPE,
296       g_param_spec_enum ("audio-type", "What type of audio to optimize for",
297           "What type of audio to optimize for", GST_OPUS_ENC_TYPE_AUDIO_TYPE,
298           DEFAULT_AUDIO_TYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
299   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BITRATE,
300       g_param_spec_int ("bitrate", "Encoding Bit-rate",
301           "Specify an encoding bit-rate (in bps).", LOWEST_BITRATE,
302           HIGHEST_BITRATE, DEFAULT_BITRATE,
303           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
304           GST_PARAM_MUTABLE_PLAYING));
305   g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
306       g_param_spec_enum ("bandwidth", "Band Width", "Audio Band Width",
307           GST_OPUS_ENC_TYPE_BANDWIDTH, DEFAULT_BANDWIDTH,
308           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
309           GST_PARAM_MUTABLE_PLAYING));
310   g_object_class_install_property (gobject_class, PROP_FRAME_SIZE,
311       g_param_spec_enum ("frame-size", "Frame Size",
312           "The duration of an audio frame, in ms", GST_OPUS_ENC_TYPE_FRAME_SIZE,
313           DEFAULT_FRAMESIZE,
314           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
315           GST_PARAM_MUTABLE_PLAYING));
316   g_object_class_install_property (gobject_class, PROP_BITRATE_TYPE,
317       g_param_spec_enum ("bitrate-type", "Bitrate type", "Bitrate type",
318           GST_OPUS_ENC_TYPE_BITRATE_TYPE, DEFAULT_BITRATE_TYPE,
319           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
320           GST_PARAM_MUTABLE_PLAYING));
321   g_object_class_install_property (gobject_class, PROP_COMPLEXITY,
322       g_param_spec_int ("complexity", "Complexity", "Complexity", 0, 10,
323           DEFAULT_COMPLEXITY,
324           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
325           GST_PARAM_MUTABLE_PLAYING));
326   g_object_class_install_property (gobject_class, PROP_INBAND_FEC,
327       g_param_spec_boolean ("inband-fec", "In-band FEC",
328           "Enable in-band forward error correction (use in combination with "
329           "the packet-loss-percentage property)", DEFAULT_INBAND_FEC,
330           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
331           GST_PARAM_MUTABLE_PLAYING));
332   g_object_class_install_property (gobject_class, PROP_DTX,
333       g_param_spec_boolean ("dtx", "DTX", "DTX", DEFAULT_DTX,
334           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
335           GST_PARAM_MUTABLE_PLAYING));
336   g_object_class_install_property (G_OBJECT_CLASS (klass),
337       PROP_PACKET_LOSS_PERCENT, g_param_spec_int ("packet-loss-percentage",
338           "Loss percentage", "Packet loss percentage", 0, 100,
339           DEFAULT_PACKET_LOSS_PERCENT,
340           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
341           GST_PARAM_MUTABLE_PLAYING));
342   g_object_class_install_property (G_OBJECT_CLASS (klass),
343       PROP_MAX_PAYLOAD_SIZE, g_param_spec_uint ("max-payload-size",
344           "Max payload size", "Maximum payload size in bytes", 2, 4000,
345           DEFAULT_MAX_PAYLOAD_SIZE,
346           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
347           GST_PARAM_MUTABLE_PLAYING));
348
349   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_opus_enc_finalize);
350
351   GST_DEBUG_CATEGORY_INIT (opusenc_debug, "opusenc", 0, "Opus encoder");
352
353   gst_type_mark_as_plugin_api (GST_OPUS_ENC_TYPE_AUDIO_TYPE, 0);
354   gst_type_mark_as_plugin_api (GST_OPUS_ENC_TYPE_BANDWIDTH, 0);
355   gst_type_mark_as_plugin_api (GST_OPUS_ENC_TYPE_BITRATE_TYPE, 0);
356   gst_type_mark_as_plugin_api (GST_OPUS_ENC_TYPE_FRAME_SIZE, 0);
357 }
358
359 static void
360 gst_opus_enc_finalize (GObject * object)
361 {
362   GstOpusEnc *enc;
363
364   enc = GST_OPUS_ENC (object);
365
366   g_mutex_clear (&enc->property_lock);
367
368   G_OBJECT_CLASS (parent_class)->finalize (object);
369 }
370
371 static void
372 gst_opus_enc_init (GstOpusEnc * enc)
373 {
374   GST_DEBUG_OBJECT (enc, "init");
375
376   GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (enc));
377
378   g_mutex_init (&enc->property_lock);
379
380   enc->n_channels = -1;
381   enc->sample_rate = -1;
382   enc->frame_samples = 0;
383   enc->unpositioned = FALSE;
384
385   enc->bitrate = DEFAULT_BITRATE;
386   enc->bandwidth = DEFAULT_BANDWIDTH;
387   enc->frame_size = DEFAULT_FRAMESIZE;
388   enc->bitrate_type = DEFAULT_BITRATE_TYPE;
389   enc->complexity = DEFAULT_COMPLEXITY;
390   enc->inband_fec = DEFAULT_INBAND_FEC;
391   enc->dtx = DEFAULT_DTX;
392   enc->packet_loss_percentage = DEFAULT_PACKET_LOSS_PERCENT;
393   enc->max_payload_size = DEFAULT_MAX_PAYLOAD_SIZE;
394   enc->audio_type = DEFAULT_AUDIO_TYPE;
395 }
396
397 static gboolean
398 gst_opus_enc_start (GstAudioEncoder * benc)
399 {
400   GstOpusEnc *enc = GST_OPUS_ENC (benc);
401
402   GST_DEBUG_OBJECT (enc, "start");
403   enc->encoded_samples = 0;
404   enc->consumed_samples = 0;
405
406   return TRUE;
407 }
408
409 static gboolean
410 gst_opus_enc_stop (GstAudioEncoder * benc)
411 {
412   GstOpusEnc *enc = GST_OPUS_ENC (benc);
413
414   GST_DEBUG_OBJECT (enc, "stop");
415   if (enc->state) {
416     opus_multistream_encoder_destroy (enc->state);
417     enc->state = NULL;
418   }
419   gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
420
421   return TRUE;
422 }
423
424 static gint64
425 gst_opus_enc_get_latency (GstOpusEnc * enc)
426 {
427   gint64 latency = gst_util_uint64_scale (enc->frame_samples, GST_SECOND,
428       enc->sample_rate);
429   GST_DEBUG_OBJECT (enc, "Latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
430   return latency;
431 }
432
433 static void
434 gst_opus_enc_setup_base_class (GstOpusEnc * enc, GstAudioEncoder * benc)
435 {
436   gst_audio_encoder_set_latency (benc,
437       gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
438   gst_audio_encoder_set_frame_samples_min (benc, enc->frame_samples);
439   gst_audio_encoder_set_frame_samples_max (benc, enc->frame_samples);
440   gst_audio_encoder_set_frame_max (benc, 1);
441 }
442
443 static gint
444 gst_opus_enc_get_frame_samples (GstOpusEnc * enc)
445 {
446   gint frame_samples = 0;
447   switch (enc->frame_size) {
448     case 2:
449       frame_samples = enc->sample_rate / 400;
450       break;
451     case 5:
452       frame_samples = enc->sample_rate / 200;
453       break;
454     case 10:
455       frame_samples = enc->sample_rate / 100;
456       break;
457     case 20:
458       frame_samples = enc->sample_rate / 50;
459       break;
460     case 40:
461       frame_samples = enc->sample_rate / 25;
462       break;
463     case 60:
464       frame_samples = 3 * enc->sample_rate / 50;
465       break;
466     default:
467       GST_WARNING_OBJECT (enc, "Unsupported frame size: %d", enc->frame_size);
468       frame_samples = 0;
469       break;
470   }
471   return frame_samples;
472 }
473
474 static void
475 gst_opus_enc_setup_trivial_mapping (GstOpusEnc * enc, guint8 mapping[256])
476 {
477   int n;
478
479   for (n = 0; n < 255; ++n)
480     mapping[n] = n;
481 }
482
483 static int
484 gst_opus_enc_find_channel_position (GstOpusEnc * enc, const GstAudioInfo * info,
485     GstAudioChannelPosition position)
486 {
487   int n;
488   for (n = 0; n < enc->n_channels; ++n) {
489     if (GST_AUDIO_INFO_POSITION (info, n) == position) {
490       return n;
491     }
492   }
493   return -1;
494 }
495
496 static int
497 gst_opus_enc_find_channel_position_in_vorbis_order (GstOpusEnc * enc,
498     GstAudioChannelPosition position)
499 {
500   int c;
501
502   for (c = 0; c < enc->n_channels; ++c) {
503     if (gst_opus_channel_positions[enc->n_channels - 1][c] == position) {
504       GST_INFO_OBJECT (enc,
505           "Channel position %s maps to index %d in Vorbis order",
506           gst_opus_channel_names[position], c);
507       return c;
508     }
509   }
510   GST_WARNING_OBJECT (enc,
511       "Channel position %s is not representable in Vorbis order",
512       gst_opus_channel_names[position]);
513   return -1;
514 }
515
516 static void
517 gst_opus_enc_setup_channel_mappings (GstOpusEnc * enc,
518     const GstAudioInfo * info)
519 {
520 #define MAPS(idx,pos) (GST_AUDIO_INFO_POSITION (info, (idx)) == GST_AUDIO_CHANNEL_POSITION_##pos)
521
522   int n;
523
524   GST_DEBUG_OBJECT (enc, "Setting up channel mapping for %d channels",
525       enc->n_channels);
526
527   /* Start by setting up a default trivial mapping */
528   enc->n_stereo_streams = 0;
529   gst_opus_enc_setup_trivial_mapping (enc, enc->encoding_channel_mapping);
530   gst_opus_enc_setup_trivial_mapping (enc, enc->decoding_channel_mapping);
531
532   /* For one channel, use the basic RTP mapping */
533   if (enc->n_channels == 1 && !enc->unpositioned) {
534     GST_INFO_OBJECT (enc, "Mono, trivial RTP mapping");
535     enc->channel_mapping_family = 0;
536     /* implicit mapping for family 0 */
537     return;
538   }
539
540   /* For two channels, use the basic RTP mapping if the channels are
541      mapped as left/right. */
542   if (enc->n_channels == 2 && !enc->unpositioned) {
543     GST_INFO_OBJECT (enc, "Stereo, trivial RTP mapping");
544     enc->channel_mapping_family = 0;
545     enc->n_stereo_streams = 1;
546     /* implicit mapping for family 0 */
547     return;
548   }
549
550   /* For channels between 3 and 8, we use the Vorbis mapping if we can
551      find a permutation that matches it. Mono and stereo will have been taken
552      care of earlier, but this code also handles it. There are two mappings.
553      One maps the input channels to an ordering which has the natural pairs
554      first so they can benefit from the Opus stereo channel coupling, and the
555      other maps this ordering to the Vorbis ordering. */
556   if (enc->n_channels >= 3 && enc->n_channels <= 8 && !enc->unpositioned) {
557     int c0, c1, c0v, c1v;
558     int mapped;
559     gboolean positions_done[256];
560     static const GstAudioChannelPosition pairs[][2] = {
561       {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
562           GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
563       {GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
564           GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
565       {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
566           GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER},
567       {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
568           GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER},
569       {GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
570           GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT},
571       {GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
572           GST_AUDIO_CHANNEL_POSITION_REAR_CENTER},
573     };
574     size_t pair;
575
576     GST_DEBUG_OBJECT (enc,
577         "In range for the Vorbis mapping, building channel mapping tables");
578
579     enc->n_stereo_streams = 0;
580     mapped = 0;
581     for (n = 0; n < 256; ++n)
582       positions_done[n] = FALSE;
583
584     /* First, find any natural pairs, and move them to the front */
585     for (pair = 0; pair < G_N_ELEMENTS (pairs); ++pair) {
586       GstAudioChannelPosition p0 = pairs[pair][0];
587       GstAudioChannelPosition p1 = pairs[pair][1];
588       c0 = gst_opus_enc_find_channel_position (enc, info, p0);
589       c1 = gst_opus_enc_find_channel_position (enc, info, p1);
590       if (c0 >= 0 && c1 >= 0) {
591         /* We found a natural pair */
592         GST_DEBUG_OBJECT (enc, "Natural pair '%s/%s' found at %d %d",
593             gst_opus_channel_names[p0], gst_opus_channel_names[p1], c0, c1);
594         /* Find where they map in Vorbis order */
595         c0v = gst_opus_enc_find_channel_position_in_vorbis_order (enc, p0);
596         c1v = gst_opus_enc_find_channel_position_in_vorbis_order (enc, p1);
597         if (c0v < 0 || c1v < 0) {
598           GST_WARNING_OBJECT (enc,
599               "Cannot map channel positions to Vorbis order, using unknown mapping");
600           enc->channel_mapping_family = 255;
601           enc->n_stereo_streams = 0;
602           return;
603         }
604
605         enc->encoding_channel_mapping[mapped] = c0;
606         enc->encoding_channel_mapping[mapped + 1] = c1;
607         enc->decoding_channel_mapping[c0v] = mapped;
608         enc->decoding_channel_mapping[c1v] = mapped + 1;
609         enc->n_stereo_streams++;
610         mapped += 2;
611         positions_done[p0] = positions_done[p1] = TRUE;
612       }
613     }
614
615     /* Now add all other input channels as mono streams */
616     for (n = 0; n < enc->n_channels; ++n) {
617       GstAudioChannelPosition position = GST_AUDIO_INFO_POSITION (info, n);
618
619       /* if we already mapped it while searching for pairs, nothing else
620          needs to be done */
621       if (!positions_done[position]) {
622         int cv;
623         GST_DEBUG_OBJECT (enc, "Channel position %s is not mapped yet, adding",
624             gst_opus_channel_names[position]);
625         cv = gst_opus_enc_find_channel_position_in_vorbis_order (enc, position);
626         if (cv < 0)
627           g_assert_not_reached ();
628         enc->encoding_channel_mapping[mapped] = n;
629         enc->decoding_channel_mapping[cv] = mapped;
630         mapped++;
631       }
632     }
633
634 #ifndef GST_DISABLE_GST_DEBUG
635     GST_INFO_OBJECT (enc,
636         "Mapping tables built: %d channels, %d stereo streams", enc->n_channels,
637         enc->n_stereo_streams);
638     gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
639         "Encoding mapping table", enc->n_channels,
640         enc->encoding_channel_mapping);
641     gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
642         "Decoding mapping table", enc->n_channels,
643         enc->decoding_channel_mapping);
644 #endif
645
646     enc->channel_mapping_family = 1;
647     return;
648   }
649
650   /* More than 8 channels, if future mappings are added for those */
651
652   /* For other cases, we use undefined, with the default trivial mapping
653      and all mono streams */
654   if (!enc->unpositioned)
655     GST_WARNING_OBJECT (enc, "Unknown mapping");
656   else
657     GST_INFO_OBJECT (enc, "Unpositioned mapping, all channels mono");
658
659   enc->channel_mapping_family = 255;
660   enc->n_stereo_streams = 0;
661
662 #undef MAPS
663 }
664
665 static gboolean
666 gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
667 {
668   GstOpusEnc *enc;
669
670   enc = GST_OPUS_ENC (benc);
671
672   g_mutex_lock (&enc->property_lock);
673
674   enc->n_channels = GST_AUDIO_INFO_CHANNELS (info);
675   enc->unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (info);
676   enc->sample_rate = GST_AUDIO_INFO_RATE (info);
677   gst_opus_enc_setup_channel_mappings (enc, info);
678   GST_DEBUG_OBJECT (benc, "Setup with %d channels, %d Hz", enc->n_channels,
679       enc->sample_rate);
680
681   /* handle reconfigure */
682   if (enc->state) {
683     opus_multistream_encoder_destroy (enc->state);
684     enc->state = NULL;
685   }
686   if (!gst_opus_enc_setup (enc)) {
687     g_mutex_unlock (&enc->property_lock);
688     return FALSE;
689   }
690
691   /* update the tags */
692   gst_opus_enc_set_tags (enc);
693
694   enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
695
696   /* feedback to base class */
697   gst_opus_enc_setup_base_class (enc, benc);
698
699   g_mutex_unlock (&enc->property_lock);
700
701   return TRUE;
702 }
703
704 static gboolean
705 gst_opus_enc_setup (GstOpusEnc * enc)
706 {
707   int error = OPUS_OK;
708   GstCaps *caps;
709   gboolean ret;
710   gint32 lookahead;
711   const GstTagList *tags;
712   GstTagList *empty_tags = NULL;
713   GstBuffer *header, *comments;
714
715 #ifndef GST_DISABLE_GST_DEBUG
716   GST_DEBUG_OBJECT (enc,
717       "setup: %d Hz, %d channels, %d stereo streams, family %d",
718       enc->sample_rate, enc->n_channels, enc->n_stereo_streams,
719       enc->channel_mapping_family);
720   GST_INFO_OBJECT (enc, "Mapping tables built: %d channels, %d stereo streams",
721       enc->n_channels, enc->n_stereo_streams);
722   gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
723       "Encoding mapping table", enc->n_channels, enc->encoding_channel_mapping);
724   gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
725       "Decoding mapping table", enc->n_channels, enc->decoding_channel_mapping);
726 #endif
727
728   enc->state = opus_multistream_encoder_create (enc->sample_rate,
729       enc->n_channels, enc->n_channels - enc->n_stereo_streams,
730       enc->n_stereo_streams, enc->encoding_channel_mapping,
731       enc->audio_type, &error);
732   if (!enc->state || error != OPUS_OK)
733     goto encoder_creation_failed;
734
735   opus_multistream_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
736   opus_multistream_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth),
737       0);
738   opus_multistream_encoder_ctl (enc->state,
739       OPUS_SET_VBR (enc->bitrate_type != BITRATE_TYPE_CBR), 0);
740   opus_multistream_encoder_ctl (enc->state,
741       OPUS_SET_VBR_CONSTRAINT (enc->bitrate_type ==
742           BITRATE_TYPE_CONSTRAINED_VBR), 0);
743   opus_multistream_encoder_ctl (enc->state,
744       OPUS_SET_COMPLEXITY (enc->complexity), 0);
745   opus_multistream_encoder_ctl (enc->state,
746       OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
747   opus_multistream_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
748   opus_multistream_encoder_ctl (enc->state,
749       OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0);
750
751   opus_multistream_encoder_ctl (enc->state, OPUS_GET_LOOKAHEAD (&lookahead), 0);
752
753   GST_LOG_OBJECT (enc, "we have frame size %d, lookahead %d", enc->frame_size,
754       lookahead);
755
756   /* lookahead is samples, the Opus header wants it in 48kHz samples */
757   lookahead = lookahead * 48000 / enc->sample_rate;
758   enc->lookahead = enc->pending_lookahead = lookahead;
759
760   header = gst_codec_utils_opus_create_header (enc->sample_rate,
761       enc->n_channels, enc->channel_mapping_family,
762       enc->n_channels - enc->n_stereo_streams, enc->n_stereo_streams,
763       enc->decoding_channel_mapping, lookahead, 0);
764   tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
765   if (!tags)
766     tags = empty_tags = gst_tag_list_new_empty ();
767   comments =
768       gst_tag_list_to_vorbiscomment_buffer (tags, (const guint8 *) "OpusTags",
769       8, "Encoded with GStreamer opusenc");
770   caps = gst_codec_utils_opus_create_caps_from_header (header, comments);
771   if (empty_tags)
772     gst_tag_list_unref (empty_tags);
773   gst_buffer_unref (header);
774   gst_buffer_unref (comments);
775
776   /* negotiate with these caps */
777   GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
778
779   ret = gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (enc), caps);
780   gst_caps_unref (caps);
781
782   return ret;
783
784 encoder_creation_failed:
785   GST_ERROR_OBJECT (enc, "Encoder creation failed");
786   return FALSE;
787 }
788
789 static gboolean
790 gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
791 {
792   GstOpusEnc *enc;
793
794   enc = GST_OPUS_ENC (benc);
795
796   GST_DEBUG_OBJECT (enc, "sink event: %s", GST_EVENT_TYPE_NAME (event));
797   switch (GST_EVENT_TYPE (event)) {
798     case GST_EVENT_TAG:
799     {
800       GstTagList *list;
801       GstTagSetter *setter = GST_TAG_SETTER (enc);
802       const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
803
804       gst_event_parse_tag (event, &list);
805       gst_tag_setter_merge_tags (setter, list, mode);
806       break;
807     }
808     case GST_EVENT_SEGMENT:
809       enc->encoded_samples = 0;
810       enc->consumed_samples = 0;
811       break;
812
813     default:
814       break;
815   }
816
817   return GST_AUDIO_ENCODER_CLASS (parent_class)->sink_event (benc, event);
818 }
819
820 static GstCaps *
821 gst_opus_enc_get_sink_template_caps (void)
822 {
823   static gsize init = 0;
824   static GstCaps *caps = NULL;
825
826   if (g_once_init_enter (&init)) {
827     GValue rate_array = G_VALUE_INIT;
828     GValue v = G_VALUE_INIT;
829     GstStructure *s1, *s2, *s;
830     gint i, c;
831
832     caps = gst_caps_new_empty ();
833
834     /* The caps is cached */
835     GST_MINI_OBJECT_FLAG_SET (caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
836
837     /* Generate our two template structures */
838     g_value_init (&rate_array, GST_TYPE_LIST);
839     g_value_init (&v, G_TYPE_INT);
840     g_value_set_int (&v, 8000);
841     gst_value_list_append_value (&rate_array, &v);
842     g_value_set_int (&v, 12000);
843     gst_value_list_append_value (&rate_array, &v);
844     g_value_set_int (&v, 16000);
845     gst_value_list_append_value (&rate_array, &v);
846     g_value_set_int (&v, 24000);
847     gst_value_list_append_value (&rate_array, &v);
848
849     s1 = gst_structure_new ("audio/x-raw",
850         "format", G_TYPE_STRING, GST_AUDIO_NE (S16),
851         "layout", G_TYPE_STRING, "interleaved",
852         "rate", G_TYPE_INT, 48000, NULL);
853     s2 = gst_structure_new ("audio/x-raw",
854         "format", G_TYPE_STRING, GST_AUDIO_NE (S16),
855         "layout", G_TYPE_STRING, "interleaved", NULL);
856     gst_structure_set_value (s2, "rate", &rate_array);
857     g_value_unset (&rate_array);
858     g_value_unset (&v);
859
860     /* Stereo and further */
861     for (i = 8; i >= 2; i--) {
862       guint64 channel_mask = 0;
863       const GstAudioChannelPosition *pos = gst_opus_channel_positions[i - 1];
864
865       for (c = 0; c < i; c++) {
866         channel_mask |= G_GUINT64_CONSTANT (1) << pos[c];
867       }
868
869       s = gst_structure_copy (s1);
870       gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
871           GST_TYPE_BITMASK, channel_mask, NULL);
872       gst_caps_append_structure (caps, s);
873
874       s = gst_structure_copy (s2);
875       gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
876           GST_TYPE_BITMASK, channel_mask, NULL);
877       gst_caps_append_structure (caps, s);
878
879       /* We also allow unpositioned channels, input will be
880        * treated as a set of individual mono channels */
881       s = gst_structure_copy (s2);
882       gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
883           GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
884       gst_caps_append_structure (caps, s);
885
886       s = gst_structure_copy (s1);
887       gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
888           GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
889       gst_caps_append_structure (caps, s);
890     }
891
892     /* Mono */
893     s = gst_structure_copy (s1);
894     gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
895     gst_caps_append_structure (caps, s);
896
897     s = gst_structure_copy (s2);
898     gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
899     gst_caps_append_structure (caps, s);
900     gst_structure_free (s1);
901     gst_structure_free (s2);
902
903     g_once_init_leave (&init, 1);
904   }
905
906   return caps;
907 }
908
909 static GstCaps *
910 gst_opus_enc_sink_getcaps (GstAudioEncoder * benc, GstCaps * filter)
911 {
912   GstOpusEnc *enc;
913   GstCaps *caps;
914
915   enc = GST_OPUS_ENC (benc);
916
917   GST_DEBUG_OBJECT (enc, "sink getcaps");
918
919   caps = gst_opus_enc_get_sink_template_caps ();
920   caps = gst_audio_encoder_proxy_getcaps (benc, caps, filter);
921
922   GST_DEBUG_OBJECT (enc, "Returning caps: %" GST_PTR_FORMAT, caps);
923
924   return caps;
925 }
926
927 static GstFlowReturn
928 gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
929 {
930   guint8 *bdata = NULL, *data, *mdata = NULL;
931   gsize bsize, size;
932   gsize bytes;
933   gint ret = GST_FLOW_OK;
934   GstMapInfo map;
935   GstMapInfo omap;
936   gint outsize;
937   GstBuffer *outbuf;
938   guint64 trim_start = 0, trim_end = 0;
939
940   guint max_payload_size;
941   gint frame_samples, input_samples, output_samples;
942
943   g_mutex_lock (&enc->property_lock);
944
945   bytes = enc->frame_samples * enc->n_channels * 2;
946   max_payload_size = enc->max_payload_size;
947   frame_samples = input_samples = enc->frame_samples;
948
949   g_mutex_unlock (&enc->property_lock);
950
951   if (G_LIKELY (buf)) {
952     gst_buffer_map (buf, &map, GST_MAP_READ);
953     bdata = map.data;
954     bsize = map.size;
955
956     if (G_UNLIKELY (bsize % bytes)) {
957       gint64 diff;
958
959       GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
960       g_assert (bsize < bytes);
961
962       input_samples = bsize / (enc->n_channels * 2);
963       diff =
964           (enc->encoded_samples + frame_samples) - (enc->consumed_samples +
965           input_samples);
966       if (diff >= 0) {
967         GST_DEBUG_OBJECT (enc,
968             "%" G_GINT64_FORMAT " extra samples of padding in this frame",
969             diff);
970         output_samples = frame_samples - diff;
971         trim_end = diff * 48000 / enc->sample_rate;
972       } else {
973         GST_DEBUG_OBJECT (enc,
974             "Need to add %" G_GINT64_FORMAT " extra samples in the next frame",
975             -diff);
976         output_samples = frame_samples;
977       }
978
979       size = ((bsize / bytes) + 1) * bytes;
980       mdata = g_malloc0 (size);
981       /* FIXME: Instead of silence, use LPC with the last real samples.
982        * Otherwise we will create a discontinuity here, which will distort the
983        * last few encoded samples
984        */
985       memcpy (mdata, bdata, bsize);
986       data = mdata;
987     } else {
988       data = bdata;
989       size = bsize;
990
991       /* Adjust for lookahead here */
992       if (enc->pending_lookahead) {
993         guint scaled_lookahead =
994             enc->pending_lookahead * enc->sample_rate / 48000;
995
996         if (input_samples > scaled_lookahead) {
997           output_samples = input_samples - scaled_lookahead;
998           trim_start = enc->pending_lookahead;
999           enc->pending_lookahead = 0;
1000         } else {
1001           trim_start = ((guint64) input_samples) * 48000 / enc->sample_rate;
1002           enc->pending_lookahead -= trim_start;
1003           output_samples = 0;
1004         }
1005       } else {
1006         output_samples = input_samples;
1007       }
1008     }
1009   } else {
1010     if (enc->encoded_samples < enc->consumed_samples) {
1011       /* FIXME: Instead of silence, use LPC with the last real samples.
1012        * Otherwise we will create a discontinuity here, which will distort the
1013        * last few encoded samples
1014        */
1015       data = mdata = g_malloc0 (bytes);
1016       size = bytes;
1017       output_samples = enc->consumed_samples - enc->encoded_samples;
1018       input_samples = 0;
1019       GST_DEBUG_OBJECT (enc, "draining %d samples", output_samples);
1020       trim_end =
1021           ((guint64) frame_samples - output_samples) * 48000 / enc->sample_rate;
1022     } else if (enc->encoded_samples == enc->consumed_samples) {
1023       GST_DEBUG_OBJECT (enc, "nothing to drain");
1024       goto done;
1025     } else {
1026       g_assert_not_reached ();
1027       goto done;
1028     }
1029   }
1030
1031   g_assert (size == bytes);
1032
1033   outbuf =
1034       gst_audio_encoder_allocate_output_buffer (GST_AUDIO_ENCODER (enc),
1035       max_payload_size * enc->n_channels);
1036   if (!outbuf)
1037     goto done;
1038
1039   GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
1040       frame_samples, (int) bytes);
1041
1042   if (trim_start || trim_end) {
1043     GST_DEBUG_OBJECT (enc,
1044         "Adding trim-start %" G_GUINT64_FORMAT " trim-end %" G_GUINT64_FORMAT,
1045         trim_start, trim_end);
1046     gst_buffer_add_audio_clipping_meta (outbuf, GST_FORMAT_DEFAULT, trim_start,
1047         trim_end);
1048   }
1049
1050   gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
1051
1052   outsize =
1053       opus_multistream_encode (enc->state, (const gint16 *) data,
1054       frame_samples, omap.data, max_payload_size * enc->n_channels);
1055
1056   gst_buffer_unmap (outbuf, &omap);
1057
1058   if (outsize < 0) {
1059     GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1060         ("Encoding failed (%d): %s", outsize, opus_strerror (outsize)));
1061     ret = GST_FLOW_ERROR;
1062     goto done;
1063   } else if (outsize > max_payload_size) {
1064     GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1065         ("Encoded size %d is higher than max payload size (%d bytes)",
1066             outsize, max_payload_size));
1067     ret = GST_FLOW_ERROR;
1068     goto done;
1069   }
1070
1071   GST_DEBUG_OBJECT (enc, "Output packet is %u bytes", outsize);
1072   gst_buffer_set_size (outbuf, outsize);
1073
1074
1075   ret =
1076       gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
1077       output_samples);
1078   enc->encoded_samples += output_samples;
1079   enc->consumed_samples += input_samples;
1080
1081 done:
1082
1083   if (bdata)
1084     gst_buffer_unmap (buf, &map);
1085
1086   g_free (mdata);
1087
1088   return ret;
1089 }
1090
1091 static GstFlowReturn
1092 gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
1093 {
1094   GstOpusEnc *enc;
1095   GstFlowReturn ret = GST_FLOW_OK;
1096
1097   enc = GST_OPUS_ENC (benc);
1098   GST_DEBUG_OBJECT (enc, "handle_frame");
1099   GST_DEBUG_OBJECT (enc, "received buffer %p of %" G_GSIZE_FORMAT " bytes", buf,
1100       buf ? gst_buffer_get_size (buf) : 0);
1101
1102   ret = gst_opus_enc_encode (enc, buf);
1103
1104   return ret;
1105 }
1106
1107 static void
1108 gst_opus_enc_get_property (GObject * object, guint prop_id, GValue * value,
1109     GParamSpec * pspec)
1110 {
1111   GstOpusEnc *enc;
1112
1113   enc = GST_OPUS_ENC (object);
1114
1115   g_mutex_lock (&enc->property_lock);
1116
1117   switch (prop_id) {
1118     case PROP_AUDIO_TYPE:
1119       g_value_set_enum (value, enc->audio_type);
1120       break;
1121     case PROP_BITRATE:
1122       g_value_set_int (value, enc->bitrate);
1123       break;
1124     case PROP_BANDWIDTH:
1125       g_value_set_enum (value, enc->bandwidth);
1126       break;
1127     case PROP_FRAME_SIZE:
1128       g_value_set_enum (value, enc->frame_size);
1129       break;
1130     case PROP_BITRATE_TYPE:
1131       g_value_set_enum (value, enc->bitrate_type);
1132       break;
1133     case PROP_COMPLEXITY:
1134       g_value_set_int (value, enc->complexity);
1135       break;
1136     case PROP_INBAND_FEC:
1137       g_value_set_boolean (value, enc->inband_fec);
1138       break;
1139     case PROP_DTX:
1140       g_value_set_boolean (value, enc->dtx);
1141       break;
1142     case PROP_PACKET_LOSS_PERCENT:
1143       g_value_set_int (value, enc->packet_loss_percentage);
1144       break;
1145     case PROP_MAX_PAYLOAD_SIZE:
1146       g_value_set_uint (value, enc->max_payload_size);
1147       break;
1148     default:
1149       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1150       break;
1151   }
1152
1153   g_mutex_unlock (&enc->property_lock);
1154 }
1155
1156 static void
1157 gst_opus_enc_set_property (GObject * object, guint prop_id,
1158     const GValue * value, GParamSpec * pspec)
1159 {
1160   GstOpusEnc *enc;
1161
1162   enc = GST_OPUS_ENC (object);
1163
1164 #define GST_OPUS_UPDATE_PROPERTY(prop,type,ctl) do { \
1165   g_mutex_lock (&enc->property_lock); \
1166   enc->prop = g_value_get_##type (value); \
1167   if (enc->state) { \
1168     opus_multistream_encoder_ctl (enc->state, OPUS_SET_##ctl (enc->prop)); \
1169   } \
1170   g_mutex_unlock (&enc->property_lock); \
1171 } while(0)
1172
1173   switch (prop_id) {
1174     case PROP_AUDIO_TYPE:
1175       enc->audio_type = g_value_get_enum (value);
1176       break;
1177     case PROP_BITRATE:
1178       GST_OPUS_UPDATE_PROPERTY (bitrate, int, BITRATE);
1179       break;
1180     case PROP_BANDWIDTH:
1181       GST_OPUS_UPDATE_PROPERTY (bandwidth, enum, BANDWIDTH);
1182       break;
1183     case PROP_FRAME_SIZE:
1184       g_mutex_lock (&enc->property_lock);
1185       enc->frame_size = g_value_get_enum (value);
1186       enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
1187       gst_opus_enc_setup_base_class (enc, GST_AUDIO_ENCODER (enc));
1188       g_mutex_unlock (&enc->property_lock);
1189       break;
1190     case PROP_BITRATE_TYPE:
1191       /* this one has an opposite meaning to the opus ctl... */
1192       g_mutex_lock (&enc->property_lock);
1193       enc->bitrate_type = g_value_get_enum (value);
1194       if (enc->state) {
1195         opus_multistream_encoder_ctl (enc->state,
1196             OPUS_SET_VBR (enc->bitrate_type != BITRATE_TYPE_CBR));
1197         opus_multistream_encoder_ctl (enc->state,
1198             OPUS_SET_VBR_CONSTRAINT (enc->bitrate_type ==
1199                 BITRATE_TYPE_CONSTRAINED_VBR), 0);
1200       }
1201       g_mutex_unlock (&enc->property_lock);
1202       break;
1203     case PROP_COMPLEXITY:
1204       GST_OPUS_UPDATE_PROPERTY (complexity, int, COMPLEXITY);
1205       break;
1206     case PROP_INBAND_FEC:
1207       GST_OPUS_UPDATE_PROPERTY (inband_fec, boolean, INBAND_FEC);
1208       break;
1209     case PROP_DTX:
1210       GST_OPUS_UPDATE_PROPERTY (dtx, boolean, DTX);
1211       break;
1212     case PROP_PACKET_LOSS_PERCENT:
1213       GST_OPUS_UPDATE_PROPERTY (packet_loss_percentage, int, PACKET_LOSS_PERC);
1214       break;
1215     case PROP_MAX_PAYLOAD_SIZE:
1216       g_mutex_lock (&enc->property_lock);
1217       enc->max_payload_size = g_value_get_uint (value);
1218       g_mutex_unlock (&enc->property_lock);
1219       break;
1220     default:
1221       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1222       break;
1223   }
1224
1225 #undef GST_OPUS_UPDATE_PROPERTY
1226
1227 }