upload tizen1.0 source
[framework/multimedia/gst-plugins-good0.10.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  * SECTION:element-speexenc
22  * @see_also: speexdec, oggmux
23  *
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
27  * Foundation</ulink>.
28  *
29  * <refsect2>
30  * <title>Example pipelines</title>
31  * |[
32  * gst-launch audiotestsrc num-buffers=100 ! speexenc ! oggmux ! filesink location=beep.ogg
33  * ]| Encode an Ogg/Speex file.
34  * </refsect2>
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 #include <math.h>
44 #include <speex/speex.h>
45 #include <speex/speex_stereo.h>
46
47 #include <gst/gsttagsetter.h>
48 #include <gst/tag/tag.h>
49 #include <gst/audio/audio.h>
50 #include "gstspeexenc.h"
51
52 GST_DEBUG_CATEGORY_STATIC (speexenc_debug);
53 #define GST_CAT_DEFAULT speexenc_debug
54
55 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
56     GST_PAD_SINK,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS ("audio/x-raw-int, "
59         "rate = (int) [ 6000, 48000 ], "
60         "channels = (int) [ 1, 2 ], "
61         "endianness = (int) BYTE_ORDER, "
62         "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16")
63     );
64
65 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
66     GST_PAD_SRC,
67     GST_PAD_ALWAYS,
68     GST_STATIC_CAPS ("audio/x-speex, "
69         "rate = (int) [ 6000, 48000 ], " "channels = (int) [ 1, 2]")
70     );
71
72 #define DEFAULT_QUALITY         8.0
73 #define DEFAULT_BITRATE         0
74 #define DEFAULT_MODE            GST_SPEEX_ENC_MODE_AUTO
75 #define DEFAULT_VBR             FALSE
76 #define DEFAULT_ABR             0
77 #define DEFAULT_VAD             FALSE
78 #define DEFAULT_DTX             FALSE
79 #define DEFAULT_COMPLEXITY      3
80 #define DEFAULT_NFRAMES         1
81
82 enum
83 {
84   PROP_0,
85   PROP_QUALITY,
86   PROP_BITRATE,
87   PROP_MODE,
88   PROP_VBR,
89   PROP_ABR,
90   PROP_VAD,
91   PROP_DTX,
92   PROP_COMPLEXITY,
93   PROP_NFRAMES,
94   PROP_LAST_MESSAGE
95 };
96
97 #define GST_TYPE_SPEEX_ENC_MODE (gst_speex_enc_mode_get_type())
98 static GType
99 gst_speex_enc_mode_get_type (void)
100 {
101   static GType speex_enc_mode_type = 0;
102   static const GEnumValue speex_enc_modes[] = {
103     {GST_SPEEX_ENC_MODE_AUTO, "Auto", "auto"},
104     {GST_SPEEX_ENC_MODE_UWB, "Ultra Wide Band", "uwb"},
105     {GST_SPEEX_ENC_MODE_WB, "Wide Band", "wb"},
106     {GST_SPEEX_ENC_MODE_NB, "Narrow Band", "nb"},
107     {0, NULL, NULL},
108   };
109   if (G_UNLIKELY (speex_enc_mode_type == 0)) {
110     speex_enc_mode_type = g_enum_register_static ("GstSpeexEncMode",
111         speex_enc_modes);
112   }
113   return speex_enc_mode_type;
114 }
115
116 #if 0
117 static const GstFormat *
118 gst_speex_enc_get_formats (GstPad * pad)
119 {
120   static const GstFormat src_formats[] = {
121     GST_FORMAT_BYTES,
122     GST_FORMAT_TIME,
123     0
124   };
125   static const GstFormat sink_formats[] = {
126     GST_FORMAT_BYTES,
127     GST_FORMAT_DEFAULT,
128     GST_FORMAT_TIME,
129     0
130   };
131
132   return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
133 }
134 #endif
135
136 static void gst_speex_enc_finalize (GObject * object);
137
138 static gboolean gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event);
139 static GstFlowReturn gst_speex_enc_chain (GstPad * pad, GstBuffer * buf);
140 static gboolean gst_speex_enc_setup (GstSpeexEnc * enc);
141
142 static void gst_speex_enc_get_property (GObject * object, guint prop_id,
143     GValue * value, GParamSpec * pspec);
144 static void gst_speex_enc_set_property (GObject * object, guint prop_id,
145     const GValue * value, GParamSpec * pspec);
146 static GstStateChangeReturn gst_speex_enc_change_state (GstElement * element,
147     GstStateChange transition);
148
149 static GstFlowReturn gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush);
150
151 static void
152 gst_speex_enc_setup_interfaces (GType speexenc_type)
153 {
154   static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
155   const GInterfaceInfo preset_interface_info = {
156     NULL,                       /* interface_init */
157     NULL,                       /* interface_finalize */
158     NULL                        /* interface_data */
159   };
160
161   g_type_add_interface_static (speexenc_type, GST_TYPE_TAG_SETTER,
162       &tag_setter_info);
163   g_type_add_interface_static (speexenc_type, GST_TYPE_PRESET,
164       &preset_interface_info);
165
166   GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
167 }
168
169 GST_BOILERPLATE_FULL (GstSpeexEnc, gst_speex_enc, GstElement, GST_TYPE_ELEMENT,
170     gst_speex_enc_setup_interfaces);
171
172 static void
173 gst_speex_enc_base_init (gpointer g_class)
174 {
175   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
176
177   gst_element_class_add_pad_template (element_class,
178       gst_static_pad_template_get (&src_factory));
179   gst_element_class_add_pad_template (element_class,
180       gst_static_pad_template_get (&sink_factory));
181   gst_element_class_set_details_simple (element_class, "Speex audio encoder",
182       "Codec/Encoder/Audio",
183       "Encodes audio in Speex format", "Wim Taymans <wim@fluendo.com>");
184 }
185
186 static void
187 gst_speex_enc_class_init (GstSpeexEncClass * klass)
188 {
189   GObjectClass *gobject_class;
190   GstElementClass *gstelement_class;
191
192   gobject_class = (GObjectClass *) klass;
193   gstelement_class = (GstElementClass *) klass;
194
195   gobject_class->set_property = gst_speex_enc_set_property;
196   gobject_class->get_property = gst_speex_enc_get_property;
197
198   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_QUALITY,
199       g_param_spec_float ("quality", "Quality", "Encoding quality",
200           0.0, 10.0, DEFAULT_QUALITY,
201           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
202   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BITRATE,
203       g_param_spec_int ("bitrate", "Encoding Bit-rate",
204           "Specify an encoding bit-rate (in bps). (0 = automatic)",
205           0, G_MAXINT, DEFAULT_BITRATE,
206           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
207   g_object_class_install_property (gobject_class, PROP_MODE,
208       g_param_spec_enum ("mode", "Mode", "The encoding mode",
209           GST_TYPE_SPEEX_ENC_MODE, GST_SPEEX_ENC_MODE_AUTO,
210           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
211   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VBR,
212       g_param_spec_boolean ("vbr", "VBR",
213           "Enable variable bit-rate", DEFAULT_VBR,
214           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
215   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ABR,
216       g_param_spec_int ("abr", "ABR",
217           "Enable average bit-rate (0 = disabled)",
218           0, G_MAXINT, DEFAULT_ABR,
219           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
220   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VAD,
221       g_param_spec_boolean ("vad", "VAD",
222           "Enable voice activity detection", DEFAULT_VAD,
223           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
224   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DTX,
225       g_param_spec_boolean ("dtx", "DTX",
226           "Enable discontinuous transmission", DEFAULT_DTX,
227           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
228   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLEXITY,
229       g_param_spec_int ("complexity", "Complexity",
230           "Set encoding complexity",
231           0, G_MAXINT, DEFAULT_COMPLEXITY,
232           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
233   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NFRAMES,
234       g_param_spec_int ("nframes", "NFrames",
235           "Number of frames per buffer",
236           0, G_MAXINT, DEFAULT_NFRAMES,
237           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
238   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
239       g_param_spec_string ("last-message", "last-message",
240           "The last status message", NULL,
241           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
242
243   gobject_class->finalize = gst_speex_enc_finalize;
244
245   gstelement_class->change_state =
246       GST_DEBUG_FUNCPTR (gst_speex_enc_change_state);
247 }
248
249 static void
250 gst_speex_enc_finalize (GObject * object)
251 {
252   GstSpeexEnc *enc;
253
254   enc = GST_SPEEX_ENC (object);
255
256   g_free (enc->last_message);
257   g_object_unref (enc->adapter);
258
259   G_OBJECT_CLASS (parent_class)->finalize (object);
260 }
261
262 static gboolean
263 gst_speex_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
264 {
265   GstSpeexEnc *enc;
266   GstStructure *structure;
267
268   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
269   enc->setup = FALSE;
270
271   structure = gst_caps_get_structure (caps, 0);
272   gst_structure_get_int (structure, "channels", &enc->channels);
273   gst_structure_get_int (structure, "rate", &enc->rate);
274
275   gst_speex_enc_setup (enc);
276
277   return enc->setup;
278 }
279
280
281 static GstCaps *
282 gst_speex_enc_sink_getcaps (GstPad * pad)
283 {
284   GstCaps *caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
285   GstCaps *peercaps = NULL;
286   GstSpeexEnc *enc = GST_SPEEX_ENC (gst_pad_get_parent_element (pad));
287
288   peercaps = gst_pad_peer_get_caps (enc->srcpad);
289
290   if (peercaps) {
291     if (!gst_caps_is_empty (peercaps) && !gst_caps_is_any (peercaps)) {
292       GstStructure *ps = gst_caps_get_structure (peercaps, 0);
293       GstStructure *s = gst_caps_get_structure (caps, 0);
294       gint rate, channels;
295
296       if (gst_structure_get_int (ps, "rate", &rate)) {
297         gst_structure_fixate_field_nearest_int (s, "rate", rate);
298       }
299
300       if (gst_structure_get_int (ps, "channels", &channels)) {
301         gst_structure_fixate_field_nearest_int (s, "channels", channels);
302       }
303     }
304     gst_caps_unref (peercaps);
305   }
306
307   gst_object_unref (enc);
308
309   return caps;
310 }
311
312
313 static gboolean
314 gst_speex_enc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
315     GstFormat * dest_format, gint64 * dest_value)
316 {
317   gboolean res = TRUE;
318   GstSpeexEnc *enc;
319   gint64 avg;
320
321   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
322
323   if (enc->samples_in == 0 || enc->bytes_out == 0 || enc->rate == 0)
324     return FALSE;
325
326   avg = (enc->bytes_out * enc->rate) / (enc->samples_in);
327
328   switch (src_format) {
329     case GST_FORMAT_BYTES:
330       switch (*dest_format) {
331         case GST_FORMAT_TIME:
332           *dest_value = src_value * GST_SECOND / avg;
333           break;
334         default:
335           res = FALSE;
336       }
337       break;
338     case GST_FORMAT_TIME:
339       switch (*dest_format) {
340         case GST_FORMAT_BYTES:
341           *dest_value = src_value * avg / GST_SECOND;
342           break;
343         default:
344           res = FALSE;
345       }
346       break;
347     default:
348       res = FALSE;
349   }
350   return res;
351 }
352
353 static gboolean
354 gst_speex_enc_convert_sink (GstPad * pad, GstFormat src_format,
355     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
356 {
357   gboolean res = TRUE;
358   guint scale = 1;
359   gint bytes_per_sample;
360   GstSpeexEnc *enc;
361
362   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
363
364   bytes_per_sample = enc->channels * 2;
365
366   switch (src_format) {
367     case GST_FORMAT_BYTES:
368       switch (*dest_format) {
369         case GST_FORMAT_DEFAULT:
370           if (bytes_per_sample == 0)
371             return FALSE;
372           *dest_value = src_value / bytes_per_sample;
373           break;
374         case GST_FORMAT_TIME:
375         {
376           gint byterate = bytes_per_sample * enc->rate;
377
378           if (byterate == 0)
379             return FALSE;
380           *dest_value = src_value * GST_SECOND / byterate;
381           break;
382         }
383         default:
384           res = FALSE;
385       }
386       break;
387     case GST_FORMAT_DEFAULT:
388       switch (*dest_format) {
389         case GST_FORMAT_BYTES:
390           *dest_value = src_value * bytes_per_sample;
391           break;
392         case GST_FORMAT_TIME:
393           if (enc->rate == 0)
394             return FALSE;
395           *dest_value = src_value * GST_SECOND / enc->rate;
396           break;
397         default:
398           res = FALSE;
399       }
400       break;
401     case GST_FORMAT_TIME:
402       switch (*dest_format) {
403         case GST_FORMAT_BYTES:
404           scale = bytes_per_sample;
405           /* fallthrough */
406         case GST_FORMAT_DEFAULT:
407           *dest_value = src_value * scale * enc->rate / GST_SECOND;
408           break;
409         default:
410           res = FALSE;
411       }
412       break;
413     default:
414       res = FALSE;
415   }
416   return res;
417 }
418
419 static gint64
420 gst_speex_enc_get_latency (GstSpeexEnc * enc)
421 {
422   /* See the Speex manual section "Latency and algorithmic delay" */
423   if (enc->rate == 8000)
424     return 30 * GST_MSECOND;
425   else
426     return 34 * GST_MSECOND;
427 }
428
429 static const GstQueryType *
430 gst_speex_enc_get_query_types (GstPad * pad)
431 {
432   static const GstQueryType gst_speex_enc_src_query_types[] = {
433     GST_QUERY_POSITION,
434     GST_QUERY_DURATION,
435     GST_QUERY_CONVERT,
436     GST_QUERY_LATENCY,
437     0
438   };
439
440   return gst_speex_enc_src_query_types;
441 }
442
443 static gboolean
444 gst_speex_enc_src_query (GstPad * pad, GstQuery * query)
445 {
446   gboolean res = TRUE;
447   GstSpeexEnc *enc;
448
449   enc = GST_SPEEX_ENC (gst_pad_get_parent (pad));
450
451   switch (GST_QUERY_TYPE (query)) {
452     case GST_QUERY_POSITION:
453     {
454       GstFormat fmt, req_fmt;
455       gint64 pos, val;
456
457       gst_query_parse_position (query, &req_fmt, NULL);
458       if ((res = gst_pad_query_peer_position (enc->sinkpad, &req_fmt, &val))) {
459         gst_query_set_position (query, req_fmt, val);
460         break;
461       }
462
463       fmt = GST_FORMAT_TIME;
464       if (!(res = gst_pad_query_peer_position (enc->sinkpad, &fmt, &pos)))
465         break;
466
467       if ((res =
468               gst_pad_query_peer_convert (enc->sinkpad, fmt, pos, &req_fmt,
469                   &val)))
470         gst_query_set_position (query, req_fmt, val);
471
472       break;
473     }
474     case GST_QUERY_DURATION:
475     {
476       GstFormat fmt, req_fmt;
477       gint64 dur, val;
478
479       gst_query_parse_duration (query, &req_fmt, NULL);
480       if ((res = gst_pad_query_peer_duration (enc->sinkpad, &req_fmt, &val))) {
481         gst_query_set_duration (query, req_fmt, val);
482         break;
483       }
484
485       fmt = GST_FORMAT_TIME;
486       if (!(res = gst_pad_query_peer_duration (enc->sinkpad, &fmt, &dur)))
487         break;
488
489       if ((res =
490               gst_pad_query_peer_convert (enc->sinkpad, fmt, dur, &req_fmt,
491                   &val))) {
492         gst_query_set_duration (query, req_fmt, val);
493       }
494       break;
495     }
496     case GST_QUERY_CONVERT:
497     {
498       GstFormat src_fmt, dest_fmt;
499       gint64 src_val, dest_val;
500
501       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
502       if (!(res = gst_speex_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
503                   &dest_val)))
504         goto error;
505       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
506       break;
507     }
508     case GST_QUERY_LATENCY:
509     {
510       gboolean live;
511       GstClockTime min_latency, max_latency;
512       gint64 latency;
513
514       if ((res = gst_pad_peer_query (enc->sinkpad, query))) {
515         gst_query_parse_latency (query, &live, &min_latency, &max_latency);
516         GST_LOG_OBJECT (pad, "Upstream latency: %" GST_PTR_FORMAT, query);
517
518         latency = gst_speex_enc_get_latency (enc);
519
520         /* add our latency */
521         min_latency += latency;
522         if (max_latency != -1)
523           max_latency += latency;
524
525         gst_query_set_latency (query, live, min_latency, max_latency);
526         GST_LOG_OBJECT (pad, "Adjusted latency: %" GST_PTR_FORMAT, query);
527       }
528       break;
529     }
530     default:
531       res = gst_pad_peer_query (enc->sinkpad, query);
532       break;
533   }
534
535 error:
536
537   gst_object_unref (enc);
538
539   return res;
540 }
541
542 static gboolean
543 gst_speex_enc_sink_query (GstPad * pad, GstQuery * query)
544 {
545   gboolean res = TRUE;
546
547   switch (GST_QUERY_TYPE (query)) {
548     case GST_QUERY_CONVERT:
549     {
550       GstFormat src_fmt, dest_fmt;
551       gint64 src_val, dest_val;
552
553       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
554       if (!(res =
555               gst_speex_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
556                   &dest_val)))
557         goto error;
558       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
559       break;
560     }
561     default:
562       res = gst_pad_query_default (pad, query);
563       break;
564   }
565
566 error:
567   return res;
568 }
569
570 static void
571 gst_speex_enc_init (GstSpeexEnc * enc, GstSpeexEncClass * klass)
572 {
573   enc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
574   gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
575   gst_pad_set_event_function (enc->sinkpad,
576       GST_DEBUG_FUNCPTR (gst_speex_enc_sinkevent));
577   gst_pad_set_chain_function (enc->sinkpad,
578       GST_DEBUG_FUNCPTR (gst_speex_enc_chain));
579   gst_pad_set_setcaps_function (enc->sinkpad,
580       GST_DEBUG_FUNCPTR (gst_speex_enc_sink_setcaps));
581   gst_pad_set_getcaps_function (enc->sinkpad,
582       GST_DEBUG_FUNCPTR (gst_speex_enc_sink_getcaps));
583   gst_pad_set_query_function (enc->sinkpad,
584       GST_DEBUG_FUNCPTR (gst_speex_enc_sink_query));
585
586   enc->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
587   gst_pad_set_query_function (enc->srcpad,
588       GST_DEBUG_FUNCPTR (gst_speex_enc_src_query));
589   gst_pad_set_query_type_function (enc->srcpad,
590       GST_DEBUG_FUNCPTR (gst_speex_enc_get_query_types));
591   gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
592
593   enc->channels = -1;
594   enc->rate = -1;
595
596   enc->quality = DEFAULT_QUALITY;
597   enc->bitrate = DEFAULT_BITRATE;
598   enc->mode = DEFAULT_MODE;
599   enc->vbr = DEFAULT_VBR;
600   enc->abr = DEFAULT_ABR;
601   enc->vad = DEFAULT_VAD;
602   enc->dtx = DEFAULT_DTX;
603   enc->complexity = DEFAULT_COMPLEXITY;
604   enc->nframes = DEFAULT_NFRAMES;
605
606   enc->setup = FALSE;
607   enc->header_sent = FALSE;
608
609   enc->adapter = gst_adapter_new ();
610 }
611
612 static GstBuffer *
613 gst_speex_enc_create_metadata_buffer (GstSpeexEnc * enc)
614 {
615   const GstTagList *user_tags;
616   GstTagList *merged_tags;
617   GstBuffer *comments = NULL;
618
619   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
620
621   GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
622   GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
623
624   /* gst_tag_list_merge() will handle NULL for either or both lists fine */
625   merged_tags = gst_tag_list_merge (user_tags, enc->tags,
626       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
627
628   if (merged_tags == NULL)
629     merged_tags = gst_tag_list_new ();
630
631   GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
632   comments = gst_tag_list_to_vorbiscomment_buffer (merged_tags, NULL,
633       0, "Encoded with GStreamer Speexenc");
634   gst_tag_list_free (merged_tags);
635
636   GST_BUFFER_OFFSET (comments) = enc->bytes_out;
637   GST_BUFFER_OFFSET_END (comments) = 0;
638
639   return comments;
640 }
641
642 static void
643 gst_speex_enc_set_last_msg (GstSpeexEnc * enc, const gchar * msg)
644 {
645   g_free (enc->last_message);
646   enc->last_message = g_strdup (msg);
647   GST_WARNING_OBJECT (enc, "%s", msg);
648   g_object_notify (G_OBJECT (enc), "last-message");
649 }
650
651 static gboolean
652 gst_speex_enc_setup (GstSpeexEnc * enc)
653 {
654   enc->setup = FALSE;
655
656   switch (enc->mode) {
657     case GST_SPEEX_ENC_MODE_UWB:
658       GST_LOG_OBJECT (enc, "configuring for requested UWB mode");
659       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_UWB);
660       break;
661     case GST_SPEEX_ENC_MODE_WB:
662       GST_LOG_OBJECT (enc, "configuring for requested WB mode");
663       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_WB);
664       break;
665     case GST_SPEEX_ENC_MODE_NB:
666       GST_LOG_OBJECT (enc, "configuring for requested NB mode");
667       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_NB);
668       break;
669     case GST_SPEEX_ENC_MODE_AUTO:
670       /* fall through */
671       GST_LOG_OBJECT (enc, "finding best mode");
672     default:
673       break;
674   }
675
676   if (enc->rate > 25000) {
677     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
678       GST_LOG_OBJECT (enc, "selected UWB mode for samplerate %d", enc->rate);
679       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_UWB);
680     } else {
681       if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_UWB)) {
682         gst_speex_enc_set_last_msg (enc,
683             "Warning: suggest to use ultra wide band mode for this rate");
684       }
685     }
686   } else if (enc->rate > 12500) {
687     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
688       GST_LOG_OBJECT (enc, "selected WB mode for samplerate %d", enc->rate);
689       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_WB);
690     } else {
691       if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_WB)) {
692         gst_speex_enc_set_last_msg (enc,
693             "Warning: suggest to use wide band mode for this rate");
694       }
695     }
696   } else {
697     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
698       GST_LOG_OBJECT (enc, "selected NB mode for samplerate %d", enc->rate);
699       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_NB);
700     } else {
701       if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_NB)) {
702         gst_speex_enc_set_last_msg (enc,
703             "Warning: suggest to use narrow band mode for this rate");
704       }
705     }
706   }
707
708   if (enc->rate != 8000 && enc->rate != 16000 && enc->rate != 32000) {
709     gst_speex_enc_set_last_msg (enc,
710         "Warning: speex is optimized for 8, 16 and 32 KHz");
711   }
712
713   speex_init_header (&enc->header, enc->rate, 1, enc->speex_mode);
714   enc->header.frames_per_packet = enc->nframes;
715   enc->header.vbr = enc->vbr;
716   enc->header.nb_channels = enc->channels;
717
718   /*Initialize Speex encoder */
719   enc->state = speex_encoder_init (enc->speex_mode);
720
721   speex_encoder_ctl (enc->state, SPEEX_GET_FRAME_SIZE, &enc->frame_size);
722   speex_encoder_ctl (enc->state, SPEEX_SET_COMPLEXITY, &enc->complexity);
723   speex_encoder_ctl (enc->state, SPEEX_SET_SAMPLING_RATE, &enc->rate);
724
725   if (enc->vbr)
726     speex_encoder_ctl (enc->state, SPEEX_SET_VBR_QUALITY, &enc->quality);
727   else {
728     gint tmp = floor (enc->quality);
729
730     speex_encoder_ctl (enc->state, SPEEX_SET_QUALITY, &tmp);
731   }
732   if (enc->bitrate) {
733     if (enc->quality >= 0.0 && enc->vbr) {
734       gst_speex_enc_set_last_msg (enc,
735           "Warning: bitrate option is overriding quality");
736     }
737     speex_encoder_ctl (enc->state, SPEEX_SET_BITRATE, &enc->bitrate);
738   }
739   if (enc->vbr) {
740     gint tmp = 1;
741
742     speex_encoder_ctl (enc->state, SPEEX_SET_VBR, &tmp);
743   } else if (enc->vad) {
744     gint tmp = 1;
745
746     speex_encoder_ctl (enc->state, SPEEX_SET_VAD, &tmp);
747   }
748
749   if (enc->dtx) {
750     gint tmp = 1;
751
752     speex_encoder_ctl (enc->state, SPEEX_SET_DTX, &tmp);
753   }
754
755   if (enc->dtx && !(enc->vbr || enc->abr || enc->vad)) {
756     gst_speex_enc_set_last_msg (enc,
757         "Warning: dtx is useless without vad, vbr or abr");
758   } else if ((enc->vbr || enc->abr) && (enc->vad)) {
759     gst_speex_enc_set_last_msg (enc,
760         "Warning: vad is already implied by vbr or abr");
761   }
762
763   if (enc->abr) {
764     speex_encoder_ctl (enc->state, SPEEX_SET_ABR, &enc->abr);
765   }
766
767   speex_encoder_ctl (enc->state, SPEEX_GET_LOOKAHEAD, &enc->lookahead);
768
769   GST_LOG_OBJECT (enc, "we have frame size %d, lookahead %d", enc->frame_size,
770       enc->lookahead);
771
772   enc->setup = TRUE;
773
774   return TRUE;
775 }
776
777 /* prepare a buffer for transmission */
778 static GstBuffer *
779 gst_speex_enc_buffer_from_data (GstSpeexEnc * enc, guchar * data,
780     gint data_len, guint64 granulepos)
781 {
782   GstBuffer *outbuf;
783
784   outbuf = gst_buffer_new_and_alloc (data_len);
785   memcpy (GST_BUFFER_DATA (outbuf), data, data_len);
786   GST_BUFFER_OFFSET (outbuf) = enc->bytes_out;
787   GST_BUFFER_OFFSET_END (outbuf) = granulepos;
788
789   GST_LOG_OBJECT (enc, "encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
790   return outbuf;
791 }
792
793
794 /* push out the buffer and do internal bookkeeping */
795 static GstFlowReturn
796 gst_speex_enc_push_buffer (GstSpeexEnc * enc, GstBuffer * buffer)
797 {
798   guint size;
799
800   size = GST_BUFFER_SIZE (buffer);
801
802   enc->bytes_out += size;
803
804   GST_DEBUG_OBJECT (enc, "pushing output buffer of size %u", size);
805
806   return gst_pad_push (enc->srcpad, buffer);
807 }
808
809 static GstCaps *
810 gst_speex_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
811     GstBuffer * buf2)
812 {
813   GstStructure *structure = NULL;
814   GstBuffer *buf;
815   GValue array = { 0 };
816   GValue value = { 0 };
817
818   caps = gst_caps_make_writable (caps);
819   structure = gst_caps_get_structure (caps, 0);
820
821   g_assert (gst_buffer_is_metadata_writable (buf1));
822   g_assert (gst_buffer_is_metadata_writable (buf2));
823
824   /* mark buffers */
825   GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
826   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
827
828   /* put buffers in a fixed list */
829   g_value_init (&array, GST_TYPE_ARRAY);
830   g_value_init (&value, GST_TYPE_BUFFER);
831   buf = gst_buffer_copy (buf1);
832   gst_value_set_buffer (&value, buf);
833   gst_buffer_unref (buf);
834   gst_value_array_append_value (&array, &value);
835   g_value_unset (&value);
836   g_value_init (&value, GST_TYPE_BUFFER);
837   buf = gst_buffer_copy (buf2);
838   gst_value_set_buffer (&value, buf);
839   gst_buffer_unref (buf);
840   gst_value_array_append_value (&array, &value);
841   gst_structure_set_value (structure, "streamheader", &array);
842   g_value_unset (&value);
843   g_value_unset (&array);
844
845   return caps;
846 }
847
848
849 static gboolean
850 gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event)
851 {
852   gboolean res = TRUE;
853   GstSpeexEnc *enc;
854
855   enc = GST_SPEEX_ENC (gst_pad_get_parent (pad));
856
857   switch (GST_EVENT_TYPE (event)) {
858     case GST_EVENT_EOS:
859       if (enc->setup)
860         gst_speex_enc_encode (enc, TRUE);
861       res = gst_pad_event_default (pad, event);
862       break;
863     case GST_EVENT_TAG:
864     {
865       if (enc->tags) {
866         GstTagList *list;
867
868         gst_event_parse_tag (event, &list);
869         gst_tag_list_insert (enc->tags, list,
870             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
871       } else {
872         g_assert_not_reached ();
873       }
874       res = gst_pad_event_default (pad, event);
875       break;
876     }
877     default:
878       res = gst_pad_event_default (pad, event);
879       break;
880   }
881
882   gst_object_unref (enc);
883
884   return res;
885 }
886
887 static GstFlowReturn
888 gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush)
889 {
890   gint frame_size = enc->frame_size;
891   gint bytes = frame_size * 2 * enc->channels;
892   GstFlowReturn ret = GST_FLOW_OK;
893
894   if (flush && gst_adapter_available (enc->adapter) % bytes != 0) {
895     guint diff = gst_adapter_available (enc->adapter) % bytes;
896     GstBuffer *buf = gst_buffer_new_and_alloc (diff);
897
898     memset (GST_BUFFER_DATA (buf), 0, diff);
899     gst_adapter_push (enc->adapter, buf);
900   }
901
902   while (gst_adapter_available (enc->adapter) >= bytes) {
903     gint16 *data;
904     gint outsize, written, dtx_ret;
905     GstBuffer *outbuf;
906
907     data = (gint16 *) gst_adapter_take (enc->adapter, bytes);
908
909     enc->samples_in += frame_size;
910
911     GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes);
912
913     if (enc->channels == 2) {
914       speex_encode_stereo_int (data, frame_size, &enc->bits);
915     }
916     dtx_ret = speex_encode_int (enc->state, data, &enc->bits);
917
918     g_free (data);
919
920     enc->frameno++;
921     enc->frameno_out++;
922
923     if ((enc->frameno % enc->nframes) != 0)
924       continue;
925
926     speex_bits_insert_terminator (&enc->bits);
927     outsize = speex_bits_nbytes (&enc->bits);
928
929     ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
930         GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (enc->srcpad), &outbuf);
931
932     if ((GST_FLOW_OK != ret))
933       goto done;
934
935     written = speex_bits_write (&enc->bits,
936         (gchar *) GST_BUFFER_DATA (outbuf), outsize);
937
938     if (G_UNLIKELY (written != outsize)) {
939       GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize);
940       GST_BUFFER_SIZE (outbuf) = written;
941     }
942
943     speex_bits_reset (&enc->bits);
944
945     if (!dtx_ret)
946       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
947
948     GST_BUFFER_TIMESTAMP (outbuf) = enc->start_ts +
949         gst_util_uint64_scale_int ((enc->frameno_out -
950             enc->nframes) * frame_size - enc->lookahead, GST_SECOND, enc->rate);
951     GST_BUFFER_DURATION (outbuf) =
952         gst_util_uint64_scale_int (frame_size * enc->nframes, GST_SECOND,
953         enc->rate);
954     /* set gp time and granulepos; see gst-plugins-base/ext/ogg/README */
955     GST_BUFFER_OFFSET_END (outbuf) = enc->granulepos_offset +
956         ((enc->frameno_out) * frame_size - enc->lookahead);
957     GST_BUFFER_OFFSET (outbuf) =
958         gst_util_uint64_scale_int (GST_BUFFER_OFFSET_END (outbuf), GST_SECOND,
959         enc->rate);
960
961     ret = gst_speex_enc_push_buffer (enc, outbuf);
962
963     if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
964       goto done;
965   }
966
967 done:
968
969   return ret;
970 }
971
972 static GstFlowReturn
973 gst_speex_enc_chain (GstPad * pad, GstBuffer * buf)
974 {
975   GstSpeexEnc *enc;
976   GstFlowReturn ret = GST_FLOW_OK;
977
978   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
979
980   if (!enc->setup)
981     goto not_setup;
982
983   if (!enc->header_sent) {
984     /* Speex streams begin with two headers; the initial header (with
985        most of the codec setup parameters) which is mandated by the Ogg
986        bitstream spec.  The second header holds any comment fields.
987        We merely need to make the headers, then pass them to libspeex 
988        one at a time; libspeex handles the additional Ogg bitstream 
989        constraints */
990     GstBuffer *buf1, *buf2;
991     GstCaps *caps;
992     guchar *data;
993     gint data_len;
994
995     /* create header buffer */
996     data = (guint8 *) speex_header_to_packet (&enc->header, &data_len);
997     buf1 = gst_speex_enc_buffer_from_data (enc, data, data_len, 0);
998     free (data);
999
1000     /* create comment buffer */
1001     buf2 = gst_speex_enc_create_metadata_buffer (enc);
1002
1003     /* mark and put on caps */
1004     caps = gst_pad_get_caps (enc->srcpad);
1005     caps = gst_speex_enc_set_header_on_caps (caps, buf1, buf2);
1006
1007     gst_caps_set_simple (caps,
1008         "rate", G_TYPE_INT, enc->rate,
1009         "channels", G_TYPE_INT, enc->channels, NULL);
1010
1011     /* negotiate with these caps */
1012     GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
1013     gst_pad_set_caps (enc->srcpad, caps);
1014
1015     gst_buffer_set_caps (buf1, caps);
1016     gst_buffer_set_caps (buf2, caps);
1017     gst_caps_unref (caps);
1018
1019     /* push out buffers */
1020     ret = gst_speex_enc_push_buffer (enc, buf1);
1021
1022     if (ret != GST_FLOW_OK) {
1023       gst_buffer_unref (buf2);
1024       goto done;
1025     }
1026
1027     ret = gst_speex_enc_push_buffer (enc, buf2);
1028
1029     if (ret != GST_FLOW_OK)
1030       goto done;
1031
1032     speex_bits_reset (&enc->bits);
1033
1034     enc->header_sent = TRUE;
1035   }
1036
1037   /* Save the timestamp of the first buffer. This will be later
1038    * used as offset for all following buffers */
1039   if (enc->start_ts == GST_CLOCK_TIME_NONE) {
1040     if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1041       enc->start_ts = GST_BUFFER_TIMESTAMP (buf);
1042       enc->granulepos_offset = gst_util_uint64_scale
1043           (GST_BUFFER_TIMESTAMP (buf), enc->rate, GST_SECOND);
1044     } else {
1045       enc->start_ts = 0;
1046       enc->granulepos_offset = 0;
1047     }
1048   }
1049
1050   /* Check if we have a continous stream, if not drop some samples or the buffer or
1051    * insert some silence samples */
1052   if (enc->next_ts != GST_CLOCK_TIME_NONE &&
1053       GST_BUFFER_TIMESTAMP (buf) < enc->next_ts) {
1054     guint64 diff = enc->next_ts - GST_BUFFER_TIMESTAMP (buf);
1055     guint64 diff_bytes;
1056
1057     GST_WARNING_OBJECT (enc, "Buffer is older than previous "
1058         "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
1059         "), cannot handle. Clipping buffer.",
1060         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
1061         GST_TIME_ARGS (enc->next_ts));
1062
1063     diff_bytes = GST_CLOCK_TIME_TO_FRAMES (diff, enc->rate) * enc->channels * 2;
1064     if (diff_bytes >= GST_BUFFER_SIZE (buf)) {
1065       gst_buffer_unref (buf);
1066       return GST_FLOW_OK;
1067     }
1068     buf = gst_buffer_make_metadata_writable (buf);
1069     GST_BUFFER_DATA (buf) += diff_bytes;
1070     GST_BUFFER_SIZE (buf) -= diff_bytes;
1071
1072     GST_BUFFER_TIMESTAMP (buf) += diff;
1073     if (GST_BUFFER_DURATION_IS_VALID (buf))
1074       GST_BUFFER_DURATION (buf) -= diff;
1075   }
1076
1077   if (enc->next_ts != GST_CLOCK_TIME_NONE
1078       && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1079     guint64 max_diff =
1080         gst_util_uint64_scale (enc->frame_size, GST_SECOND, enc->rate);
1081
1082     if (GST_BUFFER_TIMESTAMP (buf) != enc->next_ts &&
1083         GST_BUFFER_TIMESTAMP (buf) - enc->next_ts > max_diff) {
1084       GST_WARNING_OBJECT (enc,
1085           "Discontinuity detected: %" G_GUINT64_FORMAT " > %" G_GUINT64_FORMAT,
1086           GST_BUFFER_TIMESTAMP (buf) - enc->next_ts, max_diff);
1087
1088       gst_speex_enc_encode (enc, TRUE);
1089
1090       enc->frameno_out = 0;
1091       enc->start_ts = GST_BUFFER_TIMESTAMP (buf);
1092       enc->granulepos_offset = gst_util_uint64_scale
1093           (GST_BUFFER_TIMESTAMP (buf), enc->rate, GST_SECOND);
1094     }
1095   }
1096
1097   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)
1098       && GST_BUFFER_DURATION_IS_VALID (buf))
1099     enc->next_ts = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
1100   else
1101     enc->next_ts = GST_CLOCK_TIME_NONE;
1102
1103   GST_DEBUG_OBJECT (enc, "received buffer of %u bytes", GST_BUFFER_SIZE (buf));
1104
1105   /* push buffer to adapter */
1106   gst_adapter_push (enc->adapter, buf);
1107   buf = NULL;
1108
1109   ret = gst_speex_enc_encode (enc, FALSE);
1110
1111 done:
1112
1113   if (buf)
1114     gst_buffer_unref (buf);
1115
1116   return ret;
1117
1118   /* ERRORS */
1119 not_setup:
1120   {
1121     GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL),
1122         ("encoder not initialized (input is not audio?)"));
1123     ret = GST_FLOW_NOT_NEGOTIATED;
1124     goto done;
1125   }
1126
1127 }
1128
1129
1130 static void
1131 gst_speex_enc_get_property (GObject * object, guint prop_id, GValue * value,
1132     GParamSpec * pspec)
1133 {
1134   GstSpeexEnc *enc;
1135
1136   enc = GST_SPEEX_ENC (object);
1137
1138   switch (prop_id) {
1139     case PROP_QUALITY:
1140       g_value_set_float (value, enc->quality);
1141       break;
1142     case PROP_BITRATE:
1143       g_value_set_int (value, enc->bitrate);
1144       break;
1145     case PROP_MODE:
1146       g_value_set_enum (value, enc->mode);
1147       break;
1148     case PROP_VBR:
1149       g_value_set_boolean (value, enc->vbr);
1150       break;
1151     case PROP_ABR:
1152       g_value_set_int (value, enc->abr);
1153       break;
1154     case PROP_VAD:
1155       g_value_set_boolean (value, enc->vad);
1156       break;
1157     case PROP_DTX:
1158       g_value_set_boolean (value, enc->dtx);
1159       break;
1160     case PROP_COMPLEXITY:
1161       g_value_set_int (value, enc->complexity);
1162       break;
1163     case PROP_NFRAMES:
1164       g_value_set_int (value, enc->nframes);
1165       break;
1166     case PROP_LAST_MESSAGE:
1167       g_value_set_string (value, enc->last_message);
1168       break;
1169     default:
1170       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1171       break;
1172   }
1173 }
1174
1175 static void
1176 gst_speex_enc_set_property (GObject * object, guint prop_id,
1177     const GValue * value, GParamSpec * pspec)
1178 {
1179   GstSpeexEnc *enc;
1180
1181   enc = GST_SPEEX_ENC (object);
1182
1183   switch (prop_id) {
1184     case PROP_QUALITY:
1185       enc->quality = g_value_get_float (value);
1186       break;
1187     case PROP_BITRATE:
1188       enc->bitrate = g_value_get_int (value);
1189       break;
1190     case PROP_MODE:
1191       enc->mode = g_value_get_enum (value);
1192       break;
1193     case PROP_VBR:
1194       enc->vbr = g_value_get_boolean (value);
1195       break;
1196     case PROP_ABR:
1197       enc->abr = g_value_get_int (value);
1198       break;
1199     case PROP_VAD:
1200       enc->vad = g_value_get_boolean (value);
1201       break;
1202     case PROP_DTX:
1203       enc->dtx = g_value_get_boolean (value);
1204       break;
1205     case PROP_COMPLEXITY:
1206       enc->complexity = g_value_get_int (value);
1207       break;
1208     case PROP_NFRAMES:
1209       enc->nframes = g_value_get_int (value);
1210       break;
1211     default:
1212       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1213       break;
1214   }
1215 }
1216
1217 static GstStateChangeReturn
1218 gst_speex_enc_change_state (GstElement * element, GstStateChange transition)
1219 {
1220   GstSpeexEnc *enc = GST_SPEEX_ENC (element);
1221   GstStateChangeReturn res;
1222
1223   switch (transition) {
1224     case GST_STATE_CHANGE_NULL_TO_READY:
1225       enc->tags = gst_tag_list_new ();
1226       break;
1227     case GST_STATE_CHANGE_READY_TO_PAUSED:
1228       speex_bits_init (&enc->bits);
1229       enc->frameno = 0;
1230       enc->frameno_out = 0;
1231       enc->samples_in = 0;
1232       enc->start_ts = GST_CLOCK_TIME_NONE;
1233       enc->next_ts = GST_CLOCK_TIME_NONE;
1234       enc->granulepos_offset = 0;
1235       break;
1236     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1237       /* fall through */
1238     default:
1239       break;
1240   }
1241
1242   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1243   if (res == GST_STATE_CHANGE_FAILURE)
1244     return res;
1245
1246   switch (transition) {
1247     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1248       break;
1249     case GST_STATE_CHANGE_PAUSED_TO_READY:
1250       enc->setup = FALSE;
1251       enc->header_sent = FALSE;
1252       if (enc->state) {
1253         speex_encoder_destroy (enc->state);
1254         enc->state = NULL;
1255       }
1256       speex_bits_destroy (&enc->bits);
1257       break;
1258     case GST_STATE_CHANGE_READY_TO_NULL:
1259       gst_tag_list_free (enc->tags);
1260       enc->tags = NULL;
1261     default:
1262       break;
1263   }
1264
1265   return res;
1266 }