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 #define GST_OPUS_ENC_TYPE_BANDWIDTH (gst_opus_enc_bandwidth_get_type())
59 gst_opus_enc_bandwidth_get_type (void)
61 static const GEnumValue values[] = {
62 {OPUS_BANDWIDTH_NARROWBAND, "Narrow band", "narrowband"},
63 {OPUS_BANDWIDTH_MEDIUMBAND, "Medium band", "mediumband"},
64 {OPUS_BANDWIDTH_WIDEBAND, "Wide band", "wideband"},
65 {OPUS_BANDWIDTH_SUPERWIDEBAND, "Super wide band", "superwideband"},
66 {OPUS_BANDWIDTH_FULLBAND, "Full band", "fullband"},
67 {OPUS_AUTO, "Auto", "auto"},
70 static volatile GType id = 0;
72 if (g_once_init_enter ((gsize *) & id)) {
75 _id = g_enum_register_static ("GstOpusEncBandwidth", values);
77 g_once_init_leave ((gsize *) & id, _id);
83 #define GST_OPUS_ENC_TYPE_FRAME_SIZE (gst_opus_enc_frame_size_get_type())
85 gst_opus_enc_frame_size_get_type (void)
87 static const GEnumValue values[] = {
96 static volatile GType id = 0;
98 if (g_once_init_enter ((gsize *) & id)) {
101 _id = g_enum_register_static ("GstOpusEncFrameSize", values);
103 g_once_init_leave ((gsize *) & id, _id);
109 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
112 GST_STATIC_CAPS ("audio/x-raw-int, "
113 "rate = (int) { 8000, 12000, 16000, 24000, 48000 }, "
114 "channels = (int) [ 1, 2 ], "
115 "endianness = (int) BYTE_ORDER, "
116 "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16")
119 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
122 GST_STATIC_CAPS ("audio/x-opus")
125 #define DEFAULT_AUDIO TRUE
126 #define DEFAULT_BITRATE 64000
127 #define DEFAULT_BANDWIDTH OPUS_BANDWIDTH_FULLBAND
128 #define DEFAULT_FRAMESIZE 20
129 #define DEFAULT_CBR TRUE
130 #define DEFAULT_CONSTRAINED_VBR TRUE
131 #define DEFAULT_COMPLEXITY 10
132 #define DEFAULT_INBAND_FEC FALSE
133 #define DEFAULT_DTX FALSE
134 #define DEFAULT_PACKET_LOSS_PERCENT 0
144 PROP_CONSTRAINED_VBR,
148 PROP_PACKET_LOSS_PERCENT
151 static void gst_opus_enc_finalize (GObject * object);
153 static gboolean gst_opus_enc_sink_event (GstAudioEncoder * benc,
155 static gboolean gst_opus_enc_setup (GstOpusEnc * enc);
157 static void gst_opus_enc_get_property (GObject * object, guint prop_id,
158 GValue * value, GParamSpec * pspec);
159 static void gst_opus_enc_set_property (GObject * object, guint prop_id,
160 const GValue * value, GParamSpec * pspec);
162 static gboolean gst_opus_enc_start (GstAudioEncoder * benc);
163 static gboolean gst_opus_enc_stop (GstAudioEncoder * benc);
164 static gboolean gst_opus_enc_set_format (GstAudioEncoder * benc,
165 GstAudioInfo * info);
166 static GstFlowReturn gst_opus_enc_handle_frame (GstAudioEncoder * benc,
168 static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
170 static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buffer);
173 gst_opus_enc_setup_interfaces (GType opusenc_type)
175 static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
176 const GInterfaceInfo preset_interface_info = {
177 NULL, /* interface_init */
178 NULL, /* interface_finalize */
179 NULL /* interface_data */
182 g_type_add_interface_static (opusenc_type, GST_TYPE_TAG_SETTER,
184 g_type_add_interface_static (opusenc_type, GST_TYPE_PRESET,
185 &preset_interface_info);
187 GST_DEBUG_CATEGORY_INIT (opusenc_debug, "opusenc", 0, "Opus encoder");
190 GST_BOILERPLATE_FULL (GstOpusEnc, gst_opus_enc, GstAudioEncoder,
191 GST_TYPE_AUDIO_ENCODER, gst_opus_enc_setup_interfaces);
194 gst_opus_enc_base_init (gpointer g_class)
196 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
198 gst_element_class_add_pad_template (element_class,
199 gst_static_pad_template_get (&src_factory));
200 gst_element_class_add_pad_template (element_class,
201 gst_static_pad_template_get (&sink_factory));
202 gst_element_class_set_details_simple (element_class, "Opus audio encoder",
203 "Codec/Encoder/Audio",
204 "Encodes audio in Opus format",
205 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
209 gst_opus_enc_class_init (GstOpusEncClass * klass)
211 GObjectClass *gobject_class;
212 GstElementClass *gstelement_class;
213 GstAudioEncoderClass *base_class;
215 gobject_class = (GObjectClass *) klass;
216 gstelement_class = (GstElementClass *) klass;
217 base_class = (GstAudioEncoderClass *) klass;
219 gobject_class->set_property = gst_opus_enc_set_property;
220 gobject_class->get_property = gst_opus_enc_get_property;
222 base_class->start = GST_DEBUG_FUNCPTR (gst_opus_enc_start);
223 base_class->stop = GST_DEBUG_FUNCPTR (gst_opus_enc_stop);
224 base_class->set_format = GST_DEBUG_FUNCPTR (gst_opus_enc_set_format);
225 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_opus_enc_handle_frame);
226 base_class->event = GST_DEBUG_FUNCPTR (gst_opus_enc_sink_event);
228 g_object_class_install_property (gobject_class, PROP_AUDIO,
229 g_param_spec_boolean ("audio", "Audio or voice",
230 "Audio or voice", DEFAULT_AUDIO,
231 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
232 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BITRATE,
233 g_param_spec_int ("bitrate", "Encoding Bit-rate",
234 "Specify an encoding bit-rate (in bps).",
235 1, 320000, DEFAULT_BITRATE,
236 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
237 g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
238 g_param_spec_enum ("bandwidth", "Band Width",
239 "Audio Band Width", GST_OPUS_ENC_TYPE_BANDWIDTH, DEFAULT_BANDWIDTH,
240 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
241 g_object_class_install_property (gobject_class, PROP_FRAME_SIZE,
242 g_param_spec_enum ("frame-size", "Frame Size",
243 "The duration of an audio frame, in ms",
244 GST_OPUS_ENC_TYPE_FRAME_SIZE, DEFAULT_FRAMESIZE,
245 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
246 g_object_class_install_property (gobject_class, PROP_CBR,
247 g_param_spec_boolean ("cbr", "Constant bit rate",
248 "Constant bit rate", DEFAULT_CBR,
249 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
250 g_object_class_install_property (gobject_class, PROP_CONSTRAINED_VBR,
251 g_param_spec_boolean ("constrained-vbr", "Constrained VBR",
252 "Constrained VBR", DEFAULT_CONSTRAINED_VBR,
253 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
254 g_object_class_install_property (gobject_class, PROP_COMPLEXITY,
255 g_param_spec_int ("complexity", "Complexity",
256 "Complexity", 0, 10, DEFAULT_COMPLEXITY,
257 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
258 g_object_class_install_property (gobject_class, PROP_INBAND_FEC,
259 g_param_spec_boolean ("inband-fec", "In-band FEC",
260 "Enable forward error correction", DEFAULT_INBAND_FEC,
261 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
262 g_object_class_install_property (gobject_class, PROP_DTX,
263 g_param_spec_boolean ("dtx", "DTX",
264 "DTX", DEFAULT_DTX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
265 g_object_class_install_property (G_OBJECT_CLASS (klass),
266 PROP_PACKET_LOSS_PERCENT, g_param_spec_int ("packet-loss-percentage",
267 "Loss percentage", "Packet loss percentage", 0, 100,
268 DEFAULT_PACKET_LOSS_PERCENT,
269 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
271 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_opus_enc_finalize);
275 gst_opus_enc_finalize (GObject * object)
279 enc = GST_OPUS_ENC (object);
281 G_OBJECT_CLASS (parent_class)->finalize (object);
285 gst_opus_enc_init (GstOpusEnc * enc, GstOpusEncClass * klass)
287 GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
289 GST_DEBUG_OBJECT (enc, "init");
291 enc->n_channels = -1;
292 enc->sample_rate = -1;
293 enc->frame_samples = 0;
295 enc->bitrate = DEFAULT_BITRATE;
296 enc->bandwidth = DEFAULT_BANDWIDTH;
297 enc->frame_size = DEFAULT_FRAMESIZE;
298 enc->cbr = DEFAULT_CBR;
299 enc->constrained_vbr = DEFAULT_CONSTRAINED_VBR;
300 enc->complexity = DEFAULT_COMPLEXITY;
301 enc->inband_fec = DEFAULT_INBAND_FEC;
302 enc->dtx = DEFAULT_DTX;
303 enc->packet_loss_percentage = DEFAULT_PACKET_LOSS_PERCENT;
305 /* arrange granulepos marking (and required perfect ts) */
306 gst_audio_encoder_set_mark_granule (benc, TRUE);
307 gst_audio_encoder_set_perfect_timestamp (benc, TRUE);
311 gst_opus_enc_start (GstAudioEncoder * benc)
313 GstOpusEnc *enc = GST_OPUS_ENC (benc);
315 GST_DEBUG_OBJECT (enc, "start");
316 enc->tags = gst_tag_list_new ();
317 enc->header_sent = FALSE;
322 gst_opus_enc_stop (GstAudioEncoder * benc)
324 GstOpusEnc *enc = GST_OPUS_ENC (benc);
326 GST_DEBUG_OBJECT (enc, "stop");
327 enc->header_sent = FALSE;
329 opus_encoder_destroy (enc->state);
332 gst_tag_list_free (enc->tags);
334 g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
336 gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
342 gst_opus_enc_get_latency (GstOpusEnc * enc)
344 gint64 latency = gst_util_uint64_scale (enc->frame_samples, GST_SECOND,
346 GST_DEBUG_OBJECT (enc, "Latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
351 gst_opus_enc_get_frame_samples (GstOpusEnc * enc)
353 gint frame_samples = 0;
354 switch (enc->frame_size) {
356 frame_samples = enc->sample_rate / 400;
359 frame_samples = enc->sample_rate / 200;
362 frame_samples = enc->sample_rate / 100;
365 frame_samples = enc->sample_rate / 50;
368 frame_samples = enc->sample_rate / 25;
371 frame_samples = 3 * enc->sample_rate / 50;
374 GST_WARNING_OBJECT (enc, "Unsupported frame size: %d", enc->frame_size);
378 return frame_samples;
382 gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
386 enc = GST_OPUS_ENC (benc);
388 enc->n_channels = GST_AUDIO_INFO_CHANNELS (info);
389 enc->sample_rate = GST_AUDIO_INFO_RATE (info);
390 GST_DEBUG_OBJECT (benc, "Setup with %d channels, %d Hz", enc->n_channels,
393 /* handle reconfigure */
395 opus_encoder_destroy (enc->state);
398 if (!gst_opus_enc_setup (enc))
401 enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
403 /* feedback to base class */
404 gst_audio_encoder_set_latency (benc,
405 gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
406 gst_audio_encoder_set_frame_samples_min (benc,
407 enc->frame_samples * enc->n_channels * 2);
408 gst_audio_encoder_set_frame_samples_max (benc,
409 enc->frame_samples * enc->n_channels * 2);
410 gst_audio_encoder_set_frame_max (benc, 0);
416 gst_opus_enc_setup (GstOpusEnc * enc)
420 GST_DEBUG_OBJECT (enc, "setup");
424 enc->state = opus_encoder_create (enc->sample_rate, enc->n_channels,
425 enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP,
427 if (!enc->state || error != OPUS_OK)
428 goto encoder_creation_failed;
430 opus_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
431 opus_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth), 0);
432 opus_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0);
433 opus_encoder_ctl (enc->state, OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr),
435 opus_encoder_ctl (enc->state, OPUS_SET_COMPLEXITY (enc->complexity), 0);
436 opus_encoder_ctl (enc->state, OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
437 opus_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
438 opus_encoder_ctl (enc->state,
439 OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0);
441 GST_LOG_OBJECT (enc, "we have frame size %d", enc->frame_size);
447 encoder_creation_failed:
448 GST_ERROR_OBJECT (enc, "Encoder creation failed");
453 gst_opus_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
457 enc = GST_OPUS_ENC (benc);
459 GST_DEBUG_OBJECT (enc, "sink event: %s", GST_EVENT_TYPE_NAME (event));
460 switch (GST_EVENT_TYPE (event)) {
464 GstTagSetter *setter = GST_TAG_SETTER (enc);
465 const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
467 gst_event_parse_tag (event, &list);
468 gst_tag_setter_merge_tags (setter, list, mode);
479 gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
481 guint8 *bdata, *data, *mdata = NULL;
483 gsize bytes = enc->frame_samples * enc->n_channels * 2;
484 gsize bytes_per_packet =
485 (enc->bitrate * enc->frame_samples / enc->sample_rate + 4) / 8;
486 gint ret = GST_FLOW_OK;
488 if (G_LIKELY (buf)) {
489 bdata = GST_BUFFER_DATA (buf);
490 bsize = GST_BUFFER_SIZE (buf);
491 if (G_UNLIKELY (bsize % bytes)) {
492 GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
494 size = ((bsize / bytes) + 1) * bytes;
495 mdata = g_malloc0 (size);
496 memcpy (mdata, bdata, bsize);
504 GST_DEBUG_OBJECT (enc, "nothing to drain");
513 ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
514 GST_BUFFER_OFFSET_NONE, bytes_per_packet,
515 GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
517 if (GST_FLOW_OK != ret)
520 GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes) to %d bytes",
521 enc->frame_samples, bytes, bytes_per_packet);
524 opus_encode (enc->state, (const gint16 *) data, enc->frame_samples,
525 GST_BUFFER_DATA (outbuf), bytes_per_packet);
528 GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize);
529 ret = GST_FLOW_ERROR;
531 } else if (outsize > bytes_per_packet) {
532 GST_WARNING_OBJECT (enc,
533 "Encoded size %d is different from %d bytes per packet", outsize,
535 ret = GST_FLOW_ERROR;
539 GST_BUFFER_SIZE (outbuf) = outsize;
542 gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
545 if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
561 gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
564 GstFlowReturn ret = GST_FLOW_OK;
566 enc = GST_OPUS_ENC (benc);
567 GST_DEBUG_OBJECT (enc, "handle_frame");
569 if (!enc->header_sent) {
572 g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
575 gst_opus_header_create_caps (&caps, &enc->headers, enc->n_channels,
576 enc->sample_rate, gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc)));
579 /* negotiate with these caps */
580 GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
582 gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
584 enc->header_sent = TRUE;
587 GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
588 buf ? GST_BUFFER_SIZE (buf) : 0);
590 ret = gst_opus_enc_encode (enc, buf);
596 gst_opus_enc_get_property (GObject * object, guint prop_id, GValue * value,
601 enc = GST_OPUS_ENC (object);
605 g_value_set_boolean (value, enc->audio_or_voip);
608 g_value_set_int (value, enc->bitrate);
611 g_value_set_enum (value, enc->bandwidth);
613 case PROP_FRAME_SIZE:
614 g_value_set_enum (value, enc->frame_size);
617 g_value_set_boolean (value, enc->cbr);
619 case PROP_CONSTRAINED_VBR:
620 g_value_set_boolean (value, enc->constrained_vbr);
622 case PROP_COMPLEXITY:
623 g_value_set_int (value, enc->complexity);
625 case PROP_INBAND_FEC:
626 g_value_set_boolean (value, enc->inband_fec);
629 g_value_set_boolean (value, enc->dtx);
631 case PROP_PACKET_LOSS_PERCENT:
632 g_value_set_int (value, enc->packet_loss_percentage);
635 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
641 gst_opus_enc_set_property (GObject * object, guint prop_id,
642 const GValue * value, GParamSpec * pspec)
646 enc = GST_OPUS_ENC (object);
650 enc->audio_or_voip = g_value_get_boolean (value);
653 enc->bitrate = g_value_get_int (value);
656 enc->bandwidth = g_value_get_enum (value);
658 case PROP_FRAME_SIZE:
659 enc->frame_size = g_value_get_enum (value);
662 enc->cbr = g_value_get_boolean (value);
664 case PROP_CONSTRAINED_VBR:
665 enc->constrained_vbr = g_value_get_boolean (value);
667 case PROP_COMPLEXITY:
668 enc->complexity = g_value_get_int (value);
670 case PROP_INBAND_FEC:
671 enc->inband_fec = g_value_get_boolean (value);
674 enc->dtx = g_value_get_boolean (value);
676 case PROP_PACKET_LOSS_PERCENT:
677 enc->packet_loss_percentage = g_value_get_int (value);
680 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);