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>
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.
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.
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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 * Based on the speexenc element
27 * SECTION:element-opusenc
28 * @see_also: opusdec, oggmux
30 * This element encodes raw audio to OPUS.
33 * <title>Example pipelines</title>
35 * gst-launch -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! opusenc ! oggmux ! filesink location=sine.ogg
36 * ]| Encode a test sine signal to Ogg/OPUS.
47 #include <opus/opus.h>
49 #include <gst/gsttagsetter.h>
50 #include <gst/audio/audio.h>
51 #include "gstopusheader.h"
52 #include "gstopusenc.h"
54 GST_DEBUG_CATEGORY_STATIC (opusenc_debug);
55 #define GST_CAT_DEFAULT opusenc_debug
57 /* Some arbitrary bounds beyond which it really doesn't make sense.
58 The spec mentions 6 kb/s to 510 kb/s, so 4000 and 650000 ought to be
59 safe as property bounds. */
60 #define LOWEST_BITRATE 4000
61 #define HIGHEST_BITRATE 650000
63 #define GST_OPUS_ENC_TYPE_BANDWIDTH (gst_opus_enc_bandwidth_get_type())
65 gst_opus_enc_bandwidth_get_type (void)
67 static const GEnumValue values[] = {
68 {OPUS_BANDWIDTH_NARROWBAND, "Narrow band", "narrowband"},
69 {OPUS_BANDWIDTH_MEDIUMBAND, "Medium band", "mediumband"},
70 {OPUS_BANDWIDTH_WIDEBAND, "Wide band", "wideband"},
71 {OPUS_BANDWIDTH_SUPERWIDEBAND, "Super wide band", "superwideband"},
72 {OPUS_BANDWIDTH_FULLBAND, "Full band", "fullband"},
73 {OPUS_AUTO, "Auto", "auto"},
76 static volatile GType id = 0;
78 if (g_once_init_enter ((gsize *) & id)) {
81 _id = g_enum_register_static ("GstOpusEncBandwidth", values);
83 g_once_init_leave ((gsize *) & id, _id);
89 #define GST_OPUS_ENC_TYPE_FRAME_SIZE (gst_opus_enc_frame_size_get_type())
91 gst_opus_enc_frame_size_get_type (void)
93 static const GEnumValue values[] = {
102 static volatile GType id = 0;
104 if (g_once_init_enter ((gsize *) & id)) {
107 _id = g_enum_register_static ("GstOpusEncFrameSize", values);
109 g_once_init_leave ((gsize *) & id, _id);
115 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
118 GST_STATIC_CAPS ("audio/x-raw-int, "
119 "rate = (int) { 8000, 12000, 16000, 24000, 48000 }, "
120 "channels = (int) [ 1, 2 ], "
121 "endianness = (int) BYTE_ORDER, "
122 "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16")
125 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
128 GST_STATIC_CAPS ("audio/x-opus")
131 #define DEFAULT_AUDIO TRUE
132 #define DEFAULT_BITRATE 64000
133 #define DEFAULT_BANDWIDTH OPUS_BANDWIDTH_FULLBAND
134 #define DEFAULT_FRAMESIZE 20
135 #define DEFAULT_CBR TRUE
136 #define DEFAULT_CONSTRAINED_VBR TRUE
137 #define DEFAULT_COMPLEXITY 10
138 #define DEFAULT_INBAND_FEC FALSE
139 #define DEFAULT_DTX FALSE
140 #define DEFAULT_PACKET_LOSS_PERCENT 0
141 #define DEFAULT_MAX_PAYLOAD_SIZE 1024
151 PROP_CONSTRAINED_VBR,
155 PROP_PACKET_LOSS_PERCENT,
156 PROP_MAX_PAYLOAD_SIZE
159 static void gst_opus_enc_finalize (GObject * object);
161 static gboolean gst_opus_enc_sink_event (GstAudioEncoder * benc,
163 static gboolean gst_opus_enc_setup (GstOpusEnc * enc);
165 static void gst_opus_enc_get_property (GObject * object, guint prop_id,
166 GValue * value, GParamSpec * pspec);
167 static void gst_opus_enc_set_property (GObject * object, guint prop_id,
168 const GValue * value, GParamSpec * pspec);
170 static gboolean gst_opus_enc_start (GstAudioEncoder * benc);
171 static gboolean gst_opus_enc_stop (GstAudioEncoder * benc);
172 static gboolean gst_opus_enc_set_format (GstAudioEncoder * benc,
173 GstAudioInfo * info);
174 static GstFlowReturn gst_opus_enc_handle_frame (GstAudioEncoder * benc,
176 static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
178 static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buffer);
181 gst_opus_enc_setup_interfaces (GType opusenc_type)
183 static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
184 const GInterfaceInfo preset_interface_info = {
185 NULL, /* interface_init */
186 NULL, /* interface_finalize */
187 NULL /* interface_data */
190 g_type_add_interface_static (opusenc_type, GST_TYPE_TAG_SETTER,
192 g_type_add_interface_static (opusenc_type, GST_TYPE_PRESET,
193 &preset_interface_info);
195 GST_DEBUG_CATEGORY_INIT (opusenc_debug, "opusenc", 0, "Opus encoder");
198 GST_BOILERPLATE_FULL (GstOpusEnc, gst_opus_enc, GstAudioEncoder,
199 GST_TYPE_AUDIO_ENCODER, gst_opus_enc_setup_interfaces);
202 gst_opus_enc_base_init (gpointer g_class)
204 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
206 gst_element_class_add_pad_template (element_class,
207 gst_static_pad_template_get (&src_factory));
208 gst_element_class_add_pad_template (element_class,
209 gst_static_pad_template_get (&sink_factory));
210 gst_element_class_set_details_simple (element_class, "Opus audio encoder",
211 "Codec/Encoder/Audio",
212 "Encodes audio in Opus format",
213 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
217 gst_opus_enc_class_init (GstOpusEncClass * klass)
219 GObjectClass *gobject_class;
220 GstElementClass *gstelement_class;
221 GstAudioEncoderClass *base_class;
223 gobject_class = (GObjectClass *) klass;
224 gstelement_class = (GstElementClass *) klass;
225 base_class = (GstAudioEncoderClass *) klass;
227 gobject_class->set_property = gst_opus_enc_set_property;
228 gobject_class->get_property = gst_opus_enc_get_property;
230 base_class->start = GST_DEBUG_FUNCPTR (gst_opus_enc_start);
231 base_class->stop = GST_DEBUG_FUNCPTR (gst_opus_enc_stop);
232 base_class->set_format = GST_DEBUG_FUNCPTR (gst_opus_enc_set_format);
233 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_opus_enc_handle_frame);
234 base_class->event = GST_DEBUG_FUNCPTR (gst_opus_enc_sink_event);
236 g_object_class_install_property (gobject_class, PROP_AUDIO,
237 g_param_spec_boolean ("audio", "Audio or voice",
238 "Audio or voice", DEFAULT_AUDIO,
239 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
240 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BITRATE,
241 g_param_spec_int ("bitrate", "Encoding Bit-rate",
242 "Specify an encoding bit-rate (in bps).",
243 LOWEST_BITRATE, HIGHEST_BITRATE, DEFAULT_BITRATE,
244 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
245 GST_PARAM_MUTABLE_PLAYING));
246 g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
247 g_param_spec_enum ("bandwidth", "Band Width", "Audio Band Width",
248 GST_OPUS_ENC_TYPE_BANDWIDTH, DEFAULT_BANDWIDTH,
249 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
250 GST_PARAM_MUTABLE_PLAYING));
251 g_object_class_install_property (gobject_class, PROP_FRAME_SIZE,
252 g_param_spec_enum ("frame-size", "Frame Size",
253 "The duration of an audio frame, in ms", GST_OPUS_ENC_TYPE_FRAME_SIZE,
255 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
256 GST_PARAM_MUTABLE_PLAYING));
257 g_object_class_install_property (gobject_class, PROP_CBR,
258 g_param_spec_boolean ("cbr", "Constant bit rate", "Constant bit rate",
260 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
261 GST_PARAM_MUTABLE_PLAYING));
262 g_object_class_install_property (gobject_class, PROP_CONSTRAINED_VBR,
263 g_param_spec_boolean ("constrained-vbr", "Constrained VBR",
264 "Constrained VBR", DEFAULT_CONSTRAINED_VBR,
265 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
266 GST_PARAM_MUTABLE_PLAYING));
267 g_object_class_install_property (gobject_class, PROP_COMPLEXITY,
268 g_param_spec_int ("complexity", "Complexity", "Complexity", 0, 10,
270 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
271 GST_PARAM_MUTABLE_PLAYING));
272 g_object_class_install_property (gobject_class, PROP_INBAND_FEC,
273 g_param_spec_boolean ("inband-fec", "In-band FEC",
274 "Enable forward error correction", DEFAULT_INBAND_FEC,
275 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
276 GST_PARAM_MUTABLE_PLAYING));
277 g_object_class_install_property (gobject_class, PROP_DTX,
278 g_param_spec_boolean ("dtx", "DTX", "DTX", DEFAULT_DTX,
279 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
280 GST_PARAM_MUTABLE_PLAYING));
281 g_object_class_install_property (G_OBJECT_CLASS (klass),
282 PROP_PACKET_LOSS_PERCENT, g_param_spec_int ("packet-loss-percentage",
283 "Loss percentage", "Packet loss percentage", 0, 100,
284 DEFAULT_PACKET_LOSS_PERCENT,
285 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
286 GST_PARAM_MUTABLE_PLAYING));
287 g_object_class_install_property (G_OBJECT_CLASS (klass),
288 PROP_MAX_PAYLOAD_SIZE, g_param_spec_uint ("max-payload-size",
289 "Max payload size", "Maximum payload size in bytes", 2, 1275,
290 DEFAULT_MAX_PAYLOAD_SIZE,
291 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
292 GST_PARAM_MUTABLE_PLAYING));
294 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_opus_enc_finalize);
298 gst_opus_enc_finalize (GObject * object)
302 enc = GST_OPUS_ENC (object);
304 g_mutex_free (enc->property_lock);
306 G_OBJECT_CLASS (parent_class)->finalize (object);
310 gst_opus_enc_init (GstOpusEnc * enc, GstOpusEncClass * klass)
312 GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
314 GST_DEBUG_OBJECT (enc, "init");
316 enc->property_lock = g_mutex_new ();
318 enc->n_channels = -1;
319 enc->sample_rate = -1;
320 enc->frame_samples = 0;
322 enc->bitrate = DEFAULT_BITRATE;
323 enc->bandwidth = DEFAULT_BANDWIDTH;
324 enc->frame_size = DEFAULT_FRAMESIZE;
325 enc->cbr = DEFAULT_CBR;
326 enc->constrained_vbr = DEFAULT_CONSTRAINED_VBR;
327 enc->complexity = DEFAULT_COMPLEXITY;
328 enc->inband_fec = DEFAULT_INBAND_FEC;
329 enc->dtx = DEFAULT_DTX;
330 enc->packet_loss_percentage = DEFAULT_PACKET_LOSS_PERCENT;
331 enc->max_payload_size = DEFAULT_MAX_PAYLOAD_SIZE;
333 /* arrange granulepos marking (and required perfect ts) */
334 gst_audio_encoder_set_mark_granule (benc, TRUE);
335 gst_audio_encoder_set_perfect_timestamp (benc, TRUE);
339 gst_opus_enc_start (GstAudioEncoder * benc)
341 GstOpusEnc *enc = GST_OPUS_ENC (benc);
343 GST_DEBUG_OBJECT (enc, "start");
344 enc->tags = gst_tag_list_new ();
345 enc->header_sent = FALSE;
351 gst_opus_enc_stop (GstAudioEncoder * benc)
353 GstOpusEnc *enc = GST_OPUS_ENC (benc);
355 GST_DEBUG_OBJECT (enc, "stop");
356 enc->header_sent = FALSE;
358 opus_encoder_destroy (enc->state);
361 gst_tag_list_free (enc->tags);
363 g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
365 gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
371 gst_opus_enc_get_latency (GstOpusEnc * enc)
373 gint64 latency = gst_util_uint64_scale (enc->frame_samples, GST_SECOND,
375 GST_DEBUG_OBJECT (enc, "Latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
380 gst_opus_enc_setup_base_class (GstOpusEnc * enc, GstAudioEncoder * benc)
382 gst_audio_encoder_set_latency (benc,
383 gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
384 gst_audio_encoder_set_frame_samples_min (benc,
385 enc->frame_samples * enc->n_channels * 2);
386 gst_audio_encoder_set_frame_samples_max (benc,
387 enc->frame_samples * enc->n_channels * 2);
388 gst_audio_encoder_set_frame_max (benc, 0);
392 gst_opus_enc_get_frame_samples (GstOpusEnc * enc)
394 gint frame_samples = 0;
395 switch (enc->frame_size) {
397 frame_samples = enc->sample_rate / 400;
400 frame_samples = enc->sample_rate / 200;
403 frame_samples = enc->sample_rate / 100;
406 frame_samples = enc->sample_rate / 50;
409 frame_samples = enc->sample_rate / 25;
412 frame_samples = 3 * enc->sample_rate / 50;
415 GST_WARNING_OBJECT (enc, "Unsupported frame size: %d", enc->frame_size);
419 return frame_samples;
423 gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
427 enc = GST_OPUS_ENC (benc);
429 g_mutex_lock (enc->property_lock);
431 enc->n_channels = GST_AUDIO_INFO_CHANNELS (info);
432 enc->sample_rate = GST_AUDIO_INFO_RATE (info);
433 GST_DEBUG_OBJECT (benc, "Setup with %d channels, %d Hz", enc->n_channels,
436 /* handle reconfigure */
438 opus_encoder_destroy (enc->state);
441 if (!gst_opus_enc_setup (enc))
444 enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
446 /* feedback to base class */
447 gst_opus_enc_setup_base_class (enc, benc);
449 g_mutex_unlock (enc->property_lock);
455 gst_opus_enc_setup (GstOpusEnc * enc)
459 GST_DEBUG_OBJECT (enc, "setup");
463 enc->state = opus_encoder_create (enc->sample_rate, enc->n_channels,
464 enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP,
466 if (!enc->state || error != OPUS_OK)
467 goto encoder_creation_failed;
469 opus_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
470 opus_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth), 0);
471 opus_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0);
472 opus_encoder_ctl (enc->state, OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr),
474 opus_encoder_ctl (enc->state, OPUS_SET_COMPLEXITY (enc->complexity), 0);
475 opus_encoder_ctl (enc->state, OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
476 opus_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
477 opus_encoder_ctl (enc->state,
478 OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0);
480 GST_LOG_OBJECT (enc, "we have frame size %d", enc->frame_size);
486 encoder_creation_failed:
487 GST_ERROR_OBJECT (enc, "Encoder creation failed");
492 gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
496 enc = GST_OPUS_ENC (benc);
498 GST_DEBUG_OBJECT (enc, "sink event: %s", GST_EVENT_TYPE_NAME (event));
499 switch (GST_EVENT_TYPE (event)) {
503 GstTagSetter *setter = GST_TAG_SETTER (enc);
504 const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
506 gst_event_parse_tag (event, &list);
507 gst_tag_setter_merge_tags (setter, list, mode);
518 gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
520 guint8 *bdata, *data, *mdata = NULL;
523 gint ret = GST_FLOW_OK;
525 g_mutex_lock (enc->property_lock);
527 bytes = enc->frame_samples * enc->n_channels * 2;
528 if (G_LIKELY (buf)) {
529 bdata = GST_BUFFER_DATA (buf);
530 bsize = GST_BUFFER_SIZE (buf);
531 if (G_UNLIKELY (bsize % bytes)) {
532 GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
534 size = ((bsize / bytes) + 1) * bytes;
535 mdata = g_malloc0 (size);
536 memcpy (mdata, bdata, bsize);
544 GST_DEBUG_OBJECT (enc, "nothing to drain");
553 ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
554 GST_BUFFER_OFFSET_NONE, enc->max_payload_size,
555 GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
557 if (GST_FLOW_OK != ret)
560 GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
564 opus_encode (enc->state, (const gint16 *) data, enc->frame_samples,
565 GST_BUFFER_DATA (outbuf), enc->max_payload_size);
568 GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize);
569 ret = GST_FLOW_ERROR;
571 } else if (outsize > enc->max_payload_size) {
572 GST_WARNING_OBJECT (enc,
573 "Encoded size %d is higher than max payload size (%d bytes)",
574 outsize, enc->max_payload_size);
575 ret = GST_FLOW_ERROR;
579 GST_BUFFER_SIZE (outbuf) = outsize;
582 gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
585 if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
594 g_mutex_unlock (enc->property_lock);
603 gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
606 GstFlowReturn ret = GST_FLOW_OK;
608 enc = GST_OPUS_ENC (benc);
609 GST_DEBUG_OBJECT (enc, "handle_frame");
611 if (!enc->header_sent) {
614 g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
617 gst_opus_header_create_caps (&caps, &enc->headers, enc->n_channels,
618 enc->sample_rate, gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc)));
621 /* negotiate with these caps */
622 GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
624 gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
626 enc->header_sent = TRUE;
629 GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
630 buf ? GST_BUFFER_SIZE (buf) : 0);
632 ret = gst_opus_enc_encode (enc, buf);
638 gst_opus_enc_get_property (GObject * object, guint prop_id, GValue * value,
643 enc = GST_OPUS_ENC (object);
645 g_mutex_lock (enc->property_lock);
649 g_value_set_boolean (value, enc->audio_or_voip);
652 g_value_set_int (value, enc->bitrate);
655 g_value_set_enum (value, enc->bandwidth);
657 case PROP_FRAME_SIZE:
658 g_value_set_enum (value, enc->frame_size);
661 g_value_set_boolean (value, enc->cbr);
663 case PROP_CONSTRAINED_VBR:
664 g_value_set_boolean (value, enc->constrained_vbr);
666 case PROP_COMPLEXITY:
667 g_value_set_int (value, enc->complexity);
669 case PROP_INBAND_FEC:
670 g_value_set_boolean (value, enc->inband_fec);
673 g_value_set_boolean (value, enc->dtx);
675 case PROP_PACKET_LOSS_PERCENT:
676 g_value_set_int (value, enc->packet_loss_percentage);
678 case PROP_MAX_PAYLOAD_SIZE:
679 g_value_set_uint (value, enc->max_payload_size);
682 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
686 g_mutex_unlock (enc->property_lock);
690 gst_opus_enc_set_property (GObject * object, guint prop_id,
691 const GValue * value, GParamSpec * pspec)
695 enc = GST_OPUS_ENC (object);
697 #define GST_OPUS_UPDATE_PROPERTY(prop,type,ctl) do { \
698 g_mutex_lock (enc->property_lock); \
699 enc->prop = g_value_get_##type (value); \
701 opus_encoder_ctl (enc->state, OPUS_SET_##ctl (enc->prop)); \
703 g_mutex_unlock (enc->property_lock); \
708 enc->audio_or_voip = g_value_get_boolean (value);
711 GST_OPUS_UPDATE_PROPERTY (bitrate, int, BITRATE);
714 GST_OPUS_UPDATE_PROPERTY (bandwidth, enum, BANDWIDTH);
716 case PROP_FRAME_SIZE:
717 g_mutex_lock (enc->property_lock);
718 enc->frame_size = g_value_get_enum (value);
719 enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
720 gst_opus_enc_setup_base_class (enc, GST_AUDIO_ENCODER (enc));
721 g_mutex_unlock (enc->property_lock);
724 /* this one has an opposite meaning to the opus ctl... */
725 g_mutex_lock (enc->property_lock);
726 enc->cbr = g_value_get_boolean (value);
727 opus_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr));
728 g_mutex_unlock (enc->property_lock);
730 case PROP_CONSTRAINED_VBR:
731 GST_OPUS_UPDATE_PROPERTY (constrained_vbr, boolean, VBR_CONSTRAINT);
733 case PROP_COMPLEXITY:
734 GST_OPUS_UPDATE_PROPERTY (complexity, int, COMPLEXITY);
736 case PROP_INBAND_FEC:
737 GST_OPUS_UPDATE_PROPERTY (inband_fec, boolean, INBAND_FEC);
740 GST_OPUS_UPDATE_PROPERTY (dtx, boolean, DTX);
742 case PROP_PACKET_LOSS_PERCENT:
743 GST_OPUS_UPDATE_PROPERTY (packet_loss_percentage, int, PACKET_LOSS_PERC);
745 case PROP_MAX_PAYLOAD_SIZE:
746 g_mutex_lock (enc->property_lock);
747 enc->max_payload_size = g_value_get_uint (value);
748 g_mutex_unlock (enc->property_lock);
751 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
755 #undef GST_OPUS_UPDATE_PROPERTY