Use GST_DEBUG_CATEGORY_STATIC where possible (#342503) plus two minor macro fixes.
[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_STATIC (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 static const GstElementDetails speexenc_details =
42 GST_ELEMENT_DETAILS ("Speex audio encoder",
43     "Codec/Encoder/Audio",
44     "Encodes audio in Speex format",
45     "Wim Taymans <wim@fluendo.com>");
46
47 /* GstSpeexEnc signals and args */
48 enum
49 {
50   /* FILL ME */
51   LAST_SIGNAL
52 };
53
54 #define DEFAULT_QUALITY         8.0
55 #define DEFAULT_BITRATE         0
56 #define DEFAULT_VBR             FALSE
57 #define DEFAULT_ABR             0
58 #define DEFAULT_VAD             FALSE
59 #define DEFAULT_DTX             FALSE
60 #define DEFAULT_COMPLEXITY      3
61 #define DEFAULT_NFRAMES         1
62
63 enum
64 {
65   ARG_0,
66   ARG_QUALITY,
67   ARG_BITRATE,
68   ARG_VBR,
69   ARG_ABR,
70   ARG_VAD,
71   ARG_DTX,
72   ARG_COMPLEXITY,
73   ARG_NFRAMES,
74   ARG_LAST_MESSAGE
75 };
76
77 #if 0
78 static const GstFormat *
79 gst_speexenc_get_formats (GstPad * pad)
80 {
81   static const GstFormat src_formats[] = {
82     GST_FORMAT_BYTES,
83     GST_FORMAT_TIME,
84     0
85   };
86   static const GstFormat sink_formats[] = {
87     GST_FORMAT_BYTES,
88     GST_FORMAT_DEFAULT,
89     GST_FORMAT_TIME,
90     0
91   };
92
93   return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
94 }
95 #endif
96
97 static void gst_speexenc_base_init (gpointer g_class);
98 static void gst_speexenc_class_init (GstSpeexEncClass * klass);
99 static void gst_speexenc_init (GstSpeexEnc * speexenc);
100 static void gst_speexenc_finalize (GObject * object);
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_peek_parent (klass);
234
235   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_speexenc_finalize);
236
237   gstelement_class->change_state =
238       GST_DEBUG_FUNCPTR (gst_speexenc_change_state);
239 }
240
241 static void
242 gst_speexenc_finalize (GObject * object)
243 {
244   GstSpeexEnc *speexenc;
245
246   speexenc = GST_SPEEXENC (object);
247
248   g_object_unref (speexenc->adapter);
249
250   G_OBJECT_CLASS (parent_class)->finalize (object);
251 }
252
253 static gboolean
254 gst_speexenc_sink_setcaps (GstPad * pad, GstCaps * caps)
255 {
256   GstSpeexEnc *speexenc;
257   GstStructure *structure;
258
259   speexenc = GST_SPEEXENC (gst_pad_get_parent (pad));
260   speexenc->setup = FALSE;
261
262   structure = gst_caps_get_structure (caps, 0);
263   gst_structure_get_int (structure, "channels", &speexenc->channels);
264   gst_structure_get_int (structure, "rate", &speexenc->rate);
265
266   gst_speexenc_setup (speexenc);
267
268   gst_object_unref (speexenc);
269
270   return speexenc->setup;
271 }
272
273 static gboolean
274 gst_speexenc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
275     GstFormat * dest_format, gint64 * dest_value)
276 {
277   gboolean res = TRUE;
278   GstSpeexEnc *speexenc;
279   gint64 avg;
280
281   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
282
283   if (speexenc->samples_in == 0 ||
284       speexenc->bytes_out == 0 || speexenc->rate == 0)
285     return FALSE;
286
287   avg = (speexenc->bytes_out * speexenc->rate) / (speexenc->samples_in);
288
289   switch (src_format) {
290     case GST_FORMAT_BYTES:
291       switch (*dest_format) {
292         case GST_FORMAT_TIME:
293           *dest_value = src_value * GST_SECOND / avg;
294           break;
295         default:
296           res = FALSE;
297       }
298       break;
299     case GST_FORMAT_TIME:
300       switch (*dest_format) {
301         case GST_FORMAT_BYTES:
302           *dest_value = src_value * avg / GST_SECOND;
303           break;
304         default:
305           res = FALSE;
306       }
307       break;
308     default:
309       res = FALSE;
310   }
311   return res;
312 }
313
314 static gboolean
315 gst_speexenc_convert_sink (GstPad * pad, GstFormat src_format,
316     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
317 {
318   gboolean res = TRUE;
319   guint scale = 1;
320   gint bytes_per_sample;
321   GstSpeexEnc *speexenc;
322
323   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
324
325   bytes_per_sample = speexenc->channels * 2;
326
327   switch (src_format) {
328     case GST_FORMAT_BYTES:
329       switch (*dest_format) {
330         case GST_FORMAT_DEFAULT:
331           if (bytes_per_sample == 0)
332             return FALSE;
333           *dest_value = src_value / bytes_per_sample;
334           break;
335         case GST_FORMAT_TIME:
336         {
337           gint byterate = bytes_per_sample * speexenc->rate;
338
339           if (byterate == 0)
340             return FALSE;
341           *dest_value = src_value * GST_SECOND / byterate;
342           break;
343         }
344         default:
345           res = FALSE;
346       }
347       break;
348     case GST_FORMAT_DEFAULT:
349       switch (*dest_format) {
350         case GST_FORMAT_BYTES:
351           *dest_value = src_value * bytes_per_sample;
352           break;
353         case GST_FORMAT_TIME:
354           if (speexenc->rate == 0)
355             return FALSE;
356           *dest_value = src_value * GST_SECOND / speexenc->rate;
357           break;
358         default:
359           res = FALSE;
360       }
361       break;
362     case GST_FORMAT_TIME:
363       switch (*dest_format) {
364         case GST_FORMAT_BYTES:
365           scale = bytes_per_sample;
366           /* fallthrough */
367         case GST_FORMAT_DEFAULT:
368           *dest_value = src_value * scale * speexenc->rate / GST_SECOND;
369           break;
370         default:
371           res = FALSE;
372       }
373       break;
374     default:
375       res = FALSE;
376   }
377   return res;
378 }
379
380 static const GstQueryType *
381 gst_speexenc_get_query_types (GstPad * pad)
382 {
383   static const GstQueryType gst_speexenc_src_query_types[] = {
384     GST_QUERY_POSITION,
385     GST_QUERY_DURATION,
386     GST_QUERY_CONVERT,
387     0
388   };
389
390   return gst_speexenc_src_query_types;
391 }
392
393 static gboolean
394 gst_speexenc_src_query (GstPad * pad, GstQuery * query)
395 {
396   gboolean res = TRUE;
397   GstSpeexEnc *speexenc;
398   GstPad *peerpad;
399
400   speexenc = GST_SPEEXENC (gst_pad_get_parent (pad));
401   peerpad = gst_pad_get_peer (GST_PAD (speexenc->sinkpad));
402
403   switch (GST_QUERY_TYPE (query)) {
404     case GST_QUERY_POSITION:
405     {
406       GstFormat fmt, req_fmt;
407       gint64 pos, val;
408
409       gst_query_parse_position (query, &req_fmt, NULL);
410       if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
411         gst_query_set_position (query, req_fmt, val);
412         break;
413       }
414
415       fmt = GST_FORMAT_TIME;
416       if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
417         break;
418
419       if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val)))
420         gst_query_set_position (query, req_fmt, val);
421
422       break;
423     }
424     case GST_QUERY_DURATION:
425     {
426       GstFormat fmt, req_fmt;
427       gint64 dur, val;
428
429       gst_query_parse_duration (query, &req_fmt, NULL);
430       if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
431         gst_query_set_duration (query, req_fmt, val);
432         break;
433       }
434
435       fmt = GST_FORMAT_TIME;
436       if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
437         break;
438
439       if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
440         gst_query_set_duration (query, req_fmt, val);
441       }
442       break;
443     }
444     case GST_QUERY_CONVERT:
445     {
446       GstFormat src_fmt, dest_fmt;
447       gint64 src_val, dest_val;
448
449       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
450       if (!(res = gst_speexenc_convert_src (pad, src_fmt, src_val, &dest_fmt,
451                   &dest_val)))
452         goto error;
453       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
454       break;
455     }
456     default:
457       res = gst_pad_query_default (pad, query);
458       break;
459   }
460
461 error:
462   gst_object_unref (peerpad);
463   gst_object_unref (speexenc);
464   return res;
465 }
466
467 static gboolean
468 gst_speexenc_sink_query (GstPad * pad, GstQuery * query)
469 {
470   gboolean res = TRUE;
471   GstSpeexEnc *speexenc;
472
473   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
474
475   switch (GST_QUERY_TYPE (query)) {
476     case GST_QUERY_CONVERT:
477     {
478       GstFormat src_fmt, dest_fmt;
479       gint64 src_val, dest_val;
480
481       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
482       if (!(res =
483               gst_speexenc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
484                   &dest_val)))
485         goto error;
486       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
487       break;
488     }
489     default:
490       res = gst_pad_query_default (pad, query);
491       break;
492   }
493
494 error:
495   return res;
496 }
497
498 static void
499 gst_speexenc_init (GstSpeexEnc * speexenc)
500 {
501   speexenc->sinkpad =
502       gst_pad_new_from_template (gst_speexenc_sink_template, "sink");
503   gst_element_add_pad (GST_ELEMENT (speexenc), speexenc->sinkpad);
504   gst_pad_set_event_function (speexenc->sinkpad, gst_speexenc_sinkevent);
505   gst_pad_set_chain_function (speexenc->sinkpad, gst_speexenc_chain);
506   gst_pad_set_setcaps_function (speexenc->sinkpad, gst_speexenc_sink_setcaps);
507   gst_pad_set_query_function (speexenc->sinkpad,
508       GST_DEBUG_FUNCPTR (gst_speexenc_sink_query));
509
510   speexenc->srcpad =
511       gst_pad_new_from_template (gst_speexenc_src_template, "src");
512   gst_pad_set_query_function (speexenc->srcpad,
513       GST_DEBUG_FUNCPTR (gst_speexenc_src_query));
514   gst_pad_set_query_type_function (speexenc->srcpad,
515       GST_DEBUG_FUNCPTR (gst_speexenc_get_query_types));
516   gst_element_add_pad (GST_ELEMENT (speexenc), speexenc->srcpad);
517
518   speexenc->channels = -1;
519   speexenc->rate = -1;
520
521   speexenc->quality = DEFAULT_QUALITY;
522   speexenc->bitrate = DEFAULT_BITRATE;
523   speexenc->vbr = DEFAULT_VBR;
524   speexenc->abr = DEFAULT_ABR;
525   speexenc->vad = DEFAULT_VAD;
526   speexenc->dtx = DEFAULT_DTX;
527   speexenc->complexity = DEFAULT_COMPLEXITY;
528   speexenc->nframes = DEFAULT_NFRAMES;
529
530   speexenc->setup = FALSE;
531   speexenc->header_sent = FALSE;
532
533   speexenc->adapter = gst_adapter_new ();
534 }
535
536
537 /* FIXME: why are we not using the from/to vorbiscomment 
538  * functions that are in -lgsttagedit-0.9 here? */
539
540 static gchar *
541 gst_speexenc_get_tag_value (const GstTagList * list, const gchar * tag,
542     int index)
543 {
544   GType tag_type;
545   gchar *speexvalue = NULL;
546
547   if (tag == NULL)
548     return NULL;
549
550   tag_type = gst_tag_get_type (tag);
551
552   /* get tag name right */
553   if ((strcmp (tag, GST_TAG_TRACK_NUMBER) == 0)
554       || (strcmp (tag, GST_TAG_ALBUM_VOLUME_NUMBER) == 0)
555       || (strcmp (tag, GST_TAG_TRACK_COUNT) == 0)
556       || (strcmp (tag, GST_TAG_ALBUM_VOLUME_COUNT) == 0)) {
557     guint track_no;
558
559     if (gst_tag_list_get_uint_index (list, tag, index, &track_no)) {
560       speexvalue = g_strdup_printf ("%u", track_no);
561     } else {
562       GST_WARNING ("Failed to extract int tag %d for '%s'", index, tag);
563     }
564   } else if (tag_type == GST_TYPE_DATE) {
565     /* FIXME: how are dates represented in speex files? */
566     GDate *date;
567
568     if (gst_tag_list_get_date_index (list, tag, index, &date)) {
569       speexvalue =
570           g_strdup_printf ("%04d-%02d-%02d", (gint) g_date_get_year (date),
571           (gint) g_date_get_month (date), (gint) g_date_get_day (date));
572       g_date_free (date);
573     } else {
574       GST_WARNING ("Failed to extract date tag %d for '%s'", index, tag);
575     }
576   } else if (tag_type == G_TYPE_STRING) {
577     if (!gst_tag_list_get_string_index (list, tag, index, &speexvalue))
578       GST_WARNING ("Failed to extract string tag %d for '%s'", index, tag);
579   }
580
581   return speexvalue;
582 }
583
584 /*
585  *  Comments will be stored in the Vorbis style.
586  *  It is describled in the "Structure" section of
587  *  http://www.xiph.org/ogg/vorbis/doc/v-comment.html
588  *
589  *  The comment header is decoded as follows:
590  *  1) [vendor_length] = read an unsigned integer of 32 bits
591  *  2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
592  *  3) [user_comment_list_length] = read an unsigned integer of 32 bits
593  *  4) iterate [user_comment_list_length] times {
594  *     5) [length] = read an unsigned integer of 32 bits
595  *     6) this iteration's user comment = read a UTF-8 vector as [length] octets
596  *     }
597  *  7) [framing_bit] = read a single bit as boolean
598  *  8) if ( [framing_bit]  unset or end of packet ) then ERROR
599  *  9) done.
600  *
601  *  If you have troubles, please write to ymnk@jcraft.com.
602  */
603 static void
604 comment_init (guint8 ** comments, int *length, char *vendor_string)
605 {
606   int vendor_length = strlen (vendor_string);
607   int user_comment_list_length = 0;
608   int len = 4 + vendor_length + 4;
609   guint8 *p = g_malloc (len);
610
611   GST_WRITE_UINT32_LE (p, vendor_length);
612   memcpy (p + 4, vendor_string, vendor_length);
613   GST_WRITE_UINT32_LE (p + 4 + vendor_length, user_comment_list_length);
614   *length = len;
615   *comments = p;
616 }
617 static void
618 comment_add (guint8 ** comments, int *length, const char *tag, char *val)
619 {
620   guint8 *p = *comments;
621   int vendor_length = GST_READ_UINT32_LE (p);
622   int user_comment_list_length = GST_READ_UINT32_LE (p + 4 + vendor_length);
623   int tag_len = (tag ? strlen (tag) : 0);
624   int val_len = strlen (val);
625   int len = (*length) + 4 + tag_len + val_len;
626
627   p = g_realloc (p, len);
628
629   GST_WRITE_UINT32_LE (p + *length, tag_len + val_len); /* length of comment */
630   if (tag)
631     memcpy (p + *length + 4, (guint8 *) tag, tag_len);  /* comment */
632   memcpy (p + *length + 4 + tag_len, val, val_len);     /* comment */
633   GST_WRITE_UINT32_LE (p + 4 + vendor_length, user_comment_list_length + 1);
634
635   *comments = p;
636   *length = len;
637 }
638
639 static void
640 gst_speexenc_metadata_set1 (const GstTagList * list, const gchar * tag,
641     gpointer speexenc)
642 {
643   const gchar *speextag = NULL;
644   gchar *speexvalue = NULL;
645   guint i, count;
646   GstSpeexEnc *enc = GST_SPEEXENC (speexenc);
647
648   speextag = gst_tag_to_vorbis_tag (tag);
649   if (speextag == NULL) {
650     return;
651   }
652
653   count = gst_tag_list_get_tag_size (list, tag);
654   for (i = 0; i < count; i++) {
655     speexvalue = gst_speexenc_get_tag_value (list, tag, i);
656
657     if (speexvalue != NULL) {
658       comment_add (&enc->comments, &enc->comment_len, speextag, speexvalue);
659     }
660   }
661 }
662
663 static void
664 gst_speexenc_set_metadata (GstSpeexEnc * speexenc)
665 {
666   GstTagList *copy;
667   const GstTagList *user_tags;
668
669   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (speexenc));
670   if (!(speexenc->tags || user_tags))
671     return;
672
673   comment_init (&speexenc->comments, &speexenc->comment_len,
674       "Encoded with GStreamer Speexenc");
675   copy =
676       gst_tag_list_merge (user_tags, speexenc->tags,
677       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (speexenc)));
678   gst_tag_list_foreach (copy, gst_speexenc_metadata_set1, speexenc);
679   gst_tag_list_free (copy);
680 }
681
682 static gboolean
683 gst_speexenc_setup (GstSpeexEnc * speexenc)
684 {
685   speexenc->setup = FALSE;
686
687   switch (speexenc->mode) {
688     case GST_SPEEXENC_MODE_UWB:
689       speexenc->speex_mode = (SpeexMode *) & speex_uwb_mode;
690       break;
691     case GST_SPEEXENC_MODE_WB:
692       speexenc->speex_mode = (SpeexMode *) & speex_wb_mode;
693       break;
694     case GST_SPEEXENC_MODE_NB:
695       speexenc->speex_mode = (SpeexMode *) & speex_nb_mode;
696       break;
697     case GST_SPEEXENC_MODE_AUTO:
698       /* fall through */
699     default:
700       break;
701   }
702
703   if (speexenc->rate > 25000) {
704     if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
705       speexenc->speex_mode = (SpeexMode *) & speex_uwb_mode;
706     } else {
707       if (speexenc->speex_mode != &speex_uwb_mode) {
708         speexenc->last_message =
709             g_strdup_printf
710             ("Warning: suggest to use ultra wide band mode for this rate");
711         g_object_notify (G_OBJECT (speexenc), "last_message");
712       }
713     }
714   } else if (speexenc->rate > 12500) {
715     if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
716       speexenc->speex_mode = (SpeexMode *) & speex_wb_mode;
717     } else {
718       if (speexenc->speex_mode != &speex_wb_mode) {
719         speexenc->last_message =
720             g_strdup_printf
721             ("Warning: suggest to use wide band mode for this rate");
722         g_object_notify (G_OBJECT (speexenc), "last_message");
723       }
724     }
725   } else {
726     if (speexenc->mode == GST_SPEEXENC_MODE_AUTO) {
727       speexenc->speex_mode = (SpeexMode *) & speex_nb_mode;
728     } else {
729       if (speexenc->speex_mode != &speex_nb_mode) {
730         speexenc->last_message =
731             g_strdup_printf
732             ("Warning: suggest to use narrow band mode for this rate");
733         g_object_notify (G_OBJECT (speexenc), "last_message");
734       }
735     }
736   }
737
738   if (speexenc->rate != 8000 && speexenc->rate != 16000
739       && speexenc->rate != 32000) {
740     speexenc->last_message =
741         g_strdup_printf ("Warning: speex is optimized for 8, 16 and 32 KHz");
742     g_object_notify (G_OBJECT (speexenc), "last_message");
743   }
744
745   speex_init_header (&speexenc->header, speexenc->rate, 1,
746       speexenc->speex_mode);
747   speexenc->header.frames_per_packet = speexenc->nframes;
748   speexenc->header.vbr = speexenc->vbr;
749   speexenc->header.nb_channels = speexenc->channels;
750
751   /*Initialize Speex encoder */
752   speexenc->state = speex_encoder_init (speexenc->speex_mode);
753
754   speex_encoder_ctl (speexenc->state, SPEEX_GET_FRAME_SIZE,
755       &speexenc->frame_size);
756   speex_encoder_ctl (speexenc->state, SPEEX_SET_COMPLEXITY,
757       &speexenc->complexity);
758   speex_encoder_ctl (speexenc->state, SPEEX_SET_SAMPLING_RATE, &speexenc->rate);
759
760   if (speexenc->vbr)
761     speex_encoder_ctl (speexenc->state, SPEEX_SET_VBR_QUALITY,
762         &speexenc->quality);
763   else {
764     gint tmp = floor (speexenc->quality);
765
766     speex_encoder_ctl (speexenc->state, SPEEX_SET_QUALITY, &tmp);
767   }
768   if (speexenc->bitrate) {
769     if (speexenc->quality >= 0.0 && speexenc->vbr) {
770       speexenc->last_message =
771           g_strdup_printf ("Warning: bitrate option is overriding quality");
772       g_object_notify (G_OBJECT (speexenc), "last_message");
773     }
774     speex_encoder_ctl (speexenc->state, SPEEX_SET_BITRATE, &speexenc->bitrate);
775   }
776   if (speexenc->vbr) {
777     gint tmp = 1;
778
779     speex_encoder_ctl (speexenc->state, SPEEX_SET_VBR, &tmp);
780   } else if (speexenc->vad) {
781     gint tmp = 1;
782
783     speex_encoder_ctl (speexenc->state, SPEEX_SET_VAD, &tmp);
784   }
785
786   if (speexenc->dtx) {
787     gint tmp = 1;
788
789     speex_encoder_ctl (speexenc->state, SPEEX_SET_DTX, &tmp);
790   }
791
792   if (speexenc->dtx && !(speexenc->vbr || speexenc->abr || speexenc->vad)) {
793     speexenc->last_message =
794         g_strdup_printf ("Warning: dtx is useless without vad, vbr or abr");
795     g_object_notify (G_OBJECT (speexenc), "last_message");
796   } else if ((speexenc->vbr || speexenc->abr) && (speexenc->vad)) {
797     speexenc->last_message =
798         g_strdup_printf ("Warning: vad is already implied by vbr or abr");
799     g_object_notify (G_OBJECT (speexenc), "last_message");
800   }
801
802   if (speexenc->abr) {
803     speex_encoder_ctl (speexenc->state, SPEEX_SET_ABR, &speexenc->abr);
804   }
805
806   speex_encoder_ctl (speexenc->state, SPEEX_GET_LOOKAHEAD,
807       &speexenc->lookahead);
808
809   speexenc->setup = TRUE;
810
811   return TRUE;
812 }
813
814 /* prepare a buffer for transmission */
815 static GstBuffer *
816 gst_speexenc_buffer_from_data (GstSpeexEnc * speexenc, guchar * data,
817     gint data_len, guint64 granulepos)
818 {
819   GstBuffer *outbuf;
820
821   outbuf = gst_buffer_new_and_alloc (data_len);
822   memcpy (GST_BUFFER_DATA (outbuf), data, data_len);
823   GST_BUFFER_OFFSET (outbuf) = speexenc->bytes_out;
824   GST_BUFFER_OFFSET_END (outbuf) = granulepos;
825
826   GST_DEBUG ("encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
827   return outbuf;
828 }
829
830
831 /* push out the buffer and do internal bookkeeping */
832 static GstFlowReturn
833 gst_speexenc_push_buffer (GstSpeexEnc * speexenc, GstBuffer * buffer)
834 {
835   speexenc->bytes_out += GST_BUFFER_SIZE (buffer);
836
837   return gst_pad_push (speexenc->srcpad, buffer);
838
839 }
840
841 static GstCaps *
842 gst_speexenc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
843     GstBuffer * buf2)
844 {
845   GstStructure *structure = NULL;
846   GValue array = { 0 };
847   GValue value = { 0 };
848
849   caps = gst_caps_make_writable (caps);
850   structure = gst_caps_get_structure (caps, 0);
851
852   /* mark buffers */
853   GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
854   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
855
856   /* put buffers in a fixed list */
857   g_value_init (&array, GST_TYPE_ARRAY);
858   g_value_init (&value, GST_TYPE_BUFFER);
859   gst_value_set_buffer (&value, buf1);
860   gst_value_array_append_value (&array, &value);
861   g_value_unset (&value);
862   g_value_init (&value, GST_TYPE_BUFFER);
863   gst_value_set_buffer (&value, buf2);
864   gst_value_array_append_value (&array, &value);
865   gst_structure_set_value (structure, "streamheader", &array);
866   g_value_unset (&value);
867   g_value_unset (&array);
868
869   return caps;
870 }
871
872
873 static gboolean
874 gst_speexenc_sinkevent (GstPad * pad, GstEvent * event)
875 {
876   gboolean res = TRUE;
877   GstSpeexEnc *speexenc;
878
879   speexenc = GST_SPEEXENC (GST_PAD_PARENT (pad));
880
881   switch (GST_EVENT_TYPE (event)) {
882     case GST_EVENT_EOS:
883       speexenc->eos = TRUE;
884       res = gst_pad_event_default (pad, event);
885       break;
886     case GST_EVENT_TAG:
887     {
888       GstTagList *list;
889
890       gst_event_parse_tag (event, &list);
891       if (speexenc->tags) {
892         gst_tag_list_insert (speexenc->tags, list,
893             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (speexenc)));
894       } else {
895         g_assert_not_reached ();
896       }
897       res = gst_pad_event_default (pad, event);
898       break;
899     }
900     default:
901       res = gst_pad_event_default (pad, event);
902       break;
903   }
904   return res;
905 }
906
907
908 static GstFlowReturn
909 gst_speexenc_chain (GstPad * pad, GstBuffer * buf)
910 {
911   GstSpeexEnc *speexenc;
912   GstFlowReturn ret = GST_FLOW_OK;
913
914   speexenc = GST_SPEEXENC (gst_pad_get_parent (pad));
915
916   if (!speexenc->setup)
917     goto not_setup;
918
919   if (!speexenc->header_sent) {
920     /* Speex streams begin with two headers; the initial header (with
921        most of the codec setup parameters) which is mandated by the Ogg
922        bitstream spec.  The second header holds any comment fields.
923        We merely need to make the headers, then pass them to libspeex 
924        one at a time; libspeex handles the additional Ogg bitstream 
925        constraints */
926     GstBuffer *buf1, *buf2;
927     GstCaps *caps;
928     guchar *data;
929     gint data_len;
930
931     gst_speexenc_set_metadata (speexenc);
932
933     /* create header buffer */
934     data = (guint8 *) speex_header_to_packet (&speexenc->header, &data_len);
935     buf1 = gst_speexenc_buffer_from_data (speexenc, data, data_len, 0);
936
937     /* create comment buffer */
938     buf2 =
939         gst_speexenc_buffer_from_data (speexenc, speexenc->comments,
940         speexenc->comment_len, 0);
941
942     /* mark and put on caps */
943     caps = gst_pad_get_caps (speexenc->srcpad);
944     caps = gst_speexenc_set_header_on_caps (caps, buf1, buf2);
945
946     /* negotiate with these caps */
947     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
948     gst_pad_set_caps (speexenc->srcpad, caps);
949
950     gst_buffer_set_caps (buf1, caps);
951     gst_buffer_set_caps (buf2, caps);
952
953     /* push out buffers */
954     ret = gst_speexenc_push_buffer (speexenc, buf1);
955
956     if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret)) {
957       /* unref buf2 as we are not going to push it anymore */
958
959       gst_buffer_unref (buf2);
960       goto done;
961     }
962
963     ret = gst_speexenc_push_buffer (speexenc, buf2);
964
965     if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
966       goto done;
967
968     speex_bits_init (&speexenc->bits);
969     speex_bits_reset (&speexenc->bits);
970
971     speexenc->header_sent = TRUE;
972   }
973
974   {
975     gint frame_size = speexenc->frame_size;
976     gint bytes = frame_size * 2 * speexenc->channels;
977
978     /* push buffer to adapter */
979     gst_adapter_push (speexenc->adapter, buf);
980
981     while (gst_adapter_available (speexenc->adapter) >= bytes) {
982       gint16 *data;
983       gint i;
984       gint outsize, written;
985       GstBuffer *outbuf;
986
987       data = (gint16 *) gst_adapter_peek (speexenc->adapter, bytes);
988
989       for (i = 0; i < frame_size * speexenc->channels; i++) {
990         speexenc->input[i] = (gfloat) data[i];
991       }
992       gst_adapter_flush (speexenc->adapter, bytes);
993
994       speexenc->samples_in += frame_size;
995
996       if (speexenc->channels == 2) {
997         speex_encode_stereo (speexenc->input, frame_size, &speexenc->bits);
998       }
999       speex_encode (speexenc->state, speexenc->input, &speexenc->bits);
1000
1001       speexenc->frameno++;
1002
1003       if ((speexenc->frameno % speexenc->nframes) != 0)
1004         continue;
1005
1006       speex_bits_insert_terminator (&speexenc->bits);
1007       outsize = speex_bits_nbytes (&speexenc->bits);
1008
1009       ret = gst_pad_alloc_buffer_and_set_caps (speexenc->srcpad,
1010           GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (speexenc->srcpad),
1011           &outbuf);
1012
1013       if ((GST_FLOW_OK != ret))
1014         goto done;
1015
1016       written = speex_bits_write (&speexenc->bits,
1017           (gchar *) GST_BUFFER_DATA (outbuf), outsize);
1018       g_assert (written == outsize);
1019       speex_bits_reset (&speexenc->bits);
1020
1021       GST_BUFFER_TIMESTAMP (outbuf) =
1022           gst_util_uint64_scale_int (speexenc->frameno * frame_size -
1023           speexenc->lookahead, GST_SECOND, speexenc->rate);
1024       GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (frame_size,
1025           GST_SECOND, speexenc->rate);
1026       /* set gp time and granulepos; see gst-plugins-base/ext/ogg/README */
1027       GST_BUFFER_OFFSET_END (outbuf) =
1028           ((speexenc->frameno + 1) * frame_size - speexenc->lookahead);
1029       GST_BUFFER_OFFSET (outbuf) =
1030           gst_util_uint64_scale_int (GST_BUFFER_OFFSET_END (outbuf), GST_SECOND,
1031           speexenc->rate);
1032
1033       ret = gst_speexenc_push_buffer (speexenc, outbuf);
1034
1035       if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
1036         goto done;
1037     }
1038   }
1039
1040 done:
1041   gst_object_unref (speexenc);
1042   return ret;
1043
1044   /* ERRORS */
1045 not_setup:
1046   {
1047     gst_buffer_unref (buf);
1048     GST_ELEMENT_ERROR (speexenc, CORE, NEGOTIATION, (NULL),
1049         ("encoder not initialized (input is not audio?)"));
1050     ret = GST_FLOW_NOT_NEGOTIATED;
1051     goto done;
1052   }
1053
1054 }
1055
1056
1057 static void
1058 gst_speexenc_get_property (GObject * object, guint prop_id, GValue * value,
1059     GParamSpec * pspec)
1060 {
1061   GstSpeexEnc *speexenc;
1062
1063   g_return_if_fail (GST_IS_SPEEXENC (object));
1064
1065   speexenc = GST_SPEEXENC (object);
1066
1067   switch (prop_id) {
1068     case ARG_QUALITY:
1069       g_value_set_float (value, speexenc->quality);
1070       break;
1071     case ARG_BITRATE:
1072       g_value_set_int (value, speexenc->bitrate);
1073       break;
1074     case ARG_VBR:
1075       g_value_set_boolean (value, speexenc->vbr);
1076       break;
1077     case ARG_ABR:
1078       g_value_set_int (value, speexenc->abr);
1079       break;
1080     case ARG_VAD:
1081       g_value_set_boolean (value, speexenc->vad);
1082       break;
1083     case ARG_DTX:
1084       g_value_set_boolean (value, speexenc->dtx);
1085       break;
1086     case ARG_COMPLEXITY:
1087       g_value_set_int (value, speexenc->complexity);
1088       break;
1089     case ARG_NFRAMES:
1090       g_value_set_int (value, speexenc->nframes);
1091       break;
1092     case ARG_LAST_MESSAGE:
1093       g_value_set_string (value, speexenc->last_message);
1094       break;
1095     default:
1096       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1097       break;
1098   }
1099 }
1100
1101 static void
1102 gst_speexenc_set_property (GObject * object, guint prop_id,
1103     const GValue * value, GParamSpec * pspec)
1104 {
1105   GstSpeexEnc *speexenc;
1106
1107   g_return_if_fail (GST_IS_SPEEXENC (object));
1108
1109   speexenc = GST_SPEEXENC (object);
1110
1111   switch (prop_id) {
1112     case ARG_QUALITY:
1113       speexenc->quality = g_value_get_float (value);
1114       break;
1115     case ARG_BITRATE:
1116       speexenc->bitrate = g_value_get_int (value);
1117       break;
1118     case ARG_VBR:
1119       speexenc->vbr = g_value_get_boolean (value);
1120       break;
1121     case ARG_ABR:
1122       speexenc->abr = g_value_get_int (value);
1123       break;
1124     case ARG_VAD:
1125       speexenc->vad = g_value_get_boolean (value);
1126       break;
1127     case ARG_DTX:
1128       speexenc->dtx = g_value_get_boolean (value);
1129       break;
1130     case ARG_COMPLEXITY:
1131       speexenc->complexity = g_value_get_int (value);
1132       break;
1133     case ARG_NFRAMES:
1134       speexenc->nframes = g_value_get_int (value);
1135       break;
1136     default:
1137       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1138       break;
1139   }
1140 }
1141
1142 static GstStateChangeReturn
1143 gst_speexenc_change_state (GstElement * element, GstStateChange transition)
1144 {
1145   GstSpeexEnc *speexenc = GST_SPEEXENC (element);
1146   GstStateChangeReturn res;
1147
1148   switch (transition) {
1149     case GST_STATE_CHANGE_NULL_TO_READY:
1150       speexenc->tags = gst_tag_list_new ();
1151       break;
1152     case GST_STATE_CHANGE_READY_TO_PAUSED:
1153       speexenc->frameno = 0;
1154       speexenc->samples_in = 0;
1155       break;
1156     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1157       /* fall through */
1158     default:
1159       break;
1160   }
1161
1162   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1163
1164   switch (transition) {
1165     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1166       break;
1167     case GST_STATE_CHANGE_PAUSED_TO_READY:
1168       speexenc->setup = FALSE;
1169       speexenc->header_sent = FALSE;
1170       break;
1171     case GST_STATE_CHANGE_READY_TO_NULL:
1172       gst_tag_list_free (speexenc->tags);
1173       speexenc->tags = NULL;
1174     default:
1175       break;
1176   }
1177
1178   return res;
1179 }