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