71b76a75e50e02b9199e660dc36d67bfa525a8c9
[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/audio.h>
54 #include "gstvorbisenc.h"
55
56 #include "gstvorbiscommon.h"
57
58 GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
59 #define GST_CAT_DEFAULT vorbisenc_debug
60
61 static GstStaticPadTemplate vorbis_enc_sink_factory =
62 GST_STATIC_PAD_TEMPLATE ("sink",
63     GST_PAD_SINK,
64     GST_PAD_ALWAYS,
65     GST_STATIC_CAPS ("audio/x-raw, "
66         "format = (string) " GST_AUDIO_NE (F32) ", "
67         "layout = (string) interleaved, "
68         "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
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         "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
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     GstCaps * filter);
108 static gboolean gst_vorbis_enc_sink_event (GstAudioEncoder * enc,
109     GstEvent * event);
110
111 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
112
113 static void gst_vorbis_enc_dispose (GObject * object);
114 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
115     GValue * value, GParamSpec * pspec);
116 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
117     const GValue * value, GParamSpec * pspec);
118
119 #define gst_vorbis_enc_parent_class parent_class
120 G_DEFINE_TYPE_WITH_CODE (GstVorbisEnc, gst_vorbis_enc,
121     GST_TYPE_AUDIO_ENCODER, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
122
123 static void
124 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
125 {
126   GObjectClass *gobject_class;
127   GstElementClass *gstelement_class;
128   GstAudioEncoderClass *base_class;
129
130   gobject_class = (GObjectClass *) klass;
131   gstelement_class = (GstElementClass *) klass;
132   base_class = (GstAudioEncoderClass *) (klass);
133
134   gobject_class->set_property = gst_vorbis_enc_set_property;
135   gobject_class->get_property = gst_vorbis_enc_get_property;
136   gobject_class->dispose = gst_vorbis_enc_dispose;
137
138   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
139       g_param_spec_int ("max-bitrate", "Maximum Bitrate",
140           "Specify a maximum bitrate (in bps). Useful for streaming "
141           "applications. (-1 == disabled)",
142           -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
143           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
144   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
145       g_param_spec_int ("bitrate", "Target Bitrate",
146           "Attempt to encode at a bitrate averaging this (in bps). "
147           "This uses the bitrate management engine, and is not recommended for most users. "
148           "Quality is a better alternative. (-1 == disabled)", -1,
149           HIGHEST_BITRATE, BITRATE_DEFAULT,
150           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
151   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
152       g_param_spec_int ("min-bitrate", "Minimum Bitrate",
153           "Specify a minimum bitrate (in bps). Useful for encoding for a "
154           "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
155           MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
156   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
157       g_param_spec_float ("quality", "Quality",
158           "Specify quality instead of specifying a particular bitrate.", -0.1,
159           1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
160   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
161       g_param_spec_boolean ("managed", "Managed",
162           "Enable bitrate management engine", FALSE,
163           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
164   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
165       g_param_spec_string ("last-message", "last-message",
166           "The last status message", NULL,
167           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
168
169   gst_element_class_add_pad_template (gstelement_class,
170       gst_static_pad_template_get (&vorbis_enc_src_factory));
171   gst_element_class_add_pad_template (gstelement_class,
172       gst_static_pad_template_get (&vorbis_enc_sink_factory));
173
174   gst_element_class_set_details_simple (gstelement_class,
175       "Vorbis audio encoder", "Codec/Encoder/Audio",
176       "Encodes audio in Vorbis format",
177       "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
178
179   base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
180   base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
181   base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
182   base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
183   base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
184   base_class->sink_event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
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_free (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[i];
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);
305     gst_caps_unref (int_caps);
306   } else {
307     caps = gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps);
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_free (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 GstBuffer *
559 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
560     ogg_packet * packet)
561 {
562   GstBuffer *outbuf;
563
564   outbuf = gst_buffer_new_and_alloc (packet->bytes);
565   gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
566   GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
567   GST_BUFFER_OFFSET_END (outbuf) = 0;
568   GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
569   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
570
571   GST_DEBUG ("created header packet buffer, %" G_GSIZE_FORMAT " bytes",
572       gst_buffer_get_size (outbuf));
573   return outbuf;
574 }
575
576 static gboolean
577 gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event)
578 {
579   GstVorbisEnc *vorbisenc;
580
581   vorbisenc = GST_VORBISENC (enc);
582
583   switch (GST_EVENT_TYPE (event)) {
584     case GST_EVENT_TAG:
585       if (vorbisenc->tags) {
586         GstTagList *list;
587
588         gst_event_parse_tag (event, &list);
589         gst_tag_list_insert (vorbisenc->tags, list,
590             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
591       } else {
592         g_assert_not_reached ();
593       }
594       break;
595       /* fall through */
596     default:
597       break;
598   }
599
600   /* we only peeked, let base class handle it */
601   return GST_AUDIO_ENCODER_CLASS (parent_class)->sink_event (enc, event);
602 }
603
604 /*
605  * (really really) FIXME: move into core (dixit tpm)
606  */
607 /**
608  * _gst_caps_set_buffer_array:
609  * @caps: a #GstCaps
610  * @field: field in caps to set
611  * @buf: header buffers
612  *
613  * Adds given buffers to an array of buffers set as the given @field
614  * on the given @caps.  List of buffer arguments must be NULL-terminated.
615  *
616  * Returns: input caps with a streamheader field added, or NULL if some error
617  */
618 static GstCaps *
619 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
620     GstBuffer * buf, ...)
621 {
622   GstStructure *structure = NULL;
623   va_list va;
624   GValue array = { 0 };
625   GValue value = { 0 };
626
627   g_return_val_if_fail (caps != NULL, NULL);
628   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
629   g_return_val_if_fail (field != NULL, NULL);
630
631   caps = gst_caps_make_writable (caps);
632   structure = gst_caps_get_structure (caps, 0);
633
634   g_value_init (&array, GST_TYPE_ARRAY);
635
636   va_start (va, buf);
637   /* put buffers in a fixed list */
638   while (buf) {
639     g_assert (gst_buffer_is_writable (buf));
640
641     /* mark buffer */
642     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
643
644     g_value_init (&value, GST_TYPE_BUFFER);
645     buf = gst_buffer_copy (buf);
646     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
647     gst_value_set_buffer (&value, buf);
648     gst_buffer_unref (buf);
649     gst_value_array_append_value (&array, &value);
650     g_value_unset (&value);
651
652     buf = va_arg (va, GstBuffer *);
653   }
654
655   gst_structure_set_value (structure, field, &array);
656   g_value_unset (&array);
657
658   return caps;
659 }
660
661 static GstFlowReturn
662 gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
663 {
664   GstVorbisEnc *vorbisenc;
665   GstFlowReturn ret = GST_FLOW_OK;
666   GstMapInfo map;
667   gfloat *ptr;
668   gulong size;
669   gulong i, j;
670   float **vorbis_buffer;
671   GstBuffer *buf1, *buf2, *buf3;
672
673   vorbisenc = GST_VORBISENC (enc);
674
675   if (G_UNLIKELY (!vorbisenc->setup)) {
676     if (buffer) {
677       GST_DEBUG_OBJECT (vorbisenc, "forcing setup");
678       /* should not fail, as setup before same way */
679       if (!gst_vorbis_enc_setup (vorbisenc))
680         return GST_FLOW_ERROR;
681     } else {
682       /* end draining */
683       GST_LOG_OBJECT (vorbisenc, "already drained");
684       return GST_FLOW_OK;
685     }
686   }
687
688   if (!vorbisenc->header_sent) {
689     /* Vorbis streams begin with three headers; the initial header (with
690        most of the codec setup parameters) which is mandated by the Ogg
691        bitstream spec.  The second header holds any comment fields.  The
692        third header holds the bitstream codebook.  We merely need to
693        make the headers, then pass them to libvorbis one at a time;
694        libvorbis handles the additional Ogg bitstream constraints */
695     ogg_packet header;
696     ogg_packet header_comm;
697     ogg_packet header_code;
698     GstCaps *caps;
699     GList *headers;
700
701     GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
702     gst_vorbis_enc_set_metadata (vorbisenc);
703     vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
704         &header_comm, &header_code);
705     vorbis_comment_clear (&vorbisenc->vc);
706
707     /* create header buffers */
708     buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
709     buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
710     buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
711
712     /* mark and put on caps */
713     caps = gst_caps_new_simple ("audio/x-vorbis",
714         "rate", G_TYPE_INT, vorbisenc->frequency,
715         "channels", G_TYPE_INT, vorbisenc->channels, NULL);
716     caps = _gst_caps_set_buffer_array (caps, "streamheader",
717         buf1, buf2, buf3, NULL);
718
719     /* negotiate with these caps */
720     GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
721     gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (vorbisenc), caps);
722     gst_caps_unref (caps);
723
724     /* store buffers for later pre_push sending */
725     headers = NULL;
726     GST_DEBUG_OBJECT (vorbisenc, "storing header buffers");
727     headers = g_list_prepend (headers, buf3);
728     headers = g_list_prepend (headers, buf2);
729     headers = g_list_prepend (headers, buf1);
730     gst_audio_encoder_set_headers (enc, headers);
731
732     vorbisenc->header_sent = TRUE;
733   }
734
735   if (!buffer)
736     return gst_vorbis_enc_clear (vorbisenc);
737
738   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
739
740   /* data to encode */
741   size = map.size / (vorbisenc->channels * sizeof (float));
742   ptr = (gfloat *) map.data;
743
744   /* expose the buffer to submit data */
745   vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
746
747   /* deinterleave samples, write the buffer data */
748   if (vorbisenc->channels < 2 || vorbisenc->channels > 8) {
749     for (i = 0; i < size; i++) {
750       for (j = 0; j < vorbisenc->channels; j++) {
751         vorbis_buffer[j][i] = *ptr++;
752       }
753     }
754   } else {
755     gint i, j;
756
757     /* Reorder */
758     for (i = 0; i < size; i++) {
759       for (j = 0; j < vorbisenc->channels; j++) {
760         vorbis_buffer[gst_vorbis_reorder_map[vorbisenc->channels - 1][j]][i] =
761             ptr[j];
762       }
763       ptr += vorbisenc->channels;
764     }
765   }
766
767   /* tell the library how much we actually submitted */
768   vorbis_analysis_wrote (&vorbisenc->vd, size);
769   gst_buffer_unmap (buffer, &map);
770
771   GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
772
773   vorbisenc->samples_in += size;
774
775   ret = gst_vorbis_enc_output_buffers (vorbisenc);
776
777   return ret;
778 }
779
780 static GstFlowReturn
781 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
782 {
783   GstFlowReturn ret;
784
785   /* vorbis does some data preanalysis, then divides up blocks for
786      more involved (potentially parallel) processing.  Get a single
787      block for encoding now */
788   while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
789     ogg_packet op;
790
791     GST_LOG_OBJECT (vorbisenc, "analysed to a block");
792
793     /* analysis */
794     vorbis_analysis (&vorbisenc->vb, NULL);
795     vorbis_bitrate_addblock (&vorbisenc->vb);
796
797     while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
798       GstBuffer *buf;
799
800       GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
801       buf = gst_buffer_new_and_alloc (op.bytes);
802       gst_buffer_fill (buf, 0, op.packet, op.bytes);
803       /* tracking granulepos should tell us samples accounted for */
804       ret =
805           gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER
806           (vorbisenc), buf, op.granulepos - vorbisenc->samples_out);
807       vorbisenc->samples_out = op.granulepos;
808
809       if (ret != GST_FLOW_OK)
810         return ret;
811     }
812   }
813
814   return GST_FLOW_OK;
815 }
816
817 static void
818 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
819     GParamSpec * pspec)
820 {
821   GstVorbisEnc *vorbisenc;
822
823   g_return_if_fail (GST_IS_VORBISENC (object));
824
825   vorbisenc = GST_VORBISENC (object);
826
827   switch (prop_id) {
828     case ARG_MAX_BITRATE:
829       g_value_set_int (value, vorbisenc->max_bitrate);
830       break;
831     case ARG_BITRATE:
832       g_value_set_int (value, vorbisenc->bitrate);
833       break;
834     case ARG_MIN_BITRATE:
835       g_value_set_int (value, vorbisenc->min_bitrate);
836       break;
837     case ARG_QUALITY:
838       g_value_set_float (value, vorbisenc->quality);
839       break;
840     case ARG_MANAGED:
841       g_value_set_boolean (value, vorbisenc->managed);
842       break;
843     case ARG_LAST_MESSAGE:
844       g_value_set_string (value, vorbisenc->last_message);
845       break;
846     default:
847       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
848       break;
849   }
850 }
851
852 static void
853 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
854     const GValue * value, GParamSpec * pspec)
855 {
856   GstVorbisEnc *vorbisenc;
857
858   g_return_if_fail (GST_IS_VORBISENC (object));
859
860   vorbisenc = GST_VORBISENC (object);
861
862   switch (prop_id) {
863     case ARG_MAX_BITRATE:
864     {
865       gboolean old_value = vorbisenc->managed;
866
867       vorbisenc->max_bitrate = g_value_get_int (value);
868       if (vorbisenc->max_bitrate >= 0
869           && vorbisenc->max_bitrate < LOWEST_BITRATE) {
870         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
871         vorbisenc->max_bitrate = LOWEST_BITRATE;
872       }
873       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
874         vorbisenc->managed = TRUE;
875       else
876         vorbisenc->managed = FALSE;
877
878       if (old_value != vorbisenc->managed)
879         g_object_notify (object, "managed");
880       break;
881     }
882     case ARG_BITRATE:
883       vorbisenc->bitrate = g_value_get_int (value);
884       if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
885         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
886         vorbisenc->bitrate = LOWEST_BITRATE;
887       }
888       break;
889     case ARG_MIN_BITRATE:
890     {
891       gboolean old_value = vorbisenc->managed;
892
893       vorbisenc->min_bitrate = g_value_get_int (value);
894       if (vorbisenc->min_bitrate >= 0
895           && vorbisenc->min_bitrate < LOWEST_BITRATE) {
896         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
897         vorbisenc->min_bitrate = LOWEST_BITRATE;
898       }
899       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
900         vorbisenc->managed = TRUE;
901       else
902         vorbisenc->managed = FALSE;
903
904       if (old_value != vorbisenc->managed)
905         g_object_notify (object, "managed");
906       break;
907     }
908     case ARG_QUALITY:
909       vorbisenc->quality = g_value_get_float (value);
910       if (vorbisenc->quality >= 0.0)
911         vorbisenc->quality_set = TRUE;
912       else
913         vorbisenc->quality_set = FALSE;
914       break;
915     case ARG_MANAGED:
916       vorbisenc->managed = g_value_get_boolean (value);
917       break;
918     default:
919       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
920       break;
921   }
922 }