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