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