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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
28 #include <speex/speex.h>
29 #include <speex/speex_stereo.h>
31 #include <gst/gsttagsetter.h>
32 #include <gst/tag/tag.h>
33 #include "gstspeexenc.h"
35 GST_DEBUG_CATEGORY_STATIC (speexenc_debug);
36 #define GST_CAT_DEFAULT speexenc_debug
38 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
41 GST_STATIC_CAPS ("audio/x-raw-int, "
42 "rate = (int) [ 6000, 48000 ], "
43 "channels = (int) [ 1, 2 ], "
44 "endianness = (int) BYTE_ORDER, "
45 "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16")
48 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
51 GST_STATIC_CAPS ("audio/x-speex")
54 static const GstElementDetails speexenc_details =
55 GST_ELEMENT_DETAILS ("Speex audio encoder",
56 "Codec/Encoder/Audio",
57 "Encodes audio in Speex format",
58 "Wim Taymans <wim@fluendo.com>");
60 #define DEFAULT_QUALITY 8.0
61 #define DEFAULT_BITRATE 0
62 #define DEFAULT_VBR FALSE
64 #define DEFAULT_VAD FALSE
65 #define DEFAULT_DTX FALSE
66 #define DEFAULT_COMPLEXITY 3
67 #define DEFAULT_NFRAMES 1
84 static const GstFormat *
85 gst_speexenc_get_formats (GstPad * pad)
87 static const GstFormat src_formats[] = {
92 static const GstFormat sink_formats[] = {
99 return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
103 static void gst_speexenc_base_init (gpointer g_class);
104 static void gst_speexenc_class_init (GstSpeexEncClass * klass);
105 static void gst_speexenc_init (GstSpeexEnc * speexenc);
106 static void gst_speexenc_finalize (GObject * object);
108 static gboolean gst_speexenc_sinkevent (GstPad * pad, GstEvent * event);
109 static GstFlowReturn gst_speexenc_chain (GstPad * pad, GstBuffer * buf);
110 static gboolean gst_speexenc_setup (GstSpeexEnc * speexenc);
112 static void gst_speexenc_get_property (GObject * object, guint prop_id,
113 GValue * value, GParamSpec * pspec);
114 static void gst_speexenc_set_property (GObject * object, guint prop_id,
115 const GValue * value, GParamSpec * pspec);
116 static GstStateChangeReturn gst_speexenc_change_state (GstElement * element,
117 GstStateChange transition);
119 static GstElementClass *parent_class = NULL;
122 gst_speexenc_get_type (void)
124 static GType speexenc_type = 0;
126 if (!speexenc_type) {
127 static const GTypeInfo speexenc_info = {
128 sizeof (GstSpeexEncClass),
129 gst_speexenc_base_init,
131 (GClassInitFunc) gst_speexenc_class_init,
134 sizeof (GstSpeexEnc),
136 (GInstanceInitFunc) gst_speexenc_init,
138 static const GInterfaceInfo tag_setter_info = {
145 g_type_register_static (GST_TYPE_ELEMENT, "GstSpeexEnc", &speexenc_info,
148 g_type_add_interface_static (speexenc_type, GST_TYPE_TAG_SETTER,
151 GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
153 return speexenc_type;
157 gst_speexenc_base_init (gpointer g_class)
159 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
161 gst_element_class_add_pad_template (element_class,
162 gst_static_pad_template_get (&src_factory));
163 gst_element_class_add_pad_template (element_class,
164 gst_static_pad_template_get (&sink_factory));
165 gst_element_class_set_details (element_class, &speexenc_details);
169 gst_speexenc_class_init (GstSpeexEncClass * klass)
171 GObjectClass *gobject_class;
172 GstElementClass *gstelement_class;
174 gobject_class = (GObjectClass *) klass;
175 gstelement_class = (GstElementClass *) klass;
177 gobject_class->set_property = gst_speexenc_set_property;
178 gobject_class->get_property = gst_speexenc_get_property;
180 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
181 g_param_spec_float ("quality", "Quality", "Encoding quality",
182 0.0, 10.0, DEFAULT_QUALITY, G_PARAM_READWRITE));
183 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
184 g_param_spec_int ("bitrate", "Encoding Bit-rate",
185 "Specify an encoding bit-rate (in bps). (0 = automatic)",
186 0, G_MAXINT, DEFAULT_BITRATE, G_PARAM_READWRITE));
187 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
188 g_param_spec_boolean ("vbr", "VBR",
189 "Enable variable bit-rate", DEFAULT_VBR, G_PARAM_READWRITE));
190 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ABR,
191 g_param_spec_int ("abr", "ABR",
192 "Enable average bit-rate (0 = disabled)",
193 0, G_MAXINT, DEFAULT_ABR, G_PARAM_READWRITE));
194 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VAD,
195 g_param_spec_boolean ("vad", "VAD",
196 "Enable voice activity detection", DEFAULT_VAD, G_PARAM_READWRITE));
197 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DTX,
198 g_param_spec_boolean ("dtx", "DTX",
199 "Enable discontinuous transmission", DEFAULT_DTX, G_PARAM_READWRITE));
200 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COMPLEXITY,
201 g_param_spec_int ("complexity", "Complexity",
202 "Set encoding complexity",
203 0, G_MAXINT, DEFAULT_COMPLEXITY, G_PARAM_READWRITE));
204 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NFRAMES,
205 g_param_spec_int ("nframes", "NFrames",
206 "Number of frames per buffer",
207 0, G_MAXINT, DEFAULT_NFRAMES, G_PARAM_READWRITE));
208 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
209 g_param_spec_string ("last-message", "last-message",
210 "The last status message", NULL, G_PARAM_READABLE));
212 parent_class = g_type_class_peek_parent (klass);
214 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_speexenc_finalize);
216 gstelement_class->change_state =
217 GST_DEBUG_FUNCPTR (gst_speexenc_change_state);
221 gst_speexenc_finalize (GObject * object)
223 GstSpeexEnc *speexenc;
225 speexenc = GST_SPEEXENC (object);
227 g_object_unref (speexenc->adapter);
229 G_OBJECT_CLASS (parent_class)->finalize (object);
233 gst_speexenc_sink_setcaps (GstPad * pad, GstCaps * caps)
235 GstSpeexEnc *speexenc;
236 GstStructure *structure;
238 speexenc = GST_SPEEXENC (gst_pad_get_parent (pad));
239 speexenc->setup = FALSE;
241 structure = gst_caps_get_structure (caps, 0);
242 gst_structure_get_int (structure, "channels", &speexenc->channels);
243 gst_structure_get_int (structure, "rate", &speexenc->rate);
245 gst_speexenc_setup (speexenc);
247 gst_object_unref (speexenc);
249 return speexenc->setup;
253 gst_speexenc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
254 GstFormat * dest_format, gint64 * dest_value)
257 GstSpeexEnc *speexenc;
260 speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
262 if (speexenc->samples_in == 0 ||
263 speexenc->bytes_out == 0 || speexenc->rate == 0)
266 avg = (speexenc->bytes_out * speexenc->rate) / (speexenc->samples_in);
268 switch (src_format) {
269 case GST_FORMAT_BYTES:
270 switch (*dest_format) {
271 case GST_FORMAT_TIME:
272 *dest_value = src_value * GST_SECOND / avg;
278 case GST_FORMAT_TIME:
279 switch (*dest_format) {
280 case GST_FORMAT_BYTES:
281 *dest_value = src_value * avg / GST_SECOND;
294 gst_speexenc_convert_sink (GstPad * pad, GstFormat src_format,
295 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
299 gint bytes_per_sample;
300 GstSpeexEnc *speexenc;
302 speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
304 bytes_per_sample = speexenc->channels * 2;
306 switch (src_format) {
307 case GST_FORMAT_BYTES:
308 switch (*dest_format) {
309 case GST_FORMAT_DEFAULT:
310 if (bytes_per_sample == 0)
312 *dest_value = src_value / bytes_per_sample;
314 case GST_FORMAT_TIME:
316 gint byterate = bytes_per_sample * speexenc->rate;
320 *dest_value = src_value * GST_SECOND / byterate;
327 case GST_FORMAT_DEFAULT:
328 switch (*dest_format) {
329 case GST_FORMAT_BYTES:
330 *dest_value = src_value * bytes_per_sample;
332 case GST_FORMAT_TIME:
333 if (speexenc->rate == 0)
335 *dest_value = src_value * GST_SECOND / speexenc->rate;
341 case GST_FORMAT_TIME:
342 switch (*dest_format) {
343 case GST_FORMAT_BYTES:
344 scale = bytes_per_sample;
346 case GST_FORMAT_DEFAULT:
347 *dest_value = src_value * scale * speexenc->rate / GST_SECOND;
359 static const GstQueryType *
360 gst_speexenc_get_query_types (GstPad * pad)
362 static const GstQueryType gst_speexenc_src_query_types[] = {
369 return gst_speexenc_src_query_types;
373 gst_speexenc_src_query (GstPad * pad, GstQuery * query)
376 GstSpeexEnc *speexenc;
379 speexenc = GST_SPEEXENC (gst_pad_get_parent (pad));
380 peerpad = gst_pad_get_peer (GST_PAD (speexenc->sinkpad));
382 switch (GST_QUERY_TYPE (query)) {
383 case GST_QUERY_POSITION:
385 GstFormat fmt, req_fmt;
388 gst_query_parse_position (query, &req_fmt, NULL);
389 if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
390 gst_query_set_position (query, req_fmt, val);
394 fmt = GST_FORMAT_TIME;
395 if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
398 if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val)))
399 gst_query_set_position (query, req_fmt, val);
403 case GST_QUERY_DURATION:
405 GstFormat fmt, req_fmt;
408 gst_query_parse_duration (query, &req_fmt, NULL);
409 if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
410 gst_query_set_duration (query, req_fmt, val);
414 fmt = GST_FORMAT_TIME;
415 if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
418 if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
419 gst_query_set_duration (query, req_fmt, val);
423 case GST_QUERY_CONVERT:
425 GstFormat src_fmt, dest_fmt;
426 gint64 src_val, dest_val;
428 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
429 if (!(res = gst_speexenc_convert_src (pad, src_fmt, src_val, &dest_fmt,
432 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
436 res = gst_pad_query_default (pad, query);
441 gst_object_unref (peerpad);
442 gst_object_unref (speexenc);
447 gst_speexenc_sink_query (GstPad * pad, GstQuery * query)
450 GstSpeexEnc *speexenc;
452 speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
454 switch (GST_QUERY_TYPE (query)) {
455 case GST_QUERY_CONVERT:
457 GstFormat src_fmt, dest_fmt;
458 gint64 src_val, dest_val;
460 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
462 gst_speexenc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
465 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
469 res = gst_pad_query_default (pad, query);
478 gst_speexenc_init (GstSpeexEnc * speexenc)
480 speexenc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
481 gst_element_add_pad (GST_ELEMENT (speexenc), speexenc->sinkpad);
482 gst_pad_set_event_function (speexenc->sinkpad,
483 GST_DEBUG_FUNCPTR (gst_speexenc_sinkevent));
484 gst_pad_set_chain_function (speexenc->sinkpad,
485 GST_DEBUG_FUNCPTR (gst_speexenc_chain));
486 gst_pad_set_setcaps_function (speexenc->sinkpad,
487 GST_DEBUG_FUNCPTR (gst_speexenc_sink_setcaps));
488 gst_pad_set_query_function (speexenc->sinkpad,
489 GST_DEBUG_FUNCPTR (gst_speexenc_sink_query));
491 speexenc->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
492 gst_pad_set_query_function (speexenc->srcpad,
493 GST_DEBUG_FUNCPTR (gst_speexenc_src_query));
494 gst_pad_set_query_type_function (speexenc->srcpad,
495 GST_DEBUG_FUNCPTR (gst_speexenc_get_query_types));
496 gst_element_add_pad (GST_ELEMENT (speexenc), speexenc->srcpad);
498 speexenc->channels = -1;
501 speexenc->quality = DEFAULT_QUALITY;
502 speexenc->bitrate = DEFAULT_BITRATE;
503 speexenc->vbr = DEFAULT_VBR;
504 speexenc->abr = DEFAULT_ABR;
505 speexenc->vad = DEFAULT_VAD;
506 speexenc->dtx = DEFAULT_DTX;
507 speexenc->complexity = DEFAULT_COMPLEXITY;
508 speexenc->nframes = DEFAULT_NFRAMES;
510 speexenc->setup = FALSE;
511 speexenc->header_sent = FALSE;
513 speexenc->adapter = gst_adapter_new ();
517 gst_speexenc_create_metadata_buffer (GstSpeexEnc * enc)
519 const GstTagList *user_tags;
520 GstTagList *merged_tags;
521 GstBuffer *comments = NULL;
523 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
525 GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
526 GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
528 /* gst_tag_list_merge() will handle NULL for either or both lists fine */
529 merged_tags = gst_tag_list_merge (user_tags, enc->tags,
530 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
532 if (merged_tags == NULL)
533 merged_tags = gst_tag_list_new ();
535 GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
536 comments = gst_tag_list_to_vorbiscomment_buffer (merged_tags, NULL,
537 0, "Encoded with GStreamer Speexenc");
538 gst_tag_list_free (merged_tags);
540 GST_BUFFER_OFFSET (comments) = enc->bytes_out;
541 GST_BUFFER_OFFSET_END (comments) = 0;
547 gst_speexenc_setup (GstSpeexEnc * speexenc)
549 speexenc->setup = FALSE;
551 switch (speexenc->mode) {
552 case GST_SPEEXENC_MODE_UWB:
553 speexenc->speex_mode = (SpeexMode *) & speex_uwb_mode;
555 case GST_SPEEXENC_MODE_WB:
556 speexenc->speex_mode = (SpeexMode *) & speex_wb_mode;
558 case GST_SPEEXENC_MODE_NB:
559 speexenc->speex_mode = (SpeexMode *) & speex_nb_mode;
561 case GST_SPEEXENC_MODE_AUTO:
567 if (speexenc->rate > 25000) {
568 if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
569 speexenc->speex_mode = (SpeexMode *) & speex_uwb_mode;
571 if (speexenc->speex_mode != &speex_uwb_mode) {
572 speexenc->last_message =
574 ("Warning: suggest to use ultra wide band mode for this rate");
575 g_object_notify (G_OBJECT (speexenc), "last_message");
578 } else if (speexenc->rate > 12500) {
579 if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
580 speexenc->speex_mode = (SpeexMode *) & speex_wb_mode;
582 if (speexenc->speex_mode != &speex_wb_mode) {
583 speexenc->last_message =
585 ("Warning: suggest to use wide band mode for this rate");
586 g_object_notify (G_OBJECT (speexenc), "last_message");
590 if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
591 speexenc->speex_mode = (SpeexMode *) & speex_nb_mode;
593 if (speexenc->speex_mode != &speex_nb_mode) {
594 speexenc->last_message =
596 ("Warning: suggest to use narrow band mode for this rate");
597 g_object_notify (G_OBJECT (speexenc), "last_message");
602 if (speexenc->rate != 8000 && speexenc->rate != 16000
603 && speexenc->rate != 32000) {
604 speexenc->last_message =
605 g_strdup_printf ("Warning: speex is optimized for 8, 16 and 32 KHz");
606 g_object_notify (G_OBJECT (speexenc), "last_message");
609 speex_init_header (&speexenc->header, speexenc->rate, 1,
610 speexenc->speex_mode);
611 speexenc->header.frames_per_packet = speexenc->nframes;
612 speexenc->header.vbr = speexenc->vbr;
613 speexenc->header.nb_channels = speexenc->channels;
615 /*Initialize Speex encoder */
616 speexenc->state = speex_encoder_init (speexenc->speex_mode);
618 speex_encoder_ctl (speexenc->state, SPEEX_GET_FRAME_SIZE,
619 &speexenc->frame_size);
620 speex_encoder_ctl (speexenc->state, SPEEX_SET_COMPLEXITY,
621 &speexenc->complexity);
622 speex_encoder_ctl (speexenc->state, SPEEX_SET_SAMPLING_RATE, &speexenc->rate);
625 speex_encoder_ctl (speexenc->state, SPEEX_SET_VBR_QUALITY,
628 gint tmp = floor (speexenc->quality);
630 speex_encoder_ctl (speexenc->state, SPEEX_SET_QUALITY, &tmp);
632 if (speexenc->bitrate) {
633 if (speexenc->quality >= 0.0 && speexenc->vbr) {
634 speexenc->last_message =
635 g_strdup_printf ("Warning: bitrate option is overriding quality");
636 g_object_notify (G_OBJECT (speexenc), "last_message");
638 speex_encoder_ctl (speexenc->state, SPEEX_SET_BITRATE, &speexenc->bitrate);
643 speex_encoder_ctl (speexenc->state, SPEEX_SET_VBR, &tmp);
644 } else if (speexenc->vad) {
647 speex_encoder_ctl (speexenc->state, SPEEX_SET_VAD, &tmp);
653 speex_encoder_ctl (speexenc->state, SPEEX_SET_DTX, &tmp);
656 if (speexenc->dtx && !(speexenc->vbr || speexenc->abr || speexenc->vad)) {
657 speexenc->last_message =
658 g_strdup_printf ("Warning: dtx is useless without vad, vbr or abr");
659 g_object_notify (G_OBJECT (speexenc), "last_message");
660 } else if ((speexenc->vbr || speexenc->abr) && (speexenc->vad)) {
661 speexenc->last_message =
662 g_strdup_printf ("Warning: vad is already implied by vbr or abr");
663 g_object_notify (G_OBJECT (speexenc), "last_message");
667 speex_encoder_ctl (speexenc->state, SPEEX_SET_ABR, &speexenc->abr);
670 speex_encoder_ctl (speexenc->state, SPEEX_GET_LOOKAHEAD,
671 &speexenc->lookahead);
673 speexenc->setup = TRUE;
678 /* prepare a buffer for transmission */
680 gst_speexenc_buffer_from_data (GstSpeexEnc * speexenc, guchar * data,
681 gint data_len, guint64 granulepos)
685 outbuf = gst_buffer_new_and_alloc (data_len);
686 memcpy (GST_BUFFER_DATA (outbuf), data, data_len);
687 GST_BUFFER_OFFSET (outbuf) = speexenc->bytes_out;
688 GST_BUFFER_OFFSET_END (outbuf) = granulepos;
690 GST_DEBUG ("encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
695 /* push out the buffer and do internal bookkeeping */
697 gst_speexenc_push_buffer (GstSpeexEnc * speexenc, GstBuffer * buffer)
699 speexenc->bytes_out += GST_BUFFER_SIZE (buffer);
701 return gst_pad_push (speexenc->srcpad, buffer);
706 gst_speexenc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
709 GstStructure *structure = NULL;
710 GValue array = { 0 };
711 GValue value = { 0 };
713 caps = gst_caps_make_writable (caps);
714 structure = gst_caps_get_structure (caps, 0);
716 g_assert (gst_buffer_is_metadata_writable (buf1));
717 g_assert (gst_buffer_is_metadata_writable (buf2));
720 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
721 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
723 /* put buffers in a fixed list */
724 g_value_init (&array, GST_TYPE_ARRAY);
725 g_value_init (&value, GST_TYPE_BUFFER);
726 gst_value_set_buffer (&value, buf1);
727 gst_value_array_append_value (&array, &value);
728 g_value_unset (&value);
729 g_value_init (&value, GST_TYPE_BUFFER);
730 gst_value_set_buffer (&value, buf2);
731 gst_value_array_append_value (&array, &value);
732 gst_structure_set_value (structure, "streamheader", &array);
733 g_value_unset (&value);
734 g_value_unset (&array);
741 gst_speexenc_sinkevent (GstPad * pad, GstEvent * event)
744 GstSpeexEnc *speexenc;
746 speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
748 switch (GST_EVENT_TYPE (event)) {
750 speexenc->eos = TRUE;
751 res = gst_pad_event_default (pad, event);
757 gst_event_parse_tag (event, &list);
758 if (speexenc->tags) {
759 gst_tag_list_insert (speexenc->tags, list,
760 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (speexenc)));
762 g_assert_not_reached ();
764 res = gst_pad_event_default (pad, event);
768 res = gst_pad_event_default (pad, event);
776 gst_speexenc_chain (GstPad * pad, GstBuffer * buf)
778 GstSpeexEnc *speexenc;
779 GstFlowReturn ret = GST_FLOW_OK;
781 speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
783 if (!speexenc->setup)
786 if (!speexenc->header_sent) {
787 /* Speex streams begin with two headers; the initial header (with
788 most of the codec setup parameters) which is mandated by the Ogg
789 bitstream spec. The second header holds any comment fields.
790 We merely need to make the headers, then pass them to libspeex
791 one at a time; libspeex handles the additional Ogg bitstream
793 GstBuffer *buf1, *buf2;
798 /* create header buffer */
799 data = (guint8 *) speex_header_to_packet (&speexenc->header, &data_len);
800 buf1 = gst_speexenc_buffer_from_data (speexenc, data, data_len, 0);
803 /* create comment buffer */
804 buf2 = gst_speexenc_create_metadata_buffer (speexenc);
806 /* mark and put on caps */
807 caps = gst_pad_get_caps (speexenc->srcpad);
808 caps = gst_speexenc_set_header_on_caps (caps, buf1, buf2);
810 /* negotiate with these caps */
811 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
812 gst_pad_set_caps (speexenc->srcpad, caps);
814 gst_buffer_set_caps (buf1, caps);
815 gst_buffer_set_caps (buf2, caps);
816 gst_caps_unref (caps);
818 /* push out buffers */
819 ret = gst_speexenc_push_buffer (speexenc, buf1);
821 if (ret != GST_FLOW_OK) {
822 gst_buffer_unref (buf2);
826 ret = gst_speexenc_push_buffer (speexenc, buf2);
828 if (ret != GST_FLOW_OK)
831 speex_bits_reset (&speexenc->bits);
833 speexenc->header_sent = TRUE;
837 gint frame_size = speexenc->frame_size;
838 gint bytes = frame_size * 2 * speexenc->channels;
840 /* push buffer to adapter */
841 gst_adapter_push (speexenc->adapter, buf);
843 while (gst_adapter_available (speexenc->adapter) >= bytes) {
846 gint outsize, written;
849 data = (gint16 *) gst_adapter_peek (speexenc->adapter, bytes);
851 for (i = 0; i < frame_size * speexenc->channels; i++) {
852 speexenc->input[i] = (gfloat) data[i];
854 gst_adapter_flush (speexenc->adapter, bytes);
856 speexenc->samples_in += frame_size;
858 if (speexenc->channels == 2) {
859 speex_encode_stereo (speexenc->input, frame_size, &speexenc->bits);
861 speex_encode (speexenc->state, speexenc->input, &speexenc->bits);
865 if ((speexenc->frameno % speexenc->nframes) != 0)
868 speex_bits_insert_terminator (&speexenc->bits);
869 outsize = speex_bits_nbytes (&speexenc->bits);
871 ret = gst_pad_alloc_buffer_and_set_caps (speexenc->srcpad,
872 GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (speexenc->srcpad),
875 if ((GST_FLOW_OK != ret))
878 written = speex_bits_write (&speexenc->bits,
879 (gchar *) GST_BUFFER_DATA (outbuf), outsize);
880 g_assert (written == outsize);
881 speex_bits_reset (&speexenc->bits);
883 GST_BUFFER_TIMESTAMP (outbuf) =
884 gst_util_uint64_scale_int (speexenc->frameno * frame_size -
885 speexenc->lookahead, GST_SECOND, speexenc->rate);
886 GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (frame_size,
887 GST_SECOND, speexenc->rate);
888 /* set gp time and granulepos; see gst-plugins-base/ext/ogg/README */
889 GST_BUFFER_OFFSET_END (outbuf) =
890 ((speexenc->frameno + 1) * frame_size - speexenc->lookahead);
891 GST_BUFFER_OFFSET (outbuf) =
892 gst_util_uint64_scale_int (GST_BUFFER_OFFSET_END (outbuf), GST_SECOND,
895 ret = gst_speexenc_push_buffer (speexenc, outbuf);
897 if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
908 gst_buffer_unref (buf);
909 GST_ELEMENT_ERROR (speexenc, CORE, NEGOTIATION, (NULL),
910 ("encoder not initialized (input is not audio?)"));
911 ret = GST_FLOW_NOT_NEGOTIATED;
919 gst_speexenc_get_property (GObject * object, guint prop_id, GValue * value,
922 GstSpeexEnc *speexenc;
924 g_return_if_fail (GST_IS_SPEEXENC (object));
926 speexenc = GST_SPEEXENC (object);
930 g_value_set_float (value, speexenc->quality);
933 g_value_set_int (value, speexenc->bitrate);
936 g_value_set_boolean (value, speexenc->vbr);
939 g_value_set_int (value, speexenc->abr);
942 g_value_set_boolean (value, speexenc->vad);
945 g_value_set_boolean (value, speexenc->dtx);
948 g_value_set_int (value, speexenc->complexity);
951 g_value_set_int (value, speexenc->nframes);
953 case ARG_LAST_MESSAGE:
954 g_value_set_string (value, speexenc->last_message);
957 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
963 gst_speexenc_set_property (GObject * object, guint prop_id,
964 const GValue * value, GParamSpec * pspec)
966 GstSpeexEnc *speexenc;
968 g_return_if_fail (GST_IS_SPEEXENC (object));
970 speexenc = GST_SPEEXENC (object);
974 speexenc->quality = g_value_get_float (value);
977 speexenc->bitrate = g_value_get_int (value);
980 speexenc->vbr = g_value_get_boolean (value);
983 speexenc->abr = g_value_get_int (value);
986 speexenc->vad = g_value_get_boolean (value);
989 speexenc->dtx = g_value_get_boolean (value);
992 speexenc->complexity = g_value_get_int (value);
995 speexenc->nframes = g_value_get_int (value);
998 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1003 static GstStateChangeReturn
1004 gst_speexenc_change_state (GstElement * element, GstStateChange transition)
1006 GstSpeexEnc *speexenc = GST_SPEEXENC (element);
1007 GstStateChangeReturn res;
1009 switch (transition) {
1010 case GST_STATE_CHANGE_NULL_TO_READY:
1011 speexenc->tags = gst_tag_list_new ();
1013 case GST_STATE_CHANGE_READY_TO_PAUSED:
1014 speex_bits_init (&speexenc->bits);
1015 speexenc->frameno = 0;
1016 speexenc->samples_in = 0;
1018 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1024 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1026 switch (transition) {
1027 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1029 case GST_STATE_CHANGE_PAUSED_TO_READY:
1030 speexenc->setup = FALSE;
1031 speexenc->header_sent = FALSE;
1032 if (speexenc->state) {
1033 speex_encoder_destroy (speexenc->state);
1034 speexenc->state = NULL;
1036 speex_bits_destroy (&speexenc->bits);
1038 case GST_STATE_CHANGE_READY_TO_NULL:
1039 gst_tag_list_free (speexenc->tags);
1040 speexenc->tags = NULL;