ext/speex/gstspeexenc.c: Unref the buffers only once when handling not-negotiated...
[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_speex_enc_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_speex_enc_finalize (GObject * object);
104
105 static gboolean gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event);
106 static GstFlowReturn gst_speex_enc_chain (GstPad * pad, GstBuffer * buf);
107 static gboolean gst_speex_enc_setup (GstSpeexEnc * enc);
108
109 static void gst_speex_enc_get_property (GObject * object, guint prop_id,
110     GValue * value, GParamSpec * pspec);
111 static void gst_speex_enc_set_property (GObject * object, guint prop_id,
112     const GValue * value, GParamSpec * pspec);
113 static GstStateChangeReturn gst_speex_enc_change_state (GstElement * element,
114     GstStateChange transition);
115
116 static void
117 gst_speex_enc_setup_interfaces (GType speexenc_type)
118 {
119   static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
120
121   g_type_add_interface_static (speexenc_type, GST_TYPE_TAG_SETTER,
122       &tag_setter_info);
123
124   GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
125 }
126
127 GST_BOILERPLATE_FULL (GstSpeexEnc, gst_speex_enc, GstElement, GST_TYPE_ELEMENT,
128     gst_speex_enc_setup_interfaces);
129
130 static void
131 gst_speex_enc_base_init (gpointer g_class)
132 {
133   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
134
135   gst_element_class_add_pad_template (element_class,
136       gst_static_pad_template_get (&src_factory));
137   gst_element_class_add_pad_template (element_class,
138       gst_static_pad_template_get (&sink_factory));
139   gst_element_class_set_details (element_class, &speexenc_details);
140 }
141
142 static void
143 gst_speex_enc_class_init (GstSpeexEncClass * klass)
144 {
145   GObjectClass *gobject_class;
146   GstElementClass *gstelement_class;
147
148   gobject_class = (GObjectClass *) klass;
149   gstelement_class = (GstElementClass *) klass;
150
151   gobject_class->set_property = gst_speex_enc_set_property;
152   gobject_class->get_property = gst_speex_enc_get_property;
153
154   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
155       g_param_spec_float ("quality", "Quality", "Encoding quality",
156           0.0, 10.0, DEFAULT_QUALITY, G_PARAM_READWRITE));
157   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
158       g_param_spec_int ("bitrate", "Encoding Bit-rate",
159           "Specify an encoding bit-rate (in bps). (0 = automatic)",
160           0, G_MAXINT, DEFAULT_BITRATE, G_PARAM_READWRITE));
161   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
162       g_param_spec_boolean ("vbr", "VBR",
163           "Enable variable bit-rate", DEFAULT_VBR, G_PARAM_READWRITE));
164   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ABR,
165       g_param_spec_int ("abr", "ABR",
166           "Enable average bit-rate (0 = disabled)",
167           0, G_MAXINT, DEFAULT_ABR, G_PARAM_READWRITE));
168   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VAD,
169       g_param_spec_boolean ("vad", "VAD",
170           "Enable voice activity detection", DEFAULT_VAD, G_PARAM_READWRITE));
171   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DTX,
172       g_param_spec_boolean ("dtx", "DTX",
173           "Enable discontinuous transmission", DEFAULT_DTX, G_PARAM_READWRITE));
174   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COMPLEXITY,
175       g_param_spec_int ("complexity", "Complexity",
176           "Set encoding complexity",
177           0, G_MAXINT, DEFAULT_COMPLEXITY, G_PARAM_READWRITE));
178   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NFRAMES,
179       g_param_spec_int ("nframes", "NFrames",
180           "Number of frames per buffer",
181           0, G_MAXINT, DEFAULT_NFRAMES, G_PARAM_READWRITE));
182   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
183       g_param_spec_string ("last-message", "last-message",
184           "The last status message", NULL, G_PARAM_READABLE));
185
186   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_speex_enc_finalize);
187
188   gstelement_class->change_state =
189       GST_DEBUG_FUNCPTR (gst_speex_enc_change_state);
190 }
191
192 static void
193 gst_speex_enc_finalize (GObject * object)
194 {
195   GstSpeexEnc *enc;
196
197   enc = GST_SPEEX_ENC (object);
198
199   g_free (enc->last_message);
200   g_object_unref (enc->adapter);
201
202   G_OBJECT_CLASS (parent_class)->finalize (object);
203 }
204
205 static gboolean
206 gst_speex_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
207 {
208   GstSpeexEnc *enc;
209   GstStructure *structure;
210
211   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
212   enc->setup = FALSE;
213
214   structure = gst_caps_get_structure (caps, 0);
215   gst_structure_get_int (structure, "channels", &enc->channels);
216   gst_structure_get_int (structure, "rate", &enc->rate);
217
218   gst_speex_enc_setup (enc);
219
220   return enc->setup;
221 }
222
223 static gboolean
224 gst_speex_enc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
225     GstFormat * dest_format, gint64 * dest_value)
226 {
227   gboolean res = TRUE;
228   GstSpeexEnc *enc;
229   gint64 avg;
230
231   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
232
233   if (enc->samples_in == 0 || enc->bytes_out == 0 || enc->rate == 0)
234     return FALSE;
235
236   avg = (enc->bytes_out * enc->rate) / (enc->samples_in);
237
238   switch (src_format) {
239     case GST_FORMAT_BYTES:
240       switch (*dest_format) {
241         case GST_FORMAT_TIME:
242           *dest_value = src_value * GST_SECOND / avg;
243           break;
244         default:
245           res = FALSE;
246       }
247       break;
248     case GST_FORMAT_TIME:
249       switch (*dest_format) {
250         case GST_FORMAT_BYTES:
251           *dest_value = src_value * avg / GST_SECOND;
252           break;
253         default:
254           res = FALSE;
255       }
256       break;
257     default:
258       res = FALSE;
259   }
260   return res;
261 }
262
263 static gboolean
264 gst_speex_enc_convert_sink (GstPad * pad, GstFormat src_format,
265     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
266 {
267   gboolean res = TRUE;
268   guint scale = 1;
269   gint bytes_per_sample;
270   GstSpeexEnc *enc;
271
272   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
273
274   bytes_per_sample = enc->channels * 2;
275
276   switch (src_format) {
277     case GST_FORMAT_BYTES:
278       switch (*dest_format) {
279         case GST_FORMAT_DEFAULT:
280           if (bytes_per_sample == 0)
281             return FALSE;
282           *dest_value = src_value / bytes_per_sample;
283           break;
284         case GST_FORMAT_TIME:
285         {
286           gint byterate = bytes_per_sample * enc->rate;
287
288           if (byterate == 0)
289             return FALSE;
290           *dest_value = src_value * GST_SECOND / byterate;
291           break;
292         }
293         default:
294           res = FALSE;
295       }
296       break;
297     case GST_FORMAT_DEFAULT:
298       switch (*dest_format) {
299         case GST_FORMAT_BYTES:
300           *dest_value = src_value * bytes_per_sample;
301           break;
302         case GST_FORMAT_TIME:
303           if (enc->rate == 0)
304             return FALSE;
305           *dest_value = src_value * GST_SECOND / enc->rate;
306           break;
307         default:
308           res = FALSE;
309       }
310       break;
311     case GST_FORMAT_TIME:
312       switch (*dest_format) {
313         case GST_FORMAT_BYTES:
314           scale = bytes_per_sample;
315           /* fallthrough */
316         case GST_FORMAT_DEFAULT:
317           *dest_value = src_value * scale * enc->rate / GST_SECOND;
318           break;
319         default:
320           res = FALSE;
321       }
322       break;
323     default:
324       res = FALSE;
325   }
326   return res;
327 }
328
329 static const GstQueryType *
330 gst_speex_enc_get_query_types (GstPad * pad)
331 {
332   static const GstQueryType gst_speex_enc_src_query_types[] = {
333     GST_QUERY_POSITION,
334     GST_QUERY_DURATION,
335     GST_QUERY_CONVERT,
336     0
337   };
338
339   return gst_speex_enc_src_query_types;
340 }
341
342 static gboolean
343 gst_speex_enc_src_query (GstPad * pad, GstQuery * query)
344 {
345   gboolean res = TRUE;
346   GstSpeexEnc *enc;
347
348   enc = GST_SPEEX_ENC (gst_pad_get_parent (pad));
349
350   switch (GST_QUERY_TYPE (query)) {
351     case GST_QUERY_POSITION:
352     {
353       GstFormat fmt, req_fmt;
354       gint64 pos, val;
355
356       gst_query_parse_position (query, &req_fmt, NULL);
357       if ((res = gst_pad_query_peer_position (enc->sinkpad, &req_fmt, &val))) {
358         gst_query_set_position (query, req_fmt, val);
359         break;
360       }
361
362       fmt = GST_FORMAT_TIME;
363       if (!(res = gst_pad_query_peer_position (enc->sinkpad, &fmt, &pos)))
364         break;
365
366       if ((res =
367               gst_pad_query_peer_convert (enc->sinkpad, fmt, pos, &req_fmt,
368                   &val)))
369         gst_query_set_position (query, req_fmt, val);
370
371       break;
372     }
373     case GST_QUERY_DURATION:
374     {
375       GstFormat fmt, req_fmt;
376       gint64 dur, val;
377
378       gst_query_parse_duration (query, &req_fmt, NULL);
379       if ((res = gst_pad_query_peer_duration (enc->sinkpad, &req_fmt, &val))) {
380         gst_query_set_duration (query, req_fmt, val);
381         break;
382       }
383
384       fmt = GST_FORMAT_TIME;
385       if (!(res = gst_pad_query_peer_duration (enc->sinkpad, &fmt, &dur)))
386         break;
387
388       if ((res =
389               gst_pad_query_peer_convert (enc->sinkpad, fmt, dur, &req_fmt,
390                   &val))) {
391         gst_query_set_duration (query, req_fmt, val);
392       }
393       break;
394     }
395     case GST_QUERY_CONVERT:
396     {
397       GstFormat src_fmt, dest_fmt;
398       gint64 src_val, dest_val;
399
400       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
401       if (!(res = gst_speex_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
402                   &dest_val)))
403         goto error;
404       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
405       break;
406     }
407     default:
408       res = gst_pad_query_default (pad, query);
409       break;
410   }
411
412 error:
413
414   gst_object_unref (enc);
415
416   return res;
417 }
418
419 static gboolean
420 gst_speex_enc_sink_query (GstPad * pad, GstQuery * query)
421 {
422   gboolean res = TRUE;
423   GstSpeexEnc *enc;
424
425   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
426
427   switch (GST_QUERY_TYPE (query)) {
428     case GST_QUERY_CONVERT:
429     {
430       GstFormat src_fmt, dest_fmt;
431       gint64 src_val, dest_val;
432
433       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
434       if (!(res =
435               gst_speex_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
436                   &dest_val)))
437         goto error;
438       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
439       break;
440     }
441     default:
442       res = gst_pad_query_default (pad, query);
443       break;
444   }
445
446 error:
447   return res;
448 }
449
450 static void
451 gst_speex_enc_init (GstSpeexEnc * enc, GstSpeexEncClass * klass)
452 {
453   enc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
454   gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
455   gst_pad_set_event_function (enc->sinkpad,
456       GST_DEBUG_FUNCPTR (gst_speex_enc_sinkevent));
457   gst_pad_set_chain_function (enc->sinkpad,
458       GST_DEBUG_FUNCPTR (gst_speex_enc_chain));
459   gst_pad_set_setcaps_function (enc->sinkpad,
460       GST_DEBUG_FUNCPTR (gst_speex_enc_sink_setcaps));
461   gst_pad_set_query_function (enc->sinkpad,
462       GST_DEBUG_FUNCPTR (gst_speex_enc_sink_query));
463
464   enc->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
465   gst_pad_set_query_function (enc->srcpad,
466       GST_DEBUG_FUNCPTR (gst_speex_enc_src_query));
467   gst_pad_set_query_type_function (enc->srcpad,
468       GST_DEBUG_FUNCPTR (gst_speex_enc_get_query_types));
469   gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
470
471   enc->channels = -1;
472   enc->rate = -1;
473
474   enc->quality = DEFAULT_QUALITY;
475   enc->bitrate = DEFAULT_BITRATE;
476   enc->vbr = DEFAULT_VBR;
477   enc->abr = DEFAULT_ABR;
478   enc->vad = DEFAULT_VAD;
479   enc->dtx = DEFAULT_DTX;
480   enc->complexity = DEFAULT_COMPLEXITY;
481   enc->nframes = DEFAULT_NFRAMES;
482
483   /* FIXME: what about enc->mode? */
484
485   enc->setup = FALSE;
486   enc->header_sent = FALSE;
487
488   enc->adapter = gst_adapter_new ();
489 }
490
491 static GstBuffer *
492 gst_speex_enc_create_metadata_buffer (GstSpeexEnc * enc)
493 {
494   const GstTagList *user_tags;
495   GstTagList *merged_tags;
496   GstBuffer *comments = NULL;
497
498   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
499
500   GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
501   GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
502
503   /* gst_tag_list_merge() will handle NULL for either or both lists fine */
504   merged_tags = gst_tag_list_merge (user_tags, enc->tags,
505       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
506
507   if (merged_tags == NULL)
508     merged_tags = gst_tag_list_new ();
509
510   GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
511   comments = gst_tag_list_to_vorbiscomment_buffer (merged_tags, NULL,
512       0, "Encoded with GStreamer Speexenc");
513   gst_tag_list_free (merged_tags);
514
515   GST_BUFFER_OFFSET (comments) = enc->bytes_out;
516   GST_BUFFER_OFFSET_END (comments) = 0;
517
518   return comments;
519 }
520
521 static void
522 gst_speex_enc_set_last_msg (GstSpeexEnc * enc, const gchar * msg)
523 {
524   g_free (enc->last_message);
525   enc->last_message = g_strdup (msg);
526   GST_WARNING_OBJECT (enc, "%s", msg);
527   g_object_notify (G_OBJECT (enc), "last-message");
528 }
529
530 static gboolean
531 gst_speex_enc_setup (GstSpeexEnc * enc)
532 {
533   enc->setup = FALSE;
534
535   switch (enc->mode) {
536     case GST_SPEEX_ENC_MODE_UWB:
537       enc->speex_mode = (SpeexMode *) & speex_uwb_mode;
538       break;
539     case GST_SPEEX_ENC_MODE_WB:
540       enc->speex_mode = (SpeexMode *) & speex_wb_mode;
541       break;
542     case GST_SPEEX_ENC_MODE_NB:
543       enc->speex_mode = (SpeexMode *) & speex_nb_mode;
544       break;
545     case GST_SPEEX_ENC_MODE_AUTO:
546       /* fall through */
547     default:
548       break;
549   }
550
551   if (enc->rate > 25000) {
552     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
553       enc->speex_mode = (SpeexMode *) & speex_uwb_mode;
554     } else {
555       if (enc->speex_mode != &speex_uwb_mode) {
556         gst_speex_enc_set_last_msg (enc,
557             "Warning: suggest to use ultra wide band mode for this rate");
558       }
559     }
560   } else if (enc->rate > 12500) {
561     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
562       enc->speex_mode = (SpeexMode *) & speex_wb_mode;
563     } else {
564       if (enc->speex_mode != &speex_wb_mode) {
565         gst_speex_enc_set_last_msg (enc,
566             "Warning: suggest to use wide band mode for this rate");
567       }
568     }
569   } else {
570     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
571       enc->speex_mode = (SpeexMode *) & speex_nb_mode;
572     } else {
573       if (enc->speex_mode != &speex_nb_mode) {
574         gst_speex_enc_set_last_msg (enc,
575             "Warning: suggest to use narrow band mode for this rate");
576       }
577     }
578   }
579
580   if (enc->rate != 8000 && enc->rate != 16000 && enc->rate != 32000) {
581     gst_speex_enc_set_last_msg (enc,
582         "Warning: speex is optimized for 8, 16 and 32 KHz");
583   }
584
585   speex_init_header (&enc->header, enc->rate, 1, enc->speex_mode);
586   enc->header.frames_per_packet = enc->nframes;
587   enc->header.vbr = enc->vbr;
588   enc->header.nb_channels = enc->channels;
589
590   /*Initialize Speex encoder */
591   enc->state = speex_encoder_init (enc->speex_mode);
592
593   speex_encoder_ctl (enc->state, SPEEX_GET_FRAME_SIZE, &enc->frame_size);
594   speex_encoder_ctl (enc->state, SPEEX_SET_COMPLEXITY, &enc->complexity);
595   speex_encoder_ctl (enc->state, SPEEX_SET_SAMPLING_RATE, &enc->rate);
596
597   if (enc->vbr)
598     speex_encoder_ctl (enc->state, SPEEX_SET_VBR_QUALITY, &enc->quality);
599   else {
600     gint tmp = floor (enc->quality);
601
602     speex_encoder_ctl (enc->state, SPEEX_SET_QUALITY, &tmp);
603   }
604   if (enc->bitrate) {
605     if (enc->quality >= 0.0 && enc->vbr) {
606       gst_speex_enc_set_last_msg (enc,
607           "Warning: bitrate option is overriding quality");
608     }
609     speex_encoder_ctl (enc->state, SPEEX_SET_BITRATE, &enc->bitrate);
610   }
611   if (enc->vbr) {
612     gint tmp = 1;
613
614     speex_encoder_ctl (enc->state, SPEEX_SET_VBR, &tmp);
615   } else if (enc->vad) {
616     gint tmp = 1;
617
618     speex_encoder_ctl (enc->state, SPEEX_SET_VAD, &tmp);
619   }
620
621   if (enc->dtx) {
622     gint tmp = 1;
623
624     speex_encoder_ctl (enc->state, SPEEX_SET_DTX, &tmp);
625   }
626
627   if (enc->dtx && !(enc->vbr || enc->abr || enc->vad)) {
628     gst_speex_enc_set_last_msg (enc,
629         "Warning: dtx is useless without vad, vbr or abr");
630   } else if ((enc->vbr || enc->abr) && (enc->vad)) {
631     gst_speex_enc_set_last_msg (enc,
632         "Warning: vad is already implied by vbr or abr");
633   }
634
635   if (enc->abr) {
636     speex_encoder_ctl (enc->state, SPEEX_SET_ABR, &enc->abr);
637   }
638
639   speex_encoder_ctl (enc->state, SPEEX_GET_LOOKAHEAD, &enc->lookahead);
640
641   enc->setup = TRUE;
642
643   return TRUE;
644 }
645
646 /* prepare a buffer for transmission */
647 static GstBuffer *
648 gst_speex_enc_buffer_from_data (GstSpeexEnc * enc, guchar * data,
649     gint data_len, guint64 granulepos)
650 {
651   GstBuffer *outbuf;
652
653   outbuf = gst_buffer_new_and_alloc (data_len);
654   memcpy (GST_BUFFER_DATA (outbuf), data, data_len);
655   GST_BUFFER_OFFSET (outbuf) = enc->bytes_out;
656   GST_BUFFER_OFFSET_END (outbuf) = granulepos;
657
658   GST_LOG_OBJECT (enc, "encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
659   return outbuf;
660 }
661
662
663 /* push out the buffer and do internal bookkeeping */
664 static GstFlowReturn
665 gst_speex_enc_push_buffer (GstSpeexEnc * enc, GstBuffer * buffer)
666 {
667   enc->bytes_out += GST_BUFFER_SIZE (buffer);
668
669   return gst_pad_push (enc->srcpad, buffer);
670
671 }
672
673 static GstCaps *
674 gst_speex_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
675     GstBuffer * buf2)
676 {
677   GstStructure *structure = NULL;
678   GstBuffer *buf;
679   GValue array = { 0 };
680   GValue value = { 0 };
681
682   caps = gst_caps_make_writable (caps);
683   structure = gst_caps_get_structure (caps, 0);
684
685   g_assert (gst_buffer_is_metadata_writable (buf1));
686   g_assert (gst_buffer_is_metadata_writable (buf2));
687
688   /* mark buffers */
689   GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
690   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
691
692   /* put buffers in a fixed list */
693   g_value_init (&array, GST_TYPE_ARRAY);
694   g_value_init (&value, GST_TYPE_BUFFER);
695   buf = gst_buffer_copy (buf1);
696   gst_value_set_buffer (&value, buf);
697   gst_buffer_unref (buf);
698   gst_value_array_append_value (&array, &value);
699   g_value_unset (&value);
700   g_value_init (&value, GST_TYPE_BUFFER);
701   buf = gst_buffer_copy (buf2);
702   gst_value_set_buffer (&value, buf);
703   gst_buffer_unref (buf);
704   gst_value_array_append_value (&array, &value);
705   gst_structure_set_value (structure, "streamheader", &array);
706   g_value_unset (&value);
707   g_value_unset (&array);
708
709   return caps;
710 }
711
712
713 static gboolean
714 gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event)
715 {
716   gboolean res = TRUE;
717   GstSpeexEnc *enc;
718
719   enc = GST_SPEEX_ENC (gst_pad_get_parent (pad));
720
721   switch (GST_EVENT_TYPE (event)) {
722     case GST_EVENT_EOS:
723       enc->eos = TRUE;
724       res = gst_pad_event_default (pad, event);
725       break;
726     case GST_EVENT_TAG:
727     {
728       GstTagList *list;
729
730       gst_event_parse_tag (event, &list);
731       if (enc->tags) {
732         gst_tag_list_insert (enc->tags, list,
733             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
734       }
735       res = gst_pad_event_default (pad, event);
736       break;
737     }
738     default:
739       res = gst_pad_event_default (pad, event);
740       break;
741   }
742
743   gst_object_unref (enc);
744
745   return res;
746 }
747
748
749 static GstFlowReturn
750 gst_speex_enc_chain (GstPad * pad, GstBuffer * buf)
751 {
752   GstSpeexEnc *enc;
753   GstFlowReturn ret = GST_FLOW_OK;
754
755   enc = GST_SPEEX_ENC (GST_PAD_PARENT (pad));
756
757   if (!enc->setup)
758     goto not_setup;
759
760   if (!enc->header_sent) {
761     /* Speex streams begin with two headers; the initial header (with
762        most of the codec setup parameters) which is mandated by the Ogg
763        bitstream spec.  The second header holds any comment fields.
764        We merely need to make the headers, then pass them to libspeex 
765        one at a time; libspeex handles the additional Ogg bitstream 
766        constraints */
767     GstBuffer *buf1, *buf2;
768     GstCaps *caps;
769     guchar *data;
770     gint data_len;
771
772     /* create header buffer */
773     data = (guint8 *) speex_header_to_packet (&enc->header, &data_len);
774     buf1 = gst_speex_enc_buffer_from_data (enc, data, data_len, 0);
775     free (data);
776
777     /* create comment buffer */
778     buf2 = gst_speex_enc_create_metadata_buffer (enc);
779
780     /* mark and put on caps */
781     caps = gst_pad_get_caps (enc->srcpad);
782     caps = gst_speex_enc_set_header_on_caps (caps, buf1, buf2);
783
784     /* negotiate with these caps */
785     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
786     gst_pad_set_caps (enc->srcpad, caps);
787
788     gst_buffer_set_caps (buf1, caps);
789     gst_buffer_set_caps (buf2, caps);
790     gst_caps_unref (caps);
791
792     /* push out buffers */
793     ret = gst_speex_enc_push_buffer (enc, buf1);
794
795     if (ret != GST_FLOW_OK) {
796       gst_buffer_unref (buf2);
797       goto done;
798     }
799
800     ret = gst_speex_enc_push_buffer (enc, buf2);
801
802     if (ret != GST_FLOW_OK)
803       goto done;
804
805     speex_bits_reset (&enc->bits);
806
807     enc->header_sent = TRUE;
808   }
809
810   {
811     gint frame_size = enc->frame_size;
812     gint bytes = frame_size * 2 * enc->channels;
813
814     /* push buffer to adapter */
815     gst_adapter_push (enc->adapter, buf);
816     buf = NULL;
817
818     while (gst_adapter_available (enc->adapter) >= bytes) {
819       gint16 *data;
820       gint i;
821       gint outsize, written;
822       GstBuffer *outbuf;
823
824       data = (gint16 *) gst_adapter_peek (enc->adapter, bytes);
825
826       for (i = 0; i < frame_size * enc->channels; i++) {
827         enc->input[i] = (gfloat) data[i];
828       }
829       gst_adapter_flush (enc->adapter, bytes);
830
831       enc->samples_in += frame_size;
832
833       if (enc->channels == 2) {
834         speex_encode_stereo (enc->input, frame_size, &enc->bits);
835       }
836       speex_encode (enc->state, enc->input, &enc->bits);
837
838       enc->frameno++;
839
840       if ((enc->frameno % enc->nframes) != 0)
841         continue;
842
843       speex_bits_insert_terminator (&enc->bits);
844       outsize = speex_bits_nbytes (&enc->bits);
845
846       ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
847           GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (enc->srcpad), &outbuf);
848
849       if ((GST_FLOW_OK != ret))
850         goto done;
851
852       written = speex_bits_write (&enc->bits,
853           (gchar *) GST_BUFFER_DATA (outbuf), outsize);
854       g_assert (written == outsize);
855       speex_bits_reset (&enc->bits);
856
857       GST_BUFFER_TIMESTAMP (outbuf) =
858           gst_util_uint64_scale_int (enc->frameno * frame_size -
859           enc->lookahead, GST_SECOND, enc->rate);
860       GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (frame_size,
861           GST_SECOND, enc->rate);
862       /* set gp time and granulepos; see gst-plugins-base/ext/ogg/README */
863       GST_BUFFER_OFFSET_END (outbuf) =
864           ((enc->frameno + 1) * frame_size - enc->lookahead);
865       GST_BUFFER_OFFSET (outbuf) =
866           gst_util_uint64_scale_int (GST_BUFFER_OFFSET_END (outbuf), GST_SECOND,
867           enc->rate);
868
869       ret = gst_speex_enc_push_buffer (enc, outbuf);
870
871       if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret))
872         goto done;
873     }
874   }
875
876 done:
877
878   if (buf)
879     gst_buffer_unref (buf);
880
881   return ret;
882
883   /* ERRORS */
884 not_setup:
885   {
886     GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL),
887         ("encoder not initialized (input is not audio?)"));
888     ret = GST_FLOW_NOT_NEGOTIATED;
889     goto done;
890   }
891
892 }
893
894
895 static void
896 gst_speex_enc_get_property (GObject * object, guint prop_id, GValue * value,
897     GParamSpec * pspec)
898 {
899   GstSpeexEnc *enc;
900
901   enc = GST_SPEEX_ENC (object);
902
903   switch (prop_id) {
904     case ARG_QUALITY:
905       g_value_set_float (value, enc->quality);
906       break;
907     case ARG_BITRATE:
908       g_value_set_int (value, enc->bitrate);
909       break;
910     case ARG_VBR:
911       g_value_set_boolean (value, enc->vbr);
912       break;
913     case ARG_ABR:
914       g_value_set_int (value, enc->abr);
915       break;
916     case ARG_VAD:
917       g_value_set_boolean (value, enc->vad);
918       break;
919     case ARG_DTX:
920       g_value_set_boolean (value, enc->dtx);
921       break;
922     case ARG_COMPLEXITY:
923       g_value_set_int (value, enc->complexity);
924       break;
925     case ARG_NFRAMES:
926       g_value_set_int (value, enc->nframes);
927       break;
928     case ARG_LAST_MESSAGE:
929       g_value_set_string (value, enc->last_message);
930       break;
931     default:
932       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
933       break;
934   }
935 }
936
937 static void
938 gst_speex_enc_set_property (GObject * object, guint prop_id,
939     const GValue * value, GParamSpec * pspec)
940 {
941   GstSpeexEnc *enc;
942
943   enc = GST_SPEEX_ENC (object);
944
945   switch (prop_id) {
946     case ARG_QUALITY:
947       enc->quality = g_value_get_float (value);
948       break;
949     case ARG_BITRATE:
950       enc->bitrate = g_value_get_int (value);
951       break;
952     case ARG_VBR:
953       enc->vbr = g_value_get_boolean (value);
954       break;
955     case ARG_ABR:
956       enc->abr = g_value_get_int (value);
957       break;
958     case ARG_VAD:
959       enc->vad = g_value_get_boolean (value);
960       break;
961     case ARG_DTX:
962       enc->dtx = g_value_get_boolean (value);
963       break;
964     case ARG_COMPLEXITY:
965       enc->complexity = g_value_get_int (value);
966       break;
967     case ARG_NFRAMES:
968       enc->nframes = g_value_get_int (value);
969       break;
970     default:
971       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
972       break;
973   }
974 }
975
976 static GstStateChangeReturn
977 gst_speex_enc_change_state (GstElement * element, GstStateChange transition)
978 {
979   GstSpeexEnc *enc = GST_SPEEX_ENC (element);
980   GstStateChangeReturn res;
981
982   switch (transition) {
983     case GST_STATE_CHANGE_NULL_TO_READY:
984       enc->tags = gst_tag_list_new ();
985       break;
986     case GST_STATE_CHANGE_READY_TO_PAUSED:
987       speex_bits_init (&enc->bits);
988       enc->frameno = 0;
989       enc->samples_in = 0;
990       break;
991     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
992       /* fall through */
993     default:
994       break;
995   }
996
997   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
998   if (res == GST_STATE_CHANGE_FAILURE)
999     return res;
1000
1001   switch (transition) {
1002     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1003       break;
1004     case GST_STATE_CHANGE_PAUSED_TO_READY:
1005       enc->setup = FALSE;
1006       enc->header_sent = FALSE;
1007       if (enc->state) {
1008         speex_encoder_destroy (enc->state);
1009         enc->state = NULL;
1010       }
1011       speex_bits_destroy (&enc->bits);
1012       break;
1013     case GST_STATE_CHANGE_READY_TO_NULL:
1014       gst_tag_list_free (enc->tags);
1015       enc->tags = NULL;
1016     default:
1017       break;
1018   }
1019
1020   return res;
1021 }