ext/speex/gstspeexenc.c: Add negotiation for the speex channels and rate. Fixes ...
[platform/upstream/gstreamer.git] / ext / speex / gstspeexenc.c
1 /* GStreamer Speex Encoder
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <math.h>
28 #include <speex/speex.h>
29 #include <speex/speex_stereo.h>
30
31 #include <gst/gsttagsetter.h>
32 #include <gst/tag/tag.h>
33 #include "gstspeexenc.h"
34
35 GST_DEBUG_CATEGORY_STATIC (speexenc_debug);
36 #define GST_CAT_DEFAULT speexenc_debug
37
38 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
39     GST_PAD_SINK,
40     GST_PAD_ALWAYS,
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")
46     );
47
48 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
49     GST_PAD_SRC,
50     GST_PAD_ALWAYS,
51     GST_STATIC_CAPS ("audio/x-speex, "
52         "rate = (int) [ 6000, 48000 ], " "channels = (int) [ 1, 2]")
53     );
54
55 static const GstElementDetails speexenc_details =
56 GST_ELEMENT_DETAILS ("Speex audio encoder",
57     "Codec/Encoder/Audio",
58     "Encodes audio in Speex format",
59     "Wim Taymans <wim@fluendo.com>");
60
61 #define DEFAULT_QUALITY         8.0
62 #define DEFAULT_BITRATE         0
63 #define DEFAULT_VBR             FALSE
64 #define DEFAULT_ABR             0
65 #define DEFAULT_VAD             FALSE
66 #define DEFAULT_DTX             FALSE
67 #define DEFAULT_COMPLEXITY      3
68 #define DEFAULT_NFRAMES         1
69
70 enum
71 {
72   ARG_0,
73   ARG_QUALITY,
74   ARG_BITRATE,
75   ARG_VBR,
76   ARG_ABR,
77   ARG_VAD,
78   ARG_DTX,
79   ARG_COMPLEXITY,
80   ARG_NFRAMES,
81   ARG_LAST_MESSAGE
82 };
83
84 #if 0
85 static const GstFormat *
86 gst_speex_enc_get_formats (GstPad * pad)
87 {
88   static const GstFormat src_formats[] = {
89     GST_FORMAT_BYTES,
90     GST_FORMAT_TIME,
91     0
92   };
93   static const GstFormat sink_formats[] = {
94     GST_FORMAT_BYTES,
95     GST_FORMAT_DEFAULT,
96     GST_FORMAT_TIME,
97     0
98   };
99
100   return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
101 }
102 #endif
103
104 static void gst_speex_enc_finalize (GObject * object);
105
106 static gboolean gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event);
107 static GstFlowReturn gst_speex_enc_chain (GstPad * pad, GstBuffer * buf);
108 static gboolean gst_speex_enc_setup (GstSpeexEnc * enc);
109
110 static void gst_speex_enc_get_property (GObject * object, guint prop_id,
111     GValue * value, GParamSpec * pspec);
112 static void gst_speex_enc_set_property (GObject * object, guint prop_id,
113     const GValue * value, GParamSpec * pspec);
114 static GstStateChangeReturn gst_speex_enc_change_state (GstElement * element,
115     GstStateChange transition);
116
117 static void
118 gst_speex_enc_setup_interfaces (GType speexenc_type)
119 {
120   static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
121
122   g_type_add_interface_static (speexenc_type, GST_TYPE_TAG_SETTER,
123       &tag_setter_info);
124
125   GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
126 }
127
128 GST_BOILERPLATE_FULL (GstSpeexEnc, gst_speex_enc, GstElement, GST_TYPE_ELEMENT,
129     gst_speex_enc_setup_interfaces);
130
131 static void
132 gst_speex_enc_base_init (gpointer g_class)
133 {
134   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
135
136   gst_element_class_add_pad_template (element_class,
137       gst_static_pad_template_get (&src_factory));
138   gst_element_class_add_pad_template (element_class,
139       gst_static_pad_template_get (&sink_factory));
140   gst_element_class_set_details (element_class, &speexenc_details);
141 }
142
143 static void
144 gst_speex_enc_class_init (GstSpeexEncClass * klass)
145 {
146   GObjectClass *gobject_class;
147   GstElementClass *gstelement_class;
148
149   gobject_class = (GObjectClass *) klass;
150   gstelement_class = (GstElementClass *) klass;
151
152   gobject_class->set_property = gst_speex_enc_set_property;
153   gobject_class->get_property = gst_speex_enc_get_property;
154
155   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
156       g_param_spec_float ("quality", "Quality", "Encoding quality",
157           0.0, 10.0, DEFAULT_QUALITY, G_PARAM_READWRITE));
158   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
159       g_param_spec_int ("bitrate", "Encoding Bit-rate",
160           "Specify an encoding bit-rate (in bps). (0 = automatic)",
161           0, G_MAXINT, DEFAULT_BITRATE, G_PARAM_READWRITE));
162   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
163       g_param_spec_boolean ("vbr", "VBR",
164           "Enable variable bit-rate", DEFAULT_VBR, G_PARAM_READWRITE));
165   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ABR,
166       g_param_spec_int ("abr", "ABR",
167           "Enable average bit-rate (0 = disabled)",
168           0, G_MAXINT, DEFAULT_ABR, G_PARAM_READWRITE));
169   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VAD,
170       g_param_spec_boolean ("vad", "VAD",
171           "Enable voice activity detection", DEFAULT_VAD, G_PARAM_READWRITE));
172   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DTX,
173       g_param_spec_boolean ("dtx", "DTX",
174           "Enable discontinuous transmission", DEFAULT_DTX, G_PARAM_READWRITE));
175   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COMPLEXITY,
176       g_param_spec_int ("complexity", "Complexity",
177           "Set encoding complexity",
178           0, G_MAXINT, DEFAULT_COMPLEXITY, G_PARAM_READWRITE));
179   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NFRAMES,
180       g_param_spec_int ("nframes", "NFrames",
181           "Number of frames per buffer",
182           0, G_MAXINT, DEFAULT_NFRAMES, G_PARAM_READWRITE));
183   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
184       g_param_spec_string ("last-message", "last-message",
185           "The last status message", NULL, G_PARAM_READABLE));
186
187   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_speex_enc_finalize);
188
189   gstelement_class->change_state =
190       GST_DEBUG_FUNCPTR (gst_speex_enc_change_state);
191 }
192
193 static void
194 gst_speex_enc_finalize (GObject * object)
195 {
196   GstSpeexEnc *enc;
197
198   enc = GST_SPEEX_ENC (object);
199
200   g_free (enc->last_message);
201   g_object_unref (enc->adapter);
202
203   G_OBJECT_CLASS (parent_class)->finalize (object);
204 }
205
206 static gboolean
207 gst_speex_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
208 {
209   GstSpeexEnc *enc;
210   GstStructure *structure;
211
212   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
213   enc->setup = FALSE;
214
215   structure = gst_caps_get_structure (caps, 0);
216   gst_structure_get_int (structure, "channels", &enc->channels);
217   gst_structure_get_int (structure, "rate", &enc->rate);
218
219   gst_speex_enc_setup (enc);
220
221   return enc->setup;
222 }
223
224
225 static GstCaps *
226 gst_speex_enc_sink_getcaps (GstPad * pad)
227 {
228   GstCaps *caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
229   GstCaps *peercaps = NULL;
230   GstSpeexEnc *enc = GST_SPEEX_ENC (gst_pad_get_parent_element (pad));
231
232   peercaps = gst_pad_peer_get_caps (enc->srcpad);
233
234   if (peercaps) {
235     if (!gst_caps_is_empty (peercaps) && !gst_caps_is_any (peercaps)) {
236       GstStructure *ps = gst_caps_get_structure (peercaps, 0);
237       GstStructure *s = gst_caps_get_structure (caps, 0);;
238       gint rate, channels;
239
240       if (gst_structure_get_int (ps, "rate", &rate)) {
241         gst_structure_fixate_field_nearest_int (s, "rate", rate);
242       }
243
244       if (gst_structure_get_int (ps, "channels", &channels)) {
245         gst_structure_fixate_field_nearest_int (s, "channels", channels);
246       }
247     }
248     gst_caps_unref (peercaps);
249   }
250
251   gst_object_unref (enc);
252
253   return caps;
254 }
255
256
257 static gboolean
258 gst_speex_enc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
259     GstFormat * dest_format, gint64 * dest_value)
260 {
261   gboolean res = TRUE;
262   GstSpeexEnc *enc;
263   gint64 avg;
264
265   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
266
267   if (enc->samples_in == 0 || enc->bytes_out == 0 || enc->rate == 0)
268     return FALSE;
269
270   avg = (enc->bytes_out * enc->rate) / (enc->samples_in);
271
272   switch (src_format) {
273     case GST_FORMAT_BYTES:
274       switch (*dest_format) {
275         case GST_FORMAT_TIME:
276           *dest_value = src_value * GST_SECOND / avg;
277           break;
278         default:
279           res = FALSE;
280       }
281       break;
282     case GST_FORMAT_TIME:
283       switch (*dest_format) {
284         case GST_FORMAT_BYTES:
285           *dest_value = src_value * avg / GST_SECOND;
286           break;
287         default:
288           res = FALSE;
289       }
290       break;
291     default:
292       res = FALSE;
293   }
294   return res;
295 }
296
297 static gboolean
298 gst_speex_enc_convert_sink (GstPad * pad, GstFormat src_format,
299     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
300 {
301   gboolean res = TRUE;
302   guint scale = 1;
303   gint bytes_per_sample;
304   GstSpeexEnc *enc;
305
306   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
307
308   bytes_per_sample = enc->channels * 2;
309
310   switch (src_format) {
311     case GST_FORMAT_BYTES:
312       switch (*dest_format) {
313         case GST_FORMAT_DEFAULT:
314           if (bytes_per_sample == 0)
315             return FALSE;
316           *dest_value = src_value / bytes_per_sample;
317           break;
318         case GST_FORMAT_TIME:
319         {
320           gint byterate = bytes_per_sample * enc->rate;
321
322           if (byterate == 0)
323             return FALSE;
324           *dest_value = src_value * GST_SECOND / byterate;
325           break;
326         }
327         default:
328           res = FALSE;
329       }
330       break;
331     case GST_FORMAT_DEFAULT:
332       switch (*dest_format) {
333         case GST_FORMAT_BYTES:
334           *dest_value = src_value * bytes_per_sample;
335           break;
336         case GST_FORMAT_TIME:
337           if (enc->rate == 0)
338             return FALSE;
339           *dest_value = src_value * GST_SECOND / enc->rate;
340           break;
341         default:
342           res = FALSE;
343       }
344       break;
345     case GST_FORMAT_TIME:
346       switch (*dest_format) {
347         case GST_FORMAT_BYTES:
348           scale = bytes_per_sample;
349           /* fallthrough */
350         case GST_FORMAT_DEFAULT:
351           *dest_value = src_value * scale * enc->rate / GST_SECOND;
352           break;
353         default:
354           res = FALSE;
355       }
356       break;
357     default:
358       res = FALSE;
359   }
360   return res;
361 }
362
363 static const GstQueryType *
364 gst_speex_enc_get_query_types (GstPad * pad)
365 {
366   static const GstQueryType gst_speex_enc_src_query_types[] = {
367     GST_QUERY_POSITION,
368     GST_QUERY_DURATION,
369     GST_QUERY_CONVERT,
370     0
371   };
372
373   return gst_speex_enc_src_query_types;
374 }
375
376 static gboolean
377 gst_speex_enc_src_query (GstPad * pad, GstQuery * query)
378 {
379   gboolean res = TRUE;
380   GstSpeexEnc *enc;
381
382   enc = GST_SPEEX_ENC (gst_pad_get_parent (pad));
383
384   switch (GST_QUERY_TYPE (query)) {
385     case GST_QUERY_POSITION:
386     {
387       GstFormat fmt, req_fmt;
388       gint64 pos, val;
389
390       gst_query_parse_position (query, &req_fmt, NULL);
391       if ((res = gst_pad_query_peer_position (enc->sinkpad, &req_fmt, &val))) {
392         gst_query_set_position (query, req_fmt, val);
393         break;
394       }
395
396       fmt = GST_FORMAT_TIME;
397       if (!(res = gst_pad_query_peer_position (enc->sinkpad, &fmt, &pos)))
398         break;
399
400       if ((res =
401               gst_pad_query_peer_convert (enc->sinkpad, fmt, pos, &req_fmt,
402                   &val)))
403         gst_query_set_position (query, req_fmt, val);
404
405       break;
406     }
407     case GST_QUERY_DURATION:
408     {
409       GstFormat fmt, req_fmt;
410       gint64 dur, val;
411
412       gst_query_parse_duration (query, &req_fmt, NULL);
413       if ((res = gst_pad_query_peer_duration (enc->sinkpad, &req_fmt, &val))) {
414         gst_query_set_duration (query, req_fmt, val);
415         break;
416       }
417
418       fmt = GST_FORMAT_TIME;
419       if (!(res = gst_pad_query_peer_duration (enc->sinkpad, &fmt, &dur)))
420         break;
421
422       if ((res =
423               gst_pad_query_peer_convert (enc->sinkpad, fmt, dur, &req_fmt,
424                   &val))) {
425         gst_query_set_duration (query, req_fmt, val);
426       }
427       break;
428     }
429     case GST_QUERY_CONVERT:
430     {
431       GstFormat src_fmt, dest_fmt;
432       gint64 src_val, dest_val;
433
434       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
435       if (!(res = gst_speex_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
436                   &dest_val)))
437         goto error;
438       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
439       break;
440     }
441     default:
442       res = gst_pad_query_default (pad, query);
443       break;
444   }
445
446 error:
447
448   gst_object_unref (enc);
449
450   return res;
451 }
452
453 static gboolean
454 gst_speex_enc_sink_query (GstPad * pad, GstQuery * query)
455 {
456   gboolean res = TRUE;
457   GstSpeexEnc *enc;
458
459   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
460
461   switch (GST_QUERY_TYPE (query)) {
462     case GST_QUERY_CONVERT:
463     {
464       GstFormat src_fmt, dest_fmt;
465       gint64 src_val, dest_val;
466
467       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
468       if (!(res =
469               gst_speex_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
470                   &dest_val)))
471         goto error;
472       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
473       break;
474     }
475     default:
476       res = gst_pad_query_default (pad, query);
477       break;
478   }
479
480 error:
481   return res;
482 }
483
484 static void
485 gst_speex_enc_init (GstSpeexEnc * enc, GstSpeexEncClass * klass)
486 {
487   enc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
488   gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
489   gst_pad_set_event_function (enc->sinkpad,
490       GST_DEBUG_FUNCPTR (gst_speex_enc_sinkevent));
491   gst_pad_set_chain_function (enc->sinkpad,
492       GST_DEBUG_FUNCPTR (gst_speex_enc_chain));
493   gst_pad_set_setcaps_function (enc->sinkpad,
494       GST_DEBUG_FUNCPTR (gst_speex_enc_sink_setcaps));
495   gst_pad_set_getcaps_function (enc->sinkpad,
496       GST_DEBUG_FUNCPTR (gst_speex_enc_sink_getcaps));
497   gst_pad_set_query_function (enc->sinkpad,
498       GST_DEBUG_FUNCPTR (gst_speex_enc_sink_query));
499
500   enc->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
501   gst_pad_set_query_function (enc->srcpad,
502       GST_DEBUG_FUNCPTR (gst_speex_enc_src_query));
503   gst_pad_set_query_type_function (enc->srcpad,
504       GST_DEBUG_FUNCPTR (gst_speex_enc_get_query_types));
505   gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
506
507   enc->channels = -1;
508   enc->rate = -1;
509
510   enc->quality = DEFAULT_QUALITY;
511   enc->bitrate = DEFAULT_BITRATE;
512   enc->vbr = DEFAULT_VBR;
513   enc->abr = DEFAULT_ABR;
514   enc->vad = DEFAULT_VAD;
515   enc->dtx = DEFAULT_DTX;
516   enc->complexity = DEFAULT_COMPLEXITY;
517   enc->nframes = DEFAULT_NFRAMES;
518
519   /* FIXME: what about enc->mode? */
520
521   enc->setup = FALSE;
522   enc->header_sent = FALSE;
523
524   enc->adapter = gst_adapter_new ();
525 }
526
527 static GstBuffer *
528 gst_speex_enc_create_metadata_buffer (GstSpeexEnc * enc)
529 {
530   const GstTagList *user_tags;
531   GstTagList *merged_tags;
532   GstBuffer *comments = NULL;
533
534   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
535
536   GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
537   GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
538
539   /* gst_tag_list_merge() will handle NULL for either or both lists fine */
540   merged_tags = gst_tag_list_merge (user_tags, enc->tags,
541       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
542
543   if (merged_tags == NULL)
544     merged_tags = gst_tag_list_new ();
545
546   GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
547   comments = gst_tag_list_to_vorbiscomment_buffer (merged_tags, NULL,
548       0, "Encoded with GStreamer Speexenc");
549   gst_tag_list_free (merged_tags);
550
551   GST_BUFFER_OFFSET (comments) = enc->bytes_out;
552   GST_BUFFER_OFFSET_END (comments) = 0;
553
554   return comments;
555 }
556
557 static void
558 gst_speex_enc_set_last_msg (GstSpeexEnc * enc, const gchar * msg)
559 {
560   g_free (enc->last_message);
561   enc->last_message = g_strdup (msg);
562   GST_WARNING_OBJECT (enc, "%s", msg);
563   g_object_notify (G_OBJECT (enc), "last-message");
564 }
565
566 static gboolean
567 gst_speex_enc_setup (GstSpeexEnc * enc)
568 {
569   enc->setup = FALSE;
570
571   switch (enc->mode) {
572     case GST_SPEEX_ENC_MODE_UWB:
573       enc->speex_mode = (SpeexMode *) & speex_uwb_mode;
574       break;
575     case GST_SPEEX_ENC_MODE_WB:
576       enc->speex_mode = (SpeexMode *) & speex_wb_mode;
577       break;
578     case GST_SPEEX_ENC_MODE_NB:
579       enc->speex_mode = (SpeexMode *) & speex_nb_mode;
580       break;
581     case GST_SPEEX_ENC_MODE_AUTO:
582       /* fall through */
583     default:
584       break;
585   }
586
587   if (enc->rate > 25000) {
588     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
589       enc->speex_mode = (SpeexMode *) & speex_uwb_mode;
590     } else {
591       if (enc->speex_mode != &speex_uwb_mode) {
592         gst_speex_enc_set_last_msg (enc,
593             "Warning: suggest to use ultra wide band mode for this rate");
594       }
595     }
596   } else if (enc->rate > 12500) {
597     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
598       enc->speex_mode = (SpeexMode *) & speex_wb_mode;
599     } else {
600       if (enc->speex_mode != &speex_wb_mode) {
601         gst_speex_enc_set_last_msg (enc,
602             "Warning: suggest to use wide band mode for this rate");
603       }
604     }
605   } else {
606     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
607       enc->speex_mode = (SpeexMode *) & speex_nb_mode;
608     } else {
609       if (enc->speex_mode != &speex_nb_mode) {
610         gst_speex_enc_set_last_msg (enc,
611             "Warning: suggest to use narrow band mode for this rate");
612       }
613     }
614   }
615
616   if (enc->rate != 8000 && enc->rate != 16000 && enc->rate != 32000) {
617     gst_speex_enc_set_last_msg (enc,
618         "Warning: speex is optimized for 8, 16 and 32 KHz");
619   }
620
621   speex_init_header (&enc->header, enc->rate, 1, enc->speex_mode);
622   enc->header.frames_per_packet = enc->nframes;
623   enc->header.vbr = enc->vbr;
624   enc->header.nb_channels = enc->channels;
625
626   /*Initialize Speex encoder */
627   enc->state = speex_encoder_init (enc->speex_mode);
628
629   speex_encoder_ctl (enc->state, SPEEX_GET_FRAME_SIZE, &enc->frame_size);
630   speex_encoder_ctl (enc->state, SPEEX_SET_COMPLEXITY, &enc->complexity);
631   speex_encoder_ctl (enc->state, SPEEX_SET_SAMPLING_RATE, &enc->rate);
632
633   if (enc->vbr)
634     speex_encoder_ctl (enc->state, SPEEX_SET_VBR_QUALITY, &enc->quality);
635   else {
636     gint tmp = floor (enc->quality);
637
638     speex_encoder_ctl (enc->state, SPEEX_SET_QUALITY, &tmp);
639   }
640   if (enc->bitrate) {
641     if (enc->quality >= 0.0 && enc->vbr) {
642       gst_speex_enc_set_last_msg (enc,
643           "Warning: bitrate option is overriding quality");
644     }
645     speex_encoder_ctl (enc->state, SPEEX_SET_BITRATE, &enc->bitrate);
646   }
647   if (enc->vbr) {
648     gint tmp = 1;
649
650     speex_encoder_ctl (enc->state, SPEEX_SET_VBR, &tmp);
651   } else if (enc->vad) {
652     gint tmp = 1;
653
654     speex_encoder_ctl (enc->state, SPEEX_SET_VAD, &tmp);
655   }
656
657   if (enc->dtx) {
658     gint tmp = 1;
659
660     speex_encoder_ctl (enc->state, SPEEX_SET_DTX, &tmp);
661   }
662
663   if (enc->dtx && !(enc->vbr || enc->abr || enc->vad)) {
664     gst_speex_enc_set_last_msg (enc,
665         "Warning: dtx is useless without vad, vbr or abr");
666   } else if ((enc->vbr || enc->abr) && (enc->vad)) {
667     gst_speex_enc_set_last_msg (enc,
668         "Warning: vad is already implied by vbr or abr");
669   }
670
671   if (enc->abr) {
672     speex_encoder_ctl (enc->state, SPEEX_SET_ABR, &enc->abr);
673   }
674
675   speex_encoder_ctl (enc->state, SPEEX_GET_LOOKAHEAD, &enc->lookahead);
676
677   enc->setup = TRUE;
678
679   return TRUE;
680 }
681
682 /* prepare a buffer for transmission */
683 static GstBuffer *
684 gst_speex_enc_buffer_from_data (GstSpeexEnc * enc, guchar * data,
685     gint data_len, guint64 granulepos)
686 {
687   GstBuffer *outbuf;
688
689   outbuf = gst_buffer_new_and_alloc (data_len);
690   memcpy (GST_BUFFER_DATA (outbuf), data, data_len);
691   GST_BUFFER_OFFSET (outbuf) = enc->bytes_out;
692   GST_BUFFER_OFFSET_END (outbuf) = granulepos;
693
694   GST_LOG_OBJECT (enc, "encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
695   return outbuf;
696 }
697
698
699 /* push out the buffer and do internal bookkeeping */
700 static GstFlowReturn
701 gst_speex_enc_push_buffer (GstSpeexEnc * enc, GstBuffer * buffer)
702 {
703   enc->bytes_out += GST_BUFFER_SIZE (buffer);
704
705   return gst_pad_push (enc->srcpad, buffer);
706
707 }
708
709 static GstCaps *
710 gst_speex_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
711     GstBuffer * buf2)
712 {
713   GstStructure *structure = NULL;
714   GstBuffer *buf;
715   GValue array = { 0 };
716   GValue value = { 0 };
717
718   caps = gst_caps_make_writable (caps);
719   structure = gst_caps_get_structure (caps, 0);
720
721   g_assert (gst_buffer_is_metadata_writable (buf1));
722   g_assert (gst_buffer_is_metadata_writable (buf2));
723
724   /* mark buffers */
725   GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
726   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
727
728   /* put buffers in a fixed list */
729   g_value_init (&array, GST_TYPE_ARRAY);
730   g_value_init (&value, GST_TYPE_BUFFER);
731   buf = gst_buffer_copy (buf1);
732   gst_value_set_buffer (&value, buf);
733   gst_buffer_unref (buf);
734   gst_value_array_append_value (&array, &value);
735   g_value_unset (&value);
736   g_value_init (&value, GST_TYPE_BUFFER);
737   buf = gst_buffer_copy (buf2);
738   gst_value_set_buffer (&value, buf);
739   gst_buffer_unref (buf);
740   gst_value_array_append_value (&array, &value);
741   gst_structure_set_value (structure, "streamheader", &array);
742   g_value_unset (&value);
743   g_value_unset (&array);
744
745   return caps;
746 }
747
748
749 static gboolean
750 gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event)
751 {
752   gboolean res = TRUE;
753   GstSpeexEnc *enc;
754
755   enc = GST_SPEEX_ENC (gst_pad_get_parent (pad));
756
757   switch (GST_EVENT_TYPE (event)) {
758     case GST_EVENT_EOS:
759       enc->eos = TRUE;
760       res = gst_pad_event_default (pad, event);
761       break;
762     case GST_EVENT_TAG:
763     {
764       GstTagList *list;
765
766       gst_event_parse_tag (event, &list);
767       if (enc->tags) {
768         gst_tag_list_insert (enc->tags, list,
769             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
770       }
771       res = gst_pad_event_default (pad, event);
772       break;
773     }
774     default:
775       res = gst_pad_event_default (pad, event);
776       break;
777   }
778
779   gst_object_unref (enc);
780
781   return res;
782 }
783
784
785 static GstFlowReturn
786 gst_speex_enc_chain (GstPad * pad, GstBuffer * buf)
787 {
788   GstSpeexEnc *enc;
789   GstFlowReturn ret = GST_FLOW_OK;
790
791   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
792
793   if (!enc->setup)
794     goto not_setup;
795
796   if (!enc->header_sent) {
797     /* Speex streams begin with two headers; the initial header (with
798        most of the codec setup parameters) which is mandated by the Ogg
799        bitstream spec.  The second header holds any comment fields.
800        We merely need to make the headers, then pass them to libspeex 
801        one at a time; libspeex handles the additional Ogg bitstream 
802        constraints */
803     GstBuffer *buf1, *buf2;
804     GstCaps *caps;
805     guchar *data;
806     gint data_len;
807
808     /* create header buffer */
809     data = (guint8 *) speex_header_to_packet (&enc->header, &data_len);
810     buf1 = gst_speex_enc_buffer_from_data (enc, data, data_len, 0);
811     free (data);
812
813     /* create comment buffer */
814     buf2 = gst_speex_enc_create_metadata_buffer (enc);
815
816     /* mark and put on caps */
817     caps = gst_pad_get_caps (enc->srcpad);
818     caps = gst_speex_enc_set_header_on_caps (caps, buf1, buf2);
819
820     gst_caps_set_simple (caps,
821         "rate", G_TYPE_INT, enc->rate,
822         "channels", G_TYPE_INT, enc->channels, NULL);
823
824     /* negotiate with these caps */
825     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
826     gst_pad_set_caps (enc->srcpad, caps);
827
828     gst_buffer_set_caps (buf1, caps);
829     gst_buffer_set_caps (buf2, caps);
830     gst_caps_unref (caps);
831
832     /* push out buffers */
833     ret = gst_speex_enc_push_buffer (enc, buf1);
834
835     if (ret != GST_FLOW_OK) {
836       gst_buffer_unref (buf2);
837       goto done;
838     }
839
840     ret = gst_speex_enc_push_buffer (enc, buf2);
841
842     if (ret != GST_FLOW_OK)
843       goto done;
844
845     speex_bits_reset (&enc->bits);
846
847     enc->header_sent = TRUE;
848   }
849
850   {
851     gint frame_size = enc->frame_size;
852     gint bytes = frame_size * 2 * enc->channels;
853
854     /* push buffer to adapter */
855     gst_adapter_push (enc->adapter, buf);
856     buf = NULL;
857
858     while (gst_adapter_available (enc->adapter) >= bytes) {
859       gint16 *data;
860       gint i;
861       gint outsize, written;
862       GstBuffer *outbuf;
863
864       data = (gint16 *) gst_adapter_peek (enc->adapter, bytes);
865
866       for (i = 0; i < frame_size * enc->channels; i++) {
867         enc->input[i] = (gfloat) data[i];
868       }
869       gst_adapter_flush (enc->adapter, bytes);
870
871       enc->samples_in += frame_size;
872
873       if (enc->channels == 2) {
874         speex_encode_stereo (enc->input, frame_size, &enc->bits);
875       }
876       speex_encode (enc->state, enc->input, &enc->bits);
877
878       enc->frameno++;
879
880       if ((enc->frameno % enc->nframes) != 0)
881         continue;
882
883       speex_bits_insert_terminator (&enc->bits);
884       outsize = speex_bits_nbytes (&enc->bits);
885
886       ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
887           GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (enc->srcpad), &outbuf);
888
889       if ((GST_FLOW_OK != ret))
890         goto done;
891
892       written = speex_bits_write (&enc->bits,
893           (gchar *) GST_BUFFER_DATA (outbuf), outsize);
894       g_assert (written == outsize);
895       speex_bits_reset (&enc->bits);
896
897       GST_BUFFER_TIMESTAMP (outbuf) =
898           gst_util_uint64_scale_int (enc->frameno * frame_size -
899           enc->lookahead, GST_SECOND, enc->rate);
900       GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (frame_size,
901           GST_SECOND, enc->rate);
902       /* set gp time and granulepos; see gst-plugins-base/ext/ogg/README */
903       GST_BUFFER_OFFSET_END (outbuf) =
904           ((enc->frameno + 1) * frame_size - enc->lookahead);
905       GST_BUFFER_OFFSET (outbuf) =
906           gst_util_uint64_scale_int (GST_BUFFER_OFFSET_END (outbuf), GST_SECOND,
907           enc->rate);
908
909       ret = gst_speex_enc_push_buffer (enc, outbuf);
910
911       if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
912         goto done;
913     }
914   }
915
916 done:
917
918   if (buf)
919     gst_buffer_unref (buf);
920
921   return ret;
922
923   /* ERRORS */
924 not_setup:
925   {
926     GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL),
927         ("encoder not initialized (input is not audio?)"));
928     ret = GST_FLOW_NOT_NEGOTIATED;
929     goto done;
930   }
931
932 }
933
934
935 static void
936 gst_speex_enc_get_property (GObject * object, guint prop_id, GValue * value,
937     GParamSpec * pspec)
938 {
939   GstSpeexEnc *enc;
940
941   enc = GST_SPEEX_ENC (object);
942
943   switch (prop_id) {
944     case ARG_QUALITY:
945       g_value_set_float (value, enc->quality);
946       break;
947     case ARG_BITRATE:
948       g_value_set_int (value, enc->bitrate);
949       break;
950     case ARG_VBR:
951       g_value_set_boolean (value, enc->vbr);
952       break;
953     case ARG_ABR:
954       g_value_set_int (value, enc->abr);
955       break;
956     case ARG_VAD:
957       g_value_set_boolean (value, enc->vad);
958       break;
959     case ARG_DTX:
960       g_value_set_boolean (value, enc->dtx);
961       break;
962     case ARG_COMPLEXITY:
963       g_value_set_int (value, enc->complexity);
964       break;
965     case ARG_NFRAMES:
966       g_value_set_int (value, enc->nframes);
967       break;
968     case ARG_LAST_MESSAGE:
969       g_value_set_string (value, enc->last_message);
970       break;
971     default:
972       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
973       break;
974   }
975 }
976
977 static void
978 gst_speex_enc_set_property (GObject * object, guint prop_id,
979     const GValue * value, GParamSpec * pspec)
980 {
981   GstSpeexEnc *enc;
982
983   enc = GST_SPEEX_ENC (object);
984
985   switch (prop_id) {
986     case ARG_QUALITY:
987       enc->quality = g_value_get_float (value);
988       break;
989     case ARG_BITRATE:
990       enc->bitrate = g_value_get_int (value);
991       break;
992     case ARG_VBR:
993       enc->vbr = g_value_get_boolean (value);
994       break;
995     case ARG_ABR:
996       enc->abr = g_value_get_int (value);
997       break;
998     case ARG_VAD:
999       enc->vad = g_value_get_boolean (value);
1000       break;
1001     case ARG_DTX:
1002       enc->dtx = g_value_get_boolean (value);
1003       break;
1004     case ARG_COMPLEXITY:
1005       enc->complexity = g_value_get_int (value);
1006       break;
1007     case ARG_NFRAMES:
1008       enc->nframes = g_value_get_int (value);
1009       break;
1010     default:
1011       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1012       break;
1013   }
1014 }
1015
1016 static GstStateChangeReturn
1017 gst_speex_enc_change_state (GstElement * element, GstStateChange transition)
1018 {
1019   GstSpeexEnc *enc = GST_SPEEX_ENC (element);
1020   GstStateChangeReturn res;
1021
1022   switch (transition) {
1023     case GST_STATE_CHANGE_NULL_TO_READY:
1024       enc->tags = gst_tag_list_new ();
1025       break;
1026     case GST_STATE_CHANGE_READY_TO_PAUSED:
1027       speex_bits_init (&enc->bits);
1028       enc->frameno = 0;
1029       enc->samples_in = 0;
1030       break;
1031     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1032       /* fall through */
1033     default:
1034       break;
1035   }
1036
1037   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1038   if (res == GST_STATE_CHANGE_FAILURE)
1039     return res;
1040
1041   switch (transition) {
1042     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1043       break;
1044     case GST_STATE_CHANGE_PAUSED_TO_READY:
1045       enc->setup = FALSE;
1046       enc->header_sent = FALSE;
1047       if (enc->state) {
1048         speex_encoder_destroy (enc->state);
1049         enc->state = NULL;
1050       }
1051       speex_bits_destroy (&enc->bits);
1052       break;
1053     case GST_STATE_CHANGE_READY_TO_NULL:
1054       gst_tag_list_free (enc->tags);
1055       enc->tags = NULL;
1056     default:
1057       break;
1058   }
1059
1060   return res;
1061 }