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