speexenc: only push header buffers following initial events
[platform/upstream/gstreamer.git] / ext / speex / gstspeexenc.c
1 /* GStreamer Speex Encoder
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:element-speexenc
22  * @see_also: speexdec, oggmux
23  *
24  * This element encodes audio as a Speex stream.
25  * <ulink url="http://www.speex.org/">Speex</ulink> is a royalty-free
26  * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
27  * Foundation</ulink>.
28  *
29  * <refsect2>
30  * <title>Example pipelines</title>
31  * |[
32  * gst-launch audiotestsrc num-buffers=100 ! speexenc ! oggmux ! filesink location=beep.ogg
33  * ]| Encode an Ogg/Speex file.
34  * </refsect2>
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 #include <math.h>
44 #include <speex/speex.h>
45 #include <speex/speex_stereo.h>
46
47 #include <gst/gsttagsetter.h>
48 #include <gst/tag/tag.h>
49 #include <gst/audio/audio.h>
50 #include "gstspeexenc.h"
51
52 GST_DEBUG_CATEGORY_STATIC (speexenc_debug);
53 #define GST_CAT_DEFAULT speexenc_debug
54
55 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
56     GST_PAD_SINK,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS ("audio/x-raw-int, "
59         "rate = (int) [ 6000, 48000 ], "
60         "channels = (int) [ 1, 2 ], "
61         "endianness = (int) BYTE_ORDER, "
62         "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16")
63     );
64
65 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
66     GST_PAD_SRC,
67     GST_PAD_ALWAYS,
68     GST_STATIC_CAPS ("audio/x-speex, "
69         "rate = (int) [ 6000, 48000 ], " "channels = (int) [ 1, 2]")
70     );
71
72 #define DEFAULT_QUALITY         8.0
73 #define DEFAULT_BITRATE         0
74 #define DEFAULT_MODE            GST_SPEEX_ENC_MODE_AUTO
75 #define DEFAULT_VBR             FALSE
76 #define DEFAULT_ABR             0
77 #define DEFAULT_VAD             FALSE
78 #define DEFAULT_DTX             FALSE
79 #define DEFAULT_COMPLEXITY      3
80 #define DEFAULT_NFRAMES         1
81
82 enum
83 {
84   PROP_0,
85   PROP_QUALITY,
86   PROP_BITRATE,
87   PROP_MODE,
88   PROP_VBR,
89   PROP_ABR,
90   PROP_VAD,
91   PROP_DTX,
92   PROP_COMPLEXITY,
93   PROP_NFRAMES,
94   PROP_LAST_MESSAGE
95 };
96
97 #define GST_TYPE_SPEEX_ENC_MODE (gst_speex_enc_mode_get_type())
98 static GType
99 gst_speex_enc_mode_get_type (void)
100 {
101   static GType speex_enc_mode_type = 0;
102   static const GEnumValue speex_enc_modes[] = {
103     {GST_SPEEX_ENC_MODE_AUTO, "Auto", "auto"},
104     {GST_SPEEX_ENC_MODE_UWB, "Ultra Wide Band", "uwb"},
105     {GST_SPEEX_ENC_MODE_WB, "Wide Band", "wb"},
106     {GST_SPEEX_ENC_MODE_NB, "Narrow Band", "nb"},
107     {0, NULL, NULL},
108   };
109   if (G_UNLIKELY (speex_enc_mode_type == 0)) {
110     speex_enc_mode_type = g_enum_register_static ("GstSpeexEncMode",
111         speex_enc_modes);
112   }
113   return speex_enc_mode_type;
114 }
115
116 static void gst_speex_enc_finalize (GObject * object);
117
118 static gboolean gst_speex_enc_setup (GstSpeexEnc * enc);
119
120 static void gst_speex_enc_get_property (GObject * object, guint prop_id,
121     GValue * value, GParamSpec * pspec);
122 static void gst_speex_enc_set_property (GObject * object, guint prop_id,
123     const GValue * value, GParamSpec * pspec);
124
125 static GstFlowReturn gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf);
126
127 static gboolean gst_speex_enc_start (GstAudioEncoder * enc);
128 static gboolean gst_speex_enc_stop (GstAudioEncoder * enc);
129 static gboolean gst_speex_enc_set_format (GstAudioEncoder * enc,
130     GstAudioInfo * info);
131 static GstFlowReturn gst_speex_enc_handle_frame (GstAudioEncoder * enc,
132     GstBuffer * in_buf);
133 static gboolean gst_speex_enc_sink_event (GstAudioEncoder * enc,
134     GstEvent * event);
135 static GstFlowReturn
136 gst_speex_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer);
137
138 static void
139 gst_speex_enc_setup_interfaces (GType speexenc_type)
140 {
141   static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
142
143   g_type_add_interface_static (speexenc_type, GST_TYPE_TAG_SETTER,
144       &tag_setter_info);
145
146   GST_DEBUG_CATEGORY_INIT (speexenc_debug, "speexenc", 0, "Speex encoder");
147 }
148
149 GST_BOILERPLATE_FULL (GstSpeexEnc, gst_speex_enc, GstAudioEncoder,
150     GST_TYPE_AUDIO_ENCODER, gst_speex_enc_setup_interfaces);
151
152 static void
153 gst_speex_enc_base_init (gpointer g_class)
154 {
155   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
156
157   gst_element_class_add_pad_template (element_class,
158       gst_static_pad_template_get (&src_factory));
159   gst_element_class_add_pad_template (element_class,
160       gst_static_pad_template_get (&sink_factory));
161   gst_element_class_set_details_simple (element_class, "Speex audio encoder",
162       "Codec/Encoder/Audio",
163       "Encodes audio in Speex format", "Wim Taymans <wim@fluendo.com>");
164 }
165
166 static void
167 gst_speex_enc_class_init (GstSpeexEncClass * klass)
168 {
169   GObjectClass *gobject_class;
170   GstAudioEncoderClass *base_class;
171
172   gobject_class = (GObjectClass *) klass;
173   base_class = (GstAudioEncoderClass *) klass;
174
175   gobject_class->set_property = gst_speex_enc_set_property;
176   gobject_class->get_property = gst_speex_enc_get_property;
177
178   base_class->start = GST_DEBUG_FUNCPTR (gst_speex_enc_start);
179   base_class->stop = GST_DEBUG_FUNCPTR (gst_speex_enc_stop);
180   base_class->set_format = GST_DEBUG_FUNCPTR (gst_speex_enc_set_format);
181   base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_speex_enc_handle_frame);
182   base_class->event = GST_DEBUG_FUNCPTR (gst_speex_enc_sink_event);
183   base_class->pre_push = GST_DEBUG_FUNCPTR (gst_speex_enc_pre_push);
184
185   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_QUALITY,
186       g_param_spec_float ("quality", "Quality", "Encoding quality",
187           0.0, 10.0, DEFAULT_QUALITY,
188           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
189   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BITRATE,
190       g_param_spec_int ("bitrate", "Encoding Bit-rate",
191           "Specify an encoding bit-rate (in bps). (0 = automatic)",
192           0, G_MAXINT, DEFAULT_BITRATE,
193           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
194   g_object_class_install_property (gobject_class, PROP_MODE,
195       g_param_spec_enum ("mode", "Mode", "The encoding mode",
196           GST_TYPE_SPEEX_ENC_MODE, GST_SPEEX_ENC_MODE_AUTO,
197           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VBR,
199       g_param_spec_boolean ("vbr", "VBR",
200           "Enable variable bit-rate", DEFAULT_VBR,
201           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
202   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ABR,
203       g_param_spec_int ("abr", "ABR",
204           "Enable average bit-rate (0 = disabled)",
205           0, G_MAXINT, DEFAULT_ABR,
206           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
207   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VAD,
208       g_param_spec_boolean ("vad", "VAD",
209           "Enable voice activity detection", DEFAULT_VAD,
210           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
211   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DTX,
212       g_param_spec_boolean ("dtx", "DTX",
213           "Enable discontinuous transmission", DEFAULT_DTX,
214           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
215   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLEXITY,
216       g_param_spec_int ("complexity", "Complexity",
217           "Set encoding complexity",
218           0, G_MAXINT, DEFAULT_COMPLEXITY,
219           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
220   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NFRAMES,
221       g_param_spec_int ("nframes", "NFrames",
222           "Number of frames per buffer",
223           0, G_MAXINT, DEFAULT_NFRAMES,
224           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
225   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
226       g_param_spec_string ("last-message", "last-message",
227           "The last status message", NULL,
228           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
229
230   gobject_class->finalize = gst_speex_enc_finalize;
231 }
232
233 static void
234 gst_speex_enc_finalize (GObject * object)
235 {
236   GstSpeexEnc *enc;
237
238   enc = GST_SPEEX_ENC (object);
239
240   g_free (enc->last_message);
241
242   G_OBJECT_CLASS (parent_class)->finalize (object);
243 }
244
245 static void
246 gst_speex_enc_init (GstSpeexEnc * enc, GstSpeexEncClass * klass)
247 {
248   GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
249
250   /* arrange granulepos marking (and required perfect ts) */
251   gst_audio_encoder_set_mark_granule (benc, TRUE);
252   gst_audio_encoder_set_perfect_timestamp (benc, TRUE);
253 }
254
255 static gboolean
256 gst_speex_enc_start (GstAudioEncoder * benc)
257 {
258   GstSpeexEnc *enc = GST_SPEEX_ENC (benc);
259
260   GST_DEBUG_OBJECT (enc, "start");
261   speex_bits_init (&enc->bits);
262   enc->tags = gst_tag_list_new ();
263   enc->header_sent = FALSE;
264
265   return TRUE;
266 }
267
268 static gboolean
269 gst_speex_enc_stop (GstAudioEncoder * benc)
270 {
271   GstSpeexEnc *enc = GST_SPEEX_ENC (benc);
272
273   GST_DEBUG_OBJECT (enc, "stop");
274   enc->header_sent = FALSE;
275   if (enc->state) {
276     speex_encoder_destroy (enc->state);
277     enc->state = NULL;
278   }
279   speex_bits_destroy (&enc->bits);
280   gst_tag_list_free (enc->tags);
281   enc->tags = NULL;
282   g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
283   enc->headers = NULL;
284
285   return TRUE;
286 }
287
288 static gint64
289 gst_speex_enc_get_latency (GstSpeexEnc * enc)
290 {
291   /* See the Speex manual section "Latency and algorithmic delay" */
292   if (enc->rate == 8000)
293     return 30 * GST_MSECOND;
294   else
295     return 34 * GST_MSECOND;
296 }
297
298 static gboolean
299 gst_speex_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
300 {
301   GstSpeexEnc *enc;
302
303   enc = GST_SPEEX_ENC (benc);
304
305   enc->channels = GST_AUDIO_INFO_CHANNELS (info);
306   enc->rate = GST_AUDIO_INFO_RATE (info);
307
308   /* handle reconfigure */
309   if (enc->state) {
310     speex_encoder_destroy (enc->state);
311     enc->state = NULL;
312   }
313
314   if (!gst_speex_enc_setup (enc))
315     return FALSE;
316
317   /* feedback to base class */
318   gst_audio_encoder_set_latency (benc,
319       gst_speex_enc_get_latency (enc), gst_speex_enc_get_latency (enc));
320   gst_audio_encoder_set_lookahead (benc, enc->lookahead);
321
322   if (enc->nframes == 0) {
323     /* as many frames as available input allows */
324     gst_audio_encoder_set_frame_samples_min (benc, enc->frame_size);
325     gst_audio_encoder_set_frame_samples_max (benc, enc->frame_size);
326     gst_audio_encoder_set_frame_max (benc, 0);
327   } else {
328     /* exactly as many frames as configured */
329     gst_audio_encoder_set_frame_samples_min (benc,
330         enc->frame_size * enc->nframes);
331     gst_audio_encoder_set_frame_samples_max (benc,
332         enc->frame_size * enc->nframes);
333     gst_audio_encoder_set_frame_max (benc, 1);
334   }
335
336   return TRUE;
337 }
338
339 static GstBuffer *
340 gst_speex_enc_create_metadata_buffer (GstSpeexEnc * enc)
341 {
342   const GstTagList *user_tags;
343   GstTagList *merged_tags;
344   GstBuffer *comments = NULL;
345
346   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
347
348   GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
349   GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
350
351   /* gst_tag_list_merge() will handle NULL for either or both lists fine */
352   merged_tags = gst_tag_list_merge (user_tags, enc->tags,
353       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
354
355   if (merged_tags == NULL)
356     merged_tags = gst_tag_list_new ();
357
358   GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
359   comments = gst_tag_list_to_vorbiscomment_buffer (merged_tags, NULL,
360       0, "Encoded with GStreamer Speexenc");
361   gst_tag_list_free (merged_tags);
362
363   GST_BUFFER_OFFSET (comments) = 0;
364   GST_BUFFER_OFFSET_END (comments) = 0;
365
366   return comments;
367 }
368
369 static void
370 gst_speex_enc_set_last_msg (GstSpeexEnc * enc, const gchar * msg)
371 {
372   g_free (enc->last_message);
373   enc->last_message = g_strdup (msg);
374   GST_WARNING_OBJECT (enc, "%s", msg);
375   g_object_notify (G_OBJECT (enc), "last-message");
376 }
377
378 static gboolean
379 gst_speex_enc_setup (GstSpeexEnc * enc)
380 {
381   switch (enc->mode) {
382     case GST_SPEEX_ENC_MODE_UWB:
383       GST_LOG_OBJECT (enc, "configuring for requested UWB mode");
384       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_UWB);
385       break;
386     case GST_SPEEX_ENC_MODE_WB:
387       GST_LOG_OBJECT (enc, "configuring for requested WB mode");
388       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_WB);
389       break;
390     case GST_SPEEX_ENC_MODE_NB:
391       GST_LOG_OBJECT (enc, "configuring for requested NB mode");
392       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_NB);
393       break;
394     case GST_SPEEX_ENC_MODE_AUTO:
395       /* fall through */
396       GST_LOG_OBJECT (enc, "finding best mode");
397     default:
398       break;
399   }
400
401   if (enc->rate > 25000) {
402     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
403       GST_LOG_OBJECT (enc, "selected UWB mode for samplerate %d", enc->rate);
404       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_UWB);
405     } else {
406       if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_UWB)) {
407         gst_speex_enc_set_last_msg (enc,
408             "Warning: suggest to use ultra wide band mode for this rate");
409       }
410     }
411   } else if (enc->rate > 12500) {
412     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
413       GST_LOG_OBJECT (enc, "selected WB mode for samplerate %d", enc->rate);
414       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_WB);
415     } else {
416       if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_WB)) {
417         gst_speex_enc_set_last_msg (enc,
418             "Warning: suggest to use wide band mode for this rate");
419       }
420     }
421   } else {
422     if (enc->mode == GST_SPEEX_ENC_MODE_AUTO) {
423       GST_LOG_OBJECT (enc, "selected NB mode for samplerate %d", enc->rate);
424       enc->speex_mode = speex_lib_get_mode (SPEEX_MODEID_NB);
425     } else {
426       if (enc->speex_mode != speex_lib_get_mode (SPEEX_MODEID_NB)) {
427         gst_speex_enc_set_last_msg (enc,
428             "Warning: suggest to use narrow band mode for this rate");
429       }
430     }
431   }
432
433   if (enc->rate != 8000 && enc->rate != 16000 && enc->rate != 32000) {
434     gst_speex_enc_set_last_msg (enc,
435         "Warning: speex is optimized for 8, 16 and 32 KHz");
436   }
437
438   speex_init_header (&enc->header, enc->rate, 1, enc->speex_mode);
439   enc->header.frames_per_packet = enc->nframes;
440   enc->header.vbr = enc->vbr;
441   enc->header.nb_channels = enc->channels;
442
443   /*Initialize Speex encoder */
444   enc->state = speex_encoder_init (enc->speex_mode);
445
446   speex_encoder_ctl (enc->state, SPEEX_GET_FRAME_SIZE, &enc->frame_size);
447   speex_encoder_ctl (enc->state, SPEEX_SET_COMPLEXITY, &enc->complexity);
448   speex_encoder_ctl (enc->state, SPEEX_SET_SAMPLING_RATE, &enc->rate);
449
450   if (enc->vbr)
451     speex_encoder_ctl (enc->state, SPEEX_SET_VBR_QUALITY, &enc->quality);
452   else {
453     gint tmp = floor (enc->quality);
454
455     speex_encoder_ctl (enc->state, SPEEX_SET_QUALITY, &tmp);
456   }
457   if (enc->bitrate) {
458     if (enc->quality >= 0.0 && enc->vbr) {
459       gst_speex_enc_set_last_msg (enc,
460           "Warning: bitrate option is overriding quality");
461     }
462     speex_encoder_ctl (enc->state, SPEEX_SET_BITRATE, &enc->bitrate);
463   }
464   if (enc->vbr) {
465     gint tmp = 1;
466
467     speex_encoder_ctl (enc->state, SPEEX_SET_VBR, &tmp);
468   } else if (enc->vad) {
469     gint tmp = 1;
470
471     speex_encoder_ctl (enc->state, SPEEX_SET_VAD, &tmp);
472   }
473
474   if (enc->dtx) {
475     gint tmp = 1;
476
477     speex_encoder_ctl (enc->state, SPEEX_SET_DTX, &tmp);
478   }
479
480   if (enc->dtx && !(enc->vbr || enc->abr || enc->vad)) {
481     gst_speex_enc_set_last_msg (enc,
482         "Warning: dtx is useless without vad, vbr or abr");
483   } else if ((enc->vbr || enc->abr) && (enc->vad)) {
484     gst_speex_enc_set_last_msg (enc,
485         "Warning: vad is already implied by vbr or abr");
486   }
487
488   if (enc->abr) {
489     speex_encoder_ctl (enc->state, SPEEX_SET_ABR, &enc->abr);
490   }
491
492   speex_encoder_ctl (enc->state, SPEEX_GET_LOOKAHEAD, &enc->lookahead);
493
494   GST_LOG_OBJECT (enc, "we have frame size %d, lookahead %d", enc->frame_size,
495       enc->lookahead);
496
497   return TRUE;
498 }
499
500 /* push out the buffer */
501 static GstFlowReturn
502 gst_speex_enc_push_buffer (GstSpeexEnc * enc, GstBuffer * buffer)
503 {
504   guint size;
505
506   size = GST_BUFFER_SIZE (buffer);
507   GST_DEBUG_OBJECT (enc, "pushing output buffer of size %u", size);
508
509   gst_buffer_set_caps (buffer, GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)));
510   return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (enc), buffer);
511 }
512
513 static gboolean
514 gst_speex_enc_sink_event (GstAudioEncoder * benc, GstEvent * event)
515 {
516   GstSpeexEnc *enc;
517
518   enc = GST_SPEEX_ENC (benc);
519
520   switch (GST_EVENT_TYPE (event)) {
521     case GST_EVENT_TAG:
522     {
523       if (enc->tags) {
524         GstTagList *list;
525
526         gst_event_parse_tag (event, &list);
527         gst_tag_list_insert (enc->tags, list,
528             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
529       } else {
530         g_assert_not_reached ();
531       }
532       break;
533     }
534     default:
535       break;
536   }
537
538   /* we only peeked, let base class handle it */
539   return FALSE;
540 }
541
542 static GstFlowReturn
543 gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
544 {
545   gint frame_size = enc->frame_size;
546   gint bytes = frame_size * 2 * enc->channels, samples, size;
547   gint outsize, written, dtx_ret = 0;
548   guint8 *data;
549   GstBuffer *outbuf;
550   GstFlowReturn ret = GST_FLOW_OK;
551
552   if (G_LIKELY (buf)) {
553     data = GST_BUFFER_DATA (buf);
554     size = GST_BUFFER_SIZE (buf);
555
556     if (G_UNLIKELY (size % bytes)) {
557       GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
558       size = ((size / bytes) + 1) * bytes;
559       data = g_malloc0 (size);
560       memcpy (data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
561     }
562   } else {
563     GST_DEBUG_OBJECT (enc, "nothing to drain");
564     goto done;
565   }
566
567   samples = size / (2 * enc->channels);
568   speex_bits_reset (&enc->bits);
569
570   /* FIXME what about dropped samples if DTS enabled ?? */
571
572   while (size) {
573     GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes);
574
575     if (enc->channels == 2) {
576       speex_encode_stereo_int ((gint16 *) data, frame_size, &enc->bits);
577     }
578     dtx_ret += speex_encode_int (enc->state, (gint16 *) data, &enc->bits);
579
580     data += bytes;
581     size -= bytes;
582   }
583
584   speex_bits_insert_terminator (&enc->bits);
585   outsize = speex_bits_nbytes (&enc->bits);
586
587   ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
588       GST_BUFFER_OFFSET_NONE, outsize,
589       GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
590
591   if ((GST_FLOW_OK != ret))
592     goto done;
593
594   written = speex_bits_write (&enc->bits,
595       (gchar *) GST_BUFFER_DATA (outbuf), outsize);
596
597   if (G_UNLIKELY (written < outsize)) {
598     GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize);
599     GST_BUFFER_SIZE (outbuf) = written;
600   } else if (G_UNLIKELY (written > outsize)) {
601     GST_ERROR_OBJECT (enc, "overrun: %d > %d bytes", written, outsize);
602   }
603
604   if (!dtx_ret)
605     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
606
607   ret = gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc),
608       outbuf, samples);
609
610 done:
611   return ret;
612 }
613
614 /*
615  * (really really) FIXME: move into core (dixit tpm)
616  */
617 /**
618  * _gst_caps_set_buffer_array:
619  * @caps: a #GstCaps
620  * @field: field in caps to set
621  * @buf: header buffers
622  *
623  * Adds given buffers to an array of buffers set as the given @field
624  * on the given @caps.  List of buffer arguments must be NULL-terminated.
625  *
626  * Returns: input caps with a streamheader field added, or NULL if some error
627  */
628 static GstCaps *
629 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
630     GstBuffer * buf, ...)
631 {
632   GstStructure *structure = NULL;
633   va_list va;
634   GValue array = { 0 };
635   GValue value = { 0 };
636
637   g_return_val_if_fail (caps != NULL, NULL);
638   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
639   g_return_val_if_fail (field != NULL, NULL);
640
641   caps = gst_caps_make_writable (caps);
642   structure = gst_caps_get_structure (caps, 0);
643
644   g_value_init (&array, GST_TYPE_ARRAY);
645
646   va_start (va, buf);
647   /* put buffers in a fixed list */
648   while (buf) {
649     g_assert (gst_buffer_is_metadata_writable (buf));
650
651     /* mark buffer */
652     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
653
654     g_value_init (&value, GST_TYPE_BUFFER);
655     buf = gst_buffer_copy (buf);
656     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
657     gst_value_set_buffer (&value, buf);
658     gst_buffer_unref (buf);
659     gst_value_array_append_value (&array, &value);
660     g_value_unset (&value);
661
662     buf = va_arg (va, GstBuffer *);
663   }
664
665   gst_structure_set_value (structure, field, &array);
666   g_value_unset (&array);
667
668   return caps;
669 }
670
671 static GstFlowReturn
672 gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
673 {
674   GstSpeexEnc *enc;
675   GstFlowReturn ret = GST_FLOW_OK;
676
677   enc = GST_SPEEX_ENC (benc);
678
679   if (!enc->header_sent) {
680     /* Speex streams begin with two headers; the initial header (with
681        most of the codec setup parameters) which is mandated by the Ogg
682        bitstream spec.  The second header holds any comment fields.
683        We merely need to make the headers, then pass them to libspeex 
684        one at a time; libspeex handles the additional Ogg bitstream 
685        constraints */
686     GstBuffer *buf1, *buf2;
687     GstCaps *caps;
688     guchar *data;
689     gint data_len;
690
691     /* create header buffer */
692     data = (guint8 *) speex_header_to_packet (&enc->header, &data_len);
693     buf1 = gst_buffer_new ();
694     GST_BUFFER_DATA (buf1) = GST_BUFFER_MALLOCDATA (buf1) = data;
695     GST_BUFFER_SIZE (buf1) = data_len;
696     GST_BUFFER_OFFSET_END (buf1) = 0;
697     GST_BUFFER_OFFSET (buf1) = 0;
698
699     /* create comment buffer */
700     buf2 = gst_speex_enc_create_metadata_buffer (enc);
701
702     /* mark and put on caps */
703     caps = gst_caps_new_simple ("audio/x-speex", "rate", G_TYPE_INT, enc->rate,
704         "channels", G_TYPE_INT, enc->channels, NULL);
705     caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL);
706
707     /* negotiate with these caps */
708     GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
709
710     gst_buffer_set_caps (buf1, caps);
711     gst_buffer_set_caps (buf2, caps);
712     gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
713     gst_caps_unref (caps);
714
715     /* push out buffers */
716     /* store buffers for later pre_push sending */
717     g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
718     enc->headers = NULL;
719     GST_DEBUG_OBJECT (enc, "storing header buffers");
720     enc->headers = g_slist_prepend (enc->headers, buf2);
721     enc->headers = g_slist_prepend (enc->headers, buf1);
722
723     enc->header_sent = TRUE;
724   }
725
726   GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
727       buf ? GST_BUFFER_SIZE (buf) : 0);
728
729   ret = gst_speex_enc_encode (enc, buf);
730
731   return ret;
732 }
733
734 static GstFlowReturn
735 gst_speex_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer)
736 {
737   GstSpeexEnc *enc;
738   GstFlowReturn ret = GST_FLOW_OK;
739
740   enc = GST_SPEEX_ENC (benc);
741
742   /* FIXME 0.11 ? get rid of this special ogg stuff and have it
743    * put and use 'codec data' in caps like anything else,
744    * with all the usual out-of-band advantage etc */
745   if (G_UNLIKELY (enc->headers)) {
746     GSList *header = enc->headers;
747
748     /* try to push all of these, if we lose one, might as well lose all */
749     while (header) {
750       if (ret == GST_FLOW_OK)
751         ret = gst_speex_enc_push_buffer (enc, header->data);
752       else
753         gst_speex_enc_push_buffer (enc, header->data);
754       header = g_slist_next (header);
755     }
756
757     g_slist_free (enc->headers);
758     enc->headers = NULL;
759   }
760
761   return ret;
762 }
763
764 static void
765 gst_speex_enc_get_property (GObject * object, guint prop_id, GValue * value,
766     GParamSpec * pspec)
767 {
768   GstSpeexEnc *enc;
769
770   enc = GST_SPEEX_ENC (object);
771
772   switch (prop_id) {
773     case PROP_QUALITY:
774       g_value_set_float (value, enc->quality);
775       break;
776     case PROP_BITRATE:
777       g_value_set_int (value, enc->bitrate);
778       break;
779     case PROP_MODE:
780       g_value_set_enum (value, enc->mode);
781       break;
782     case PROP_VBR:
783       g_value_set_boolean (value, enc->vbr);
784       break;
785     case PROP_ABR:
786       g_value_set_int (value, enc->abr);
787       break;
788     case PROP_VAD:
789       g_value_set_boolean (value, enc->vad);
790       break;
791     case PROP_DTX:
792       g_value_set_boolean (value, enc->dtx);
793       break;
794     case PROP_COMPLEXITY:
795       g_value_set_int (value, enc->complexity);
796       break;
797     case PROP_NFRAMES:
798       g_value_set_int (value, enc->nframes);
799       break;
800     case PROP_LAST_MESSAGE:
801       g_value_set_string (value, enc->last_message);
802       break;
803     default:
804       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
805       break;
806   }
807 }
808
809 static void
810 gst_speex_enc_set_property (GObject * object, guint prop_id,
811     const GValue * value, GParamSpec * pspec)
812 {
813   GstSpeexEnc *enc;
814
815   enc = GST_SPEEX_ENC (object);
816
817   switch (prop_id) {
818     case PROP_QUALITY:
819       enc->quality = g_value_get_float (value);
820       break;
821     case PROP_BITRATE:
822       enc->bitrate = g_value_get_int (value);
823       break;
824     case PROP_MODE:
825       enc->mode = g_value_get_enum (value);
826       break;
827     case PROP_VBR:
828       enc->vbr = g_value_get_boolean (value);
829       break;
830     case PROP_ABR:
831       enc->abr = g_value_get_int (value);
832       break;
833     case PROP_VAD:
834       enc->vad = g_value_get_boolean (value);
835       break;
836     case PROP_DTX:
837       enc->dtx = g_value_get_boolean (value);
838       break;
839     case PROP_COMPLEXITY:
840       enc->complexity = g_value_get_int (value);
841       break;
842     case PROP_NFRAMES:
843       enc->nframes = g_value_get_int (value);
844       break;
845     default:
846       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
847       break;
848   }
849 }