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