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