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>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Based on the speexenc element
26 * SECTION:element-opusenc
27 * @see_also: opusdec, oggmux
29 * This element encodes raw audio to OPUS.
32 * <title>Example pipelines</title>
34 * gst-launch -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! opusenc ! oggmux ! filesink location=sine.ogg
35 * ]| Encode a test sine signal to Ogg/OPUS.
46 #include <opus/opus.h>
48 #include <gst/gsttagsetter.h>
49 #include <gst/tag/tag.h>
50 #include <gst/audio/audio.h>
51 #include "gstopusenc.h"
53 GST_DEBUG_CATEGORY_STATIC (opusenc_debug);
54 #define GST_CAT_DEFAULT opusenc_debug
56 #define GST_OPUS_ENC_TYPE_BANDWIDTH (gst_opus_enc_bandwidth_get_type())
58 gst_opus_enc_bandwidth_get_type (void)
60 static const GEnumValue values[] = {
61 {OPUS_BANDWIDTH_NARROWBAND, "Narrow band", "narrowband"},
62 {OPUS_BANDWIDTH_MEDIUMBAND, "Medium band", "mediumband"},
63 {OPUS_BANDWIDTH_WIDEBAND, "Wide band", "wideband"},
64 {OPUS_BANDWIDTH_SUPERWIDEBAND, "Super wide band", "superwideband"},
65 {OPUS_BANDWIDTH_FULLBAND, "Full band", "fullband"},
66 {OPUS_AUTO, "Auto", "auto"},
69 static volatile GType id = 0;
71 if (g_once_init_enter ((gsize *) & id)) {
74 _id = g_enum_register_static ("GstOpusEncBandwidth", values);
76 g_once_init_leave ((gsize *) & id, _id);
82 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
85 GST_STATIC_CAPS ("audio/x-raw-int, "
86 "rate = (int) { 8000, 12000, 16000, 24000, 48000 }, "
87 "channels = (int) [ 1, 2 ], "
88 "endianness = (int) BYTE_ORDER, "
89 "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16")
92 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
95 GST_STATIC_CAPS ("audio/x-opus, "
96 "rate = (int) { 8000, 12000, 16000, 24000, 48000 }, "
97 "channels = (int) [ 1, 2 ], " "frame-size = (int) [ 2, 60 ]")
100 #define DEFAULT_AUDIO TRUE
101 #define DEFAULT_BITRATE 64000
102 #define DEFAULT_BANDWIDTH OPUS_BANDWIDTH_FULLBAND
103 #define DEFAULT_FRAMESIZE 20
104 #define DEFAULT_CBR TRUE
105 #define DEFAULT_CONSTRAINED_VBR TRUE
106 #define DEFAULT_COMPLEXITY 10
107 #define DEFAULT_INBAND_FEC FALSE
108 #define DEFAULT_DTX FALSE
109 #define DEFAULT_PACKET_LOSS_PERCENT 0
119 PROP_CONSTRAINED_VBR,
123 PROP_PACKET_LOSS_PERCENT
126 static void gst_opus_enc_finalize (GObject * object);
128 static gboolean gst_opus_enc_sinkevent (GstPad * pad, GstEvent * event);
129 static GstFlowReturn gst_opus_enc_chain (GstPad * pad, GstBuffer * buf);
130 static gboolean gst_opus_enc_setup (GstOpusEnc * enc);
132 static void gst_opus_enc_get_property (GObject * object, guint prop_id,
133 GValue * value, GParamSpec * pspec);
134 static void gst_opus_enc_set_property (GObject * object, guint prop_id,
135 const GValue * value, GParamSpec * pspec);
136 static GstStateChangeReturn gst_opus_enc_change_state (GstElement * element,
137 GstStateChange transition);
139 static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, gboolean flush);
142 gst_opus_enc_setup_interfaces (GType opusenc_type)
144 static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
145 const GInterfaceInfo preset_interface_info = {
146 NULL, /* interface_init */
147 NULL, /* interface_finalize */
148 NULL /* interface_data */
151 g_type_add_interface_static (opusenc_type, GST_TYPE_TAG_SETTER,
153 g_type_add_interface_static (opusenc_type, GST_TYPE_PRESET,
154 &preset_interface_info);
156 GST_DEBUG_CATEGORY_INIT (opusenc_debug, "opusenc", 0, "Opus encoder");
159 GST_BOILERPLATE_FULL (GstOpusEnc, gst_opus_enc, GstElement, GST_TYPE_ELEMENT,
160 gst_opus_enc_setup_interfaces);
163 gst_opus_enc_base_init (gpointer g_class)
165 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
167 gst_element_class_add_pad_template (element_class,
168 gst_static_pad_template_get (&src_factory));
169 gst_element_class_add_pad_template (element_class,
170 gst_static_pad_template_get (&sink_factory));
171 gst_element_class_set_details_simple (element_class, "Opus audio encoder",
172 "Codec/Encoder/Audio",
173 "Encodes audio in Opus format",
174 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
178 gst_opus_enc_class_init (GstOpusEncClass * klass)
180 GObjectClass *gobject_class;
181 GstElementClass *gstelement_class;
183 gobject_class = (GObjectClass *) klass;
184 gstelement_class = (GstElementClass *) klass;
186 gobject_class->set_property = gst_opus_enc_set_property;
187 gobject_class->get_property = gst_opus_enc_get_property;
189 g_object_class_install_property (gobject_class, PROP_AUDIO,
190 g_param_spec_boolean ("audio", "Audio or voice",
191 "Audio or voice", DEFAULT_AUDIO,
192 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
193 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BITRATE,
194 g_param_spec_int ("bitrate", "Encoding Bit-rate",
195 "Specify an encoding bit-rate (in bps).",
196 1, 320000, DEFAULT_BITRATE,
197 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198 g_object_class_install_property (gobject_class, PROP_BANDWIDTH,
199 g_param_spec_enum ("bandwidth", "Band Width",
200 "Audio Band Width", GST_OPUS_ENC_TYPE_BANDWIDTH, DEFAULT_BANDWIDTH,
201 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
202 g_object_class_install_property (gobject_class, PROP_FRAME_SIZE,
203 g_param_spec_int ("frame-size", "Frame Size",
204 "The duration of an audio frame, in ms", 2, 60, DEFAULT_FRAMESIZE,
205 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
206 g_object_class_install_property (gobject_class, PROP_CBR,
207 g_param_spec_boolean ("cbr", "Constant bit rate",
208 "Constant bit rate", DEFAULT_CBR,
209 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
210 g_object_class_install_property (gobject_class, PROP_CONSTRAINED_VBR,
211 g_param_spec_boolean ("constrained-cbr", "Constrained VBR",
212 "Constrained VBR", DEFAULT_CONSTRAINED_VBR,
213 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
214 g_object_class_install_property (gobject_class, PROP_COMPLEXITY,
215 g_param_spec_int ("complexity", "Complexity",
216 "Complexity", 0, 10, DEFAULT_COMPLEXITY,
217 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
218 g_object_class_install_property (gobject_class, PROP_INBAND_FEC,
219 g_param_spec_boolean ("inband-fec", "In-band FEC",
220 "Enable forward error correction", DEFAULT_INBAND_FEC,
221 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
222 g_object_class_install_property (gobject_class, PROP_DTX,
223 g_param_spec_boolean ("dtx", "DTX",
224 "DTX", DEFAULT_DTX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
225 g_object_class_install_property (G_OBJECT_CLASS (klass),
226 PROP_PACKET_LOSS_PERCENT, g_param_spec_int ("packet-loss-percentage",
227 "Loss percentage", "Packet loss percentage", 0, 100,
228 DEFAULT_PACKET_LOSS_PERCENT,
229 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
231 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_opus_enc_finalize);
233 gstelement_class->change_state =
234 GST_DEBUG_FUNCPTR (gst_opus_enc_change_state);
238 gst_opus_enc_finalize (GObject * object)
242 enc = GST_OPUS_ENC (object);
244 g_object_unref (enc->adapter);
246 G_OBJECT_CLASS (parent_class)->finalize (object);
250 gst_opus_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
253 GstStructure *structure;
254 GstCaps *otherpadcaps;
256 enc = GST_OPUS_ENC (GST_PAD_PARENT (pad));
258 enc->frame_size = DEFAULT_FRAMESIZE;
259 otherpadcaps = gst_pad_get_allowed_caps (pad);
261 structure = gst_caps_get_structure (caps, 0);
262 gst_structure_get_int (structure, "channels", &enc->n_channels);
263 gst_structure_get_int (structure, "rate", &enc->sample_rate);
266 if (!gst_caps_is_empty (otherpadcaps)) {
267 GstStructure *ps = gst_caps_get_structure (otherpadcaps, 0);
268 gst_structure_get_int (ps, "frame-size", &enc->frame_size);
270 gst_caps_unref (otherpadcaps);
273 GST_ERROR_OBJECT (pad, "channels=%d rate=%d frame-size=%d",
274 enc->n_channels, enc->sample_rate, enc->frame_size);
275 switch (enc->frame_size) {
277 enc->frame_samples = enc->sample_rate / 400;
280 enc->frame_samples = enc->sample_rate / 200;
283 enc->frame_samples = enc->sample_rate / 100;
286 enc->frame_samples = enc->sample_rate / 50;
289 enc->frame_samples = enc->sample_rate / 20;
292 enc->frame_samples = 3 * enc->sample_rate / 50;
298 GST_ERROR ("frame_samples %d", enc->frame_samples);
300 gst_opus_enc_setup (enc);
307 gst_opus_enc_sink_getcaps (GstPad * pad)
309 GstCaps *caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
310 GstCaps *peercaps = NULL;
311 GstOpusEnc *enc = GST_OPUS_ENC (gst_pad_get_parent_element (pad));
313 peercaps = gst_pad_peer_get_caps (enc->srcpad);
316 if (!gst_caps_is_empty (peercaps) && !gst_caps_is_any (peercaps)) {
317 GstStructure *ps = gst_caps_get_structure (peercaps, 0);
318 GstStructure *s = gst_caps_get_structure (caps, 0);
321 if (gst_structure_get_int (ps, "rate", &rate)) {
322 gst_structure_fixate_field_nearest_int (s, "rate", rate);
325 if (gst_structure_get_int (ps, "channels", &channels)) {
326 gst_structure_fixate_field_nearest_int (s, "channels", channels);
329 gst_caps_unref (peercaps);
332 gst_object_unref (enc);
339 gst_opus_enc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
340 GstFormat * dest_format, gint64 * dest_value)
346 enc = GST_OPUS_ENC (GST_PAD_PARENT (pad));
348 if (enc->samples_in == 0 || enc->bytes_out == 0 || enc->sample_rate == 0)
351 avg = (enc->bytes_out * enc->sample_rate) / (enc->samples_in);
353 switch (src_format) {
354 case GST_FORMAT_BYTES:
355 switch (*dest_format) {
356 case GST_FORMAT_TIME:
357 *dest_value = src_value * GST_SECOND / avg;
363 case GST_FORMAT_TIME:
364 switch (*dest_format) {
365 case GST_FORMAT_BYTES:
366 *dest_value = src_value * avg / GST_SECOND;
379 gst_opus_enc_convert_sink (GstPad * pad, GstFormat src_format,
380 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
384 gint bytes_per_sample;
387 enc = GST_OPUS_ENC (GST_PAD_PARENT (pad));
389 bytes_per_sample = enc->n_channels * 2;
391 switch (src_format) {
392 case GST_FORMAT_BYTES:
393 switch (*dest_format) {
394 case GST_FORMAT_DEFAULT:
395 if (bytes_per_sample == 0)
397 *dest_value = src_value / bytes_per_sample;
399 case GST_FORMAT_TIME:
401 gint byterate = bytes_per_sample * enc->sample_rate;
405 *dest_value = src_value * GST_SECOND / byterate;
412 case GST_FORMAT_DEFAULT:
413 switch (*dest_format) {
414 case GST_FORMAT_BYTES:
415 *dest_value = src_value * bytes_per_sample;
417 case GST_FORMAT_TIME:
418 if (enc->sample_rate == 0)
420 *dest_value = src_value * GST_SECOND / enc->sample_rate;
426 case GST_FORMAT_TIME:
427 switch (*dest_format) {
428 case GST_FORMAT_BYTES:
429 scale = bytes_per_sample;
431 case GST_FORMAT_DEFAULT:
432 *dest_value = src_value * scale * enc->sample_rate / GST_SECOND;
445 gst_opus_enc_get_latency (GstOpusEnc * enc)
447 return gst_util_uint64_scale (enc->frame_samples, GST_SECOND,
451 static const GstQueryType *
452 gst_opus_enc_get_query_types (GstPad * pad)
454 static const GstQueryType gst_opus_enc_src_query_types[] = {
462 return gst_opus_enc_src_query_types;
466 gst_opus_enc_src_query (GstPad * pad, GstQuery * query)
471 enc = GST_OPUS_ENC (gst_pad_get_parent (pad));
473 switch (GST_QUERY_TYPE (query)) {
474 case GST_QUERY_POSITION:
476 GstFormat fmt, req_fmt;
479 gst_query_parse_position (query, &req_fmt, NULL);
480 if ((res = gst_pad_query_peer_position (enc->sinkpad, &req_fmt, &val))) {
481 gst_query_set_position (query, req_fmt, val);
485 fmt = GST_FORMAT_TIME;
486 if (!(res = gst_pad_query_peer_position (enc->sinkpad, &fmt, &pos)))
490 gst_pad_query_peer_convert (enc->sinkpad, fmt, pos, &req_fmt,
492 gst_query_set_position (query, req_fmt, val);
496 case GST_QUERY_DURATION:
498 GstFormat fmt, req_fmt;
501 gst_query_parse_duration (query, &req_fmt, NULL);
502 if ((res = gst_pad_query_peer_duration (enc->sinkpad, &req_fmt, &val))) {
503 gst_query_set_duration (query, req_fmt, val);
507 fmt = GST_FORMAT_TIME;
508 if (!(res = gst_pad_query_peer_duration (enc->sinkpad, &fmt, &dur)))
512 gst_pad_query_peer_convert (enc->sinkpad, fmt, dur, &req_fmt,
514 gst_query_set_duration (query, req_fmt, val);
518 case GST_QUERY_CONVERT:
520 GstFormat src_fmt, dest_fmt;
521 gint64 src_val, dest_val;
523 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
524 if (!(res = gst_opus_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
527 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
530 case GST_QUERY_LATENCY:
533 GstClockTime min_latency, max_latency;
536 if ((res = gst_pad_peer_query (pad, query))) {
537 gst_query_parse_latency (query, &live, &min_latency, &max_latency);
539 latency = gst_opus_enc_get_latency (enc);
541 /* add our latency */
542 min_latency += latency;
543 if (max_latency != -1)
544 max_latency += latency;
546 gst_query_set_latency (query, live, min_latency, max_latency);
551 res = gst_pad_peer_query (pad, query);
557 gst_object_unref (enc);
563 gst_opus_enc_sink_query (GstPad * pad, GstQuery * query)
567 switch (GST_QUERY_TYPE (query)) {
568 case GST_QUERY_CONVERT:
570 GstFormat src_fmt, dest_fmt;
571 gint64 src_val, dest_val;
573 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
575 gst_opus_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
578 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
582 res = gst_pad_query_default (pad, query);
591 gst_opus_enc_init (GstOpusEnc * enc, GstOpusEncClass * klass)
593 enc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
594 gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
595 gst_pad_set_event_function (enc->sinkpad,
596 GST_DEBUG_FUNCPTR (gst_opus_enc_sinkevent));
597 gst_pad_set_chain_function (enc->sinkpad,
598 GST_DEBUG_FUNCPTR (gst_opus_enc_chain));
599 gst_pad_set_setcaps_function (enc->sinkpad,
600 GST_DEBUG_FUNCPTR (gst_opus_enc_sink_setcaps));
601 gst_pad_set_getcaps_function (enc->sinkpad,
602 GST_DEBUG_FUNCPTR (gst_opus_enc_sink_getcaps));
603 gst_pad_set_query_function (enc->sinkpad,
604 GST_DEBUG_FUNCPTR (gst_opus_enc_sink_query));
606 enc->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
607 gst_pad_set_query_function (enc->srcpad,
608 GST_DEBUG_FUNCPTR (gst_opus_enc_src_query));
609 gst_pad_set_query_type_function (enc->srcpad,
610 GST_DEBUG_FUNCPTR (gst_opus_enc_get_query_types));
611 gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
613 enc->n_channels = -1;
614 enc->sample_rate = -1;
615 enc->frame_samples = 0;
617 enc->bitrate = DEFAULT_BITRATE;
618 enc->bandwidth = DEFAULT_BANDWIDTH;
619 enc->frame_size = DEFAULT_FRAMESIZE;
620 enc->cbr = DEFAULT_CBR;
621 enc->constrained_vbr = DEFAULT_CONSTRAINED_VBR;
622 enc->complexity = DEFAULT_COMPLEXITY;
623 enc->inband_fec = DEFAULT_INBAND_FEC;
624 enc->dtx = DEFAULT_DTX;
625 enc->packet_loss_percentage = DEFAULT_PACKET_LOSS_PERCENT;
628 enc->header_sent = FALSE;
630 enc->adapter = gst_adapter_new ();
635 gst_opus_enc_create_metadata_buffer (GstOpusEnc * enc)
637 const GstTagList *tags;
638 GstTagList *empty_tags = NULL;
639 GstBuffer *comments = NULL;
641 tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
643 GST_DEBUG_OBJECT (enc, "tags = %" GST_PTR_FORMAT, tags);
646 /* FIXME: better fix chain of callers to not write metadata at all,
647 * if there is none */
648 empty_tags = gst_tag_list_new ();
651 comments = gst_tag_list_to_vorbiscomment_buffer (tags, NULL,
652 0, "Encoded with GStreamer Opusenc");
654 GST_BUFFER_OFFSET (comments) = enc->bytes_out;
655 GST_BUFFER_OFFSET_END (comments) = 0;
658 gst_tag_list_free (empty_tags);
665 gst_opus_enc_setup (GstOpusEnc * enc)
671 enc->state = opus_encoder_create (enc->sample_rate, enc->n_channels,
672 enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP,
674 if (!enc->state || error != OPUS_OK)
675 goto encoder_creation_failed;
677 opus_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
678 opus_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth), 0);
679 opus_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0);
680 opus_encoder_ctl (enc->state, OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr),
682 opus_encoder_ctl (enc->state, OPUS_SET_COMPLEXITY (enc->complexity), 0);
683 opus_encoder_ctl (enc->state, OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
684 opus_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
685 opus_encoder_ctl (enc->state,
686 OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0);
688 GST_LOG_OBJECT (enc, "we have frame size %d", enc->frame_size);
695 mode_initialization_failed:
696 GST_ERROR_OBJECT (enc, "Mode initialization failed: %d", error);
700 encoder_creation_failed:
701 GST_ERROR_OBJECT (enc, "Encoder creation failed");
706 /* push out the buffer and do internal bookkeeping */
708 gst_opus_enc_push_buffer (GstOpusEnc * enc, GstBuffer * buffer)
712 size = GST_BUFFER_SIZE (buffer);
714 enc->bytes_out += size;
716 GST_DEBUG_OBJECT (enc, "pushing output buffer of size %u", size);
718 return gst_pad_push (enc->srcpad, buffer);
723 gst_opus_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
726 GstStructure *structure = NULL;
728 GValue array = { 0 };
729 GValue value = { 0 };
731 caps = gst_caps_make_writable (caps);
732 structure = gst_caps_get_structure (caps, 0);
734 g_assert (gst_buffer_is_metadata_writable (buf1));
735 g_assert (gst_buffer_is_metadata_writable (buf2));
738 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
739 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
741 /* put buffers in a fixed list */
742 g_value_init (&array, GST_TYPE_ARRAY);
743 g_value_init (&value, GST_TYPE_BUFFER);
744 buf = gst_buffer_copy (buf1);
745 gst_value_set_buffer (&value, buf);
746 gst_buffer_unref (buf);
747 gst_value_array_append_value (&array, &value);
748 g_value_unset (&value);
749 g_value_init (&value, GST_TYPE_BUFFER);
750 buf = gst_buffer_copy (buf2);
751 gst_value_set_buffer (&value, buf);
752 gst_buffer_unref (buf);
753 gst_value_array_append_value (&array, &value);
754 gst_structure_set_value (structure, "streamheader", &array);
755 g_value_unset (&value);
756 g_value_unset (&array);
764 gst_opus_enc_sinkevent (GstPad * pad, GstEvent * event)
769 enc = GST_OPUS_ENC (gst_pad_get_parent (pad));
771 switch (GST_EVENT_TYPE (event)) {
773 gst_opus_enc_encode (enc, TRUE);
774 res = gst_pad_event_default (pad, event);
779 GstTagSetter *setter = GST_TAG_SETTER (enc);
780 const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);
782 gst_event_parse_tag (event, &list);
783 gst_tag_setter_merge_tags (setter, list, mode);
784 res = gst_pad_event_default (pad, event);
788 res = gst_pad_event_default (pad, event);
792 gst_object_unref (enc);
798 gst_opus_enc_encode (GstOpusEnc * enc, gboolean flush)
801 GstFlowReturn ret = GST_FLOW_OK;
802 gint bytes = enc->frame_samples * 2 * enc->n_channels;
803 gint bytes_per_packet;
806 (enc->bitrate * enc->frame_samples / enc->sample_rate + 4) / 8;
808 if (flush && gst_adapter_available (enc->adapter) % bytes != 0) {
809 guint diff = gst_adapter_available (enc->adapter) % bytes;
810 GstBuffer *buf = gst_buffer_new_and_alloc (diff);
812 memset (GST_BUFFER_DATA (buf), 0, diff);
813 gst_adapter_push (enc->adapter, buf);
817 while (gst_adapter_available (enc->adapter) >= bytes) {
822 ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
823 GST_BUFFER_OFFSET_NONE, bytes_per_packet, GST_PAD_CAPS (enc->srcpad),
826 if (GST_FLOW_OK != ret)
829 data = (gint16 *) gst_adapter_take (enc->adapter, bytes);
830 enc->samples_in += enc->frame_samples;
832 GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
833 enc->frame_samples, bytes);
835 outsize = opus_encode (enc->state, data, enc->frame_samples,
836 GST_BUFFER_DATA (outbuf), bytes_per_packet);
841 GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize);
842 ret = GST_FLOW_ERROR;
846 GST_BUFFER_TIMESTAMP (outbuf) = enc->start_ts +
847 gst_util_uint64_scale_int (enc->frameno_out * enc->frame_samples,
848 GST_SECOND, enc->sample_rate);
849 GST_BUFFER_DURATION (outbuf) =
850 gst_util_uint64_scale_int (enc->frame_samples, GST_SECOND,
852 GST_BUFFER_OFFSET (outbuf) =
853 gst_util_uint64_scale_int (GST_BUFFER_OFFSET_END (outbuf), GST_SECOND,
859 ret = gst_opus_enc_push_buffer (enc, outbuf);
861 if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
871 gst_opus_enc_chain (GstPad * pad, GstBuffer * buf)
874 GstFlowReturn ret = GST_FLOW_OK;
876 enc = GST_OPUS_ENC (GST_PAD_PARENT (pad));
882 if (!enc->header_sent) {
883 /* Opus streams begin with two headers; the initial header (with
884 most of the codec setup parameters) which is mandated by the Ogg
885 bitstream spec. The second header holds any comment fields.
886 We merely need to make the headers, then pass them to libopus
887 one at a time; libopus handles the additional Ogg bitstream
889 GstBuffer *buf1, *buf2;
893 /* create header buffer */
894 opus_header_to_packet (&enc->header, data, 100);
895 buf1 = gst_opus_enc_buffer_from_data (enc, data, 100, 0);
897 /* create comment buffer */
898 buf2 = gst_opus_enc_create_metadata_buffer (enc);
900 /* mark and put on caps */
901 caps = gst_pad_get_caps (enc->srcpad);
902 caps = gst_opus_enc_set_header_on_caps (caps, buf1, buf2);
904 gst_caps_set_simple (caps,
905 "rate", G_TYPE_INT, enc->sample_rate,
906 "channels", G_TYPE_INT, enc->n_channels,
907 "frame-size", G_TYPE_INT, enc->frame_size, NULL);
909 /* negotiate with these caps */
910 GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
911 GST_LOG_OBJECT (enc, "rate=%d channels=%d frame-size=%d",
912 enc->sample_rate, enc->n_channels, enc->frame_size);
913 gst_pad_set_caps (enc->srcpad, caps);
915 gst_buffer_set_caps (buf1, caps);
916 gst_buffer_set_caps (buf2, caps);
917 gst_caps_unref (caps);
919 /* push out buffers */
920 ret = gst_opus_enc_push_buffer (enc, buf1);
922 if (ret != GST_FLOW_OK) {
923 gst_buffer_unref (buf2);
927 ret = gst_opus_enc_push_buffer (enc, buf2);
929 if (ret != GST_FLOW_OK)
932 enc->header_sent = TRUE;
936 GST_DEBUG_OBJECT (enc, "received buffer of %u bytes", GST_BUFFER_SIZE (buf));
938 /* Save the timestamp of the first buffer. This will be later
939 * used as offset for all following buffers */
940 if (enc->start_ts == GST_CLOCK_TIME_NONE) {
941 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
942 enc->start_ts = GST_BUFFER_TIMESTAMP (buf);
949 /* Check if we have a continous stream, if not drop some samples or the buffer or
950 * insert some silence samples */
951 if (enc->next_ts != GST_CLOCK_TIME_NONE &&
952 GST_BUFFER_TIMESTAMP (buf) < enc->next_ts) {
953 guint64 diff = enc->next_ts - GST_BUFFER_TIMESTAMP (buf);
956 GST_WARNING_OBJECT (enc, "Buffer is older than previous "
957 "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
958 "), cannot handle. Clipping buffer.",
959 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
960 GST_TIME_ARGS (enc->next_ts));
963 GST_CLOCK_TIME_TO_FRAMES (diff, enc->sample_rate) * enc->n_channels * 2;
964 if (diff_bytes >= GST_BUFFER_SIZE (buf)) {
965 gst_buffer_unref (buf);
968 buf = gst_buffer_make_metadata_writable (buf);
969 GST_BUFFER_DATA (buf) += diff_bytes;
970 GST_BUFFER_SIZE (buf) -= diff_bytes;
972 GST_BUFFER_TIMESTAMP (buf) += diff;
973 if (GST_BUFFER_DURATION_IS_VALID (buf))
974 GST_BUFFER_DURATION (buf) -= diff;
977 if (enc->next_ts != GST_CLOCK_TIME_NONE
978 && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
980 gst_util_uint64_scale (enc->frame_size, GST_SECOND, enc->sample_rate);
982 if (GST_BUFFER_TIMESTAMP (buf) != enc->next_ts &&
983 GST_BUFFER_TIMESTAMP (buf) - enc->next_ts > max_diff) {
984 GST_WARNING_OBJECT (enc,
985 "Discontinuity detected: %" G_GUINT64_FORMAT " > %" G_GUINT64_FORMAT,
986 GST_BUFFER_TIMESTAMP (buf) - enc->next_ts, max_diff);
988 gst_opus_enc_encode (enc, TRUE);
990 enc->frameno_out = 0;
991 enc->start_ts = GST_BUFFER_TIMESTAMP (buf);
995 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)
996 && GST_BUFFER_DURATION_IS_VALID (buf))
997 enc->next_ts = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
999 enc->next_ts = GST_CLOCK_TIME_NONE;
1001 /* push buffer to adapter */
1002 gst_adapter_push (enc->adapter, buf);
1005 ret = gst_opus_enc_encode (enc, FALSE);
1010 gst_buffer_unref (buf);
1017 GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL),
1018 ("encoder not initialized (input is not audio?)"));
1019 ret = GST_FLOW_NOT_NEGOTIATED;
1027 gst_opus_enc_get_property (GObject * object, guint prop_id, GValue * value,
1032 enc = GST_OPUS_ENC (object);
1036 g_value_set_boolean (value, enc->audio_or_voip);
1039 g_value_set_int (value, enc->bitrate);
1041 case PROP_BANDWIDTH:
1042 g_value_set_int (value, enc->bandwidth);
1044 case PROP_FRAME_SIZE:
1045 g_value_set_int (value, enc->frame_size);
1048 g_value_set_boolean (value, enc->cbr);
1050 case PROP_CONSTRAINED_VBR:
1051 g_value_set_boolean (value, enc->constrained_vbr);
1053 case PROP_COMPLEXITY:
1054 g_value_set_int (value, enc->complexity);
1056 case PROP_INBAND_FEC:
1057 g_value_set_boolean (value, enc->inband_fec);
1060 g_value_set_boolean (value, enc->dtx);
1062 case PROP_PACKET_LOSS_PERCENT:
1063 g_value_set_int (value, enc->packet_loss_percentage);
1066 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1072 gst_opus_enc_set_property (GObject * object, guint prop_id,
1073 const GValue * value, GParamSpec * pspec)
1077 enc = GST_OPUS_ENC (object);
1081 enc->audio_or_voip = g_value_get_boolean (value);
1084 enc->bitrate = g_value_get_int (value);
1086 case PROP_BANDWIDTH:
1087 enc->bandwidth = g_value_get_int (value);
1089 case PROP_FRAME_SIZE:
1090 enc->frame_size = g_value_get_int (value);
1093 enc->cbr = g_value_get_boolean (value);
1095 case PROP_CONSTRAINED_VBR:
1096 enc->constrained_vbr = g_value_get_boolean (value);
1098 case PROP_COMPLEXITY:
1099 enc->complexity = g_value_get_int (value);
1101 case PROP_INBAND_FEC:
1102 enc->inband_fec = g_value_get_boolean (value);
1105 enc->dtx = g_value_get_boolean (value);
1107 case PROP_PACKET_LOSS_PERCENT:
1108 enc->packet_loss_percentage = g_value_get_int (value);
1111 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1116 static GstStateChangeReturn
1117 gst_opus_enc_change_state (GstElement * element, GstStateChange transition)
1119 GstOpusEnc *enc = GST_OPUS_ENC (element);
1120 GstStateChangeReturn res;
1122 switch (transition) {
1123 case GST_STATE_CHANGE_NULL_TO_READY:
1125 case GST_STATE_CHANGE_READY_TO_PAUSED:
1127 enc->samples_in = 0;
1128 enc->frameno_out = 0;
1129 enc->start_ts = GST_CLOCK_TIME_NONE;
1130 enc->next_ts = GST_CLOCK_TIME_NONE;
1132 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1138 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1139 if (res == GST_STATE_CHANGE_FAILURE)
1142 switch (transition) {
1143 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1145 case GST_STATE_CHANGE_PAUSED_TO_READY:
1147 enc->header_sent = FALSE;
1149 opus_encoder_destroy (enc->state);
1153 case GST_STATE_CHANGE_READY_TO_NULL:
1154 gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));