Speexenc ported to 0.9.
[platform/upstream/gstreamer.git] / ext / speex / gstspeexenc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <math.h>
28 #include <speex/speex.h>
29 #include <speex/speex_stereo.h>
30
31 #include <gst/gsttagsetter.h>
32 #include <gst/tag/tag.h>
33 #include "gstspeexenc.h"
34
35 GST_DEBUG_CATEGORY (speexenc_debug);
36 #define GST_CAT_DEFAULT speexenc_debug
37
38 static GstPadTemplate *gst_speexenc_src_template, *gst_speexenc_sink_template;
39
40 /* elementfactory information */
41 GstElementDetails speexenc_details = {
42   "Speex encoder",
43   "Codec/Encoder/Audio",
44   "Encodes audio in Speex format",
45   "Wim Taymans <wim@fluendo.com>",
46 };
47
48 /* GstSpeexEnc signals and args */
49 enum
50 {
51   /* FILL ME */
52   LAST_SIGNAL
53 };
54
55 #define DEFAULT_QUALITY         8.0
56 #define DEFAULT_BITRATE         0
57 #define DEFAULT_VBR             FALSE
58 #define DEFAULT_ABR             0
59 #define DEFAULT_VAD             FALSE
60 #define DEFAULT_DTX             FALSE
61 #define DEFAULT_COMPLEXITY      3
62 #define DEFAULT_NFRAMES         1
63
64 enum
65 {
66   ARG_0,
67   ARG_QUALITY,
68   ARG_BITRATE,
69   ARG_VBR,
70   ARG_ABR,
71   ARG_VAD,
72   ARG_DTX,
73   ARG_COMPLEXITY,
74   ARG_NFRAMES,
75   ARG_LAST_MESSAGE
76 };
77
78 #if 0
79 static const GstFormat *
80 gst_speexenc_get_formats (GstPad * pad)
81 {
82   static const GstFormat src_formats[] = {
83     GST_FORMAT_BYTES,
84     GST_FORMAT_TIME,
85     0
86   };
87   static const GstFormat sink_formats[] = {
88     GST_FORMAT_BYTES,
89     GST_FORMAT_DEFAULT,
90     GST_FORMAT_TIME,
91     0
92   };
93
94   return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
95 }
96 #endif
97
98 static void gst_speexenc_base_init (gpointer g_class);
99 static void gst_speexenc_class_init (GstSpeexEncClass * klass);
100 static void gst_speexenc_init (GstSpeexEnc * speexenc);
101
102 static gboolean gst_speexenc_sinkevent (GstPad * pad, GstEvent * event);
103 static GstFlowReturn gst_speexenc_chain (GstPad * pad, GstBuffer * buf);
104 static gboolean gst_speexenc_setup (GstSpeexEnc * speexenc);
105
106 static void gst_speexenc_get_property (GObject * object, guint prop_id,
107     GValue * value, GParamSpec * pspec);
108 static void gst_speexenc_set_property (GObject * object, guint prop_id,
109     const GValue * value, GParamSpec * pspec);
110 static GstStateChangeReturn gst_speexenc_change_state (GstElement * element,
111     GstStateChange transition);
112
113 static GstElementClass *parent_class = NULL;
114
115 /*static guint gst_speexenc_signals[LAST_SIGNAL] = { 0 }; */
116
117 GType
118 gst_speexenc_get_type (void)
119 {
120   static GType speexenc_type = 0;
121
122   if (!speexenc_type) {
123     static const GTypeInfo speexenc_info = {
124       sizeof (GstSpeexEncClass),
125       gst_speexenc_base_init,
126       NULL,
127       (GClassInitFunc) gst_speexenc_class_init,
128       NULL,
129       NULL,
130       sizeof (GstSpeexEnc),
131       0,
132       (GInstanceInitFunc) gst_speexenc_init,
133     };
134     static const GInterfaceInfo tag_setter_info = {
135       NULL,
136       NULL,
137       NULL
138     };
139
140     speexenc_type =
141         g_type_register_static (GST_TYPE_ELEMENT, "GstSpeexEnc", &speexenc_info,
142         0);
143
144     g_type_add_interface_static (speexenc_type, GST_TYPE_TAG_SETTER,
145         &tag_setter_info);
146
147     GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
148   }
149   return speexenc_type;
150 }
151
152 static GstCaps *
153 speex_caps_factory (void)
154 {
155   return gst_caps_new_simple ("audio/x-speex", NULL);
156 }
157
158 static GstCaps *
159 raw_caps_factory (void)
160 {
161   return
162       gst_caps_new_simple ("audio/x-raw-int",
163       "rate", GST_TYPE_INT_RANGE, 6000, 48000,
164       "channels", GST_TYPE_INT_RANGE, 1, 2,
165       "endianness", G_TYPE_INT, G_BYTE_ORDER,
166       "signed", G_TYPE_BOOLEAN, TRUE,
167       "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, NULL);
168 }
169
170 static void
171 gst_speexenc_base_init (gpointer g_class)
172 {
173   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
174   GstCaps *raw_caps, *speex_caps;
175
176   raw_caps = raw_caps_factory ();
177   speex_caps = speex_caps_factory ();
178
179   gst_speexenc_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
180       GST_PAD_ALWAYS, raw_caps);
181   gst_speexenc_src_template = gst_pad_template_new ("src", GST_PAD_SRC,
182       GST_PAD_ALWAYS, speex_caps);
183   gst_element_class_add_pad_template (element_class,
184       gst_speexenc_sink_template);
185   gst_element_class_add_pad_template (element_class, gst_speexenc_src_template);
186   gst_element_class_set_details (element_class, &speexenc_details);
187 }
188
189 static void
190 gst_speexenc_class_init (GstSpeexEncClass * klass)
191 {
192   GObjectClass *gobject_class;
193   GstElementClass *gstelement_class;
194
195   gobject_class = (GObjectClass *) klass;
196   gstelement_class = (GstElementClass *) klass;
197
198   gobject_class->set_property = gst_speexenc_set_property;
199   gobject_class->get_property = gst_speexenc_get_property;
200
201   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
202       g_param_spec_float ("quality", "Quality", "Encoding quality",
203           0.0, 10.0, DEFAULT_QUALITY, G_PARAM_READWRITE));
204   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
205       g_param_spec_int ("bitrate", "Encoding Bit-rate",
206           "Specify an encoding bit-rate (in bps). (0 = automatic)",
207           0, G_MAXINT, DEFAULT_BITRATE, G_PARAM_READWRITE));
208   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
209       g_param_spec_boolean ("vbr", "VBR",
210           "Enable variable bit-rate", DEFAULT_VBR, G_PARAM_READWRITE));
211   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ABR,
212       g_param_spec_int ("abr", "ABR",
213           "Enable average bit-rate (0 = disabled)",
214           0, G_MAXINT, DEFAULT_ABR, G_PARAM_READWRITE));
215   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VAD,
216       g_param_spec_boolean ("vad", "VAD",
217           "Enable voice activity detection", DEFAULT_VAD, G_PARAM_READWRITE));
218   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DTX,
219       g_param_spec_boolean ("dtx", "DTX",
220           "Enable discontinuous transmission", DEFAULT_DTX, G_PARAM_READWRITE));
221   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COMPLEXITY,
222       g_param_spec_int ("complexity", "Complexity",
223           "Set encoding complexity",
224           0, G_MAXINT, DEFAULT_COMPLEXITY, G_PARAM_READWRITE));
225   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NFRAMES,
226       g_param_spec_int ("nframes", "NFrames",
227           "Number of frames per buffer",
228           0, G_MAXINT, DEFAULT_NFRAMES, G_PARAM_READWRITE));
229   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
230       g_param_spec_string ("last-message", "last-message",
231           "The last status message", NULL, G_PARAM_READABLE));
232
233   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
234
235   gstelement_class->change_state = gst_speexenc_change_state;
236 }
237
238 static gboolean
239 gst_speexenc_sink_setcaps (GstPad * pad, GstCaps * caps)
240 {
241   GstSpeexEnc *speexenc;
242   GstStructure *structure;
243
244   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
245   speexenc->setup = FALSE;
246
247   structure = gst_caps_get_structure (caps, 0);
248   gst_structure_get_int (structure, "channels", &speexenc->channels);
249   gst_structure_get_int (structure, "rate", &speexenc->rate);
250
251   gst_speexenc_setup (speexenc);
252
253   if (speexenc->setup)
254     return TRUE;
255
256   return FALSE;
257 }
258
259 static gboolean
260 gst_speexenc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
261     GstFormat * dest_format, gint64 * dest_value)
262 {
263   gboolean res = TRUE;
264   GstSpeexEnc *speexenc;
265   gint64 avg;
266
267   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
268
269   if (speexenc->samples_in == 0 ||
270       speexenc->bytes_out == 0 || speexenc->rate == 0)
271     return FALSE;
272
273   avg = (speexenc->bytes_out * speexenc->rate) / (speexenc->samples_in);
274
275   switch (src_format) {
276     case GST_FORMAT_BYTES:
277       switch (*dest_format) {
278         case GST_FORMAT_TIME:
279           *dest_value = src_value * GST_SECOND / avg;
280           break;
281         default:
282           res = FALSE;
283       }
284       break;
285     case GST_FORMAT_TIME:
286       switch (*dest_format) {
287         case GST_FORMAT_BYTES:
288           *dest_value = src_value * avg / GST_SECOND;
289           break;
290         default:
291           res = FALSE;
292       }
293       break;
294     default:
295       res = FALSE;
296   }
297   return res;
298 }
299
300 static gboolean
301 gst_speexenc_convert_sink (GstPad * pad, GstFormat src_format,
302     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
303 {
304   gboolean res = TRUE;
305   guint scale = 1;
306   gint bytes_per_sample;
307   GstSpeexEnc *speexenc;
308
309   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
310
311   bytes_per_sample = speexenc->channels * 2;
312
313   switch (src_format) {
314     case GST_FORMAT_BYTES:
315       switch (*dest_format) {
316         case GST_FORMAT_DEFAULT:
317           if (bytes_per_sample == 0)
318             return FALSE;
319           *dest_value = src_value / bytes_per_sample;
320           break;
321         case GST_FORMAT_TIME:
322         {
323           gint byterate = bytes_per_sample * speexenc->rate;
324
325           if (byterate == 0)
326             return FALSE;
327           *dest_value = src_value * GST_SECOND / byterate;
328           break;
329         }
330         default:
331           res = FALSE;
332       }
333       break;
334     case GST_FORMAT_DEFAULT:
335       switch (*dest_format) {
336         case GST_FORMAT_BYTES:
337           *dest_value = src_value * bytes_per_sample;
338           break;
339         case GST_FORMAT_TIME:
340           if (speexenc->rate == 0)
341             return FALSE;
342           *dest_value = src_value * GST_SECOND / speexenc->rate;
343           break;
344         default:
345           res = FALSE;
346       }
347       break;
348     case GST_FORMAT_TIME:
349       switch (*dest_format) {
350         case GST_FORMAT_BYTES:
351           scale = bytes_per_sample;
352           /* fallthrough */
353         case GST_FORMAT_DEFAULT:
354           *dest_value = src_value * scale * speexenc->rate / GST_SECOND;
355           break;
356         default:
357           res = FALSE;
358       }
359       break;
360     default:
361       res = FALSE;
362   }
363   return res;
364 }
365
366 static const GstQueryType *
367 gst_speexenc_get_query_types (GstPad * pad)
368 {
369   static const GstQueryType gst_speexenc_src_query_types[] = {
370     GST_QUERY_POSITION,
371     0
372   };
373
374   return gst_speexenc_src_query_types;
375 }
376
377 static gboolean
378 gst_speexenc_src_query (GstPad * pad, GstQuery * query)
379 {
380   gboolean res = TRUE;
381   GstSpeexEnc *speexenc;
382
383   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
384
385   switch (GST_QUERY_TYPE (query)) {
386     case GST_QUERY_POSITION:
387     {
388 #if 0
389       switch (*format) {
390         case GST_FORMAT_BYTES:
391         case GST_FORMAT_TIME:
392         {
393           gint64 peer_value;
394           const GstFormat *peer_formats;
395
396           res = FALSE;
397
398           peer_formats = gst_pad_get_formats (GST_PAD_PEER (speexenc->sinkpad));
399
400           while (peer_formats && *peer_formats && !res) {
401
402             GstFormat peer_format = *peer_formats;
403
404             /* do the probe */
405             if (gst_pad_query (GST_PAD_PEER (speexenc->sinkpad),
406                     GST_QUERY_TOTAL, &peer_format, &peer_value)) {
407               GstFormat conv_format;
408
409               /* convert to TIME */
410               conv_format = GST_FORMAT_TIME;
411               res = gst_pad_convert (speexenc->sinkpad,
412                   peer_format, peer_value, &conv_format, value);
413               /* and to final format */
414               res &= gst_pad_convert (pad,
415                   GST_FORMAT_TIME, *value, format, value);
416             }
417             peer_formats++;
418           }
419           break;
420         }
421       }
422 #endif
423       res = FALSE;
424       break;
425     }
426     case GST_QUERY_CONVERT:
427     {
428       GstFormat src_fmt, dest_fmt;
429       gint64 src_val, dest_val;
430
431       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
432       if (!(res = gst_speexenc_convert_src (pad, src_fmt, src_val, &dest_fmt,
433                   &dest_val)))
434         goto error;
435       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
436       break;
437     }
438     default:
439       res = FALSE;
440       break;
441   }
442
443 error:
444   return res;
445 }
446
447 static gboolean
448 gst_speexenc_sink_query (GstPad * pad, GstQuery * query)
449 {
450   gboolean res = TRUE;
451   GstSpeexEnc *speexenc;
452
453   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
454
455   switch (GST_QUERY_TYPE (query)) {
456     case GST_QUERY_CONVERT:
457     {
458       GstFormat src_fmt, dest_fmt;
459       gint64 src_val, dest_val;
460
461       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
462       if (!(res =
463               gst_speexenc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
464                   &dest_val)))
465         goto error;
466       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
467       break;
468     }
469     default:
470       res = FALSE;
471       break;
472   }
473
474 error:
475   return res;
476 }
477
478 static void
479 gst_speexenc_init (GstSpeexEnc * speexenc)
480 {
481   speexenc->sinkpad =
482       gst_pad_new_from_template (gst_speexenc_sink_template, "sink");
483   gst_element_add_pad (GST_ELEMENT (speexenc), speexenc->sinkpad);
484   gst_pad_set_event_function (speexenc->sinkpad, gst_speexenc_sinkevent);
485   gst_pad_set_chain_function (speexenc->sinkpad, gst_speexenc_chain);
486   gst_pad_set_setcaps_function (speexenc->sinkpad, gst_speexenc_sink_setcaps);
487   gst_pad_set_query_function (speexenc->sinkpad,
488       GST_DEBUG_FUNCPTR (gst_speexenc_sink_query));
489
490   speexenc->srcpad =
491       gst_pad_new_from_template (gst_speexenc_src_template, "src");
492   gst_pad_set_query_function (speexenc->srcpad,
493       GST_DEBUG_FUNCPTR (gst_speexenc_src_query));
494   gst_pad_set_query_type_function (speexenc->srcpad,
495       GST_DEBUG_FUNCPTR (gst_speexenc_get_query_types));
496   gst_element_add_pad (GST_ELEMENT (speexenc), speexenc->srcpad);
497
498   speexenc->channels = -1;
499   speexenc->rate = -1;
500
501   speexenc->quality = DEFAULT_QUALITY;
502   speexenc->bitrate = DEFAULT_BITRATE;
503   speexenc->vbr = DEFAULT_VBR;
504   speexenc->abr = DEFAULT_ABR;
505   speexenc->vad = DEFAULT_VAD;
506   speexenc->dtx = DEFAULT_DTX;
507   speexenc->complexity = DEFAULT_COMPLEXITY;
508   speexenc->nframes = DEFAULT_NFRAMES;
509
510   speexenc->setup = FALSE;
511   speexenc->header_sent = FALSE;
512
513   speexenc->adapter = gst_adapter_new ();
514 }
515
516
517 static gchar *
518 gst_speexenc_get_tag_value (const GstTagList * list, const gchar * tag,
519     int index)
520 {
521   gchar *speexvalue = NULL;
522
523   if (tag == NULL) {
524     return NULL;
525   }
526
527   /* get tag name right */
528   if ((strcmp (tag, GST_TAG_TRACK_NUMBER) == 0)
529       || (strcmp (tag, GST_TAG_ALBUM_VOLUME_NUMBER) == 0)
530       || (strcmp (tag, GST_TAG_TRACK_COUNT) == 0)
531       || (strcmp (tag, GST_TAG_ALBUM_VOLUME_COUNT) == 0)) {
532     guint track_no;
533
534     if (!gst_tag_list_get_uint_index (list, tag, index, &track_no))
535       g_assert_not_reached ();
536     speexvalue = g_strdup_printf ("%u", track_no);
537   } else if (strcmp (tag, GST_TAG_DATE) == 0) {
538     /* FIXME: how are dates represented in speex files? */
539     GDate *date;
540     guint u;
541
542     if (!gst_tag_list_get_uint_index (list, tag, index, &u))
543       g_assert_not_reached ();
544     date = g_date_new_julian (u);
545     speexvalue =
546         g_strdup_printf ("%04d-%02d-%02d", (gint) g_date_get_year (date),
547         (gint) g_date_get_month (date), (gint) g_date_get_day (date));
548     g_date_free (date);
549   } else if (gst_tag_get_type (tag) == G_TYPE_STRING) {
550     if (!gst_tag_list_get_string_index (list, tag, index, &speexvalue))
551       g_assert_not_reached ();
552   }
553
554   return speexvalue;
555 }
556
557 /*
558  *  Comments will be stored in the Vorbis style.
559  *  It is describled in the "Structure" section of
560  *  http://www.xiph.org/ogg/vorbis/doc/v-comment.html
561  *
562  *  The comment header is decoded as follows:
563  *  1) [vendor_length] = read an unsigned integer of 32 bits
564  *  2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
565  *  3) [user_comment_list_length] = read an unsigned integer of 32 bits
566  *  4) iterate [user_comment_list_length] times {
567  *     5) [length] = read an unsigned integer of 32 bits
568  *     6) this iteration's user comment = read a UTF-8 vector as [length] octets
569  *     }
570  *  7) [framing_bit] = read a single bit as boolean
571  *  8) if ( [framing_bit]  unset or end of packet ) then ERROR
572  *  9) done.
573  *
574  *  If you have troubles, please write to ymnk@jcraft.com.
575  */
576 #define readint(buf, base) (((buf[base+3]<<24) & 0xff000000)|   \
577                             ((buf[base+2]<<16) & 0xff0000)|     \
578                             ((buf[base+1]<< 8) & 0xff00)|       \
579                             (buf[base  ]      & 0xff))
580 #define writeint(buf, base, val) do{ buf[base+3] = ((val)>>24) & 0xff;  \
581     buf[base+2] = ((val)>>16) & 0xff;                                   \
582     buf[base+1] = ((val)>> 8) & 0xff;                                   \
583     buf[base  ] =  (val)      & 0xff;                                   \
584   }while(0)
585
586 static void
587 comment_init (char **comments, int *length, char *vendor_string)
588 {
589   int vendor_length = strlen (vendor_string);
590   int user_comment_list_length = 0;
591   int len = 4 + vendor_length + 4;
592   char *p = (char *) malloc (len);
593
594   if (p == NULL) {
595   }
596   writeint (p, 0, vendor_length);
597   memcpy (p + 4, vendor_string, vendor_length);
598   writeint (p, 4 + vendor_length, user_comment_list_length);
599   *length = len;
600   *comments = p;
601 }
602 static void
603 comment_add (char **comments, int *length, const char *tag, char *val)
604 {
605   char *p = *comments;
606   int vendor_length = readint (p, 0);
607   int user_comment_list_length = readint (p, 4 + vendor_length);
608   int tag_len = (tag ? strlen (tag) : 0);
609   int val_len = strlen (val);
610   int len = (*length) + 4 + tag_len + val_len;
611
612   p = (char *) realloc (p, len);
613
614   writeint (p, *length, tag_len + val_len);     /* length of comment */
615   if (tag)
616     memcpy (p + *length + 4, tag, tag_len);     /* comment */
617   memcpy (p + *length + 4 + tag_len, val, val_len);     /* comment */
618   writeint (p, 4 + vendor_length, user_comment_list_length + 1);
619
620   *comments = p;
621   *length = len;
622 }
623
624 #undef readint
625 #undef writeint
626
627 static void
628 gst_speexenc_metadata_set1 (const GstTagList * list, const gchar * tag,
629     gpointer speexenc)
630 {
631   const gchar *speextag = NULL;
632   gchar *speexvalue = NULL;
633   guint i, count;
634   GstSpeexEnc *enc = GST_SPEEXENC (speexenc);
635
636   speextag = gst_tag_to_vorbis_tag (tag);
637   if (speextag == NULL) {
638     return;
639   }
640
641   count = gst_tag_list_get_tag_size (list, tag);
642   for (i = 0; i < count; i++) {
643     speexvalue = gst_speexenc_get_tag_value (list, tag, i);
644
645     if (speexvalue != NULL) {
646       comment_add (&enc->comments, &enc->comment_len, speextag, speexvalue);
647     }
648   }
649 }
650
651 static void
652 gst_speexenc_set_metadata (GstSpeexEnc * speexenc)
653 {
654   GstTagList *copy;
655   const GstTagList *user_tags;
656
657   user_tags = gst_tag_setter_get_list (GST_TAG_SETTER (speexenc));
658   if (!(speexenc->tags || user_tags))
659     return;
660
661   comment_init (&speexenc->comments, &speexenc->comment_len,
662       "Encoded with GStreamer Speexenc");
663   copy =
664       gst_tag_list_merge (user_tags, speexenc->tags,
665       gst_tag_setter_get_merge_mode (GST_TAG_SETTER (speexenc)));
666   gst_tag_list_foreach (copy, gst_speexenc_metadata_set1, speexenc);
667   gst_tag_list_free (copy);
668 }
669
670 static gboolean
671 gst_speexenc_setup (GstSpeexEnc * speexenc)
672 {
673   speexenc->setup = FALSE;
674
675   switch (speexenc->mode) {
676     case GST_SPEEXENC_MODE_UWB:
677       speexenc->speex_mode = (SpeexMode *) & speex_uwb_mode;
678       break;
679     case GST_SPEEXENC_MODE_WB:
680       speexenc->speex_mode = (SpeexMode *) & speex_wb_mode;
681       break;
682     case GST_SPEEXENC_MODE_NB:
683       speexenc->speex_mode = (SpeexMode *) & speex_nb_mode;
684       break;
685     case GST_SPEEXENC_MODE_AUTO:
686       /* fall through */
687     default:
688       break;
689   }
690
691   if (speexenc->rate > 25000) {
692     if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
693       speexenc->speex_mode = (SpeexMode *) & speex_uwb_mode;
694     } else {
695       if (speexenc->speex_mode != &speex_uwb_mode) {
696         speexenc->last_message =
697             g_strdup_printf
698             ("Warning: suggest to use ultra wide band mode for this rate");
699         g_object_notify (G_OBJECT (speexenc), "last_message");
700       }
701     }
702   } else if (speexenc->rate > 12500) {
703     if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
704       speexenc->speex_mode = (SpeexMode *) & speex_wb_mode;
705     } else {
706       if (speexenc->speex_mode != &speex_wb_mode) {
707         speexenc->last_message =
708             g_strdup_printf
709             ("Warning: suggest to use wide band mode for this rate");
710         g_object_notify (G_OBJECT (speexenc), "last_message");
711       }
712     }
713   } else {
714     if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
715       speexenc->speex_mode = (SpeexMode *) & speex_nb_mode;
716     } else {
717       if (speexenc->speex_mode != &speex_nb_mode) {
718         speexenc->last_message =
719             g_strdup_printf
720             ("Warning: suggest to use narrow band mode for this rate");
721         g_object_notify (G_OBJECT (speexenc), "last_message");
722       }
723     }
724   }
725
726   if (speexenc->rate != 8000 && speexenc->rate != 16000
727       && speexenc->rate != 32000) {
728     speexenc->last_message =
729         g_strdup_printf ("Warning: speex is optimized for 8, 16 and 32 KHz");
730     g_object_notify (G_OBJECT (speexenc), "last_message");
731   }
732
733   speex_init_header (&speexenc->header, speexenc->rate, 1,
734       speexenc->speex_mode);
735   speexenc->header.frames_per_packet = speexenc->nframes;
736   speexenc->header.vbr = speexenc->vbr;
737   speexenc->header.nb_channels = speexenc->channels;
738
739   /*Initialize Speex encoder */
740   speexenc->state = speex_encoder_init (speexenc->speex_mode);
741
742   speex_encoder_ctl (speexenc->state, SPEEX_GET_FRAME_SIZE,
743       &speexenc->frame_size);
744   speex_encoder_ctl (speexenc->state, SPEEX_SET_COMPLEXITY,
745       &speexenc->complexity);
746   speex_encoder_ctl (speexenc->state, SPEEX_SET_SAMPLING_RATE, &speexenc->rate);
747
748   if (speexenc->vbr)
749     speex_encoder_ctl (speexenc->state, SPEEX_SET_VBR_QUALITY,
750         &speexenc->quality);
751   else {
752     gint tmp = floor (speexenc->quality);
753
754     speex_encoder_ctl (speexenc->state, SPEEX_SET_QUALITY, &tmp);
755   }
756   if (speexenc->bitrate) {
757     if (speexenc->quality >= 0.0 && speexenc->vbr) {
758       speexenc->last_message =
759           g_strdup_printf ("Warning: bitrate option is overriding quality");
760       g_object_notify (G_OBJECT (speexenc), "last_message");
761     }
762     speex_encoder_ctl (speexenc->state, SPEEX_SET_BITRATE, &speexenc->bitrate);
763   }
764   if (speexenc->vbr) {
765     gint tmp = 1;
766
767     speex_encoder_ctl (speexenc->state, SPEEX_SET_VBR, &tmp);
768   } else if (speexenc->vad) {
769     gint tmp = 1;
770
771     speex_encoder_ctl (speexenc->state, SPEEX_SET_VAD, &tmp);
772   }
773
774   if (speexenc->dtx) {
775     gint tmp = 1;
776
777     speex_encoder_ctl (speexenc->state, SPEEX_SET_DTX, &tmp);
778   }
779
780   if (speexenc->dtx && !(speexenc->vbr || speexenc->abr || speexenc->vad)) {
781     speexenc->last_message =
782         g_strdup_printf ("Warning: dtx is useless without vad, vbr or abr");
783     g_object_notify (G_OBJECT (speexenc), "last_message");
784   } else if ((speexenc->vbr || speexenc->abr) && (speexenc->vad)) {
785     speexenc->last_message =
786         g_strdup_printf ("Warning: vad is already implied by vbr or abr");
787     g_object_notify (G_OBJECT (speexenc), "last_message");
788   }
789
790   if (speexenc->abr) {
791     speex_encoder_ctl (speexenc->state, SPEEX_SET_ABR, &speexenc->abr);
792   }
793
794   speex_encoder_ctl (speexenc->state, SPEEX_GET_LOOKAHEAD,
795       &speexenc->lookahead);
796
797   speexenc->setup = TRUE;
798
799   return TRUE;
800 }
801
802 /* prepare a buffer for transmission */
803 static GstBuffer *
804 gst_speexenc_buffer_from_data (GstSpeexEnc * speexenc, guchar * data,
805     gint data_len, guint64 granulepos)
806 {
807   GstBuffer *outbuf;
808
809   outbuf = gst_buffer_new_and_alloc (data_len);
810   memcpy (GST_BUFFER_DATA (outbuf), data, data_len);
811   GST_BUFFER_OFFSET (outbuf) = speexenc->bytes_out;
812   GST_BUFFER_OFFSET_END (outbuf) = granulepos;
813
814   GST_DEBUG ("encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
815   return outbuf;
816 }
817
818 /* push out the buffer and do internal bookkeeping */
819 static void
820 gst_speexenc_push_buffer (GstSpeexEnc * speexenc, GstBuffer * buffer)
821 {
822   speexenc->bytes_out += GST_BUFFER_SIZE (buffer);
823
824   if (GST_PAD_IS_USABLE (speexenc->srcpad)) {
825     gst_pad_push (speexenc->srcpad, buffer);
826   } else {
827     gst_buffer_unref (buffer);
828   }
829 }
830
831 static GstCaps *
832 gst_speexenc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
833     GstBuffer * buf2)
834 {
835   caps = gst_caps_make_writable (caps);
836   GstStructure *structure = gst_caps_get_structure (caps, 0);
837   GValue list = { 0 };
838   GValue value = { 0 };
839
840   /* mark buffers */
841   GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
842   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
843
844   /* put buffers in a fixed list */
845   g_value_init (&list, GST_TYPE_ARRAY);
846   g_value_init (&value, GST_TYPE_BUFFER);
847   gst_value_set_buffer (&value, buf1);
848   gst_value_list_append_value (&list, &value);
849   g_value_unset (&value);
850   g_value_init (&value, GST_TYPE_BUFFER);
851   gst_value_set_buffer (&value, buf2);
852   gst_value_list_append_value (&list, &value);
853   gst_structure_set_value (structure, "streamheader", &list);
854   g_value_unset (&value);
855   g_value_unset (&list);
856
857   return caps;
858 }
859
860
861 static gboolean
862 gst_speexenc_sinkevent (GstPad * pad, GstEvent * event)
863 {
864   gboolean res = TRUE;
865   GstSpeexEnc *speexenc;
866
867   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
868
869   switch (GST_EVENT_TYPE (event)) {
870     case GST_EVENT_EOS:
871       speexenc->eos = TRUE;
872       res = gst_pad_event_default (pad, event);
873       break;
874     case GST_EVENT_TAG:
875     {
876       GstTagList *list;
877
878       gst_event_parse_tag (event, &list);
879       if (speexenc->tags) {
880         gst_tag_list_insert (speexenc->tags, list,
881             gst_tag_setter_get_merge_mode (GST_TAG_SETTER (speexenc)));
882       } else {
883         g_assert_not_reached ();
884       }
885       res = gst_pad_event_default (pad, event);
886       break;
887     }
888     default:
889       res = gst_pad_event_default (pad, event);
890       break;
891   }
892   return res;
893 }
894
895 static GstFlowReturn
896 gst_speexenc_chain (GstPad * pad, GstBuffer * buf)
897 {
898   GstSpeexEnc *speexenc;
899
900   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
901
902   if (!speexenc->setup) {
903     gst_buffer_unref (buf);
904     GST_ELEMENT_ERROR (speexenc, CORE, NEGOTIATION, (NULL),
905         ("encoder not initialized (input is not audio?)"));
906     return GST_FLOW_UNEXPECTED;
907   }
908
909   if (!speexenc->header_sent) {
910     /* Speex streams begin with two headers; the initial header (with
911        most of the codec setup parameters) which is mandated by the Ogg
912        bitstream spec.  The second header holds any comment fields.
913        We merely need to make the headers, then pass them to libspeex 
914        one at a time; libspeex handles the additional Ogg bitstream 
915        constraints */
916     GstBuffer *buf1, *buf2;
917     GstCaps *caps;
918     guchar *data;
919     gint data_len;
920
921     gst_speexenc_set_metadata (speexenc);
922
923     /* create header buffer */
924     data = speex_header_to_packet (&speexenc->header, &data_len);
925     buf1 = gst_speexenc_buffer_from_data (speexenc, data, data_len, 0);
926
927     /* create comment buffer */
928     buf2 =
929         gst_speexenc_buffer_from_data (speexenc, speexenc->comments,
930         speexenc->comment_len, 0);
931
932     /* mark and put on caps */
933     caps = gst_pad_get_caps (speexenc->srcpad);
934     caps = gst_speexenc_set_header_on_caps (caps, buf1, buf2);
935
936     /* negotiate with these caps */
937     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
938     gst_pad_set_caps (speexenc->srcpad, caps);
939
940     gst_buffer_set_caps (buf1, caps);
941     gst_buffer_set_caps (buf2, caps);
942
943     /* push out buffers */
944     gst_speexenc_push_buffer (speexenc, buf1);
945     gst_speexenc_push_buffer (speexenc, buf2);
946
947     speex_bits_init (&speexenc->bits);
948     speex_bits_reset (&speexenc->bits);
949
950     speexenc->header_sent = TRUE;
951   }
952
953   {
954     gint frame_size = speexenc->frame_size;
955     gint bytes = frame_size * 2 * speexenc->channels;
956
957     /* push buffer to adapter */
958     gst_adapter_push (speexenc->adapter, buf);
959
960     while (gst_adapter_available (speexenc->adapter) >= bytes) {
961       gint16 *data;
962       gint i;
963       gint outsize, written;
964       GstBuffer *outbuf;
965
966       data = (gint16 *) gst_adapter_peek (speexenc->adapter, bytes);
967
968       for (i = 0; i < frame_size * speexenc->channels; i++) {
969         speexenc->input[i] = (gfloat) data[i];
970       }
971       gst_adapter_flush (speexenc->adapter, bytes);
972
973       speexenc->samples_in += frame_size;
974
975       if (speexenc->channels == 2) {
976         speex_encode_stereo (speexenc->input, frame_size, &speexenc->bits);
977       }
978       speex_encode (speexenc->state, speexenc->input, &speexenc->bits);
979
980       speexenc->frameno++;
981
982       if ((speexenc->frameno % speexenc->nframes) != 0)
983         continue;
984
985       speex_bits_insert_terminator (&speexenc->bits);
986       outsize = speex_bits_nbytes (&speexenc->bits);
987
988       gst_pad_alloc_buffer (speexenc->srcpad,
989           GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (speexenc->srcpad),
990           &outbuf);
991
992       written =
993           speex_bits_write (&speexenc->bits, GST_BUFFER_DATA (outbuf), outsize);
994       g_assert (written == outsize);
995       speex_bits_reset (&speexenc->bits);
996
997       GST_BUFFER_TIMESTAMP (outbuf) =
998           (speexenc->frameno * frame_size -
999           speexenc->lookahead) * GST_SECOND / speexenc->rate;
1000       GST_BUFFER_DURATION (outbuf) = frame_size * GST_SECOND / speexenc->rate;
1001       GST_BUFFER_OFFSET (outbuf) = speexenc->bytes_out;
1002       GST_BUFFER_OFFSET_END (outbuf) =
1003           speexenc->frameno * frame_size - speexenc->lookahead;
1004
1005       gst_speexenc_push_buffer (speexenc, outbuf);
1006     }
1007   }
1008
1009   return GST_FLOW_OK;
1010 }
1011
1012 static void
1013 gst_speexenc_get_property (GObject * object, guint prop_id, GValue * value,
1014     GParamSpec * pspec)
1015 {
1016   GstSpeexEnc *speexenc;
1017
1018   g_return_if_fail (GST_IS_SPEEXENC (object));
1019
1020   speexenc = GST_SPEEXENC (object);
1021
1022   switch (prop_id) {
1023     case ARG_QUALITY:
1024       g_value_set_float (value, speexenc->quality);
1025       break;
1026     case ARG_BITRATE:
1027       g_value_set_int (value, speexenc->bitrate);
1028       break;
1029     case ARG_VBR:
1030       g_value_set_boolean (value, speexenc->vbr);
1031       break;
1032     case ARG_ABR:
1033       g_value_set_int (value, speexenc->abr);
1034       break;
1035     case ARG_VAD:
1036       g_value_set_boolean (value, speexenc->vad);
1037       break;
1038     case ARG_DTX:
1039       g_value_set_boolean (value, speexenc->dtx);
1040       break;
1041     case ARG_COMPLEXITY:
1042       g_value_set_int (value, speexenc->complexity);
1043       break;
1044     case ARG_NFRAMES:
1045       g_value_set_int (value, speexenc->nframes);
1046       break;
1047     case ARG_LAST_MESSAGE:
1048       g_value_set_string (value, speexenc->last_message);
1049       break;
1050     default:
1051       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1052       break;
1053   }
1054 }
1055
1056 static void
1057 gst_speexenc_set_property (GObject * object, guint prop_id,
1058     const GValue * value, GParamSpec * pspec)
1059 {
1060   GstSpeexEnc *speexenc;
1061
1062   g_return_if_fail (GST_IS_SPEEXENC (object));
1063
1064   speexenc = GST_SPEEXENC (object);
1065
1066   switch (prop_id) {
1067     case ARG_QUALITY:
1068       speexenc->quality = g_value_get_float (value);
1069       break;
1070     case ARG_BITRATE:
1071       speexenc->bitrate = g_value_get_int (value);
1072       break;
1073     case ARG_VBR:
1074       speexenc->vbr = g_value_get_boolean (value);
1075       break;
1076     case ARG_ABR:
1077       speexenc->abr = g_value_get_int (value);
1078       break;
1079     case ARG_VAD:
1080       speexenc->vad = g_value_get_boolean (value);
1081       break;
1082     case ARG_DTX:
1083       speexenc->dtx = g_value_get_boolean (value);
1084       break;
1085     case ARG_COMPLEXITY:
1086       speexenc->complexity = g_value_get_int (value);
1087       break;
1088     case ARG_NFRAMES:
1089       speexenc->nframes = g_value_get_int (value);
1090       break;
1091     default:
1092       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1093       break;
1094   }
1095 }
1096
1097 static GstStateChangeReturn
1098 gst_speexenc_change_state (GstElement * element, GstStateChange transition)
1099 {
1100   GstSpeexEnc *speexenc = GST_SPEEXENC (element);
1101   GstStateChangeReturn res;
1102
1103   switch (transition) {
1104     case GST_STATE_CHANGE_NULL_TO_READY:
1105       speexenc->tags = gst_tag_list_new ();
1106       break;
1107     case GST_STATE_CHANGE_READY_TO_PAUSED:
1108       speexenc->frameno = 0;
1109       speexenc->samples_in = 0;
1110       break;
1111     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1112       /* fall through */
1113     default:
1114       break;
1115   }
1116
1117   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1118
1119   switch (transition) {
1120     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1121       break;
1122     case GST_STATE_CHANGE_PAUSED_TO_READY:
1123       speexenc->setup = FALSE;
1124       speexenc->header_sent = FALSE;
1125       break;
1126     case GST_STATE_CHANGE_READY_TO_NULL:
1127       gst_tag_list_free (speexenc->tags);
1128       speexenc->tags = NULL;
1129     default:
1130       break;
1131   }
1132
1133   return res;
1134 }