1 /* GStreamer Speex Encoder
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 * SECTION:element-speexenc
22 * @see_also: speexdec, oggmux
24 * This element encodes audio as a Speex stream.
25 * <ulink url="http://www.speex.org/">Speex</ulink> is a royalty-free
26 * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
30 * <title>Example pipelines</title>
32 * gst-launch-1.0 audiotestsrc num-buffers=100 ! speexenc ! oggmux ! filesink location=beep.ogg
33 * ]| Encode an Ogg/Speex file.
44 #include <speex/speex.h>
45 #include <speex/speex_stereo.h>
47 #include <gst/gsttagsetter.h>
48 #include <gst/tag/tag.h>
49 #include <gst/audio/audio.h>
50 #include "gstspeexenc.h"
52 GST_DEBUG_CATEGORY_STATIC (speexenc_debug);
53 #define GST_CAT_DEFAULT speexenc_debug
55 #define FORMAT_STR GST_AUDIO_NE(S16)
57 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
60 GST_STATIC_CAPS ("audio/x-raw, "
61 "format = (string) " FORMAT_STR ", "
62 "layout = (string) interleaved, "
63 "rate = (int) [ 6000, 48000 ], "
64 "channels = (int) 1; "
66 "format = (string) " FORMAT_STR ", "
67 "layout = (string) interleaved, "
68 "rate = (int) [ 6000, 48000 ], "
69 "channels = (int) 2, " "channel-mask = (bitmask) 0x3")
72 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
75 GST_STATIC_CAPS ("audio/x-speex, "
76 "rate = (int) [ 6000, 48000 ], " "channels = (int) [ 1, 2]")
79 #define DEFAULT_QUALITY 8.0
80 #define DEFAULT_BITRATE 0
81 #define DEFAULT_MODE GST_SPEEX_ENC_MODE_AUTO
82 #define DEFAULT_VBR FALSE
84 #define DEFAULT_VAD FALSE
85 #define DEFAULT_DTX FALSE
86 #define DEFAULT_COMPLEXITY 3
87 #define DEFAULT_NFRAMES 1
104 #define GST_TYPE_SPEEX_ENC_MODE (gst_speex_enc_mode_get_type())
106 gst_speex_enc_mode_get_type (void)
108 static GType speex_enc_mode_type = 0;
109 static const GEnumValue speex_enc_modes[] = {
110 {GST_SPEEX_ENC_MODE_AUTO, "Auto", "auto"},
111 {GST_SPEEX_ENC_MODE_UWB, "Ultra Wide Band", "uwb"},
112 {GST_SPEEX_ENC_MODE_WB, "Wide Band", "wb"},
113 {GST_SPEEX_ENC_MODE_NB, "Narrow Band", "nb"},
116 if (G_UNLIKELY (speex_enc_mode_type == 0)) {
117 speex_enc_mode_type = g_enum_register_static ("GstSpeexEncMode",
120 return speex_enc_mode_type;
123 static void gst_speex_enc_finalize (GObject * object);
125 static gboolean gst_speex_enc_setup (GstSpeexEnc * enc);
127 static void gst_speex_enc_get_property (GObject * object, guint prop_id,
128 GValue * value, GParamSpec * pspec);
129 static void gst_speex_enc_set_property (GObject * object, guint prop_id,
130 const GValue * value, GParamSpec * pspec);
132 static GstFlowReturn gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf);
134 static gboolean gst_speex_enc_start (GstAudioEncoder * enc);
135 static gboolean gst_speex_enc_stop (GstAudioEncoder * enc);
136 static gboolean gst_speex_enc_set_format (GstAudioEncoder * enc,
137 GstAudioInfo * info);
138 static GstFlowReturn gst_speex_enc_handle_frame (GstAudioEncoder * enc,
140 static gboolean gst_speex_enc_sink_event (GstAudioEncoder * enc,
143 #define gst_speex_enc_parent_class parent_class
144 G_DEFINE_TYPE_WITH_CODE (GstSpeexEnc, gst_speex_enc, GST_TYPE_AUDIO_ENCODER,
145 G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
146 G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
149 gst_speex_enc_class_init (GstSpeexEncClass * klass)
151 GObjectClass *gobject_class;
152 GstElementClass *gstelement_class;
153 GstAudioEncoderClass *base_class;
155 gobject_class = (GObjectClass *) klass;
156 gstelement_class = (GstElementClass *) klass;
157 base_class = (GstAudioEncoderClass *) klass;
159 gobject_class->finalize = gst_speex_enc_finalize;
160 gobject_class->set_property = gst_speex_enc_set_property;
161 gobject_class->get_property = gst_speex_enc_get_property;
163 base_class->start = GST_DEBUG_FUNCPTR (gst_speex_enc_start);
164 base_class->stop = GST_DEBUG_FUNCPTR (gst_speex_enc_stop);
165 base_class->set_format = GST_DEBUG_FUNCPTR (gst_speex_enc_set_format);
166 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_speex_enc_handle_frame);
167 base_class->sink_event = GST_DEBUG_FUNCPTR (gst_speex_enc_sink_event);
169 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_QUALITY,
170 g_param_spec_float ("quality", "Quality", "Encoding quality",
171 0.0, 10.0, DEFAULT_QUALITY,
172 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
173 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BITRATE,
174 g_param_spec_int ("bitrate", "Encoding Bit-rate",
175 "Specify an encoding bit-rate (in bps). (0 = automatic)",
176 0, G_MAXINT, DEFAULT_BITRATE,
177 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
178 g_object_class_install_property (gobject_class, PROP_MODE,
179 g_param_spec_enum ("mode", "Mode", "The encoding mode",
180 GST_TYPE_SPEEX_ENC_MODE, GST_SPEEX_ENC_MODE_AUTO,
181 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
182 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VBR,
183 g_param_spec_boolean ("vbr", "VBR",
184 "Enable variable bit-rate", DEFAULT_VBR,
185 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
186 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ABR,
187 g_param_spec_int ("abr", "ABR",
188 "Enable average bit-rate (0 = disabled)",
189 0, G_MAXINT, DEFAULT_ABR,
190 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
191 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VAD,
192 g_param_spec_boolean ("vad", "VAD",
193 "Enable voice activity detection", DEFAULT_VAD,
194 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
195 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DTX,
196 g_param_spec_boolean ("dtx", "DTX",
197 "Enable discontinuous transmission", DEFAULT_DTX,
198 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
199 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLEXITY,
200 g_param_spec_int ("complexity", "Complexity",
201 "Set encoding complexity",
202 0, G_MAXINT, DEFAULT_COMPLEXITY,
203 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
204 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NFRAMES,
205 g_param_spec_int ("nframes", "NFrames",
206 "Number of frames per buffer",
207 0, G_MAXINT, DEFAULT_NFRAMES,
208 G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
209 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
210 g_param_spec_string ("last-message", "last-message",
211 "The last status message", NULL,
212 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
214 gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
215 gst_element_class_add_static_pad_template (gstelement_class, &sink_factory);
216 gst_element_class_set_static_metadata (gstelement_class,
217 "Speex audio encoder", "Codec/Encoder/Audio",
218 "Encodes audio in Speex format", "Wim Taymans <wim@fluendo.com>");
220 GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
224 gst_speex_enc_finalize (GObject * object)
228 enc = GST_SPEEX_ENC (object);
230 g_free (enc->last_message);
232 G_OBJECT_CLASS (parent_class)->finalize (object);
236 gst_speex_enc_init (GstSpeexEnc * enc)
238 GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
240 /* arrange granulepos marking (and required perfect ts) */
241 gst_audio_encoder_set_mark_granule (benc, TRUE);
242 gst_audio_encoder_set_perfect_timestamp (benc, TRUE);
243 GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (enc));
247 gst_speex_enc_start (GstAudioEncoder * benc)
249 GstSpeexEnc *enc = GST_SPEEX_ENC (benc);
251 GST_DEBUG_OBJECT (enc, "start");
252 speex_bits_init (&enc->bits);
253 enc->tags = gst_tag_list_new_empty ();
254 enc->header_sent = FALSE;
255 enc->encoded_samples = 0;
261 gst_speex_enc_stop (GstAudioEncoder * benc)
263 GstSpeexEnc *enc = GST_SPEEX_ENC (benc);
265 GST_DEBUG_OBJECT (enc, "stop");
266 enc->header_sent = FALSE;
268 speex_encoder_destroy (enc->state);
271 speex_bits_destroy (&enc->bits);
272 speex_bits_set_bit_buffer (&enc->bits, NULL, 0);
273 gst_tag_list_unref (enc->tags);
276 gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
282 gst_speex_enc_get_latency (GstSpeexEnc * enc)
284 /* See the Speex manual section "Latency and algorithmic delay" */
285 if (enc->rate == 8000)
286 return 30 * GST_MSECOND;
288 return 34 * GST_MSECOND;
292 gst_speex_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
296 enc = GST_SPEEX_ENC (benc);
298 enc->channels = GST_AUDIO_INFO_CHANNELS (info);
299 enc->rate = GST_AUDIO_INFO_RATE (info);
301 /* handle reconfigure */
303 speex_encoder_destroy (enc->state);
307 if (!gst_speex_enc_setup (enc))
310 /* feedback to base class */
311 gst_audio_encoder_set_latency (benc,
312 gst_speex_enc_get_latency (enc), gst_speex_enc_get_latency (enc));
313 gst_audio_encoder_set_lookahead (benc, enc->lookahead);
315 if (enc->nframes == 0) {
316 /* as many frames as available input allows */
317 gst_audio_encoder_set_frame_samples_min (benc, enc->frame_size);
318 gst_audio_encoder_set_frame_samples_max (benc, enc->frame_size);
319 gst_audio_encoder_set_frame_max (benc, 0);
321 /* exactly as many frames as configured */
322 gst_audio_encoder_set_frame_samples_min (benc,
323 enc->frame_size * enc->nframes);
324 gst_audio_encoder_set_frame_samples_max (benc,
325 enc->frame_size * enc->nframes);
326 gst_audio_encoder_set_frame_max (benc, 1);
333 gst_speex_enc_create_metadata_buffer (GstSpeexEnc * enc)
335 const GstTagList *user_tags;
336 GstTagList *merged_tags;
337 GstBuffer *comments = NULL;
339 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
341 GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
342 GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
344 /* gst_tag_list_merge() will handle NULL for either or both lists fine */
345 merged_tags = gst_tag_list_merge (user_tags, enc->tags,
346 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
348 if (merged_tags == NULL)
349 merged_tags = gst_tag_list_new_empty ();
351 GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
352 comments = gst_tag_list_to_vorbiscomment_buffer (merged_tags, NULL,
353 0, "Encoded with GStreamer Speexenc");
354 gst_tag_list_unref (merged_tags);
356 GST_BUFFER_OFFSET (comments) = 0;
357 GST_BUFFER_OFFSET_END (comments) = 0;
363 gst_speex_enc_set_last_msg (GstSpeexEnc * enc, const gchar * msg)
365 g_free (enc->last_message);
366 enc->last_message = g_strdup (msg);
367 GST_WARNING_OBJECT (enc, "%s", msg);
368 g_object_notify (G_OBJECT (enc), "last-message");
372 gst_speex_enc_setup (GstSpeexEnc * enc)
375 case GST_SPEEX_ENC_MODE_UWB:
376 GST_LOG_OBJECT (enc, "configuring for requested UWB mode");
377 enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_UWB);
379 case GST_SPEEX_ENC_MODE_WB:
380 GST_LOG_OBJECT (enc, "configuring for requested WB mode");
381 enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_WB);
383 case GST_SPEEX_ENC_MODE_NB:
384 GST_LOG_OBJECT (enc, "configuring for requested NB mode");
385 enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_NB);
387 case GST_SPEEX_ENC_MODE_AUTO:
389 GST_LOG_OBJECT (enc, "finding best mode");
394 if (enc->rate > 25000) {
395 if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
396 GST_LOG_OBJECT (enc, "selected UWB mode for samplerate %d", enc->rate);
397 enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_UWB);
399 if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_UWB)) {
400 gst_speex_enc_set_last_msg (enc,
401 "Warning: suggest to use ultra wide band mode for this rate");
404 } else if (enc->rate > 12500) {
405 if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
406 GST_LOG_OBJECT (enc, "selected WB mode for samplerate %d", enc->rate);
407 enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_WB);
409 if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_WB)) {
410 gst_speex_enc_set_last_msg (enc,
411 "Warning: suggest to use wide band mode for this rate");
415 if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
416 GST_LOG_OBJECT (enc, "selected NB mode for samplerate %d", enc->rate);
417 enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_NB);
419 if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_NB)) {
420 gst_speex_enc_set_last_msg (enc,
421 "Warning: suggest to use narrow band mode for this rate");
426 if (enc->rate != 8000 && enc->rate != 16000 && enc->rate != 32000) {
427 gst_speex_enc_set_last_msg (enc,
428 "Warning: speex is optimized for 8, 16 and 32 KHz");
431 speex_init_header (&enc->header, enc->rate, 1, enc->speex_mode);
432 enc->header.frames_per_packet = enc->nframes;
433 enc->header.vbr = enc->vbr;
434 enc->header.nb_channels = enc->channels;
436 /*Initialize Speex encoder */
437 enc->state = speex_encoder_init (enc->speex_mode);
439 speex_encoder_ctl (enc->state, SPEEX_GET_FRAME_SIZE, &enc->frame_size);
440 speex_encoder_ctl (enc->state, SPEEX_SET_COMPLEXITY, &enc->complexity);
441 speex_encoder_ctl (enc->state, SPEEX_SET_SAMPLING_RATE, &enc->rate);
444 speex_encoder_ctl (enc->state, SPEEX_SET_VBR_QUALITY, &enc->quality);
446 gint tmp = floor (enc->quality);
448 speex_encoder_ctl (enc->state, SPEEX_SET_QUALITY, &tmp);
451 if (enc->quality >= 0.0 && enc->vbr) {
452 gst_speex_enc_set_last_msg (enc,
453 "Warning: bitrate option is overriding quality");
455 speex_encoder_ctl (enc->state, SPEEX_SET_BITRATE, &enc->bitrate);
460 speex_encoder_ctl (enc->state, SPEEX_SET_VBR, &tmp);
461 } else if (enc->vad) {
464 speex_encoder_ctl (enc->state, SPEEX_SET_VAD, &tmp);
470 speex_encoder_ctl (enc->state, SPEEX_SET_DTX, &tmp);
473 if (enc->dtx && !(enc->vbr || enc->abr || enc->vad)) {
474 gst_speex_enc_set_last_msg (enc,
475 "Warning: dtx is useless without vad, vbr or abr");
476 } else if ((enc->vbr || enc->abr) && (enc->vad)) {
477 gst_speex_enc_set_last_msg (enc,
478 "Warning: vad is already implied by vbr or abr");
482 speex_encoder_ctl (enc->state, SPEEX_SET_ABR, &enc->abr);
485 speex_encoder_ctl (enc->state, SPEEX_GET_LOOKAHEAD, &enc->lookahead);
487 GST_LOG_OBJECT (enc, "we have frame size %d, lookahead %d", enc->frame_size,
494 gst_speex_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
498 enc = GST_SPEEX_ENC (benc);
500 switch (GST_EVENT_TYPE (event)) {
506 gst_event_parse_tag (event, &list);
507 gst_tag_list_insert (enc->tags, list,
508 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
510 g_assert_not_reached ();
514 case GST_EVENT_SEGMENT:
515 enc->encoded_samples = 0;
521 /* we only peeked, let base class handle it */
522 return GST_AUDIO_ENCODER_CLASS (parent_class)->sink_event (benc, event);
526 gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
528 gint frame_size = enc->frame_size;
529 gint bytes = frame_size * 2 * enc->channels, samples;
530 gint outsize, written, dtx_ret = 0;
532 guint8 *data, *data0 = NULL, *bdata;
535 GstFlowReturn ret = GST_FLOW_OK;
537 GstClockTime duration;
539 if (G_LIKELY (buf)) {
540 gst_buffer_map (buf, &map, GST_MAP_READ);
544 if (G_UNLIKELY (bsize % bytes)) {
545 GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
547 /* If encoding part of a frame, and we have no set stop time on
548 * the output segment, we update the segment stop time to reflect
549 * the last sample. This will let oggmux set the last page's
550 * granpos to tell a decoder the dummy samples should be clipped.
552 segment = &GST_AUDIO_ENCODER_OUTPUT_SEGMENT (enc);
553 GST_DEBUG_OBJECT (enc, "existing output segment %" GST_SEGMENT_FORMAT,
555 if (!GST_CLOCK_TIME_IS_VALID (segment->stop)) {
556 int input_samples = bsize / (enc->channels * 2);
557 GST_DEBUG_OBJECT (enc,
558 "No stop time and partial frame, updating segment");
560 gst_util_uint64_scale (enc->encoded_samples + input_samples,
561 GST_SECOND, enc->rate);
562 segment->stop = segment->start + duration;
563 GST_DEBUG_OBJECT (enc, "new output segment %" GST_SEGMENT_FORMAT,
565 gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (enc),
566 gst_event_new_segment (segment));
569 size = ((bsize / bytes) + 1) * bytes;
570 data0 = data = g_malloc0 (size);
571 memcpy (data, bdata, bsize);
572 gst_buffer_unmap (buf, &map);
579 GST_DEBUG_OBJECT (enc, "nothing to drain");
583 samples = size / (2 * enc->channels);
584 speex_bits_reset (&enc->bits);
586 /* FIXME what about dropped samples if DTS enabled ?? */
589 GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes);
591 if (enc->channels == 2) {
592 speex_encode_stereo_int ((gint16 *) data, frame_size, &enc->bits);
594 dtx_ret += speex_encode_int (enc->state, (gint16 *) data, &enc->bits);
600 speex_bits_insert_terminator (&enc->bits);
601 outsize = speex_bits_nbytes (&enc->bits);
604 gst_buffer_unmap (buf, &map);
607 ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
608 GST_BUFFER_OFFSET_NONE, outsize,
609 GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
611 if ((GST_FLOW_OK != ret))
614 outbuf = gst_buffer_new_allocate (NULL, outsize, NULL);
615 gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
617 written = speex_bits_write (&enc->bits, (gchar *) map.data, outsize);
619 if (G_UNLIKELY (written < outsize)) {
620 GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize);
621 } else if (G_UNLIKELY (written > outsize)) {
622 GST_ERROR_OBJECT (enc, "overrun: %d > %d bytes", written, outsize);
625 gst_buffer_unmap (outbuf, &map);
626 gst_buffer_resize (outbuf, 0, written);
629 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
631 ret = gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc),
633 enc->encoded_samples += frame_size;
641 * (really really) FIXME: move into core (dixit tpm)
644 * _gst_caps_set_buffer_array:
645 * @caps: (transfer full): a #GstCaps
646 * @field: field in caps to set
647 * @buf: header buffers
649 * Adds given buffers to an array of buffers set as the given @field
650 * on the given @caps. List of buffer arguments must be NULL-terminated.
652 * Returns: (transfer full): input caps with a streamheader field added, or NULL
653 * if some error occurred
656 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
657 GstBuffer * buf, ...)
659 GstStructure *structure = NULL;
661 GValue array = { 0 };
662 GValue value = { 0 };
664 g_return_val_if_fail (caps != NULL, NULL);
665 g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
666 g_return_val_if_fail (field != NULL, NULL);
668 caps = gst_caps_make_writable (caps);
669 structure = gst_caps_get_structure (caps, 0);
671 g_value_init (&array, GST_TYPE_ARRAY);
674 /* put buffers in a fixed list */
676 g_assert (gst_buffer_is_writable (buf));
679 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
681 g_value_init (&value, GST_TYPE_BUFFER);
682 buf = gst_buffer_copy (buf);
683 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
684 gst_value_set_buffer (&value, buf);
685 gst_buffer_unref (buf);
686 gst_value_array_append_value (&array, &value);
687 g_value_unset (&value);
689 buf = va_arg (va, GstBuffer *);
693 gst_structure_set_value (structure, field, &array);
694 g_value_unset (&array);
700 gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
703 GstFlowReturn ret = GST_FLOW_OK;
705 enc = GST_SPEEX_ENC (benc);
707 if (!enc->header_sent) {
708 /* Speex streams begin with two headers; the initial header (with
709 most of the codec setup parameters) which is mandated by the Ogg
710 bitstream spec. The second header holds any comment fields.
711 We merely need to make the headers, then pass them to libspeex
712 one at a time; libspeex handles the additional Ogg bitstream
714 GstBuffer *buf1, *buf2;
720 /* create header buffer */
721 data = (guint8 *) speex_header_to_packet (&enc->header, &data_len);
722 buf1 = gst_buffer_new_wrapped (data, data_len);
723 GST_BUFFER_OFFSET_END (buf1) = 0;
724 GST_BUFFER_OFFSET (buf1) = 0;
726 /* create comment buffer */
727 buf2 = gst_speex_enc_create_metadata_buffer (enc);
729 /* mark and put on caps */
730 caps = gst_caps_new_simple ("audio/x-speex", "rate", G_TYPE_INT, enc->rate,
731 "channels", G_TYPE_INT, enc->channels, NULL);
732 caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL);
734 /* negotiate with these caps */
735 GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
737 gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (enc), caps);
738 gst_caps_unref (caps);
740 /* push out buffers */
741 /* store buffers for later pre_push sending */
743 GST_DEBUG_OBJECT (enc, "storing header buffers");
744 headers = g_list_prepend (headers, buf2);
745 headers = g_list_prepend (headers, buf1);
746 gst_audio_encoder_set_headers (benc, headers);
748 enc->header_sent = TRUE;
751 GST_DEBUG_OBJECT (enc, "received buffer %p of %" G_GSIZE_FORMAT " bytes", buf,
752 buf ? gst_buffer_get_size (buf) : 0);
754 ret = gst_speex_enc_encode (enc, buf);
760 gst_speex_enc_get_property (GObject * object, guint prop_id, GValue * value,
765 enc = GST_SPEEX_ENC (object);
769 g_value_set_float (value, enc->quality);
772 g_value_set_int (value, enc->bitrate);
775 g_value_set_enum (value, enc->mode);
778 g_value_set_boolean (value, enc->vbr);
781 g_value_set_int (value, enc->abr);
784 g_value_set_boolean (value, enc->vad);
787 g_value_set_boolean (value, enc->dtx);
789 case PROP_COMPLEXITY:
790 g_value_set_int (value, enc->complexity);
793 g_value_set_int (value, enc->nframes);
795 case PROP_LAST_MESSAGE:
796 g_value_set_string (value, enc->last_message);
799 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
805 gst_speex_enc_set_property (GObject * object, guint prop_id,
806 const GValue * value, GParamSpec * pspec)
810 enc = GST_SPEEX_ENC (object);
814 enc->quality = g_value_get_float (value);
817 enc->bitrate = g_value_get_int (value);
820 enc->mode = g_value_get_enum (value);
823 enc->vbr = g_value_get_boolean (value);
826 enc->abr = g_value_get_int (value);
829 enc->vad = g_value_get_boolean (value);
832 enc->dtx = g_value_get_boolean (value);
834 case PROP_COMPLEXITY:
835 enc->complexity = g_value_get_int (value);
838 enc->nframes = g_value_get_int (value);
841 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);