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