opusenc: improve inband-fec property documentation
[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     /* Mono */
861     s = gst_structure_copy (s1);
862     gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
863     gst_caps_append_structure (caps, s);
864
865     s = gst_structure_copy (s2);
866     gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
867     gst_caps_append_structure (caps, s);
868
869     /* Stereo and further */
870     for (i = 2; i <= 8; i++) {
871       guint64 channel_mask = 0;
872       const GstAudioChannelPosition *pos = gst_opus_channel_positions[i - 1];
873
874       for (c = 0; c < i; c++) {
875         channel_mask |= G_GUINT64_CONSTANT (1) << pos[c];
876       }
877
878       s = gst_structure_copy (s1);
879       gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
880           GST_TYPE_BITMASK, channel_mask, NULL);
881       gst_caps_append_structure (caps, s);
882
883       s = gst_structure_copy (s2);
884       gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
885           GST_TYPE_BITMASK, channel_mask, NULL);
886       gst_caps_append_structure (caps, s);
887
888       /* We also allow unpositioned channels, input will be
889        * treated as a set of individual mono channels */
890       s = gst_structure_copy (s2);
891       gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
892           GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
893       gst_caps_append_structure (caps, s);
894
895       s = gst_structure_copy (s1);
896       gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
897           GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
898       gst_caps_append_structure (caps, s);
899     }
900
901     gst_structure_free (s1);
902     gst_structure_free (s2);
903
904     g_once_init_leave (&init, 1);
905   }
906
907   return caps;
908 }
909
910 static GstCaps *
911 gst_opus_enc_sink_getcaps (GstAudioEncoder * benc, GstCaps * filter)
912 {
913   GstOpusEnc *enc;
914   GstCaps *caps;
915
916   enc = GST_OPUS_ENC (benc);
917
918   GST_DEBUG_OBJECT (enc, "sink getcaps");
919
920   caps = gst_opus_enc_get_sink_template_caps ();
921   caps = gst_audio_encoder_proxy_getcaps (benc, caps, filter);
922
923   GST_DEBUG_OBJECT (enc, "Returning caps: %" GST_PTR_FORMAT, caps);
924
925   return caps;
926 }
927
928 static GstFlowReturn
929 gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
930 {
931   guint8 *bdata = NULL, *data, *mdata = NULL;
932   gsize bsize, size;
933   gsize bytes;
934   gint ret = GST_FLOW_OK;
935   GstMapInfo map;
936   GstMapInfo omap;
937   gint outsize;
938   GstBuffer *outbuf;
939   guint64 trim_start = 0, trim_end = 0;
940
941   guint max_payload_size;
942   gint frame_samples, input_samples, output_samples;
943
944   g_mutex_lock (&enc->property_lock);
945
946   bytes = enc->frame_samples * enc->n_channels * 2;
947   max_payload_size = enc->max_payload_size;
948   frame_samples = input_samples = enc->frame_samples;
949
950   g_mutex_unlock (&enc->property_lock);
951
952   if (G_LIKELY (buf)) {
953     gst_buffer_map (buf, &map, GST_MAP_READ);
954     bdata = map.data;
955     bsize = map.size;
956
957     if (G_UNLIKELY (bsize % bytes)) {
958       gint64 diff;
959
960       GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
961       g_assert (bsize < bytes);
962
963       input_samples = bsize / (enc->n_channels * 2);
964       diff =
965           (enc->encoded_samples + frame_samples) - (enc->consumed_samples +
966           input_samples);
967       if (diff >= 0) {
968         GST_DEBUG_OBJECT (enc,
969             "%" G_GINT64_FORMAT " extra samples of padding in this frame",
970             diff);
971         output_samples = frame_samples - diff;
972         trim_end = diff * 48000 / enc->sample_rate;
973       } else {
974         GST_DEBUG_OBJECT (enc,
975             "Need to add %" G_GINT64_FORMAT " extra samples in the next frame",
976             -diff);
977         output_samples = frame_samples;
978       }
979
980       size = ((bsize / bytes) + 1) * bytes;
981       mdata = g_malloc0 (size);
982       /* FIXME: Instead of silence, use LPC with the last real samples.
983        * Otherwise we will create a discontinuity here, which will distort the
984        * last few encoded samples
985        */
986       memcpy (mdata, bdata, bsize);
987       data = mdata;
988     } else {
989       data = bdata;
990       size = bsize;
991
992       /* Adjust for lookahead here */
993       if (enc->pending_lookahead) {
994         guint scaled_lookahead =
995             enc->pending_lookahead * enc->sample_rate / 48000;
996
997         if (input_samples > scaled_lookahead) {
998           output_samples = input_samples - scaled_lookahead;
999           trim_start = enc->pending_lookahead;
1000           enc->pending_lookahead = 0;
1001         } else {
1002           trim_start = ((guint64) input_samples) * 48000 / enc->sample_rate;
1003           enc->pending_lookahead -= trim_start;
1004           output_samples = 0;
1005         }
1006       } else {
1007         output_samples = input_samples;
1008       }
1009     }
1010   } else {
1011     if (enc->encoded_samples < enc->consumed_samples) {
1012       /* FIXME: Instead of silence, use LPC with the last real samples.
1013        * Otherwise we will create a discontinuity here, which will distort the
1014        * last few encoded samples
1015        */
1016       data = mdata = g_malloc0 (bytes);
1017       size = bytes;
1018       output_samples = enc->consumed_samples - enc->encoded_samples;
1019       input_samples = 0;
1020       GST_DEBUG_OBJECT (enc, "draining %d samples", output_samples);
1021       trim_end =
1022           ((guint64) frame_samples - output_samples) * 48000 / enc->sample_rate;
1023     } else if (enc->encoded_samples == enc->consumed_samples) {
1024       GST_DEBUG_OBJECT (enc, "nothing to drain");
1025       goto done;
1026     } else {
1027       g_assert_not_reached ();
1028       goto done;
1029     }
1030   }
1031
1032   g_assert (size == bytes);
1033
1034   outbuf =
1035       gst_audio_encoder_allocate_output_buffer (GST_AUDIO_ENCODER (enc),
1036       max_payload_size * enc->n_channels);
1037   if (!outbuf)
1038     goto done;
1039
1040   GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
1041       frame_samples, (int) bytes);
1042
1043   if (trim_start || trim_end) {
1044     GST_DEBUG_OBJECT (enc,
1045         "Adding trim-start %" G_GUINT64_FORMAT " trim-end %" G_GUINT64_FORMAT,
1046         trim_start, trim_end);
1047     gst_buffer_add_audio_clipping_meta (outbuf, GST_FORMAT_DEFAULT, trim_start,
1048         trim_end);
1049   }
1050
1051   gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
1052
1053   outsize =
1054       opus_multistream_encode (enc->state, (const gint16 *) data,
1055       frame_samples, omap.data, max_payload_size * enc->n_channels);
1056
1057   gst_buffer_unmap (outbuf, &omap);
1058
1059   if (outsize < 0) {
1060     GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1061         ("Encoding failed (%d): %s", outsize, opus_strerror (outsize)));
1062     ret = GST_FLOW_ERROR;
1063     goto done;
1064   } else if (outsize > max_payload_size) {
1065     GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1066         ("Encoded size %d is higher than max payload size (%d bytes)",
1067             outsize, max_payload_size));
1068     ret = GST_FLOW_ERROR;
1069     goto done;
1070   }
1071
1072   GST_DEBUG_OBJECT (enc, "Output packet is %u bytes", outsize);
1073   gst_buffer_set_size (outbuf, outsize);
1074
1075
1076   ret =
1077       gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
1078       output_samples);
1079   enc->encoded_samples += output_samples;
1080   enc->consumed_samples += input_samples;
1081
1082 done:
1083
1084   if (bdata)
1085     gst_buffer_unmap (buf, &map);
1086
1087   g_free (mdata);
1088
1089   return ret;
1090 }
1091
1092 static GstFlowReturn
1093 gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
1094 {
1095   GstOpusEnc *enc;
1096   GstFlowReturn ret = GST_FLOW_OK;
1097
1098   enc = GST_OPUS_ENC (benc);
1099   GST_DEBUG_OBJECT (enc, "handle_frame");
1100   GST_DEBUG_OBJECT (enc, "received buffer %p of %" G_GSIZE_FORMAT " bytes", buf,
1101       buf ? gst_buffer_get_size (buf) : 0);
1102
1103   ret = gst_opus_enc_encode (enc, buf);
1104
1105   return ret;
1106 }
1107
1108 static void
1109 gst_opus_enc_get_property (GObject * object, guint prop_id, GValue * value,
1110     GParamSpec * pspec)
1111 {
1112   GstOpusEnc *enc;
1113
1114   enc = GST_OPUS_ENC (object);
1115
1116   g_mutex_lock (&enc->property_lock);
1117
1118   switch (prop_id) {
1119     case PROP_AUDIO_TYPE:
1120       g_value_set_enum (value, enc->audio_type);
1121       break;
1122     case PROP_BITRATE:
1123       g_value_set_int (value, enc->bitrate);
1124       break;
1125     case PROP_BANDWIDTH:
1126       g_value_set_enum (value, enc->bandwidth);
1127       break;
1128     case PROP_FRAME_SIZE:
1129       g_value_set_enum (value, enc->frame_size);
1130       break;
1131     case PROP_BITRATE_TYPE:
1132       g_value_set_enum (value, enc->bitrate_type);
1133       break;
1134     case PROP_COMPLEXITY:
1135       g_value_set_int (value, enc->complexity);
1136       break;
1137     case PROP_INBAND_FEC:
1138       g_value_set_boolean (value, enc->inband_fec);
1139       break;
1140     case PROP_DTX:
1141       g_value_set_boolean (value, enc->dtx);
1142       break;
1143     case PROP_PACKET_LOSS_PERCENT:
1144       g_value_set_int (value, enc->packet_loss_percentage);
1145       break;
1146     case PROP_MAX_PAYLOAD_SIZE:
1147       g_value_set_uint (value, enc->max_payload_size);
1148       break;
1149     default:
1150       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1151       break;
1152   }
1153
1154   g_mutex_unlock (&enc->property_lock);
1155 }
1156
1157 static void
1158 gst_opus_enc_set_property (GObject * object, guint prop_id,
1159     const GValue * value, GParamSpec * pspec)
1160 {
1161   GstOpusEnc *enc;
1162
1163   enc = GST_OPUS_ENC (object);
1164
1165 #define GST_OPUS_UPDATE_PROPERTY(prop,type,ctl) do { \
1166   g_mutex_lock (&enc->property_lock); \
1167   enc->prop = g_value_get_##type (value); \
1168   if (enc->state) { \
1169     opus_multistream_encoder_ctl (enc->state, OPUS_SET_##ctl (enc->prop)); \
1170   } \
1171   g_mutex_unlock (&enc->property_lock); \
1172 } while(0)
1173
1174   switch (prop_id) {
1175     case PROP_AUDIO_TYPE:
1176       enc->audio_type = g_value_get_enum (value);
1177       break;
1178     case PROP_BITRATE:
1179       GST_OPUS_UPDATE_PROPERTY (bitrate, int, BITRATE);
1180       break;
1181     case PROP_BANDWIDTH:
1182       GST_OPUS_UPDATE_PROPERTY (bandwidth, enum, BANDWIDTH);
1183       break;
1184     case PROP_FRAME_SIZE:
1185       g_mutex_lock (&enc->property_lock);
1186       enc->frame_size = g_value_get_enum (value);
1187       enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
1188       gst_opus_enc_setup_base_class (enc, GST_AUDIO_ENCODER (enc));
1189       g_mutex_unlock (&enc->property_lock);
1190       break;
1191     case PROP_BITRATE_TYPE:
1192       /* this one has an opposite meaning to the opus ctl... */
1193       g_mutex_lock (&enc->property_lock);
1194       enc->bitrate_type = g_value_get_enum (value);
1195       if (enc->state) {
1196         opus_multistream_encoder_ctl (enc->state,
1197             OPUS_SET_VBR (enc->bitrate_type != BITRATE_TYPE_CBR));
1198         opus_multistream_encoder_ctl (enc->state,
1199             OPUS_SET_VBR_CONSTRAINT (enc->bitrate_type ==
1200                 BITRATE_TYPE_CONSTRAINED_VBR), 0);
1201       }
1202       g_mutex_unlock (&enc->property_lock);
1203       break;
1204     case PROP_COMPLEXITY:
1205       GST_OPUS_UPDATE_PROPERTY (complexity, int, COMPLEXITY);
1206       break;
1207     case PROP_INBAND_FEC:
1208       GST_OPUS_UPDATE_PROPERTY (inband_fec, boolean, INBAND_FEC);
1209       break;
1210     case PROP_DTX:
1211       GST_OPUS_UPDATE_PROPERTY (dtx, boolean, DTX);
1212       break;
1213     case PROP_PACKET_LOSS_PERCENT:
1214       GST_OPUS_UPDATE_PROPERTY (packet_loss_percentage, int, PACKET_LOSS_PERC);
1215       break;
1216     case PROP_MAX_PAYLOAD_SIZE:
1217       g_mutex_lock (&enc->property_lock);
1218       enc->max_payload_size = g_value_get_uint (value);
1219       g_mutex_unlock (&enc->property_lock);
1220       break;
1221     default:
1222       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1223       break;
1224   }
1225
1226 #undef GST_OPUS_UPDATE_PROPERTY
1227
1228 }