9cdf484e1553a76d16e78c10c073b56d3b6aed01
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / ext / vorbis / gstvorbisenc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:element-vorbisenc
22  * @see_also: vorbisdec, oggmux
23  *
24  * This element encodes raw float audio into a Vorbis stream.
25  * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
26  * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
27  * Foundation</ulink>.
28  *
29  * <refsect2>
30  * <title>Example pipelines</title>
31  * |[
32  * gst-launch -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sine.ogg
33  * ]| Encode a test sine signal to Ogg/Vorbis.  Note that the resulting file
34  * will be really small because a sine signal compresses very well.
35  * |[
36  * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
37  * ]| Record from a sound card using ALSA and encode to Ogg/Vorbis.
38  * </refsect2>
39  *
40  * Last reviewed on 2006-03-01 (0.10.4)
41  */
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45
46 #include <stdlib.h>
47 #include <string.h>
48 #include <time.h>
49 #include <vorbis/vorbisenc.h>
50
51 #include <gst/gsttagsetter.h>
52 #include <gst/tag/tag.h>
53 #include <gst/audio/multichannel.h>
54 #include <gst/audio/audio.h>
55 #include "gstvorbisenc.h"
56
57 #include "gstvorbiscommon.h"
58
59 GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
60 #define GST_CAT_DEFAULT vorbisenc_debug
61
62 static GstStaticPadTemplate vorbis_enc_sink_factory =
63 GST_STATIC_PAD_TEMPLATE ("sink",
64     GST_PAD_SINK,
65     GST_PAD_ALWAYS,
66     GST_STATIC_CAPS ("audio/x-raw-float, "
67         "rate = (int) [ 1, 200000 ], "
68         "channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, "
69         "width = (int) 32")
70     );
71
72 static GstStaticPadTemplate vorbis_enc_src_factory =
73 GST_STATIC_PAD_TEMPLATE ("src",
74     GST_PAD_SRC,
75     GST_PAD_ALWAYS,
76     GST_STATIC_CAPS ("audio/x-vorbis")
77     );
78
79 enum
80 {
81   ARG_0,
82   ARG_MAX_BITRATE,
83   ARG_BITRATE,
84   ARG_MIN_BITRATE,
85   ARG_QUALITY,
86   ARG_MANAGED,
87   ARG_LAST_MESSAGE
88 };
89
90 static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
91
92 /* this function takes into account the granulepos_offset and the subgranule
93  * time offset */
94 static GstClockTime
95 granulepos_to_timestamp_offset (GstVorbisEnc * vorbisenc,
96     ogg_int64_t granulepos)
97 {
98   if (granulepos >= 0)
99     return gst_util_uint64_scale ((guint64) granulepos
100         + vorbisenc->granulepos_offset, GST_SECOND, vorbisenc->frequency)
101         + vorbisenc->subgranule_offset;
102   return GST_CLOCK_TIME_NONE;
103 }
104
105 /* this function does a straight granulepos -> timestamp conversion */
106 static GstClockTime
107 granulepos_to_timestamp (GstVorbisEnc * vorbisenc, ogg_int64_t granulepos)
108 {
109   if (granulepos >= 0)
110     return gst_util_uint64_scale ((guint64) granulepos,
111         GST_SECOND, vorbisenc->frequency);
112   return GST_CLOCK_TIME_NONE;
113 }
114
115 #define MAX_BITRATE_DEFAULT     -1
116 #define BITRATE_DEFAULT         -1
117 #define MIN_BITRATE_DEFAULT     -1
118 #define QUALITY_DEFAULT         0.3
119 #define LOWEST_BITRATE          6000    /* lowest allowed for a 8 kHz stream */
120 #define HIGHEST_BITRATE         250001  /* highest allowed for a 44 kHz stream */
121
122 static gboolean gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event);
123 static GstFlowReturn gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer);
124 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
125
126 static void gst_vorbis_enc_dispose (GObject * object);
127 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
128     GValue * value, GParamSpec * pspec);
129 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
130     const GValue * value, GParamSpec * pspec);
131 static GstStateChangeReturn gst_vorbis_enc_change_state (GstElement * element,
132     GstStateChange transition);
133 static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
134
135 GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstElement,
136     GST_TYPE_ELEMENT, gst_vorbis_enc_add_interfaces);
137
138 static void
139 gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
140 {
141   static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
142   static const GInterfaceInfo preset_info = { NULL, NULL, NULL };
143
144   g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
145       &tag_setter_info);
146   g_type_add_interface_static (vorbisenc_type, GST_TYPE_PRESET, &preset_info);
147 }
148
149 static void
150 gst_vorbis_enc_base_init (gpointer g_class)
151 {
152   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
153   GstPadTemplate *src_template, *sink_template;
154
155
156   src_template = gst_static_pad_template_get (&vorbis_enc_src_factory);
157   gst_element_class_add_pad_template (element_class, src_template);
158
159   sink_template = gst_static_pad_template_get (&vorbis_enc_sink_factory);
160   gst_element_class_add_pad_template (element_class, sink_template);
161   gst_element_class_set_details_simple (element_class,
162       "Vorbis audio encoder", "Codec/Encoder/Audio",
163       "Encodes audio in Vorbis format",
164       "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
165 }
166
167 static void
168 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
169 {
170   GObjectClass *gobject_class;
171   GstElementClass *gstelement_class;
172
173   gobject_class = (GObjectClass *) klass;
174   gstelement_class = (GstElementClass *) klass;
175
176   gobject_class->set_property = gst_vorbis_enc_set_property;
177   gobject_class->get_property = gst_vorbis_enc_get_property;
178   gobject_class->dispose = gst_vorbis_enc_dispose;
179
180   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
181       g_param_spec_int ("max-bitrate", "Maximum Bitrate",
182           "Specify a maximum bitrate (in bps). Useful for streaming "
183           "applications. (-1 == disabled)",
184           -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
185           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
186   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
187       g_param_spec_int ("bitrate", "Target Bitrate",
188           "Attempt to encode at a bitrate averaging this (in bps). "
189           "This uses the bitrate management engine, and is not recommended for most users. "
190           "Quality is a better alternative. (-1 == disabled)", -1,
191           HIGHEST_BITRATE, BITRATE_DEFAULT,
192           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
193   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
194       g_param_spec_int ("min-bitrate", "Minimum Bitrate",
195           "Specify a minimum bitrate (in bps). Useful for encoding for a "
196           "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
197           MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
199       g_param_spec_float ("quality", "Quality",
200           "Specify quality instead of specifying a particular bitrate.", -0.1,
201           1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
202   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
203       g_param_spec_boolean ("managed", "Managed",
204           "Enable bitrate management engine", FALSE,
205           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
206   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
207       g_param_spec_string ("last-message", "last-message",
208           "The last status message", NULL,
209           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
210
211   gstelement_class->change_state =
212       GST_DEBUG_FUNCPTR (gst_vorbis_enc_change_state);
213 }
214
215 static void
216 gst_vorbis_enc_dispose (GObject * object)
217 {
218   GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
219
220   if (vorbisenc->sinkcaps) {
221     gst_caps_unref (vorbisenc->sinkcaps);
222     vorbisenc->sinkcaps = NULL;
223   }
224
225   G_OBJECT_CLASS (parent_class)->dispose (object);
226 }
227
228 static GstCaps *
229 gst_vorbis_enc_generate_sink_caps (void)
230 {
231   GstCaps *caps = gst_caps_new_empty ();
232   int i, c;
233
234   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
235           "rate", GST_TYPE_INT_RANGE, 1, 200000,
236           "channels", G_TYPE_INT, 1,
237           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
238           NULL));
239
240   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
241           "rate", GST_TYPE_INT_RANGE, 1, 200000,
242           "channels", G_TYPE_INT, 2,
243           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
244           NULL));
245
246   for (i = 3; i <= 8; i++) {
247     GValue chanpos = { 0 };
248     GValue pos = { 0 };
249     GstStructure *structure;
250
251     g_value_init (&chanpos, GST_TYPE_ARRAY);
252     g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
253
254     for (c = 0; c < i; c++) {
255       g_value_set_enum (&pos, gst_vorbis_channel_positions[i - 1][c]);
256       gst_value_array_append_value (&chanpos, &pos);
257     }
258     g_value_unset (&pos);
259
260     structure = gst_structure_new ("audio/x-raw-float",
261         "rate", GST_TYPE_INT_RANGE, 1, 200000,
262         "channels", G_TYPE_INT, i,
263         "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
264     gst_structure_set_value (structure, "channel-positions", &chanpos);
265     g_value_unset (&chanpos);
266
267     gst_caps_append_structure (caps, structure);
268   }
269
270   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
271           "rate", GST_TYPE_INT_RANGE, 1, 200000,
272           "channels", GST_TYPE_INT_RANGE, 9, 256,
273           "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
274           NULL));
275
276   return caps;
277 }
278
279 static GstCaps *
280 gst_vorbis_enc_sink_getcaps (GstPad * pad)
281 {
282   GstVorbisEnc *vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
283
284   if (vorbisenc->sinkcaps == NULL)
285     vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
286
287   return gst_caps_ref (vorbisenc->sinkcaps);
288 }
289
290 static gboolean
291 gst_vorbis_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
292 {
293   GstVorbisEnc *vorbisenc;
294   GstStructure *structure;
295
296   vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
297   vorbisenc->setup = FALSE;
298
299   structure = gst_caps_get_structure (caps, 0);
300   gst_structure_get_int (structure, "channels", &vorbisenc->channels);
301   gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
302
303   gst_vorbis_enc_setup (vorbisenc);
304
305   if (vorbisenc->setup)
306     return TRUE;
307
308   return FALSE;
309 }
310
311 static gboolean
312 gst_vorbis_enc_convert_src (GstPad * pad, GstFormat src_format,
313     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
314 {
315   gboolean res = TRUE;
316   GstVorbisEnc *vorbisenc;
317   gint64 avg;
318
319   vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
320
321   if (vorbisenc->samples_in == 0 ||
322       vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0) {
323     gst_object_unref (vorbisenc);
324     return FALSE;
325   }
326
327   avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in);
328
329   switch (src_format) {
330     case GST_FORMAT_BYTES:
331       switch (*dest_format) {
332         case GST_FORMAT_TIME:
333           *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, avg);
334           break;
335         default:
336           res = FALSE;
337       }
338       break;
339     case GST_FORMAT_TIME:
340       switch (*dest_format) {
341         case GST_FORMAT_BYTES:
342           *dest_value = gst_util_uint64_scale_int (src_value, avg, GST_SECOND);
343           break;
344         default:
345           res = FALSE;
346       }
347       break;
348     default:
349       res = FALSE;
350   }
351   gst_object_unref (vorbisenc);
352   return res;
353 }
354
355 static gboolean
356 gst_vorbis_enc_convert_sink (GstPad * pad, GstFormat src_format,
357     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
358 {
359   gboolean res = TRUE;
360   guint scale = 1;
361   gint bytes_per_sample;
362   GstVorbisEnc *vorbisenc;
363
364   vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
365
366   bytes_per_sample = vorbisenc->channels * 2;
367
368   switch (src_format) {
369     case GST_FORMAT_BYTES:
370       switch (*dest_format) {
371         case GST_FORMAT_DEFAULT:
372           if (bytes_per_sample == 0)
373             return FALSE;
374           *dest_value = src_value / bytes_per_sample;
375           break;
376         case GST_FORMAT_TIME:
377         {
378           gint byterate = bytes_per_sample * vorbisenc->frequency;
379
380           if (byterate == 0)
381             return FALSE;
382           *dest_value =
383               gst_util_uint64_scale_int (src_value, GST_SECOND, byterate);
384           break;
385         }
386         default:
387           res = FALSE;
388       }
389       break;
390     case GST_FORMAT_DEFAULT:
391       switch (*dest_format) {
392         case GST_FORMAT_BYTES:
393           *dest_value = src_value * bytes_per_sample;
394           break;
395         case GST_FORMAT_TIME:
396           if (vorbisenc->frequency == 0)
397             return FALSE;
398           *dest_value =
399               gst_util_uint64_scale_int (src_value, GST_SECOND,
400               vorbisenc->frequency);
401           break;
402         default:
403           res = FALSE;
404       }
405       break;
406     case GST_FORMAT_TIME:
407       switch (*dest_format) {
408         case GST_FORMAT_BYTES:
409           scale = bytes_per_sample;
410           /* fallthrough */
411         case GST_FORMAT_DEFAULT:
412           *dest_value =
413               gst_util_uint64_scale_int (src_value,
414               scale * vorbisenc->frequency, GST_SECOND);
415           break;
416         default:
417           res = FALSE;
418       }
419       break;
420     default:
421       res = FALSE;
422   }
423   gst_object_unref (vorbisenc);
424   return res;
425 }
426
427 static gint64
428 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
429 {
430   /* FIXME, this probably depends on the bitrate and other setting but for now
431    * we return this value, which was obtained by totally unscientific
432    * measurements */
433   return 58 * GST_MSECOND;
434 }
435
436 static const GstQueryType *
437 gst_vorbis_enc_get_query_types (GstPad * pad)
438 {
439   static const GstQueryType gst_vorbis_enc_src_query_types[] = {
440     GST_QUERY_POSITION,
441     GST_QUERY_DURATION,
442     GST_QUERY_CONVERT,
443     0
444   };
445
446   return gst_vorbis_enc_src_query_types;
447 }
448
449 static gboolean
450 gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query)
451 {
452   gboolean res = TRUE;
453   GstVorbisEnc *vorbisenc;
454   GstPad *peerpad;
455
456   vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
457   peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad));
458
459   switch (GST_QUERY_TYPE (query)) {
460     case GST_QUERY_POSITION:
461     {
462       GstFormat fmt, req_fmt;
463       gint64 pos, val;
464
465       gst_query_parse_position (query, &req_fmt, NULL);
466       if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
467         gst_query_set_position (query, req_fmt, val);
468         break;
469       }
470
471       fmt = GST_FORMAT_TIME;
472       if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
473         break;
474
475       if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
476         gst_query_set_position (query, req_fmt, val);
477       }
478       break;
479     }
480     case GST_QUERY_DURATION:
481     {
482       GstFormat fmt, req_fmt;
483       gint64 dur, val;
484
485       gst_query_parse_duration (query, &req_fmt, NULL);
486       if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
487         gst_query_set_duration (query, req_fmt, val);
488         break;
489       }
490
491       fmt = GST_FORMAT_TIME;
492       if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
493         break;
494
495       if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
496         gst_query_set_duration (query, req_fmt, val);
497       }
498       break;
499     }
500     case GST_QUERY_CONVERT:
501     {
502       GstFormat src_fmt, dest_fmt;
503       gint64 src_val, dest_val;
504
505       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
506       if (!(res =
507               gst_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
508                   &dest_val)))
509         goto error;
510       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
511       break;
512     }
513     case GST_QUERY_LATENCY:
514     {
515       gboolean live;
516       GstClockTime min_latency, max_latency;
517       gint64 latency;
518
519       if ((res = gst_pad_query (peerpad, query))) {
520         gst_query_parse_latency (query, &live, &min_latency, &max_latency);
521
522         latency = gst_vorbis_enc_get_latency (vorbisenc);
523
524         /* add our latency */
525         min_latency += latency;
526         if (max_latency != -1)
527           max_latency += latency;
528
529         gst_query_set_latency (query, live, min_latency, max_latency);
530       }
531       break;
532     }
533     default:
534       res = gst_pad_query (peerpad, query);
535       break;
536   }
537
538 error:
539   gst_object_unref (peerpad);
540   gst_object_unref (vorbisenc);
541   return res;
542 }
543
544 static gboolean
545 gst_vorbis_enc_sink_query (GstPad * pad, GstQuery * query)
546 {
547   gboolean res = TRUE;
548
549   switch (GST_QUERY_TYPE (query)) {
550     case GST_QUERY_CONVERT:
551     {
552       GstFormat src_fmt, dest_fmt;
553       gint64 src_val, dest_val;
554
555       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
556       if (!(res =
557               gst_vorbis_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
558                   &dest_val)))
559         goto error;
560       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
561       break;
562     }
563     default:
564       res = gst_pad_query_default (pad, query);
565       break;
566   }
567
568 error:
569   return res;
570 }
571
572 static void
573 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
574 {
575   vorbisenc->sinkpad =
576       gst_pad_new_from_static_template (&vorbis_enc_sink_factory, "sink");
577   gst_pad_set_event_function (vorbisenc->sinkpad,
578       GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event));
579   gst_pad_set_chain_function (vorbisenc->sinkpad,
580       GST_DEBUG_FUNCPTR (gst_vorbis_enc_chain));
581   gst_pad_set_setcaps_function (vorbisenc->sinkpad,
582       GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_setcaps));
583   gst_pad_set_getcaps_function (vorbisenc->sinkpad,
584       GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_getcaps));
585   gst_pad_set_query_function (vorbisenc->sinkpad,
586       GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_query));
587   gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
588
589   vorbisenc->srcpad =
590       gst_pad_new_from_static_template (&vorbis_enc_src_factory, "src");
591   gst_pad_set_query_function (vorbisenc->srcpad,
592       GST_DEBUG_FUNCPTR (gst_vorbis_enc_src_query));
593   gst_pad_set_query_type_function (vorbisenc->srcpad,
594       GST_DEBUG_FUNCPTR (gst_vorbis_enc_get_query_types));
595   gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
596
597   vorbisenc->channels = -1;
598   vorbisenc->frequency = -1;
599
600   vorbisenc->managed = FALSE;
601   vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
602   vorbisenc->bitrate = BITRATE_DEFAULT;
603   vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
604   vorbisenc->quality = QUALITY_DEFAULT;
605   vorbisenc->quality_set = FALSE;
606   vorbisenc->last_message = NULL;
607 }
608
609 static void
610 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
611     gpointer vorbisenc)
612 {
613   GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
614   GList *vc_list, *l;
615
616   vc_list = gst_tag_to_vorbis_comments (list, tag);
617
618   for (l = vc_list; l != NULL; l = l->next) {
619     const gchar *vc_string = (const gchar *) l->data;
620     gchar *key = NULL, *val = NULL;
621
622     GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
623     if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
624       vorbis_comment_add_tag (&enc->vc, key, val);
625       g_free (key);
626       g_free (val);
627     }
628   }
629
630   g_list_foreach (vc_list, (GFunc) g_free, NULL);
631   g_list_free (vc_list);
632 }
633
634 static void
635 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
636 {
637   GstTagList *merged_tags;
638   const GstTagList *user_tags;
639
640   vorbis_comment_init (&enc->vc);
641
642   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
643
644   GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
645   GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
646
647   /* gst_tag_list_merge() will handle NULL for either or both lists fine */
648   merged_tags = gst_tag_list_merge (user_tags, enc->tags,
649       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
650
651   if (merged_tags) {
652     GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
653     gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
654     gst_tag_list_free (merged_tags);
655   }
656 }
657
658 static gchar *
659 get_constraints_string (GstVorbisEnc * vorbisenc)
660 {
661   gint min = vorbisenc->min_bitrate;
662   gint max = vorbisenc->max_bitrate;
663   gchar *result;
664
665   if (min > 0 && max > 0)
666     result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
667   else if (min > 0)
668     result = g_strdup_printf ("(min %d bps, no max)", min);
669   else if (max > 0)
670     result = g_strdup_printf ("(no min, max %d bps)", max);
671   else
672     result = g_strdup_printf ("(no min or max)");
673
674   return result;
675 }
676
677 static void
678 update_start_message (GstVorbisEnc * vorbisenc)
679 {
680   gchar *constraints;
681
682   g_free (vorbisenc->last_message);
683
684   if (vorbisenc->bitrate > 0) {
685     if (vorbisenc->managed) {
686       constraints = get_constraints_string (vorbisenc);
687       vorbisenc->last_message =
688           g_strdup_printf ("encoding at average bitrate %d bps %s",
689           vorbisenc->bitrate, constraints);
690       g_free (constraints);
691     } else {
692       vorbisenc->last_message =
693           g_strdup_printf
694           ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
695           vorbisenc->bitrate);
696     }
697   } else {
698     if (vorbisenc->quality_set) {
699       if (vorbisenc->managed) {
700         constraints = get_constraints_string (vorbisenc);
701         vorbisenc->last_message =
702             g_strdup_printf
703             ("encoding at quality level %2.2f using constrained VBR %s",
704             vorbisenc->quality, constraints);
705         g_free (constraints);
706       } else {
707         vorbisenc->last_message =
708             g_strdup_printf ("encoding at quality level %2.2f",
709             vorbisenc->quality);
710       }
711     } else {
712       constraints = get_constraints_string (vorbisenc);
713       vorbisenc->last_message =
714           g_strdup_printf ("encoding using bitrate management %s", constraints);
715       g_free (constraints);
716     }
717   }
718
719   g_object_notify (G_OBJECT (vorbisenc), "last_message");
720 }
721
722 static gboolean
723 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
724 {
725   vorbisenc->setup = FALSE;
726
727   if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
728       && vorbisenc->max_bitrate < 0) {
729     vorbisenc->quality_set = TRUE;
730   }
731
732   update_start_message (vorbisenc);
733
734   /* choose an encoding mode */
735   /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
736   vorbis_info_init (&vorbisenc->vi);
737
738   if (vorbisenc->quality_set) {
739     if (vorbis_encode_setup_vbr (&vorbisenc->vi,
740             vorbisenc->channels, vorbisenc->frequency,
741             vorbisenc->quality) != 0) {
742       GST_ERROR_OBJECT (vorbisenc,
743           "vorbisenc: initialisation failed: invalid parameters for quality");
744       vorbis_info_clear (&vorbisenc->vi);
745       return FALSE;
746     }
747
748     /* do we have optional hard quality restrictions? */
749     if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
750       struct ovectl_ratemanage_arg ai;
751
752       vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
753
754       ai.bitrate_hard_min = vorbisenc->min_bitrate;
755       ai.bitrate_hard_max = vorbisenc->max_bitrate;
756       ai.management_active = 1;
757
758       vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
759     }
760   } else {
761     long min_bitrate, max_bitrate;
762
763     min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
764     max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
765
766     if (vorbis_encode_setup_managed (&vorbisenc->vi,
767             vorbisenc->channels,
768             vorbisenc->frequency,
769             max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
770       GST_ERROR_OBJECT (vorbisenc,
771           "vorbis_encode_setup_managed "
772           "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
773           vorbisenc->channels, vorbisenc->frequency, max_bitrate,
774           vorbisenc->bitrate, min_bitrate);
775       vorbis_info_clear (&vorbisenc->vi);
776       return FALSE;
777     }
778   }
779
780   if (vorbisenc->managed && vorbisenc->bitrate < 0) {
781     vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
782   } else if (!vorbisenc->managed) {
783     /* Turn off management entirely (if it was turned on). */
784     vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
785   }
786   vorbis_encode_setup_init (&vorbisenc->vi);
787
788   /* set up the analysis state and auxiliary encoding storage */
789   vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
790   vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
791
792   vorbisenc->next_ts = 0;
793
794   vorbisenc->setup = TRUE;
795
796   return TRUE;
797 }
798
799 static GstFlowReturn
800 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
801 {
802   GstFlowReturn ret = GST_FLOW_OK;
803
804   if (vorbisenc->setup) {
805     vorbis_analysis_wrote (&vorbisenc->vd, 0);
806     ret = gst_vorbis_enc_output_buffers (vorbisenc);
807
808     vorbisenc->setup = FALSE;
809   }
810
811   /* clean up and exit.  vorbis_info_clear() must be called last */
812   vorbis_block_clear (&vorbisenc->vb);
813   vorbis_dsp_clear (&vorbisenc->vd);
814   vorbis_info_clear (&vorbisenc->vi);
815
816   vorbisenc->header_sent = FALSE;
817
818   return ret;
819 }
820
821 /* prepare a buffer for transmission by passing data through libvorbis */
822 static GstBuffer *
823 gst_vorbis_enc_buffer_from_packet (GstVorbisEnc * vorbisenc,
824     ogg_packet * packet)
825 {
826   GstBuffer *outbuf;
827
828   outbuf = gst_buffer_new_and_alloc (packet->bytes);
829   memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
830   /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
831    * time representation */
832   GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos +
833       vorbisenc->granulepos_offset;
834   GST_BUFFER_OFFSET (outbuf) = granulepos_to_timestamp (vorbisenc,
835       GST_BUFFER_OFFSET_END (outbuf));
836   GST_BUFFER_TIMESTAMP (outbuf) = vorbisenc->next_ts;
837
838   /* update the next timestamp, taking granulepos_offset and subgranule offset
839    * into account */
840   vorbisenc->next_ts =
841       granulepos_to_timestamp_offset (vorbisenc, packet->granulepos) +
842       vorbisenc->initial_ts;
843   GST_BUFFER_DURATION (outbuf) =
844       vorbisenc->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
845
846   if (vorbisenc->next_discont) {
847     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
848     vorbisenc->next_discont = FALSE;
849   }
850
851   gst_buffer_set_caps (outbuf, vorbisenc->srccaps);
852
853   GST_LOG_OBJECT (vorbisenc, "encoded buffer of %d bytes",
854       GST_BUFFER_SIZE (outbuf));
855   return outbuf;
856 }
857
858 /* the same as above, but different logic for setting timestamp and granulepos
859  * */
860 static GstBuffer *
861 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
862     ogg_packet * packet)
863 {
864   GstBuffer *outbuf;
865
866   outbuf = gst_buffer_new_and_alloc (packet->bytes);
867   memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
868   GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
869   GST_BUFFER_OFFSET_END (outbuf) = 0;
870   GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
871   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
872
873   gst_buffer_set_caps (outbuf, vorbisenc->srccaps);
874
875   GST_DEBUG ("created header packet buffer, %d bytes",
876       GST_BUFFER_SIZE (outbuf));
877   return outbuf;
878 }
879
880 /* push out the buffer and do internal bookkeeping */
881 static GstFlowReturn
882 gst_vorbis_enc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
883 {
884   vorbisenc->bytes_out += GST_BUFFER_SIZE (buffer);
885
886   GST_DEBUG_OBJECT (vorbisenc,
887       "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
888       GST_BUFFER_OFFSET_END (buffer),
889       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
890   return gst_pad_push (vorbisenc->srcpad, buffer);
891 }
892
893 static GstFlowReturn
894 gst_vorbis_enc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
895 {
896   GstBuffer *outbuf;
897
898   outbuf = gst_vorbis_enc_buffer_from_packet (vorbisenc, packet);
899   return gst_vorbis_enc_push_buffer (vorbisenc, outbuf);
900 }
901
902 /* Set a copy of these buffers as 'streamheader' on the caps.
903  * We need a copy to avoid these buffers ending up with (indirect) refs on
904  * themselves
905  */
906 static GstCaps *
907 gst_vorbis_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
908     GstBuffer * buf2, GstBuffer * buf3)
909 {
910   GstBuffer *buf;
911   GstStructure *structure;
912   GValue array = { 0 };
913   GValue value = { 0 };
914
915   caps = gst_caps_make_writable (caps);
916   structure = gst_caps_get_structure (caps, 0);
917
918   /* mark buffers */
919   GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
920   GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
921   GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
922
923   /* put buffers in a fixed list */
924   g_value_init (&array, GST_TYPE_ARRAY);
925   g_value_init (&value, GST_TYPE_BUFFER);
926   buf = gst_buffer_copy (buf1);
927   gst_value_set_buffer (&value, buf);
928   gst_buffer_unref (buf);
929   gst_value_array_append_value (&array, &value);
930   g_value_unset (&value);
931   g_value_init (&value, GST_TYPE_BUFFER);
932   buf = gst_buffer_copy (buf2);
933   gst_value_set_buffer (&value, buf);
934   gst_buffer_unref (buf);
935   gst_value_array_append_value (&array, &value);
936   g_value_unset (&value);
937   g_value_init (&value, GST_TYPE_BUFFER);
938   buf = gst_buffer_copy (buf3);
939   gst_value_set_buffer (&value, buf);
940   gst_buffer_unref (buf);
941   gst_value_array_append_value (&array, &value);
942   gst_structure_set_value (structure, "streamheader", &array);
943   g_value_unset (&value);
944   g_value_unset (&array);
945
946   return caps;
947 }
948
949 static gboolean
950 gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event)
951 {
952   gboolean res = TRUE;
953   GstVorbisEnc *vorbisenc;
954
955   vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
956
957   switch (GST_EVENT_TYPE (event)) {
958     case GST_EVENT_EOS:
959       /* Tell the library we're at end of stream so that it can handle
960        * the last frame and mark end of stream in the output properly */
961       GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on");
962       gst_vorbis_enc_clear (vorbisenc);
963
964       res = gst_pad_push_event (vorbisenc->srcpad, event);
965       break;
966     case GST_EVENT_TAG:
967       if (vorbisenc->tags) {
968         GstTagList *list;
969
970         gst_event_parse_tag (event, &list);
971         gst_tag_list_insert (vorbisenc->tags, list,
972             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
973       } else {
974         g_assert_not_reached ();
975       }
976       res = gst_pad_push_event (vorbisenc->srcpad, event);
977       break;
978     case GST_EVENT_NEWSEGMENT:
979     {
980       gboolean update;
981       gdouble rate, applied_rate;
982       GstFormat format;
983       gint64 start, stop, position;
984
985       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
986           &format, &start, &stop, &position);
987       if (format == GST_FORMAT_TIME) {
988         gst_segment_set_newsegment (&vorbisenc->segment, update, rate, format,
989             start, stop, position);
990         if (vorbisenc->initial_ts == GST_CLOCK_TIME_NONE) {
991           GST_DEBUG_OBJECT (vorbisenc, "Initial segment %" GST_SEGMENT_FORMAT,
992               &vorbisenc->segment);
993           vorbisenc->initial_ts = start;
994         }
995       }
996     }
997       /* fall through */
998     default:
999       res = gst_pad_push_event (vorbisenc->srcpad, event);
1000       break;
1001   }
1002   return res;
1003 }
1004
1005 static gboolean
1006 gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
1007     GstClockTime timestamp, GstClockTime duration)
1008 {
1009   gboolean ret = FALSE;
1010
1011   if (timestamp != GST_CLOCK_TIME_NONE &&
1012       vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
1013       timestamp + duration != vorbisenc->expected_ts) {
1014     /* It turns out that a lot of elements don't generate perfect streams due
1015      * to rounding errors. So, we permit small errors (< 1/2 a sample) without
1016      * causing a discont.
1017      */
1018     int halfsample = GST_SECOND / vorbisenc->frequency / 2;
1019
1020     if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > halfsample) {
1021       GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
1022           ", buffer TS %" GST_TIME_FORMAT,
1023           GST_TIME_ARGS (vorbisenc->expected_ts), GST_TIME_ARGS (timestamp));
1024       ret = TRUE;
1025     }
1026   }
1027
1028   if (timestamp != GST_CLOCK_TIME_NONE && duration != GST_CLOCK_TIME_NONE) {
1029     vorbisenc->expected_ts = timestamp + duration;
1030   } else
1031     vorbisenc->expected_ts = GST_CLOCK_TIME_NONE;
1032
1033   return ret;
1034 }
1035
1036 static GstFlowReturn
1037 gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
1038 {
1039   GstVorbisEnc *vorbisenc;
1040   GstFlowReturn ret = GST_FLOW_OK;
1041   gfloat *data;
1042   gulong size;
1043   gulong i, j;
1044   float **vorbis_buffer;
1045   GstBuffer *buf1, *buf2, *buf3;
1046   gboolean first = FALSE;
1047   GstClockTime timestamp = GST_CLOCK_TIME_NONE;
1048   GstClockTime running_time = GST_CLOCK_TIME_NONE;
1049
1050   vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
1051
1052   if (!vorbisenc->setup)
1053     goto not_setup;
1054
1055   buffer = gst_audio_buffer_clip (buffer, &vorbisenc->segment,
1056       vorbisenc->frequency, 4 * vorbisenc->channels);
1057   if (buffer == NULL) {
1058     GST_DEBUG_OBJECT (vorbisenc, "Dropping buffer, out of segment");
1059     return GST_FLOW_OK;
1060   }
1061   running_time =
1062       gst_segment_to_running_time (&vorbisenc->segment, GST_FORMAT_TIME,
1063       GST_BUFFER_TIMESTAMP (buffer));
1064   timestamp = running_time + vorbisenc->initial_ts;
1065   GST_DEBUG_OBJECT (vorbisenc, "Initial ts is %" GST_TIME_FORMAT,
1066       GST_TIME_ARGS (vorbisenc->initial_ts));
1067   if (!vorbisenc->header_sent) {
1068     /* Vorbis streams begin with three headers; the initial header (with
1069        most of the codec setup parameters) which is mandated by the Ogg
1070        bitstream spec.  The second header holds any comment fields.  The
1071        third header holds the bitstream codebook.  We merely need to
1072        make the headers, then pass them to libvorbis one at a time;
1073        libvorbis handles the additional Ogg bitstream constraints */
1074     ogg_packet header;
1075     ogg_packet header_comm;
1076     ogg_packet header_code;
1077     GstCaps *caps;
1078
1079     /* first, make sure header buffers get timestamp == 0 */
1080     vorbisenc->next_ts = 0;
1081     vorbisenc->granulepos_offset = 0;
1082     vorbisenc->subgranule_offset = 0;
1083
1084     GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
1085     gst_vorbis_enc_set_metadata (vorbisenc);
1086     vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
1087         &header_comm, &header_code);
1088     vorbis_comment_clear (&vorbisenc->vc);
1089
1090     /* create header buffers */
1091     buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
1092     buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
1093     buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
1094
1095     /* mark and put on caps */
1096     vorbisenc->srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
1097     caps = vorbisenc->srccaps;
1098     caps = gst_vorbis_enc_set_header_on_caps (caps, buf1, buf2, buf3);
1099
1100     /* negotiate with these caps */
1101     GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
1102     gst_pad_set_caps (vorbisenc->srcpad, caps);
1103
1104     gst_buffer_set_caps (buf1, caps);
1105     gst_buffer_set_caps (buf2, caps);
1106     gst_buffer_set_caps (buf3, caps);
1107
1108     /* push out buffers */
1109     /* push_buffer takes the reference even for failure */
1110     if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf1)) != GST_FLOW_OK)
1111       goto failed_header_push;
1112     if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf2)) != GST_FLOW_OK) {
1113       buf2 = NULL;
1114       goto failed_header_push;
1115     }
1116     if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf3)) != GST_FLOW_OK) {
1117       buf3 = NULL;
1118       goto failed_header_push;
1119     }
1120
1121     /* now adjust starting granulepos accordingly if the buffer's timestamp is
1122        nonzero */
1123     vorbisenc->next_ts = timestamp;
1124     vorbisenc->expected_ts = timestamp;
1125     vorbisenc->granulepos_offset = gst_util_uint64_scale
1126         (running_time, vorbisenc->frequency, GST_SECOND);
1127     vorbisenc->subgranule_offset = 0;
1128     vorbisenc->subgranule_offset =
1129         (vorbisenc->next_ts - vorbisenc->initial_ts) -
1130         granulepos_to_timestamp_offset (vorbisenc, 0);
1131
1132     vorbisenc->header_sent = TRUE;
1133     first = TRUE;
1134   }
1135
1136   if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
1137       timestamp < vorbisenc->expected_ts) {
1138     guint64 diff = vorbisenc->expected_ts - timestamp;
1139     guint64 diff_bytes;
1140
1141     GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
1142         "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
1143         "), cannot handle. Clipping buffer.",
1144         GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts));
1145
1146     diff_bytes =
1147         GST_CLOCK_TIME_TO_FRAMES (diff,
1148         vorbisenc->frequency) * vorbisenc->channels * sizeof (gfloat);
1149     if (diff_bytes >= GST_BUFFER_SIZE (buffer)) {
1150       gst_buffer_unref (buffer);
1151       return GST_FLOW_OK;
1152     }
1153     buffer = gst_buffer_make_metadata_writable (buffer);
1154     GST_BUFFER_DATA (buffer) += diff_bytes;
1155     GST_BUFFER_SIZE (buffer) -= diff_bytes;
1156
1157     GST_BUFFER_TIMESTAMP (buffer) += diff;
1158     if (GST_BUFFER_DURATION_IS_VALID (buffer))
1159       GST_BUFFER_DURATION (buffer) -= diff;
1160   }
1161
1162   if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, timestamp,
1163           GST_BUFFER_DURATION (buffer)) && !first) {
1164     GST_WARNING_OBJECT (vorbisenc,
1165         "Buffer is discontinuous, flushing encoder "
1166         "and restarting (Discont from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT
1167         ")", GST_TIME_ARGS (vorbisenc->next_ts), GST_TIME_ARGS (timestamp));
1168     /* Re-initialise encoder (there's unfortunately no API to flush it) */
1169     if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK)
1170       return ret;
1171     if (!gst_vorbis_enc_setup (vorbisenc))
1172       return GST_FLOW_ERROR;    /* Should be impossible, we can only get here if
1173                                    we successfully initialised earlier */
1174
1175     /* Now, set our granulepos offset appropriately. */
1176     vorbisenc->next_ts = timestamp;
1177     /* We need to round to the nearest whole number of samples, not just do
1178      * a truncating division here */
1179     vorbisenc->granulepos_offset = gst_util_uint64_scale
1180         (running_time + GST_SECOND / vorbisenc->frequency / 2
1181         - vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND);
1182
1183     vorbisenc->header_sent = TRUE;
1184
1185     /* And our next output buffer must have DISCONT set on it */
1186     vorbisenc->next_discont = TRUE;
1187   }
1188
1189   /* Sending zero samples to libvorbis marks EOS, so we mustn't do that */
1190   if (GST_BUFFER_SIZE (buffer) == 0) {
1191     gst_buffer_unref (buffer);
1192     return GST_FLOW_OK;
1193   }
1194
1195   /* data to encode */
1196   data = (gfloat *) GST_BUFFER_DATA (buffer);
1197   size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
1198
1199   /* expose the buffer to submit data */
1200   vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
1201
1202   /* deinterleave samples, write the buffer data */
1203   for (i = 0; i < size; i++) {
1204     for (j = 0; j < vorbisenc->channels; j++) {
1205       vorbis_buffer[j][i] = *data++;
1206     }
1207   }
1208
1209   /* tell the library how much we actually submitted */
1210   vorbis_analysis_wrote (&vorbisenc->vd, size);
1211
1212   GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
1213
1214   vorbisenc->samples_in += size;
1215
1216   gst_buffer_unref (buffer);
1217
1218   ret = gst_vorbis_enc_output_buffers (vorbisenc);
1219
1220   return ret;
1221
1222   /* error cases */
1223 not_setup:
1224   {
1225     gst_buffer_unref (buffer);
1226     GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL),
1227         ("encoder not initialized (input is not audio?)"));
1228     return GST_FLOW_UNEXPECTED;
1229   }
1230 failed_header_push:
1231   {
1232     GST_WARNING_OBJECT (vorbisenc, "Failed to push headers");
1233     /* buf1 is always already unreffed */
1234     if (buf2)
1235       gst_buffer_unref (buf2);
1236     if (buf3)
1237       gst_buffer_unref (buf3);
1238     gst_buffer_unref (buffer);
1239     return ret;
1240   }
1241 }
1242
1243 static GstFlowReturn
1244 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
1245 {
1246   GstFlowReturn ret;
1247
1248   /* vorbis does some data preanalysis, then divides up blocks for
1249      more involved (potentially parallel) processing.  Get a single
1250      block for encoding now */
1251   while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
1252     ogg_packet op;
1253
1254     GST_LOG_OBJECT (vorbisenc, "analysed to a block");
1255
1256     /* analysis */
1257     vorbis_analysis (&vorbisenc->vb, NULL);
1258     vorbis_bitrate_addblock (&vorbisenc->vb);
1259
1260     while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
1261       GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
1262       ret = gst_vorbis_enc_push_packet (vorbisenc, &op);
1263
1264       if (ret != GST_FLOW_OK)
1265         return ret;
1266     }
1267   }
1268
1269   return GST_FLOW_OK;
1270 }
1271
1272 static void
1273 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
1274     GParamSpec * pspec)
1275 {
1276   GstVorbisEnc *vorbisenc;
1277
1278   g_return_if_fail (GST_IS_VORBISENC (object));
1279
1280   vorbisenc = GST_VORBISENC (object);
1281
1282   switch (prop_id) {
1283     case ARG_MAX_BITRATE:
1284       g_value_set_int (value, vorbisenc->max_bitrate);
1285       break;
1286     case ARG_BITRATE:
1287       g_value_set_int (value, vorbisenc->bitrate);
1288       break;
1289     case ARG_MIN_BITRATE:
1290       g_value_set_int (value, vorbisenc->min_bitrate);
1291       break;
1292     case ARG_QUALITY:
1293       g_value_set_float (value, vorbisenc->quality);
1294       break;
1295     case ARG_MANAGED:
1296       g_value_set_boolean (value, vorbisenc->managed);
1297       break;
1298     case ARG_LAST_MESSAGE:
1299       g_value_set_string (value, vorbisenc->last_message);
1300       break;
1301     default:
1302       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1303       break;
1304   }
1305 }
1306
1307 static void
1308 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
1309     const GValue * value, GParamSpec * pspec)
1310 {
1311   GstVorbisEnc *vorbisenc;
1312
1313   g_return_if_fail (GST_IS_VORBISENC (object));
1314
1315   vorbisenc = GST_VORBISENC (object);
1316
1317   switch (prop_id) {
1318     case ARG_MAX_BITRATE:
1319     {
1320       gboolean old_value = vorbisenc->managed;
1321
1322       vorbisenc->max_bitrate = g_value_get_int (value);
1323       if (vorbisenc->max_bitrate >= 0
1324           && vorbisenc->max_bitrate < LOWEST_BITRATE) {
1325         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1326         vorbisenc->max_bitrate = LOWEST_BITRATE;
1327       }
1328       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1329         vorbisenc->managed = TRUE;
1330       else
1331         vorbisenc->managed = FALSE;
1332
1333       if (old_value != vorbisenc->managed)
1334         g_object_notify (object, "managed");
1335       break;
1336     }
1337     case ARG_BITRATE:
1338       vorbisenc->bitrate = g_value_get_int (value);
1339       if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
1340         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1341         vorbisenc->bitrate = LOWEST_BITRATE;
1342       }
1343       break;
1344     case ARG_MIN_BITRATE:
1345     {
1346       gboolean old_value = vorbisenc->managed;
1347
1348       vorbisenc->min_bitrate = g_value_get_int (value);
1349       if (vorbisenc->min_bitrate >= 0
1350           && vorbisenc->min_bitrate < LOWEST_BITRATE) {
1351         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1352         vorbisenc->min_bitrate = LOWEST_BITRATE;
1353       }
1354       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1355         vorbisenc->managed = TRUE;
1356       else
1357         vorbisenc->managed = FALSE;
1358
1359       if (old_value != vorbisenc->managed)
1360         g_object_notify (object, "managed");
1361       break;
1362     }
1363     case ARG_QUALITY:
1364       vorbisenc->quality = g_value_get_float (value);
1365       if (vorbisenc->quality >= 0.0)
1366         vorbisenc->quality_set = TRUE;
1367       else
1368         vorbisenc->quality_set = FALSE;
1369       break;
1370     case ARG_MANAGED:
1371       vorbisenc->managed = g_value_get_boolean (value);
1372       break;
1373     default:
1374       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1375       break;
1376   }
1377 }
1378
1379 static GstStateChangeReturn
1380 gst_vorbis_enc_change_state (GstElement * element, GstStateChange transition)
1381 {
1382   GstVorbisEnc *vorbisenc = GST_VORBISENC (element);
1383   GstStateChangeReturn res;
1384
1385
1386   switch (transition) {
1387     case GST_STATE_CHANGE_NULL_TO_READY:
1388       vorbisenc->tags = gst_tag_list_new ();
1389       break;
1390     case GST_STATE_CHANGE_READY_TO_PAUSED:
1391       vorbisenc->setup = FALSE;
1392       vorbisenc->next_discont = FALSE;
1393       vorbisenc->header_sent = FALSE;
1394       gst_segment_init (&vorbisenc->segment, GST_FORMAT_TIME);
1395       vorbisenc->initial_ts = GST_CLOCK_TIME_NONE;
1396       break;
1397     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1398       break;
1399     default:
1400       break;
1401   }
1402
1403   res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1404
1405   switch (transition) {
1406     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1407       break;
1408     case GST_STATE_CHANGE_PAUSED_TO_READY:
1409       vorbis_block_clear (&vorbisenc->vb);
1410       vorbis_dsp_clear (&vorbisenc->vd);
1411       vorbis_info_clear (&vorbisenc->vi);
1412       g_free (vorbisenc->last_message);
1413       vorbisenc->last_message = NULL;
1414       if (vorbisenc->srccaps) {
1415         gst_caps_unref (vorbisenc->srccaps);
1416         vorbisenc->srccaps = NULL;
1417       }
1418       break;
1419     case GST_STATE_CHANGE_READY_TO_NULL:
1420       gst_tag_list_free (vorbisenc->tags);
1421       vorbisenc->tags = NULL;
1422     default:
1423       break;
1424   }
1425
1426   return res;
1427 }