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