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