6aac4ab6f5c7fb45b2143ac1a9e0ffde8a15035b
[platform/upstream/gstreamer.git] / ext / vorbis / gstvorbisenc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:element-vorbisenc
22  * @see_also: vorbisdec, oggmux
23  *
24  * This element encodes raw float audio into a Vorbis stream.
25  * <ulink url="http://www.vorbis.com/">Vorbis</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 -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sine.ogg
33  * ]| Encode a test sine signal to Ogg/Vorbis.  Note that the resulting file
34  * will be really small because a sine signal compresses very well.
35  * |[
36  * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
37  * ]| Record from a sound card using ALSA and encode to Ogg/Vorbis.
38  * </refsect2>
39  *
40  * Last reviewed on 2006-03-01 (0.10.4)
41  */
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45
46 #include <stdlib.h>
47 #include <string.h>
48 #include <time.h>
49 #include <vorbis/vorbisenc.h>
50
51 #include <gst/gsttagsetter.h>
52 #include <gst/tag/tag.h>
53 #include <gst/audio/multichannel.h>
54 #include <gst/audio/audio.h>
55 #include "gstvorbisenc.h"
56
57 #include "gstvorbiscommon.h"
58
59 GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
60 #define GST_CAT_DEFAULT vorbisenc_debug
61
62 static GstStaticPadTemplate vorbis_enc_sink_factory =
63 GST_STATIC_PAD_TEMPLATE ("sink",
64     GST_PAD_SINK,
65     GST_PAD_ALWAYS,
66     GST_STATIC_CAPS ("audio/x-raw-float, "
67         "rate = (int) [ 1, 200000 ], "
68         "channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, "
69         "width = (int) 32")
70     );
71
72 static GstStaticPadTemplate vorbis_enc_src_factory =
73 GST_STATIC_PAD_TEMPLATE ("src",
74     GST_PAD_SRC,
75     GST_PAD_ALWAYS,
76     GST_STATIC_CAPS ("audio/x-vorbis")
77     );
78
79 enum
80 {
81   ARG_0,
82   ARG_MAX_BITRATE,
83   ARG_BITRATE,
84   ARG_MIN_BITRATE,
85   ARG_QUALITY,
86   ARG_MANAGED,
87   ARG_LAST_MESSAGE
88 };
89
90 static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
91
92
93 #define MAX_BITRATE_DEFAULT     -1
94 #define BITRATE_DEFAULT         -1
95 #define MIN_BITRATE_DEFAULT     -1
96 #define QUALITY_DEFAULT         0.3
97 #define LOWEST_BITRATE          6000    /* lowest allowed for a 8 kHz stream */
98 #define HIGHEST_BITRATE         250001  /* highest allowed for a 44 kHz stream */
99
100 static gboolean gst_vorbis_enc_start (GstAudioEncoder * enc);
101 static gboolean gst_vorbis_enc_stop (GstAudioEncoder * enc);
102 static gboolean gst_vorbis_enc_set_format (GstAudioEncoder * enc,
103     GstAudioInfo * info);
104 static GstFlowReturn gst_vorbis_enc_handle_frame (GstAudioEncoder * enc,
105     GstBuffer * in_buf);
106 static GstCaps *gst_vorbis_enc_getcaps (GstAudioEncoder * enc);
107 static gboolean gst_vorbis_enc_sink_event (GstAudioEncoder * enc,
108     GstEvent * event);
109
110 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
111
112 static void gst_vorbis_enc_dispose (GObject * object);
113 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
114     GValue * value, GParamSpec * pspec);
115 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
116     const GValue * value, GParamSpec * pspec);
117 static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
118
119 GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstAudioEncoder,
120     GST_TYPE_AUDIO_ENCODER, gst_vorbis_enc_add_interfaces);
121
122 static void
123 gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
124 {
125   static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
126
127   g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
128       &tag_setter_info);
129 }
130
131 static void
132 gst_vorbis_enc_base_init (gpointer g_class)
133 {
134   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
135
136   gst_element_class_add_pad_template (element_class,
137       gst_static_pad_template_get (&vorbis_enc_src_factory));
138   gst_element_class_add_pad_template (element_class,
139       gst_static_pad_template_get (&vorbis_enc_sink_factory));
140
141   gst_element_class_set_details_simple (element_class,
142       "Vorbis audio encoder", "Codec/Encoder/Audio",
143       "Encodes audio in Vorbis format",
144       "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
145 }
146
147 static void
148 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
149 {
150   GObjectClass *gobject_class;
151   GstAudioEncoderClass *base_class;
152
153   gobject_class = (GObjectClass *) klass;
154   base_class = (GstAudioEncoderClass *) (klass);
155
156   gobject_class->set_property = gst_vorbis_enc_set_property;
157   gobject_class->get_property = gst_vorbis_enc_get_property;
158   gobject_class->dispose = gst_vorbis_enc_dispose;
159
160   base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
161   base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
162   base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
163   base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
164   base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
165   base_class->event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
166
167   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
168       g_param_spec_int ("max-bitrate", "Maximum Bitrate",
169           "Specify a maximum bitrate (in bps). Useful for streaming "
170           "applications. (-1 == disabled)",
171           -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
172           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
173   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
174       g_param_spec_int ("bitrate", "Target Bitrate",
175           "Attempt to encode at a bitrate averaging this (in bps). "
176           "This uses the bitrate management engine, and is not recommended for most users. "
177           "Quality is a better alternative. (-1 == disabled)", -1,
178           HIGHEST_BITRATE, BITRATE_DEFAULT,
179           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
180   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
181       g_param_spec_int ("min-bitrate", "Minimum Bitrate",
182           "Specify a minimum bitrate (in bps). Useful for encoding for a "
183           "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
184           MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
185   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
186       g_param_spec_float ("quality", "Quality",
187           "Specify quality instead of specifying a particular bitrate.", -0.1,
188           1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
189   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
190       g_param_spec_boolean ("managed", "Managed",
191           "Enable bitrate management engine", FALSE,
192           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
193   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
194       g_param_spec_string ("last-message", "last-message",
195           "The last status message", NULL,
196           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
197 }
198
199 static void
200 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
201 {
202   GstAudioEncoder *enc = GST_AUDIO_ENCODER (vorbisenc);
203
204   vorbisenc->channels = -1;
205   vorbisenc->frequency = -1;
206
207   vorbisenc->managed = FALSE;
208   vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
209   vorbisenc->bitrate = BITRATE_DEFAULT;
210   vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
211   vorbisenc->quality = QUALITY_DEFAULT;
212   vorbisenc->quality_set = FALSE;
213   vorbisenc->last_message = NULL;
214
215   /* arrange granulepos marking (and required perfect ts) */
216   gst_audio_encoder_set_mark_granule (enc, TRUE);
217   gst_audio_encoder_set_perfect_timestamp (enc, TRUE);
218 }
219
220 static void
221 gst_vorbis_enc_dispose (GObject * object)
222 {
223   GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
224
225   if (vorbisenc->sinkcaps) {
226     gst_caps_unref (vorbisenc->sinkcaps);
227     vorbisenc->sinkcaps = NULL;
228   }
229
230   G_OBJECT_CLASS (parent_class)->dispose (object);
231 }
232
233 static gboolean
234 gst_vorbis_enc_start (GstAudioEncoder * enc)
235 {
236   GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
237
238   GST_DEBUG_OBJECT (enc, "start");
239   vorbisenc->tags = gst_tag_list_new ();
240   vorbisenc->header_sent = FALSE;
241
242   return TRUE;
243 }
244
245 static gboolean
246 gst_vorbis_enc_stop (GstAudioEncoder * enc)
247 {
248   GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
249
250   GST_DEBUG_OBJECT (enc, "stop");
251   vorbis_block_clear (&vorbisenc->vb);
252   vorbis_dsp_clear (&vorbisenc->vd);
253   vorbis_info_clear (&vorbisenc->vi);
254   g_free (vorbisenc->last_message);
255   vorbisenc->last_message = NULL;
256   gst_tag_list_free (vorbisenc->tags);
257   vorbisenc->tags = NULL;
258
259   return TRUE;
260 }
261
262 static GstCaps *
263 gst_vorbis_enc_generate_sink_caps (void)
264 {
265   GstCaps *caps = gst_caps_new_empty ();
266   int i, c;
267
268   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
269           "rate", GST_TYPE_INT_RANGE, 1, 200000,
270           "channels", G_TYPE_INT, 1,
271           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
272           NULL));
273
274   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
275           "rate", GST_TYPE_INT_RANGE, 1, 200000,
276           "channels", G_TYPE_INT, 2,
277           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
278           NULL));
279
280   for (i = 3; i <= 8; i++) {
281     GValue chanpos = { 0 };
282     GValue pos = { 0 };
283     GstStructure *structure;
284
285     g_value_init (&chanpos, GST_TYPE_ARRAY);
286     g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
287
288     for (c = 0; c < i; c++) {
289       g_value_set_enum (&pos, gst_vorbis_channel_positions[i - 1][c]);
290       gst_value_array_append_value (&chanpos, &pos);
291     }
292     g_value_unset (&pos);
293
294     structure = gst_structure_new ("audio/x-raw-float",
295         "rate", GST_TYPE_INT_RANGE, 1, 200000,
296         "channels", G_TYPE_INT, i,
297         "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
298     gst_structure_set_value (structure, "channel-positions", &chanpos);
299     g_value_unset (&chanpos);
300
301     gst_caps_append_structure (caps, structure);
302   }
303
304   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
305           "rate", GST_TYPE_INT_RANGE, 1, 200000,
306           "channels", GST_TYPE_INT_RANGE, 9, 256,
307           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
308           NULL));
309
310   return caps;
311 }
312
313 static GstCaps *
314 gst_vorbis_enc_getcaps (GstAudioEncoder * enc)
315 {
316   GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
317
318   if (vorbisenc->sinkcaps == NULL)
319     vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
320
321   return gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps);
322 }
323
324 static gint64
325 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
326 {
327   /* FIXME, this probably depends on the bitrate and other setting but for now
328    * we return this value, which was obtained by totally unscientific
329    * measurements */
330   return 58 * GST_MSECOND;
331 }
332
333 static gboolean
334 gst_vorbis_enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
335 {
336   GstVorbisEnc *vorbisenc;
337
338   vorbisenc = GST_VORBISENC (enc);
339
340   vorbisenc->channels = GST_AUDIO_INFO_CHANNELS (info);
341   vorbisenc->frequency = GST_AUDIO_INFO_RATE (info);
342
343   /* if re-configured, we were drained and cleared already */
344   if (!gst_vorbis_enc_setup (vorbisenc))
345     return FALSE;
346
347   /* feedback to base class */
348   gst_audio_encoder_set_latency (enc,
349       gst_vorbis_enc_get_latency (vorbisenc),
350       gst_vorbis_enc_get_latency (vorbisenc));
351
352   return TRUE;
353 }
354
355 static void
356 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
357     gpointer vorbisenc)
358 {
359   GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
360   GList *vc_list, *l;
361
362   vc_list = gst_tag_to_vorbis_comments (list, tag);
363
364   for (l = vc_list; l != NULL; l = l->next) {
365     const gchar *vc_string = (const gchar *) l->data;
366     gchar *key = NULL, *val = NULL;
367
368     GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
369     if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
370       vorbis_comment_add_tag (&enc->vc, key, val);
371       g_free (key);
372       g_free (val);
373     }
374   }
375
376   g_list_foreach (vc_list, (GFunc) g_free, NULL);
377   g_list_free (vc_list);
378 }
379
380 static void
381 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
382 {
383   GstTagList *merged_tags;
384   const GstTagList *user_tags;
385
386   vorbis_comment_init (&enc->vc);
387
388   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
389
390   GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
391   GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
392
393   /* gst_tag_list_merge() will handle NULL for either or both lists fine */
394   merged_tags = gst_tag_list_merge (user_tags, enc->tags,
395       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
396
397   if (merged_tags) {
398     GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
399     gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
400     gst_tag_list_free (merged_tags);
401   }
402 }
403
404 static gchar *
405 get_constraints_string (GstVorbisEnc * vorbisenc)
406 {
407   gint min = vorbisenc->min_bitrate;
408   gint max = vorbisenc->max_bitrate;
409   gchar *result;
410
411   if (min > 0 && max > 0)
412     result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
413   else if (min > 0)
414     result = g_strdup_printf ("(min %d bps, no max)", min);
415   else if (max > 0)
416     result = g_strdup_printf ("(no min, max %d bps)", max);
417   else
418     result = g_strdup_printf ("(no min or max)");
419
420   return result;
421 }
422
423 static void
424 update_start_message (GstVorbisEnc * vorbisenc)
425 {
426   gchar *constraints;
427
428   g_free (vorbisenc->last_message);
429
430   if (vorbisenc->bitrate > 0) {
431     if (vorbisenc->managed) {
432       constraints = get_constraints_string (vorbisenc);
433       vorbisenc->last_message =
434           g_strdup_printf ("encoding at average bitrate %d bps %s",
435           vorbisenc->bitrate, constraints);
436       g_free (constraints);
437     } else {
438       vorbisenc->last_message =
439           g_strdup_printf
440           ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
441           vorbisenc->bitrate);
442     }
443   } else {
444     if (vorbisenc->quality_set) {
445       if (vorbisenc->managed) {
446         constraints = get_constraints_string (vorbisenc);
447         vorbisenc->last_message =
448             g_strdup_printf
449             ("encoding at quality level %2.2f using constrained VBR %s",
450             vorbisenc->quality, constraints);
451         g_free (constraints);
452       } else {
453         vorbisenc->last_message =
454             g_strdup_printf ("encoding at quality level %2.2f",
455             vorbisenc->quality);
456       }
457     } else {
458       constraints = get_constraints_string (vorbisenc);
459       vorbisenc->last_message =
460           g_strdup_printf ("encoding using bitrate management %s", constraints);
461       g_free (constraints);
462     }
463   }
464
465   g_object_notify (G_OBJECT (vorbisenc), "last_message");
466 }
467
468 static gboolean
469 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
470 {
471
472   GST_LOG_OBJECT (vorbisenc, "setup");
473
474   if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
475       && vorbisenc->max_bitrate < 0) {
476     vorbisenc->quality_set = TRUE;
477   }
478
479   update_start_message (vorbisenc);
480
481   /* choose an encoding mode */
482   /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
483   vorbis_info_init (&vorbisenc->vi);
484
485   if (vorbisenc->quality_set) {
486     if (vorbis_encode_setup_vbr (&vorbisenc->vi,
487             vorbisenc->channels, vorbisenc->frequency,
488             vorbisenc->quality) != 0) {
489       GST_ERROR_OBJECT (vorbisenc,
490           "vorbisenc: initialisation failed: invalid parameters for quality");
491       vorbis_info_clear (&vorbisenc->vi);
492       return FALSE;
493     }
494
495     /* do we have optional hard quality restrictions? */
496     if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
497       struct ovectl_ratemanage_arg ai;
498
499       vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
500
501       ai.bitrate_hard_min = vorbisenc->min_bitrate;
502       ai.bitrate_hard_max = vorbisenc->max_bitrate;
503       ai.management_active = 1;
504
505       vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
506     }
507   } else {
508     long min_bitrate, max_bitrate;
509
510     min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
511     max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
512
513     if (vorbis_encode_setup_managed (&vorbisenc->vi,
514             vorbisenc->channels,
515             vorbisenc->frequency,
516             max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
517       GST_ERROR_OBJECT (vorbisenc,
518           "vorbis_encode_setup_managed "
519           "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
520           vorbisenc->channels, vorbisenc->frequency, max_bitrate,
521           vorbisenc->bitrate, min_bitrate);
522       vorbis_info_clear (&vorbisenc->vi);
523       return FALSE;
524     }
525   }
526
527   if (vorbisenc->managed && vorbisenc->bitrate < 0) {
528     vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
529   } else if (!vorbisenc->managed) {
530     /* Turn off management entirely (if it was turned on). */
531     vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
532   }
533   vorbis_encode_setup_init (&vorbisenc->vi);
534
535   /* set up the analysis state and auxiliary encoding storage */
536   vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
537   vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
538
539   /* samples == granulepos start at 0 again */
540   vorbisenc->samples_out = 0;
541
542   /* fresh encoder available */
543   vorbisenc->setup = TRUE;
544
545   return TRUE;
546 }
547
548 static GstFlowReturn
549 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
550 {
551   GstFlowReturn ret = GST_FLOW_OK;
552
553   if (vorbisenc->setup) {
554     vorbis_analysis_wrote (&vorbisenc->vd, 0);
555     ret = gst_vorbis_enc_output_buffers (vorbisenc);
556
557     /* marked EOS to encoder, recreate if needed */
558     vorbisenc->setup = FALSE;
559   }
560
561   /* clean up and exit.  vorbis_info_clear() must be called last */
562   vorbis_block_clear (&vorbisenc->vb);
563   vorbis_dsp_clear (&vorbisenc->vd);
564   vorbis_info_clear (&vorbisenc->vi);
565
566   return ret;
567 }
568
569 static GstBuffer *
570 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
571     ogg_packet * packet)
572 {
573   GstBuffer *outbuf;
574
575   outbuf = gst_buffer_new_and_alloc (packet->bytes);
576   memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
577   GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
578   GST_BUFFER_OFFSET_END (outbuf) = 0;
579   GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
580   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
581
582   GST_DEBUG ("created header packet buffer, %d bytes",
583       GST_BUFFER_SIZE (outbuf));
584   return outbuf;
585 }
586
587 static gboolean
588 gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event)
589 {
590   GstVorbisEnc *vorbisenc;
591
592   vorbisenc = GST_VORBISENC (enc);
593
594   switch (GST_EVENT_TYPE (event)) {
595     case GST_EVENT_TAG:
596       if (vorbisenc->tags) {
597         GstTagList *list;
598
599         gst_event_parse_tag (event, &list);
600         gst_tag_list_insert (vorbisenc->tags, list,
601             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
602       } else {
603         g_assert_not_reached ();
604       }
605       break;
606       /* fall through */
607     default:
608       break;
609   }
610
611   /* we only peeked, let base class handle it */
612   return FALSE;
613 }
614
615 /* push out the buffer and do internal bookkeeping */
616 static GstFlowReturn
617 gst_vorbis_enc_push_header (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
618 {
619   GST_DEBUG_OBJECT (vorbisenc,
620       "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
621       GST_BUFFER_OFFSET_END (buffer),
622       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
623   return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), buffer);
624 }
625
626 /*
627  * (really really) FIXME: move into core (dixit tpm)
628  */
629 /**
630  * _gst_caps_set_buffer_array:
631  * @caps: a #GstCaps
632  * @field: field in caps to set
633  * @buf: header buffers
634  *
635  * Adds given buffers to an array of buffers set as the given @field
636  * on the given @caps.  List of buffer arguments must be NULL-terminated.
637  *
638  * Returns: input caps with a streamheader field added, or NULL if some error
639  */
640 static GstCaps *
641 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
642     GstBuffer * buf, ...)
643 {
644   GstStructure *structure = NULL;
645   va_list va;
646   GValue array = { 0 };
647   GValue value = { 0 };
648
649   g_return_val_if_fail (caps != NULL, NULL);
650   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
651   g_return_val_if_fail (field != NULL, NULL);
652
653   caps = gst_caps_make_writable (caps);
654   structure = gst_caps_get_structure (caps, 0);
655
656   g_value_init (&array, GST_TYPE_ARRAY);
657
658   va_start (va, buf);
659   /* put buffers in a fixed list */
660   while (buf) {
661     g_assert (gst_buffer_is_metadata_writable (buf));
662
663     /* mark buffer */
664     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
665
666     g_value_init (&value, GST_TYPE_BUFFER);
667     buf = gst_buffer_copy (buf);
668     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
669     gst_value_set_buffer (&value, buf);
670     gst_buffer_unref (buf);
671     gst_value_array_append_value (&array, &value);
672     g_value_unset (&value);
673
674     buf = va_arg (va, GstBuffer *);
675   }
676
677   gst_structure_set_value (structure, field, &array);
678   g_value_unset (&array);
679
680   return caps;
681 }
682
683 static GstFlowReturn
684 gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
685 {
686   GstVorbisEnc *vorbisenc;
687   GstFlowReturn ret = GST_FLOW_OK;
688   gfloat *data;
689   gulong size;
690   gulong i, j;
691   float **vorbis_buffer;
692   GstBuffer *buf1, *buf2, *buf3;
693
694   vorbisenc = GST_VORBISENC (enc);
695
696   if (G_UNLIKELY (!vorbisenc->setup)) {
697     if (buffer) {
698       GST_DEBUG_OBJECT (vorbisenc, "forcing setup");
699       /* should not fail, as setup before same way */
700       if (!gst_vorbis_enc_setup (vorbisenc))
701         return GST_FLOW_ERROR;
702     } else {
703       /* end draining */
704       GST_LOG_OBJECT (vorbisenc, "already drained");
705       return GST_FLOW_OK;
706     }
707   }
708
709   if (!vorbisenc->header_sent) {
710     /* Vorbis streams begin with three headers; the initial header (with
711        most of the codec setup parameters) which is mandated by the Ogg
712        bitstream spec.  The second header holds any comment fields.  The
713        third header holds the bitstream codebook.  We merely need to
714        make the headers, then pass them to libvorbis one at a time;
715        libvorbis handles the additional Ogg bitstream constraints */
716     ogg_packet header;
717     ogg_packet header_comm;
718     ogg_packet header_code;
719     GstCaps *caps;
720
721     GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
722     gst_vorbis_enc_set_metadata (vorbisenc);
723     vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
724         &header_comm, &header_code);
725     vorbis_comment_clear (&vorbisenc->vc);
726
727     /* create header buffers */
728     buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
729     buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
730     buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
731
732     /* mark and put on caps */
733     caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
734     caps = _gst_caps_set_buffer_array (caps, "streamheader",
735         buf1, buf2, buf3, NULL);
736
737     /* negotiate with these caps */
738     GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
739
740     gst_buffer_set_caps (buf1, caps);
741     gst_buffer_set_caps (buf2, caps);
742     gst_buffer_set_caps (buf3, caps);
743     gst_caps_unref (caps);
744
745     /* push out buffers */
746     /* push_buffer takes the reference even for failure */
747     if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf1)) != GST_FLOW_OK)
748       goto failed_header_push;
749     if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf2)) != GST_FLOW_OK) {
750       buf2 = NULL;
751       goto failed_header_push;
752     }
753     if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf3)) != GST_FLOW_OK) {
754       buf3 = NULL;
755       goto failed_header_push;
756     }
757
758     vorbisenc->header_sent = TRUE;
759   }
760
761   if (!buffer)
762     return gst_vorbis_enc_clear (vorbisenc);
763
764   /* data to encode */
765   data = (gfloat *) GST_BUFFER_DATA (buffer);
766   size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
767
768   /* expose the buffer to submit data */
769   vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
770
771   /* deinterleave samples, write the buffer data */
772   for (i = 0; i < size; i++) {
773     for (j = 0; j < vorbisenc->channels; j++) {
774       vorbis_buffer[j][i] = *data++;
775     }
776   }
777
778   /* tell the library how much we actually submitted */
779   vorbis_analysis_wrote (&vorbisenc->vd, size);
780
781   GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
782
783   vorbisenc->samples_in += size;
784
785   ret = gst_vorbis_enc_output_buffers (vorbisenc);
786
787   return ret;
788
789   /* error cases */
790 failed_header_push:
791   {
792     GST_WARNING_OBJECT (vorbisenc, "Failed to push headers");
793     /* buf1 is always already unreffed */
794     if (buf2)
795       gst_buffer_unref (buf2);
796     if (buf3)
797       gst_buffer_unref (buf3);
798     return ret;
799   }
800 }
801
802 static GstFlowReturn
803 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
804 {
805   GstFlowReturn ret;
806
807   /* vorbis does some data preanalysis, then divides up blocks for
808      more involved (potentially parallel) processing.  Get a single
809      block for encoding now */
810   while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
811     ogg_packet op;
812
813     GST_LOG_OBJECT (vorbisenc, "analysed to a block");
814
815     /* analysis */
816     vorbis_analysis (&vorbisenc->vb, NULL);
817     vorbis_bitrate_addblock (&vorbisenc->vb);
818
819     while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
820       GstBuffer *buf;
821
822       GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
823       buf = gst_buffer_new_and_alloc (op.bytes);
824       memcpy (GST_BUFFER_DATA (buf), op.packet, op.bytes);
825       /* tracking granulepos should tell us samples accounted for */
826       ret =
827           gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER
828           (vorbisenc), buf, op.granulepos - vorbisenc->samples_out);
829       vorbisenc->samples_out = op.granulepos;
830
831       if (ret != GST_FLOW_OK)
832         return ret;
833     }
834   }
835
836   return GST_FLOW_OK;
837 }
838
839 static void
840 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
841     GParamSpec * pspec)
842 {
843   GstVorbisEnc *vorbisenc;
844
845   g_return_if_fail (GST_IS_VORBISENC (object));
846
847   vorbisenc = GST_VORBISENC (object);
848
849   switch (prop_id) {
850     case ARG_MAX_BITRATE:
851       g_value_set_int (value, vorbisenc->max_bitrate);
852       break;
853     case ARG_BITRATE:
854       g_value_set_int (value, vorbisenc->bitrate);
855       break;
856     case ARG_MIN_BITRATE:
857       g_value_set_int (value, vorbisenc->min_bitrate);
858       break;
859     case ARG_QUALITY:
860       g_value_set_float (value, vorbisenc->quality);
861       break;
862     case ARG_MANAGED:
863       g_value_set_boolean (value, vorbisenc->managed);
864       break;
865     case ARG_LAST_MESSAGE:
866       g_value_set_string (value, vorbisenc->last_message);
867       break;
868     default:
869       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
870       break;
871   }
872 }
873
874 static void
875 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
876     const GValue * value, GParamSpec * pspec)
877 {
878   GstVorbisEnc *vorbisenc;
879
880   g_return_if_fail (GST_IS_VORBISENC (object));
881
882   vorbisenc = GST_VORBISENC (object);
883
884   switch (prop_id) {
885     case ARG_MAX_BITRATE:
886     {
887       gboolean old_value = vorbisenc->managed;
888
889       vorbisenc->max_bitrate = g_value_get_int (value);
890       if (vorbisenc->max_bitrate >= 0
891           && vorbisenc->max_bitrate < LOWEST_BITRATE) {
892         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
893         vorbisenc->max_bitrate = LOWEST_BITRATE;
894       }
895       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
896         vorbisenc->managed = TRUE;
897       else
898         vorbisenc->managed = FALSE;
899
900       if (old_value != vorbisenc->managed)
901         g_object_notify (object, "managed");
902       break;
903     }
904     case ARG_BITRATE:
905       vorbisenc->bitrate = g_value_get_int (value);
906       if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
907         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
908         vorbisenc->bitrate = LOWEST_BITRATE;
909       }
910       break;
911     case ARG_MIN_BITRATE:
912     {
913       gboolean old_value = vorbisenc->managed;
914
915       vorbisenc->min_bitrate = g_value_get_int (value);
916       if (vorbisenc->min_bitrate >= 0
917           && vorbisenc->min_bitrate < LOWEST_BITRATE) {
918         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
919         vorbisenc->min_bitrate = LOWEST_BITRATE;
920       }
921       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
922         vorbisenc->managed = TRUE;
923       else
924         vorbisenc->managed = FALSE;
925
926       if (old_value != vorbisenc->managed)
927         g_object_notify (object, "managed");
928       break;
929     }
930     case ARG_QUALITY:
931       vorbisenc->quality = g_value_get_float (value);
932       if (vorbisenc->quality >= 0.0)
933         vorbisenc->quality_set = TRUE;
934       else
935         vorbisenc->quality_set = FALSE;
936       break;
937     case ARG_MANAGED:
938       vorbisenc->managed = g_value_get_boolean (value);
939       break;
940     default:
941       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
942       break;
943   }
944 }