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
gst_opus_enc_bandwidth_get_type(void)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
gst_opus_enc_frame_size_get_type(void)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
gst_opus_enc_audio_type_get_type(void)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
gst_opus_enc_bitrate_type_get_type(void)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_CBR
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
gst_opus_enc_set_tags(GstOpusEnc * enc)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
gst_opus_enc_class_init(GstOpusEncClass * klass)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 forward error correction", DEFAULT_INBAND_FEC,
329 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
330 GST_PARAM_MUTABLE_PLAYING));
331 g_object_class_install_property (gobject_class, PROP_DTX,
332 g_param_spec_boolean ("dtx", "DTX", "DTX", DEFAULT_DTX,
333 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
334 GST_PARAM_MUTABLE_PLAYING));
335 g_object_class_install_property (G_OBJECT_CLASS (klass),
336 PROP_PACKET_LOSS_PERCENT, g_param_spec_int ("packet-loss-percentage",
337 "Loss percentage", "Packet loss percentage", 0, 100,
338 DEFAULT_PACKET_LOSS_PERCENT,
339 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
340 GST_PARAM_MUTABLE_PLAYING));
341 g_object_class_install_property (G_OBJECT_CLASS (klass),
342 PROP_MAX_PAYLOAD_SIZE, g_param_spec_uint ("max-payload-size",
343 "Max payload size", "Maximum payload size in bytes", 2, 4000,
344 DEFAULT_MAX_PAYLOAD_SIZE,
345 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
346 GST_PARAM_MUTABLE_PLAYING));
347
348 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_opus_enc_finalize);
349
350 GST_DEBUG_CATEGORY_INIT (opusenc_debug, "opusenc", 0, "Opus encoder");
351
352 gst_type_mark_as_plugin_api (GST_OPUS_ENC_TYPE_AUDIO_TYPE, 0);
353 gst_type_mark_as_plugin_api (GST_OPUS_ENC_TYPE_BANDWIDTH, 0);
354 gst_type_mark_as_plugin_api (GST_OPUS_ENC_TYPE_BITRATE_TYPE, 0);
355 gst_type_mark_as_plugin_api (GST_OPUS_ENC_TYPE_FRAME_SIZE, 0);
356 }
357
358 static void
gst_opus_enc_finalize(GObject * object)359 gst_opus_enc_finalize (GObject * object)
360 {
361 GstOpusEnc *enc;
362
363 enc = GST_OPUS_ENC (object);
364
365 g_mutex_clear (&enc->property_lock);
366
367 G_OBJECT_CLASS (parent_class)->finalize (object);
368 }
369
370 static void
gst_opus_enc_init(GstOpusEnc * enc)371 gst_opus_enc_init (GstOpusEnc * enc)
372 {
373 GST_DEBUG_OBJECT (enc, "init");
374
375 GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (enc));
376
377 g_mutex_init (&enc->property_lock);
378
379 enc->n_channels = -1;
380 enc->sample_rate = -1;
381 enc->frame_samples = 0;
382 enc->unpositioned = FALSE;
383
384 enc->bitrate = DEFAULT_BITRATE;
385 enc->bandwidth = DEFAULT_BANDWIDTH;
386 enc->frame_size = DEFAULT_FRAMESIZE;
387 enc->bitrate_type = DEFAULT_BITRATE_TYPE;
388 enc->complexity = DEFAULT_COMPLEXITY;
389 enc->inband_fec = DEFAULT_INBAND_FEC;
390 enc->dtx = DEFAULT_DTX;
391 enc->packet_loss_percentage = DEFAULT_PACKET_LOSS_PERCENT;
392 enc->max_payload_size = DEFAULT_MAX_PAYLOAD_SIZE;
393 enc->audio_type = DEFAULT_AUDIO_TYPE;
394 }
395
396 static gboolean
gst_opus_enc_start(GstAudioEncoder * benc)397 gst_opus_enc_start (GstAudioEncoder * benc)
398 {
399 GstOpusEnc *enc = GST_OPUS_ENC (benc);
400
401 GST_DEBUG_OBJECT (enc, "start");
402 enc->encoded_samples = 0;
403 enc->consumed_samples = 0;
404
405 return TRUE;
406 }
407
408 static gboolean
gst_opus_enc_stop(GstAudioEncoder * benc)409 gst_opus_enc_stop (GstAudioEncoder * benc)
410 {
411 GstOpusEnc *enc = GST_OPUS_ENC (benc);
412
413 GST_DEBUG_OBJECT (enc, "stop");
414 if (enc->state) {
415 opus_multistream_encoder_destroy (enc->state);
416 enc->state = NULL;
417 }
418 gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
419
420 return TRUE;
421 }
422
423 static gint64
gst_opus_enc_get_latency(GstOpusEnc * enc)424 gst_opus_enc_get_latency (GstOpusEnc * enc)
425 {
426 gint64 latency = gst_util_uint64_scale (enc->frame_samples, GST_SECOND,
427 enc->sample_rate);
428 GST_DEBUG_OBJECT (enc, "Latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
429 return latency;
430 }
431
432 static void
gst_opus_enc_setup_base_class(GstOpusEnc * enc,GstAudioEncoder * benc)433 gst_opus_enc_setup_base_class (GstOpusEnc * enc, GstAudioEncoder * benc)
434 {
435 gst_audio_encoder_set_latency (benc,
436 gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
437 gst_audio_encoder_set_frame_samples_min (benc, enc->frame_samples);
438 gst_audio_encoder_set_frame_samples_max (benc, enc->frame_samples);
439 gst_audio_encoder_set_frame_max (benc, 1);
440 }
441
442 static gint
gst_opus_enc_get_frame_samples(GstOpusEnc * enc)443 gst_opus_enc_get_frame_samples (GstOpusEnc * enc)
444 {
445 gint frame_samples = 0;
446 switch (enc->frame_size) {
447 case 2:
448 frame_samples = enc->sample_rate / 400;
449 break;
450 case 5:
451 frame_samples = enc->sample_rate / 200;
452 break;
453 case 10:
454 frame_samples = enc->sample_rate / 100;
455 break;
456 case 20:
457 frame_samples = enc->sample_rate / 50;
458 break;
459 case 40:
460 frame_samples = enc->sample_rate / 25;
461 break;
462 case 60:
463 frame_samples = 3 * enc->sample_rate / 50;
464 break;
465 default:
466 GST_WARNING_OBJECT (enc, "Unsupported frame size: %d", enc->frame_size);
467 frame_samples = 0;
468 break;
469 }
470 return frame_samples;
471 }
472
473 static void
gst_opus_enc_setup_trivial_mapping(GstOpusEnc * enc,guint8 mapping[256])474 gst_opus_enc_setup_trivial_mapping (GstOpusEnc * enc, guint8 mapping[256])
475 {
476 int n;
477
478 for (n = 0; n < 255; ++n)
479 mapping[n] = n;
480 }
481
482 static int
gst_opus_enc_find_channel_position(GstOpusEnc * enc,const GstAudioInfo * info,GstAudioChannelPosition position)483 gst_opus_enc_find_channel_position (GstOpusEnc * enc, const GstAudioInfo * info,
484 GstAudioChannelPosition position)
485 {
486 int n;
487 for (n = 0; n < enc->n_channels; ++n) {
488 if (GST_AUDIO_INFO_POSITION (info, n) == position) {
489 return n;
490 }
491 }
492 return -1;
493 }
494
495 static int
gst_opus_enc_find_channel_position_in_vorbis_order(GstOpusEnc * enc,GstAudioChannelPosition position)496 gst_opus_enc_find_channel_position_in_vorbis_order (GstOpusEnc * enc,
497 GstAudioChannelPosition position)
498 {
499 int c;
500
501 for (c = 0; c < enc->n_channels; ++c) {
502 if (gst_opus_channel_positions[enc->n_channels - 1][c] == position) {
503 GST_INFO_OBJECT (enc,
504 "Channel position %s maps to index %d in Vorbis order",
505 gst_opus_channel_names[position], c);
506 return c;
507 }
508 }
509 GST_WARNING_OBJECT (enc,
510 "Channel position %s is not representable in Vorbis order",
511 gst_opus_channel_names[position]);
512 return -1;
513 }
514
515 static void
gst_opus_enc_setup_channel_mappings(GstOpusEnc * enc,const GstAudioInfo * info)516 gst_opus_enc_setup_channel_mappings (GstOpusEnc * enc,
517 const GstAudioInfo * info)
518 {
519 #define MAPS(idx,pos) (GST_AUDIO_INFO_POSITION (info, (idx)) == GST_AUDIO_CHANNEL_POSITION_##pos)
520
521 int n;
522
523 GST_DEBUG_OBJECT (enc, "Setting up channel mapping for %d channels",
524 enc->n_channels);
525
526 /* Start by setting up a default trivial mapping */
527 enc->n_stereo_streams = 0;
528 gst_opus_enc_setup_trivial_mapping (enc, enc->encoding_channel_mapping);
529 gst_opus_enc_setup_trivial_mapping (enc, enc->decoding_channel_mapping);
530
531 /* For one channel, use the basic RTP mapping */
532 if (enc->n_channels == 1 && !enc->unpositioned) {
533 GST_INFO_OBJECT (enc, "Mono, trivial RTP mapping");
534 enc->channel_mapping_family = 0;
535 /* implicit mapping for family 0 */
536 return;
537 }
538
539 /* For two channels, use the basic RTP mapping if the channels are
540 mapped as left/right. */
541 if (enc->n_channels == 2 && !enc->unpositioned) {
542 GST_INFO_OBJECT (enc, "Stereo, trivial RTP mapping");
543 enc->channel_mapping_family = 0;
544 enc->n_stereo_streams = 1;
545 /* implicit mapping for family 0 */
546 return;
547 }
548
549 /* For channels between 3 and 8, we use the Vorbis mapping if we can
550 find a permutation that matches it. Mono and stereo will have been taken
551 care of earlier, but this code also handles it. There are two mappings.
552 One maps the input channels to an ordering which has the natural pairs
553 first so they can benefit from the Opus stereo channel coupling, and the
554 other maps this ordering to the Vorbis ordering. */
555 if (enc->n_channels >= 3 && enc->n_channels <= 8 && !enc->unpositioned) {
556 int c0, c1, c0v, c1v;
557 int mapped;
558 gboolean positions_done[256];
559 static const GstAudioChannelPosition pairs[][2] = {
560 {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
561 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
562 {GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
563 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
564 {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
565 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER},
566 {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
567 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER},
568 {GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
569 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT},
570 {GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
571 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER},
572 };
573 size_t pair;
574
575 GST_DEBUG_OBJECT (enc,
576 "In range for the Vorbis mapping, building channel mapping tables");
577
578 enc->n_stereo_streams = 0;
579 mapped = 0;
580 for (n = 0; n < 256; ++n)
581 positions_done[n] = FALSE;
582
583 /* First, find any natural pairs, and move them to the front */
584 for (pair = 0; pair < G_N_ELEMENTS (pairs); ++pair) {
585 GstAudioChannelPosition p0 = pairs[pair][0];
586 GstAudioChannelPosition p1 = pairs[pair][1];
587 c0 = gst_opus_enc_find_channel_position (enc, info, p0);
588 c1 = gst_opus_enc_find_channel_position (enc, info, p1);
589 if (c0 >= 0 && c1 >= 0) {
590 /* We found a natural pair */
591 GST_DEBUG_OBJECT (enc, "Natural pair '%s/%s' found at %d %d",
592 gst_opus_channel_names[p0], gst_opus_channel_names[p1], c0, c1);
593 /* Find where they map in Vorbis order */
594 c0v = gst_opus_enc_find_channel_position_in_vorbis_order (enc, p0);
595 c1v = gst_opus_enc_find_channel_position_in_vorbis_order (enc, p1);
596 if (c0v < 0 || c1v < 0) {
597 GST_WARNING_OBJECT (enc,
598 "Cannot map channel positions to Vorbis order, using unknown mapping");
599 enc->channel_mapping_family = 255;
600 enc->n_stereo_streams = 0;
601 return;
602 }
603
604 enc->encoding_channel_mapping[mapped] = c0;
605 enc->encoding_channel_mapping[mapped + 1] = c1;
606 enc->decoding_channel_mapping[c0v] = mapped;
607 enc->decoding_channel_mapping[c1v] = mapped + 1;
608 enc->n_stereo_streams++;
609 mapped += 2;
610 positions_done[p0] = positions_done[p1] = TRUE;
611 }
612 }
613
614 /* Now add all other input channels as mono streams */
615 for (n = 0; n < enc->n_channels; ++n) {
616 GstAudioChannelPosition position = GST_AUDIO_INFO_POSITION (info, n);
617
618 /* if we already mapped it while searching for pairs, nothing else
619 needs to be done */
620 if (!positions_done[position]) {
621 int cv;
622 GST_DEBUG_OBJECT (enc, "Channel position %s is not mapped yet, adding",
623 gst_opus_channel_names[position]);
624 cv = gst_opus_enc_find_channel_position_in_vorbis_order (enc, position);
625 if (cv < 0)
626 g_assert_not_reached ();
627 enc->encoding_channel_mapping[mapped] = n;
628 enc->decoding_channel_mapping[cv] = mapped;
629 mapped++;
630 }
631 }
632
633 #ifndef GST_DISABLE_GST_DEBUG
634 GST_INFO_OBJECT (enc,
635 "Mapping tables built: %d channels, %d stereo streams", enc->n_channels,
636 enc->n_stereo_streams);
637 gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
638 "Encoding mapping table", enc->n_channels,
639 enc->encoding_channel_mapping);
640 gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
641 "Decoding mapping table", enc->n_channels,
642 enc->decoding_channel_mapping);
643 #endif
644
645 enc->channel_mapping_family = 1;
646 return;
647 }
648
649 /* More than 8 channels, if future mappings are added for those */
650
651 /* For other cases, we use undefined, with the default trivial mapping
652 and all mono streams */
653 if (!enc->unpositioned)
654 GST_WARNING_OBJECT (enc, "Unknown mapping");
655 else
656 GST_INFO_OBJECT (enc, "Unpositioned mapping, all channels mono");
657
658 enc->channel_mapping_family = 255;
659 enc->n_stereo_streams = 0;
660
661 #undef MAPS
662 }
663
664 static gboolean
gst_opus_enc_set_format(GstAudioEncoder * benc,GstAudioInfo * info)665 gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
666 {
667 GstOpusEnc *enc;
668
669 enc = GST_OPUS_ENC (benc);
670
671 g_mutex_lock (&enc->property_lock);
672
673 enc->n_channels = GST_AUDIO_INFO_CHANNELS (info);
674 enc->unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (info);
675 enc->sample_rate = GST_AUDIO_INFO_RATE (info);
676 gst_opus_enc_setup_channel_mappings (enc, info);
677 GST_DEBUG_OBJECT (benc, "Setup with %d channels, %d Hz", enc->n_channels,
678 enc->sample_rate);
679
680 /* handle reconfigure */
681 if (enc->state) {
682 opus_multistream_encoder_destroy (enc->state);
683 enc->state = NULL;
684 }
685 if (!gst_opus_enc_setup (enc)) {
686 g_mutex_unlock (&enc->property_lock);
687 return FALSE;
688 }
689
690 /* update the tags */
691 gst_opus_enc_set_tags (enc);
692
693 enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
694
695 /* feedback to base class */
696 gst_opus_enc_setup_base_class (enc, benc);
697
698 g_mutex_unlock (&enc->property_lock);
699
700 return TRUE;
701 }
702
703 static gboolean
gst_opus_enc_setup(GstOpusEnc * enc)704 gst_opus_enc_setup (GstOpusEnc * enc)
705 {
706 int error = OPUS_OK;
707 GstCaps *caps;
708 gboolean ret;
709 gint32 lookahead;
710 const GstTagList *tags;
711 GstTagList *empty_tags = NULL;
712 GstBuffer *header, *comments;
713
714 #ifndef GST_DISABLE_GST_DEBUG
715 GST_DEBUG_OBJECT (enc,
716 "setup: %d Hz, %d channels, %d stereo streams, family %d",
717 enc->sample_rate, enc->n_channels, enc->n_stereo_streams,
718 enc->channel_mapping_family);
719 GST_INFO_OBJECT (enc, "Mapping tables built: %d channels, %d stereo streams",
720 enc->n_channels, enc->n_stereo_streams);
721 gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
722 "Encoding mapping table", enc->n_channels, enc->encoding_channel_mapping);
723 gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
724 "Decoding mapping table", enc->n_channels, enc->decoding_channel_mapping);
725 #endif
726
727 enc->state = opus_multistream_encoder_create (enc->sample_rate,
728 enc->n_channels, enc->n_channels - enc->n_stereo_streams,
729 enc->n_stereo_streams, enc->encoding_channel_mapping,
730 enc->audio_type, &error);
731 if (!enc->state || error != OPUS_OK)
732 goto encoder_creation_failed;
733
734 opus_multistream_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
735 opus_multistream_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth),
736 0);
737 opus_multistream_encoder_ctl (enc->state,
738 OPUS_SET_VBR (enc->bitrate_type != BITRATE_TYPE_CBR), 0);
739 opus_multistream_encoder_ctl (enc->state,
740 OPUS_SET_VBR_CONSTRAINT (enc->bitrate_type ==
741 BITRATE_TYPE_CONSTRAINED_VBR), 0);
742 opus_multistream_encoder_ctl (enc->state,
743 OPUS_SET_COMPLEXITY (enc->complexity), 0);
744 opus_multistream_encoder_ctl (enc->state,
745 OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
746 opus_multistream_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
747 opus_multistream_encoder_ctl (enc->state,
748 OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0);
749
750 opus_multistream_encoder_ctl (enc->state, OPUS_GET_LOOKAHEAD (&lookahead), 0);
751
752 GST_LOG_OBJECT (enc, "we have frame size %d, lookahead %d", enc->frame_size,
753 lookahead);
754
755 /* lookahead is samples, the Opus header wants it in 48kHz samples */
756 lookahead = lookahead * 48000 / enc->sample_rate;
757 enc->lookahead = enc->pending_lookahead = lookahead;
758
759 header = gst_codec_utils_opus_create_header (enc->sample_rate,
760 enc->n_channels, enc->channel_mapping_family,
761 enc->n_channels - enc->n_stereo_streams, enc->n_stereo_streams,
762 enc->decoding_channel_mapping, lookahead, 0);
763 tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
764 if (!tags)
765 tags = empty_tags = gst_tag_list_new_empty ();
766 comments =
767 gst_tag_list_to_vorbiscomment_buffer (tags, (const guint8 *) "OpusTags",
768 8, "Encoded with GStreamer opusenc");
769 caps = gst_codec_utils_opus_create_caps_from_header (header, comments);
770 if (empty_tags)
771 gst_tag_list_unref (empty_tags);
772 gst_buffer_unref (header);
773 gst_buffer_unref (comments);
774
775 /* negotiate with these caps */
776 GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
777
778 ret = gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (enc), caps);
779 gst_caps_unref (caps);
780
781 return ret;
782
783 encoder_creation_failed:
784 GST_ERROR_OBJECT (enc, "Encoder creation failed");
785 return FALSE;
786 }
787
788 static gboolean
gst_opus_enc_sink_event(GstAudioEncoder * benc,GstEvent * event)789 gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
790 {
791 GstOpusEnc *enc;
792
793 enc = GST_OPUS_ENC (benc);
794
795 GST_DEBUG_OBJECT (enc, "sink event: %s", GST_EVENT_TYPE_NAME (event));
796 switch (GST_EVENT_TYPE (event)) {
797 case GST_EVENT_TAG:
798 {
799 GstTagList *list;
800 GstTagSetter *setter = GST_TAG_SETTER (enc);
801 const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
802
803 gst_event_parse_tag (event, &list);
804 gst_tag_setter_merge_tags (setter, list, mode);
805 break;
806 }
807 case GST_EVENT_SEGMENT:
808 enc->encoded_samples = 0;
809 enc->consumed_samples = 0;
810 break;
811
812 default:
813 break;
814 }
815
816 return GST_AUDIO_ENCODER_CLASS (parent_class)->sink_event (benc, event);
817 }
818
819 static GstCaps *
gst_opus_enc_get_sink_template_caps(void)820 gst_opus_enc_get_sink_template_caps (void)
821 {
822 static gsize init = 0;
823 static GstCaps *caps = NULL;
824
825 if (g_once_init_enter (&init)) {
826 GValue rate_array = G_VALUE_INIT;
827 GValue v = G_VALUE_INIT;
828 GstStructure *s1, *s2, *s;
829 gint i, c;
830
831 caps = gst_caps_new_empty ();
832
833 /* The caps is cached */
834 GST_MINI_OBJECT_FLAG_SET (caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
835
836 /* Generate our two template structures */
837 g_value_init (&rate_array, GST_TYPE_LIST);
838 g_value_init (&v, G_TYPE_INT);
839 g_value_set_int (&v, 8000);
840 gst_value_list_append_value (&rate_array, &v);
841 g_value_set_int (&v, 12000);
842 gst_value_list_append_value (&rate_array, &v);
843 g_value_set_int (&v, 16000);
844 gst_value_list_append_value (&rate_array, &v);
845 g_value_set_int (&v, 24000);
846 gst_value_list_append_value (&rate_array, &v);
847
848 s1 = gst_structure_new ("audio/x-raw",
849 "format", G_TYPE_STRING, GST_AUDIO_NE (S16),
850 "layout", G_TYPE_STRING, "interleaved",
851 "rate", G_TYPE_INT, 48000, NULL);
852 s2 = gst_structure_new ("audio/x-raw",
853 "format", G_TYPE_STRING, GST_AUDIO_NE (S16),
854 "layout", G_TYPE_STRING, "interleaved", NULL);
855 gst_structure_set_value (s2, "rate", &rate_array);
856 g_value_unset (&rate_array);
857 g_value_unset (&v);
858
859 /* Mono */
860 s = gst_structure_copy (s1);
861 gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
862 gst_caps_append_structure (caps, s);
863
864 s = gst_structure_copy (s2);
865 gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
866 gst_caps_append_structure (caps, s);
867
868 /* Stereo and further */
869 for (i = 2; i <= 8; i++) {
870 guint64 channel_mask = 0;
871 const GstAudioChannelPosition *pos = gst_opus_channel_positions[i - 1];
872
873 for (c = 0; c < i; c++) {
874 channel_mask |= G_GUINT64_CONSTANT (1) << pos[c];
875 }
876
877 s = gst_structure_copy (s1);
878 gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
879 GST_TYPE_BITMASK, channel_mask, NULL);
880 gst_caps_append_structure (caps, s);
881
882 s = gst_structure_copy (s2);
883 gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
884 GST_TYPE_BITMASK, channel_mask, NULL);
885 gst_caps_append_structure (caps, s);
886
887 /* We also allow unpositioned channels, input will be
888 * treated as a set of individual mono channels */
889 s = gst_structure_copy (s2);
890 gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
891 GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
892 gst_caps_append_structure (caps, s);
893
894 s = gst_structure_copy (s1);
895 gst_structure_set (s, "channels", G_TYPE_INT, i, "channel-mask",
896 GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
897 gst_caps_append_structure (caps, s);
898 }
899
900 gst_structure_free (s1);
901 gst_structure_free (s2);
902
903 g_once_init_leave (&init, 1);
904 }
905
906 return caps;
907 }
908
909 static GstCaps *
gst_opus_enc_sink_getcaps(GstAudioEncoder * benc,GstCaps * filter)910 gst_opus_enc_sink_getcaps (GstAudioEncoder * benc, GstCaps * filter)
911 {
912 GstOpusEnc *enc;
913 GstCaps *caps;
914
915 enc = GST_OPUS_ENC (benc);
916
917 GST_DEBUG_OBJECT (enc, "sink getcaps");
918
919 caps = gst_opus_enc_get_sink_template_caps ();
920 caps = gst_audio_encoder_proxy_getcaps (benc, caps, filter);
921
922 GST_DEBUG_OBJECT (enc, "Returning caps: %" GST_PTR_FORMAT, caps);
923
924 return caps;
925 }
926
927 static GstFlowReturn
gst_opus_enc_encode(GstOpusEnc * enc,GstBuffer * buf)928 gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
929 {
930 guint8 *bdata = NULL, *data, *mdata = NULL;
931 gsize bsize, size;
932 gsize bytes;
933 gint ret = GST_FLOW_OK;
934 GstMapInfo map;
935 GstMapInfo omap;
936 gint outsize;
937 GstBuffer *outbuf;
938 guint64 trim_start = 0, trim_end = 0;
939
940 guint max_payload_size;
941 gint frame_samples, input_samples, output_samples;
942
943 g_mutex_lock (&enc->property_lock);
944
945 bytes = enc->frame_samples * enc->n_channels * 2;
946 max_payload_size = enc->max_payload_size;
947 frame_samples = input_samples = enc->frame_samples;
948
949 g_mutex_unlock (&enc->property_lock);
950
951 if (G_LIKELY (buf)) {
952 gst_buffer_map (buf, &map, GST_MAP_READ);
953 bdata = map.data;
954 bsize = map.size;
955
956 if (G_UNLIKELY (bsize % bytes)) {
957 gint64 diff;
958
959 GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
960 g_assert (bsize < bytes);
961
962 input_samples = bsize / (enc->n_channels * 2);
963 diff =
964 (enc->encoded_samples + frame_samples) - (enc->consumed_samples +
965 input_samples);
966 if (diff >= 0) {
967 GST_DEBUG_OBJECT (enc,
968 "%" G_GINT64_FORMAT " extra samples of padding in this frame",
969 diff);
970 output_samples = frame_samples - diff;
971 trim_end = diff * 48000 / enc->sample_rate;
972 } else {
973 GST_DEBUG_OBJECT (enc,
974 "Need to add %" G_GINT64_FORMAT " extra samples in the next frame",
975 -diff);
976 output_samples = frame_samples;
977 }
978
979 size = ((bsize / bytes) + 1) * bytes;
980 mdata = g_malloc0 (size);
981 /* FIXME: Instead of silence, use LPC with the last real samples.
982 * Otherwise we will create a discontinuity here, which will distort the
983 * last few encoded samples
984 */
985 memcpy (mdata, bdata, bsize);
986 data = mdata;
987 } else {
988 data = bdata;
989 size = bsize;
990
991 /* Adjust for lookahead here */
992 if (enc->pending_lookahead) {
993 guint scaled_lookahead =
994 enc->pending_lookahead * enc->sample_rate / 48000;
995
996 if (input_samples > scaled_lookahead) {
997 output_samples = input_samples - scaled_lookahead;
998 trim_start = enc->pending_lookahead;
999 enc->pending_lookahead = 0;
1000 } else {
1001 trim_start = ((guint64) input_samples) * 48000 / enc->sample_rate;
1002 enc->pending_lookahead -= trim_start;
1003 output_samples = 0;
1004 }
1005 } else {
1006 output_samples = input_samples;
1007 }
1008 }
1009 } else {
1010 if (enc->encoded_samples < enc->consumed_samples) {
1011 /* FIXME: Instead of silence, use LPC with the last real samples.
1012 * Otherwise we will create a discontinuity here, which will distort the
1013 * last few encoded samples
1014 */
1015 data = mdata = g_malloc0 (bytes);
1016 size = bytes;
1017 output_samples = enc->consumed_samples - enc->encoded_samples;
1018 input_samples = 0;
1019 GST_DEBUG_OBJECT (enc, "draining %d samples", output_samples);
1020 trim_end =
1021 ((guint64) frame_samples - output_samples) * 48000 / enc->sample_rate;
1022 } else if (enc->encoded_samples == enc->consumed_samples) {
1023 GST_DEBUG_OBJECT (enc, "nothing to drain");
1024 goto done;
1025 } else {
1026 g_assert_not_reached ();
1027 goto done;
1028 }
1029 }
1030
1031 g_assert (size == bytes);
1032
1033 outbuf =
1034 gst_audio_encoder_allocate_output_buffer (GST_AUDIO_ENCODER (enc),
1035 max_payload_size * enc->n_channels);
1036 if (!outbuf)
1037 goto done;
1038
1039 GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
1040 frame_samples, (int) bytes);
1041
1042 if (trim_start || trim_end) {
1043 GST_DEBUG_OBJECT (enc,
1044 "Adding trim-start %" G_GUINT64_FORMAT " trim-end %" G_GUINT64_FORMAT,
1045 trim_start, trim_end);
1046 gst_buffer_add_audio_clipping_meta (outbuf, GST_FORMAT_DEFAULT, trim_start,
1047 trim_end);
1048 }
1049
1050 gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
1051
1052 outsize =
1053 opus_multistream_encode (enc->state, (const gint16 *) data,
1054 frame_samples, omap.data, max_payload_size * enc->n_channels);
1055
1056 gst_buffer_unmap (outbuf, &omap);
1057
1058 if (outsize < 0) {
1059 GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1060 ("Encoding failed (%d): %s", outsize, opus_strerror (outsize)));
1061 ret = GST_FLOW_ERROR;
1062 goto done;
1063 } else if (outsize > max_payload_size) {
1064 GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
1065 ("Encoded size %d is higher than max payload size (%d bytes)",
1066 outsize, max_payload_size));
1067 ret = GST_FLOW_ERROR;
1068 goto done;
1069 }
1070
1071 GST_DEBUG_OBJECT (enc, "Output packet is %u bytes", outsize);
1072 gst_buffer_set_size (outbuf, outsize);
1073
1074
1075 ret =
1076 gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
1077 output_samples);
1078 enc->encoded_samples += output_samples;
1079 enc->consumed_samples += input_samples;
1080
1081 done:
1082
1083 if (bdata)
1084 gst_buffer_unmap (buf, &map);
1085
1086 g_free (mdata);
1087
1088 return ret;
1089 }
1090
1091 static GstFlowReturn
gst_opus_enc_handle_frame(GstAudioEncoder * benc,GstBuffer * buf)1092 gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
1093 {
1094 GstOpusEnc *enc;
1095 GstFlowReturn ret = GST_FLOW_OK;
1096
1097 enc = GST_OPUS_ENC (benc);
1098 GST_DEBUG_OBJECT (enc, "handle_frame");
1099 GST_DEBUG_OBJECT (enc, "received buffer %p of %" G_GSIZE_FORMAT " bytes", buf,
1100 buf ? gst_buffer_get_size (buf) : 0);
1101
1102 ret = gst_opus_enc_encode (enc, buf);
1103
1104 return ret;
1105 }
1106
1107 static void
gst_opus_enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1108 gst_opus_enc_get_property (GObject * object, guint prop_id, GValue * value,
1109 GParamSpec * pspec)
1110 {
1111 GstOpusEnc *enc;
1112
1113 enc = GST_OPUS_ENC (object);
1114
1115 g_mutex_lock (&enc->property_lock);
1116
1117 switch (prop_id) {
1118 case PROP_AUDIO_TYPE:
1119 g_value_set_enum (value, enc->audio_type);
1120 break;
1121 case PROP_BITRATE:
1122 g_value_set_int (value, enc->bitrate);
1123 break;
1124 case PROP_BANDWIDTH:
1125 g_value_set_enum (value, enc->bandwidth);
1126 break;
1127 case PROP_FRAME_SIZE:
1128 g_value_set_enum (value, enc->frame_size);
1129 break;
1130 case PROP_BITRATE_TYPE:
1131 g_value_set_enum (value, enc->bitrate_type);
1132 break;
1133 case PROP_COMPLEXITY:
1134 g_value_set_int (value, enc->complexity);
1135 break;
1136 case PROP_INBAND_FEC:
1137 g_value_set_boolean (value, enc->inband_fec);
1138 break;
1139 case PROP_DTX:
1140 g_value_set_boolean (value, enc->dtx);
1141 break;
1142 case PROP_PACKET_LOSS_PERCENT:
1143 g_value_set_int (value, enc->packet_loss_percentage);
1144 break;
1145 case PROP_MAX_PAYLOAD_SIZE:
1146 g_value_set_uint (value, enc->max_payload_size);
1147 break;
1148 default:
1149 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1150 break;
1151 }
1152
1153 g_mutex_unlock (&enc->property_lock);
1154 }
1155
1156 static void
gst_opus_enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1157 gst_opus_enc_set_property (GObject * object, guint prop_id,
1158 const GValue * value, GParamSpec * pspec)
1159 {
1160 GstOpusEnc *enc;
1161
1162 enc = GST_OPUS_ENC (object);
1163
1164 #define GST_OPUS_UPDATE_PROPERTY(prop,type,ctl) do { \
1165 g_mutex_lock (&enc->property_lock); \
1166 enc->prop = g_value_get_##type (value); \
1167 if (enc->state) { \
1168 opus_multistream_encoder_ctl (enc->state, OPUS_SET_##ctl (enc->prop)); \
1169 } \
1170 g_mutex_unlock (&enc->property_lock); \
1171 } while(0)
1172
1173 switch (prop_id) {
1174 case PROP_AUDIO_TYPE:
1175 enc->audio_type = g_value_get_enum (value);
1176 break;
1177 case PROP_BITRATE:
1178 GST_OPUS_UPDATE_PROPERTY (bitrate, int, BITRATE);
1179 break;
1180 case PROP_BANDWIDTH:
1181 GST_OPUS_UPDATE_PROPERTY (bandwidth, enum, BANDWIDTH);
1182 break;
1183 case PROP_FRAME_SIZE:
1184 g_mutex_lock (&enc->property_lock);
1185 enc->frame_size = g_value_get_enum (value);
1186 enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
1187 gst_opus_enc_setup_base_class (enc, GST_AUDIO_ENCODER (enc));
1188 g_mutex_unlock (&enc->property_lock);
1189 break;
1190 case PROP_BITRATE_TYPE:
1191 /* this one has an opposite meaning to the opus ctl... */
1192 g_mutex_lock (&enc->property_lock);
1193 enc->bitrate_type = g_value_get_enum (value);
1194 if (enc->state) {
1195 opus_multistream_encoder_ctl (enc->state,
1196 OPUS_SET_VBR (enc->bitrate_type != BITRATE_TYPE_CBR));
1197 opus_multistream_encoder_ctl (enc->state,
1198 OPUS_SET_VBR_CONSTRAINT (enc->bitrate_type ==
1199 BITRATE_TYPE_CONSTRAINED_VBR), 0);
1200 }
1201 g_mutex_unlock (&enc->property_lock);
1202 break;
1203 case PROP_COMPLEXITY:
1204 GST_OPUS_UPDATE_PROPERTY (complexity, int, COMPLEXITY);
1205 break;
1206 case PROP_INBAND_FEC:
1207 GST_OPUS_UPDATE_PROPERTY (inband_fec, boolean, INBAND_FEC);
1208 break;
1209 case PROP_DTX:
1210 GST_OPUS_UPDATE_PROPERTY (dtx, boolean, DTX);
1211 break;
1212 case PROP_PACKET_LOSS_PERCENT:
1213 GST_OPUS_UPDATE_PROPERTY (packet_loss_percentage, int, PACKET_LOSS_PERC);
1214 break;
1215 case PROP_MAX_PAYLOAD_SIZE:
1216 g_mutex_lock (&enc->property_lock);
1217 enc->max_payload_size = g_value_get_uint (value);
1218 g_mutex_unlock (&enc->property_lock);
1219 break;
1220 default:
1221 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1222 break;
1223 }
1224
1225 #undef GST_OPUS_UPDATE_PROPERTY
1226
1227 }
1228