• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 /**
21  * SECTION:element-vorbisenc
22  * @title: vorbisenc
23  * @see_also: vorbisdec, oggmux
24  *
25  * This element encodes raw float audio into a Vorbis stream.
26  * [Vorbis](http://www.vorbis.com/) is a royalty-free audio codec maintained by
27  * the [Xiph.org Foundation](http://www.xiph.org/).
28  *
29  * ## Example pipelines
30  * |[
31  * gst-launch-1.0 -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sine.ogg
32  * ]|
33  *  Encode a test sine signal to Ogg/Vorbis.  Note that the resulting file
34  * will be really small because a sine signal compresses very well.
35  * |[
36  * gst-launch-1.0 -v autoaudiosrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
37  * ]|
38  *  Record from a sound card and encode to Ogg/Vorbis.
39  *
40  */
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44 
45 #include <stdlib.h>
46 #include <string.h>
47 #include <time.h>
48 #include <vorbis/vorbisenc.h>
49 
50 #include <gst/gsttagsetter.h>
51 #include <gst/tag/tag.h>
52 #include <gst/audio/audio.h>
53 #include "gstvorbisenc.h"
54 
55 #include "gstvorbiselements.h"
56 #include "gstvorbiscommon.h"
57 
58 GST_DEBUG_CATEGORY_STATIC (vorbisenc_debug);
59 #define GST_CAT_DEFAULT vorbisenc_debug
60 
61 static GstStaticPadTemplate vorbis_enc_src_factory =
62 GST_STATIC_PAD_TEMPLATE ("src",
63     GST_PAD_SRC,
64     GST_PAD_ALWAYS,
65     GST_STATIC_CAPS ("audio/x-vorbis, "
66         "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
67     );
68 
69 enum
70 {
71   ARG_0,
72   ARG_MAX_BITRATE,
73   ARG_BITRATE,
74   ARG_MIN_BITRATE,
75   ARG_QUALITY,
76   ARG_MANAGED,
77   ARG_LAST_MESSAGE
78 };
79 
80 static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
81 static GstCaps *gst_vorbis_enc_generate_sink_caps (void);
82 
83 
84 #define MAX_BITRATE_DEFAULT     -1
85 #define BITRATE_DEFAULT         -1
86 #define MIN_BITRATE_DEFAULT     -1
87 #define QUALITY_DEFAULT         0.3
88 #define LOWEST_BITRATE          6000    /* lowest allowed for a 8 kHz stream */
89 #define HIGHEST_BITRATE         250001  /* highest allowed for a 44 kHz stream */
90 
91 static gboolean gst_vorbis_enc_start (GstAudioEncoder * enc);
92 static gboolean gst_vorbis_enc_stop (GstAudioEncoder * enc);
93 static gboolean gst_vorbis_enc_set_format (GstAudioEncoder * enc,
94     GstAudioInfo * info);
95 static GstFlowReturn gst_vorbis_enc_handle_frame (GstAudioEncoder * enc,
96     GstBuffer * in_buf);
97 static gboolean gst_vorbis_enc_sink_event (GstAudioEncoder * enc,
98     GstEvent * event);
99 
100 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
101 
102 static void gst_vorbis_enc_dispose (GObject * object);
103 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
104     GValue * value, GParamSpec * pspec);
105 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
106     const GValue * value, GParamSpec * pspec);
107 static void gst_vorbis_enc_flush (GstAudioEncoder * vorbisenc);
108 
109 #define gst_vorbis_enc_parent_class parent_class
110 G_DEFINE_TYPE_WITH_CODE (GstVorbisEnc, gst_vorbis_enc,
111     GST_TYPE_AUDIO_ENCODER, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
112 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (vorbisenc, "vorbisenc",
113     GST_RANK_PRIMARY, GST_TYPE_VORBISENC,
114     GST_DEBUG_CATEGORY_INIT (vorbisenc_debug, "vorbisenc", 0,
115         "vorbis encoding element");
116     vorbis_element_init (plugin));
117 
118 static void
gst_vorbis_enc_class_init(GstVorbisEncClass * klass)119 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
120 {
121   GObjectClass *gobject_class;
122   GstElementClass *gstelement_class;
123   GstAudioEncoderClass *base_class;
124   GstCaps *sink_caps;
125   GstPadTemplate *sink_templ;
126 
127   gobject_class = (GObjectClass *) klass;
128   gstelement_class = (GstElementClass *) klass;
129   base_class = (GstAudioEncoderClass *) (klass);
130 
131   gobject_class->set_property = gst_vorbis_enc_set_property;
132   gobject_class->get_property = gst_vorbis_enc_get_property;
133   gobject_class->dispose = gst_vorbis_enc_dispose;
134 
135   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
136       g_param_spec_int ("max-bitrate", "Maximum Bitrate",
137           "Specify a maximum bitrate (in bps). Useful for streaming "
138           "applications. (-1 == disabled)",
139           -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
140           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
141   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
142       g_param_spec_int ("bitrate", "Target Bitrate",
143           "Attempt to encode at a bitrate averaging this (in bps). "
144           "This uses the bitrate management engine, and is not recommended for most users. "
145           "Quality is a better alternative. (-1 == disabled)", -1,
146           HIGHEST_BITRATE, BITRATE_DEFAULT,
147           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
148   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
149       g_param_spec_int ("min-bitrate", "Minimum Bitrate",
150           "Specify a minimum bitrate (in bps). Useful for encoding for a "
151           "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
152           MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
153   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
154       g_param_spec_float ("quality", "Quality",
155           "Specify quality instead of specifying a particular bitrate.", -0.1,
156           1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
157   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
158       g_param_spec_boolean ("managed", "Managed",
159           "Enable bitrate management engine", FALSE,
160           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
161   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
162       g_param_spec_string ("last-message", "last-message",
163           "The last status message", NULL,
164           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
165 
166   sink_caps = gst_vorbis_enc_generate_sink_caps ();
167   sink_templ = gst_pad_template_new ("sink",
168       GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps);
169   gst_element_class_add_pad_template (gstelement_class, sink_templ);
170   gst_caps_unref (sink_caps);
171 
172   gst_element_class_add_static_pad_template (gstelement_class,
173       &vorbis_enc_src_factory);
174 
175   gst_element_class_set_static_metadata (gstelement_class,
176       "Vorbis audio encoder", "Codec/Encoder/Audio",
177       "Encodes audio in Vorbis format",
178       "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
179 
180   base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
181   base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
182   base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
183   base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
184   base_class->sink_event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
185   base_class->flush = GST_DEBUG_FUNCPTR (gst_vorbis_enc_flush);
186 }
187 
188 static void
gst_vorbis_enc_init(GstVorbisEnc * vorbisenc)189 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc)
190 {
191   GstAudioEncoder *enc = GST_AUDIO_ENCODER (vorbisenc);
192 
193   GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (enc));
194 
195   vorbisenc->channels = -1;
196   vorbisenc->frequency = -1;
197 
198   vorbisenc->managed = FALSE;
199   vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
200   vorbisenc->bitrate = BITRATE_DEFAULT;
201   vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
202   vorbisenc->quality = QUALITY_DEFAULT;
203   vorbisenc->quality_set = FALSE;
204   vorbisenc->last_message = NULL;
205 
206   /* arrange granulepos marking (and required perfect ts) */
207   gst_audio_encoder_set_mark_granule (enc, TRUE);
208   gst_audio_encoder_set_perfect_timestamp (enc, TRUE);
209 }
210 
211 static void
gst_vorbis_enc_dispose(GObject * object)212 gst_vorbis_enc_dispose (GObject * object)
213 {
214   GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
215 
216   if (vorbisenc->sinkcaps) {
217     gst_caps_unref (vorbisenc->sinkcaps);
218     vorbisenc->sinkcaps = NULL;
219   }
220 
221   G_OBJECT_CLASS (parent_class)->dispose (object);
222 }
223 
224 static gboolean
gst_vorbis_enc_start(GstAudioEncoder * enc)225 gst_vorbis_enc_start (GstAudioEncoder * enc)
226 {
227   GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
228 
229   GST_DEBUG_OBJECT (enc, "start");
230   vorbisenc->tags = gst_tag_list_new_empty ();
231   vorbisenc->header_sent = FALSE;
232   vorbisenc->last_size = 0;
233 
234   return TRUE;
235 }
236 
237 static gboolean
gst_vorbis_enc_stop(GstAudioEncoder * enc)238 gst_vorbis_enc_stop (GstAudioEncoder * enc)
239 {
240   GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
241 
242   GST_DEBUG_OBJECT (enc, "stop");
243   vorbis_block_clear (&vorbisenc->vb);
244   vorbis_dsp_clear (&vorbisenc->vd);
245   vorbis_info_clear (&vorbisenc->vi);
246   g_free (vorbisenc->last_message);
247   vorbisenc->last_message = NULL;
248   gst_tag_list_unref (vorbisenc->tags);
249   vorbisenc->tags = NULL;
250 
251   gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
252 
253   return TRUE;
254 }
255 
256 static GstCaps *
gst_vorbis_enc_generate_sink_caps(void)257 gst_vorbis_enc_generate_sink_caps (void)
258 {
259   GstCaps *caps = gst_caps_new_empty ();
260   int i, c;
261 
262   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
263           "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
264           "layout", G_TYPE_STRING, "interleaved",
265           "rate", GST_TYPE_INT_RANGE, 1, 200000,
266           "channels", G_TYPE_INT, 1, NULL));
267 
268   for (i = 2; i <= 8; i++) {
269     GstStructure *structure;
270     guint64 channel_mask = 0;
271     const GstAudioChannelPosition *pos = gst_vorbis_channel_positions[i - 1];
272 
273     for (c = 0; c < i; c++) {
274       channel_mask |= G_GUINT64_CONSTANT (1) << pos[c];
275     }
276 
277     structure = gst_structure_new ("audio/x-raw",
278         "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
279         "layout", G_TYPE_STRING, "interleaved",
280         "rate", GST_TYPE_INT_RANGE, 1, 200000, "channels", G_TYPE_INT, i,
281         "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL);
282 
283     gst_caps_append_structure (caps, structure);
284   }
285 
286   gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
287           "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
288           "layout", G_TYPE_STRING, "interleaved",
289           "rate", GST_TYPE_INT_RANGE, 1, 200000,
290           "channels", GST_TYPE_INT_RANGE, 9, 255,
291           "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL));
292 
293   return caps;
294 }
295 
296 static gint64
gst_vorbis_enc_get_latency(GstVorbisEnc * vorbisenc)297 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
298 {
299   /* FIXME, this probably depends on the bitrate and other setting but for now
300    * we return this value, which was obtained by totally unscientific
301    * measurements */
302   return 58 * GST_MSECOND;
303 }
304 
305 static gboolean
gst_vorbis_enc_set_format(GstAudioEncoder * enc,GstAudioInfo * info)306 gst_vorbis_enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
307 {
308   GstVorbisEnc *vorbisenc;
309 
310   vorbisenc = GST_VORBISENC (enc);
311 
312   vorbisenc->channels = GST_AUDIO_INFO_CHANNELS (info);
313   vorbisenc->frequency = GST_AUDIO_INFO_RATE (info);
314 
315   /* if re-configured, we were drained and cleared already */
316   vorbisenc->header_sent = FALSE;
317   if (!gst_vorbis_enc_setup (vorbisenc))
318     return FALSE;
319 
320   /* feedback to base class */
321   gst_audio_encoder_set_latency (enc,
322       gst_vorbis_enc_get_latency (vorbisenc),
323       gst_vorbis_enc_get_latency (vorbisenc));
324 
325   return TRUE;
326 }
327 
328 static void
gst_vorbis_enc_metadata_set1(const GstTagList * list,const gchar * tag,gpointer vorbisenc)329 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
330     gpointer vorbisenc)
331 {
332   GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
333   GList *vc_list, *l;
334 
335   vc_list = gst_tag_to_vorbis_comments (list, tag);
336 
337   for (l = vc_list; l != NULL; l = l->next) {
338     const gchar *vc_string = (const gchar *) l->data;
339     gchar *key = NULL, *val = NULL;
340 
341     GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
342     if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
343       vorbis_comment_add_tag (&enc->vc, key, val);
344       g_free (key);
345       g_free (val);
346     }
347   }
348 
349   g_list_foreach (vc_list, (GFunc) g_free, NULL);
350   g_list_free (vc_list);
351 }
352 
353 static void
gst_vorbis_enc_set_metadata(GstVorbisEnc * enc)354 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
355 {
356   GstTagList *merged_tags;
357   const GstTagList *user_tags;
358 
359   vorbis_comment_init (&enc->vc);
360 
361   user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
362 
363   GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
364   GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
365 
366   /* gst_tag_list_merge() will handle NULL for either or both lists fine */
367   merged_tags = gst_tag_list_merge (user_tags, enc->tags,
368       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
369 
370   if (merged_tags) {
371     GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
372     gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
373     gst_tag_list_unref (merged_tags);
374   }
375 }
376 
377 static gchar *
get_constraints_string(GstVorbisEnc * vorbisenc)378 get_constraints_string (GstVorbisEnc * vorbisenc)
379 {
380   gint min = vorbisenc->min_bitrate;
381   gint max = vorbisenc->max_bitrate;
382   gchar *result;
383 
384   if (min > 0 && max > 0)
385     result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
386   else if (min > 0)
387     result = g_strdup_printf ("(min %d bps, no max)", min);
388   else if (max > 0)
389     result = g_strdup_printf ("(no min, max %d bps)", max);
390   else
391     result = g_strdup_printf ("(no min or max)");
392 
393   return result;
394 }
395 
396 static void
update_start_message(GstVorbisEnc * vorbisenc)397 update_start_message (GstVorbisEnc * vorbisenc)
398 {
399   gchar *constraints;
400 
401   g_free (vorbisenc->last_message);
402 
403   if (vorbisenc->bitrate > 0) {
404     if (vorbisenc->managed) {
405       constraints = get_constraints_string (vorbisenc);
406       vorbisenc->last_message =
407           g_strdup_printf ("encoding at average bitrate %d bps %s",
408           vorbisenc->bitrate, constraints);
409       g_free (constraints);
410     } else {
411       vorbisenc->last_message =
412           g_strdup_printf
413           ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
414           vorbisenc->bitrate);
415     }
416   } else {
417     if (vorbisenc->quality_set) {
418       if (vorbisenc->managed) {
419         constraints = get_constraints_string (vorbisenc);
420         vorbisenc->last_message =
421             g_strdup_printf
422             ("encoding at quality level %2.2f using constrained VBR %s",
423             vorbisenc->quality, constraints);
424         g_free (constraints);
425       } else {
426         vorbisenc->last_message =
427             g_strdup_printf ("encoding at quality level %2.2f",
428             vorbisenc->quality);
429       }
430     } else {
431       constraints = get_constraints_string (vorbisenc);
432       vorbisenc->last_message =
433           g_strdup_printf ("encoding using bitrate management %s", constraints);
434       g_free (constraints);
435     }
436   }
437 
438   g_object_notify (G_OBJECT (vorbisenc), "last_message");
439 }
440 
441 static gboolean
gst_vorbis_enc_setup(GstVorbisEnc * vorbisenc)442 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
443 {
444 
445   GST_LOG_OBJECT (vorbisenc, "setup");
446 
447   if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
448       && vorbisenc->max_bitrate < 0) {
449     vorbisenc->quality_set = TRUE;
450   }
451 
452   update_start_message (vorbisenc);
453 
454   /* choose an encoding mode */
455   /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
456   vorbis_info_init (&vorbisenc->vi);
457 
458   if (vorbisenc->quality_set) {
459     if (vorbis_encode_setup_vbr (&vorbisenc->vi,
460             vorbisenc->channels, vorbisenc->frequency,
461             vorbisenc->quality) != 0) {
462       GST_ERROR_OBJECT (vorbisenc,
463           "vorbisenc: initialisation failed: invalid parameters for quality");
464       vorbis_info_clear (&vorbisenc->vi);
465       return FALSE;
466     }
467 
468     /* do we have optional hard quality restrictions? */
469     if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
470       struct ovectl_ratemanage_arg ai;
471 
472       vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
473 
474       ai.bitrate_hard_min = vorbisenc->min_bitrate;
475       ai.bitrate_hard_max = vorbisenc->max_bitrate;
476       ai.management_active = 1;
477 
478       vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
479     }
480   } else {
481     long min_bitrate, max_bitrate;
482 
483     min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
484     max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
485 
486     if (vorbis_encode_setup_managed (&vorbisenc->vi,
487             vorbisenc->channels,
488             vorbisenc->frequency,
489             max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
490       GST_ERROR_OBJECT (vorbisenc,
491           "vorbis_encode_setup_managed "
492           "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
493           vorbisenc->channels, vorbisenc->frequency, max_bitrate,
494           vorbisenc->bitrate, min_bitrate);
495       vorbis_info_clear (&vorbisenc->vi);
496       return FALSE;
497     }
498   }
499 
500   if (vorbisenc->managed && vorbisenc->bitrate < 0) {
501     vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
502   } else if (!vorbisenc->managed) {
503     /* Turn off management entirely (if it was turned on). */
504     vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
505   }
506   vorbis_encode_setup_init (&vorbisenc->vi);
507 
508   /* set up the analysis state and auxiliary encoding storage */
509   vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
510   vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
511 
512   /* samples == granulepos start at 0 again */
513   vorbisenc->samples_out = 0;
514 
515   /* fresh encoder available */
516   vorbisenc->setup = TRUE;
517 
518   return TRUE;
519 }
520 
521 static GstFlowReturn
gst_vorbis_enc_clear(GstVorbisEnc * vorbisenc)522 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
523 {
524   GstFlowReturn ret = GST_FLOW_OK;
525 
526   if (vorbisenc->setup) {
527     vorbis_analysis_wrote (&vorbisenc->vd, 0);
528     ret = gst_vorbis_enc_output_buffers (vorbisenc);
529 
530     /* marked EOS to encoder, recreate if needed */
531     vorbisenc->setup = FALSE;
532   }
533 
534   /* clean up and exit.  vorbis_info_clear() must be called last */
535   vorbis_block_clear (&vorbisenc->vb);
536   vorbis_dsp_clear (&vorbisenc->vd);
537   vorbis_info_clear (&vorbisenc->vi);
538 
539   return ret;
540 }
541 
542 static void
gst_vorbis_enc_flush(GstAudioEncoder * enc)543 gst_vorbis_enc_flush (GstAudioEncoder * enc)
544 {
545   GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
546 
547   gst_vorbis_enc_clear (vorbisenc);
548   vorbisenc->header_sent = FALSE;
549 }
550 
551 /* copied and adapted from ext/ogg/gstoggstream.c */
552 static gint64
packet_duration_vorbis(GstVorbisEnc * enc,ogg_packet * packet)553 packet_duration_vorbis (GstVorbisEnc * enc, ogg_packet * packet)
554 {
555   int mode;
556   int size;
557   int duration;
558 
559   if (packet->bytes == 0 || packet->packet[0] & 1)
560     return 0;
561 
562   mode = (packet->packet[0] >> 1) & ((1 << enc->vorbis_log2_num_modes) - 1);
563   size = enc->vorbis_mode_sizes[mode] ? enc->long_size : enc->short_size;
564 
565   if (enc->last_size == 0) {
566     duration = 0;
567   } else {
568     duration = enc->last_size / 4 + size / 4;
569   }
570   enc->last_size = size;
571 
572   GST_DEBUG_OBJECT (enc, "duration %d", (int) duration);
573 
574   return duration;
575 }
576 
577 /* copied and adapted from ext/ogg/gstoggstream.c */
578 static void
parse_vorbis_header_packet(GstVorbisEnc * enc,ogg_packet * packet)579 parse_vorbis_header_packet (GstVorbisEnc * enc, ogg_packet * packet)
580 {
581   /*
582    * on the first (b_o_s) packet, determine the long and short sizes,
583    * and then calculate l/2, l/4 - s/4, 3 * l/4 - s/4, l/2 - s/2 and s/2
584    */
585 
586   enc->long_size = 1 << (packet->packet[28] >> 4);
587   enc->short_size = 1 << (packet->packet[28] & 0xF);
588 }
589 
590 /* copied and adapted from ext/ogg/gstoggstream.c */
591 static void
parse_vorbis_codebooks_packet(GstVorbisEnc * enc,ogg_packet * op)592 parse_vorbis_codebooks_packet (GstVorbisEnc * enc, ogg_packet * op)
593 {
594   /*
595    * the code pages, a whole bunch of other fairly useless stuff, AND,
596    * RIGHT AT THE END (of a bunch of variable-length compressed rubbish that
597    * basically has only one actual set of values that everyone uses BUT YOU
598    * CAN'T BE SURE OF THAT, OH NO YOU CAN'T) is the only piece of data that's
599    * actually useful to us - the packet modes (because it's inconceivable to
600    * think people might want _just that_ and nothing else, you know, for
601    * seeking and stuff).
602    *
603    * Fortunately, because of the mandate that non-used bits must be zero
604    * at the end of the packet, we might be able to sneakily work backwards
605    * and find out the information we need (namely a mapping of modes to
606    * packet sizes)
607    */
608   unsigned char *current_pos = &op->packet[op->bytes - 1];
609   int offset;
610   int size;
611   int size_check;
612   int *mode_size_ptr;
613   int i;
614   int ii;
615 
616   /*
617    * This is the format of the mode data at the end of the packet for all
618    * Vorbis Version 1 :
619    *
620    * [ 6:number_of_modes ]
621    * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
622    * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
623    * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
624    * [ 1:framing(1) ]
625    *
626    * e.g.:
627    *
628    *              <-
629    * 0 0 0 0 0 1 0 0
630    * 0 0 1 0 0 0 0 0
631    * 0 0 1 0 0 0 0 0
632    * 0 0 1|0 0 0 0 0
633    * 0 0 0 0|0|0 0 0
634    * 0 0 0 0 0 0 0 0
635    * 0 0 0 0|0 0 0 0
636    * 0 0 0 0 0 0 0 0
637    * 0 0 0 0|0 0 0 0
638    * 0 0 0|1|0 0 0 0 |
639    * 0 0 0 0 0 0 0 0 V
640    * 0 0 0|0 0 0 0 0
641    * 0 0 0 0 0 0 0 0
642    * 0 0 1|0 0 0 0 0
643    * 0 0|1|0 0 0 0 0
644    *
645    *
646    * i.e. each entry is an important bit, 32 bits of 0, 8 bits of blah, a
647    * bit of 1.
648    * Let's find our last 1 bit first.
649    *
650    */
651 
652   size = 0;
653 
654   offset = 8;
655   while (!((1 << --offset) & *current_pos)) {
656     if (offset == 0) {
657       offset = 8;
658       current_pos -= 1;
659     }
660   }
661 
662   while (1) {
663 
664     /*
665      * from current_pos-5:(offset+1) to current_pos-1:(offset+1) should
666      * be zero
667      */
668     offset = (offset + 7) % 8;
669     if (offset == 7)
670       current_pos -= 1;
671 
672     if (((current_pos[-5] & ~((1 << (offset + 1)) - 1)) != 0)
673         ||
674         current_pos[-4] != 0
675         ||
676         current_pos[-3] != 0
677         ||
678         current_pos[-2] != 0
679         || ((current_pos[-1] & ((1 << (offset + 1)) - 1)) != 0)
680         ) {
681       break;
682     }
683 
684     size += 1;
685 
686     current_pos -= 5;
687 
688   }
689 
690   /* Give ourselves a chance to recover if we went back too far by using
691    * the size check. */
692   for (ii = 0; ii < 2; ii++) {
693     if (offset > 4) {
694       size_check = (current_pos[0] >> (offset - 5)) & 0x3F;
695     } else {
696       /* mask part of byte from current_pos */
697       size_check = (current_pos[0] & ((1 << (offset + 1)) - 1));
698       /* shift to appropriate position */
699       size_check <<= (5 - offset);
700       /* or in part of byte from current_pos - 1 */
701       size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >>
702           (offset + 3);
703     }
704 
705     size_check += 1;
706     if (size_check == size) {
707       break;
708     }
709     offset = (offset + 1) % 8;
710     if (offset == 0)
711       current_pos += 1;
712     current_pos += 5;
713     size -= 1;
714   }
715 
716   /* Store mode size information in our info struct */
717   i = -1;
718   while ((1 << (++i)) < size);
719   enc->vorbis_log2_num_modes = i;
720 
721   mode_size_ptr = enc->vorbis_mode_sizes;
722 
723   for (i = 0; i < size; i++) {
724     offset = (offset + 1) % 8;
725     if (offset == 0)
726       current_pos += 1;
727     *mode_size_ptr++ = (current_pos[0] >> offset) & 0x1;
728     current_pos += 5;
729   }
730 
731 }
732 
733 static GstBuffer *
gst_vorbis_enc_buffer_from_header_packet(GstVorbisEnc * vorbisenc,ogg_packet * packet)734 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
735     ogg_packet * packet)
736 {
737   GstBuffer *outbuf;
738 
739   if (packet->bytes > 0 && packet->packet[0] == '\001') {
740     parse_vorbis_header_packet (vorbisenc, packet);
741   } else if (packet->bytes > 0 && packet->packet[0] == '\005') {
742     parse_vorbis_codebooks_packet (vorbisenc, packet);
743   }
744 
745   outbuf =
746       gst_audio_encoder_allocate_output_buffer (GST_AUDIO_ENCODER (vorbisenc),
747       packet->bytes);
748   gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
749   GST_BUFFER_OFFSET (outbuf) = 0;
750   GST_BUFFER_OFFSET_END (outbuf) = 0;
751   GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
752   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
753   GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_HEADER);
754 
755   GST_DEBUG ("created header packet buffer, %" G_GSIZE_FORMAT " bytes",
756       gst_buffer_get_size (outbuf));
757   return outbuf;
758 }
759 
760 static gboolean
gst_vorbis_enc_sink_event(GstAudioEncoder * enc,GstEvent * event)761 gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event)
762 {
763   GstVorbisEnc *vorbisenc;
764 
765   vorbisenc = GST_VORBISENC (enc);
766 
767   switch (GST_EVENT_TYPE (event)) {
768     case GST_EVENT_TAG:
769       if (vorbisenc->tags) {
770         GstTagList *list;
771 
772         gst_event_parse_tag (event, &list);
773         gst_tag_list_insert (vorbisenc->tags, list,
774             gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
775       } else {
776         g_assert_not_reached ();
777       }
778       break;
779       /* fall through */
780     default:
781       break;
782   }
783 
784   /* we only peeked, let base class handle it */
785   return GST_AUDIO_ENCODER_CLASS (parent_class)->sink_event (enc, event);
786 }
787 
788 /*
789  * (really really) FIXME: move into core (dixit tpm)
790  */
791 /*
792  * _gst_caps_set_buffer_array:
793  * @caps: (transfer full): a #GstCaps
794  * @field: field in caps to set
795  * @buf: header buffers
796  *
797  * Adds given buffers to an array of buffers set as the given @field
798  * on the given @caps.  List of buffer arguments must be NULL-terminated.
799  *
800  * Returns: (transfer full): input caps with a streamheader field added, or NULL
801  *     if some error occurred
802  */
803 static GstCaps *
_gst_caps_set_buffer_array(GstCaps * caps,const gchar * field,GstBuffer * buf,...)804 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
805     GstBuffer * buf, ...)
806 {
807   GstStructure *structure = NULL;
808   va_list va;
809   GValue array = { 0 };
810   GValue value = { 0 };
811 
812   g_return_val_if_fail (caps != NULL, NULL);
813   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
814   g_return_val_if_fail (field != NULL, NULL);
815 
816   caps = gst_caps_make_writable (caps);
817   structure = gst_caps_get_structure (caps, 0);
818 
819   g_value_init (&array, GST_TYPE_ARRAY);
820 
821   va_start (va, buf);
822   /* put buffers in a fixed list */
823   while (buf) {
824     g_value_init (&value, GST_TYPE_BUFFER);
825     gst_value_set_buffer (&value, buf);
826     gst_value_array_append_value (&array, &value);
827     g_value_unset (&value);
828 
829     buf = va_arg (va, GstBuffer *);
830   }
831   va_end (va);
832 
833   gst_structure_take_value (structure, field, &array);
834 
835   return caps;
836 }
837 
838 static GstFlowReturn
gst_vorbis_enc_handle_frame(GstAudioEncoder * enc,GstBuffer * buffer)839 gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
840 {
841   GstVorbisEnc *vorbisenc;
842   GstFlowReturn ret = GST_FLOW_OK;
843   GstMapInfo map;
844   gfloat *ptr;
845   gulong size;
846   gulong i, j;
847   float **vorbis_buffer;
848   GstBuffer *buf1, *buf2, *buf3;
849 
850   vorbisenc = GST_VORBISENC (enc);
851 
852   if (G_UNLIKELY (!vorbisenc->setup)) {
853     if (buffer) {
854       GST_DEBUG_OBJECT (vorbisenc, "forcing setup");
855       /* should not fail, as setup before same way */
856       if (!gst_vorbis_enc_setup (vorbisenc))
857         return GST_FLOW_ERROR;
858     } else {
859       /* end draining */
860       GST_LOG_OBJECT (vorbisenc, "already drained");
861       return GST_FLOW_OK;
862     }
863   }
864 
865   if (!vorbisenc->header_sent) {
866     /* Vorbis streams begin with three headers; the initial header (with
867        most of the codec setup parameters) which is mandated by the Ogg
868        bitstream spec.  The second header holds any comment fields.  The
869        third header holds the bitstream codebook.  We merely need to
870        make the headers, then pass them to libvorbis one at a time;
871        libvorbis handles the additional Ogg bitstream constraints */
872     ogg_packet header;
873     ogg_packet header_comm;
874     ogg_packet header_code;
875     GstCaps *caps;
876     GList *headers;
877 
878     GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
879     gst_vorbis_enc_set_metadata (vorbisenc);
880     vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
881         &header_comm, &header_code);
882     vorbis_comment_clear (&vorbisenc->vc);
883 
884     /* create header buffers */
885     buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
886     buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
887     buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
888 
889     /* mark and put on caps */
890     caps = gst_caps_new_simple ("audio/x-vorbis",
891         "rate", G_TYPE_INT, vorbisenc->frequency,
892         "channels", G_TYPE_INT, vorbisenc->channels, NULL);
893     caps = _gst_caps_set_buffer_array (caps, "streamheader",
894         buf1, buf2, buf3, NULL);
895 
896     /* negotiate with these caps */
897     GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
898     gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (vorbisenc), caps);
899     gst_caps_unref (caps);
900 
901     /* store buffers for later pre_push sending */
902     headers = NULL;
903     GST_DEBUG_OBJECT (vorbisenc, "storing header buffers");
904     headers = g_list_prepend (headers, buf3);
905     headers = g_list_prepend (headers, buf2);
906     headers = g_list_prepend (headers, buf1);
907     gst_audio_encoder_set_headers (enc, headers);
908 
909     vorbisenc->header_sent = TRUE;
910   }
911 
912   if (!buffer)
913     return gst_vorbis_enc_clear (vorbisenc);
914 
915   gst_buffer_map (buffer, &map, GST_MAP_READ);
916 
917   /* data to encode */
918   size = map.size / (vorbisenc->channels * sizeof (float));
919   ptr = (gfloat *) map.data;
920 
921   /* expose the buffer to submit data */
922   vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
923 
924   /* deinterleave samples, write the buffer data */
925   if (vorbisenc->channels < 2 || vorbisenc->channels > 8) {
926     for (i = 0; i < size; i++) {
927       for (j = 0; j < vorbisenc->channels; j++) {
928         vorbis_buffer[j][i] = *ptr++;
929       }
930     }
931   } else {
932     gint i, j;
933 
934     /* Reorder */
935     for (i = 0; i < size; i++) {
936       for (j = 0; j < vorbisenc->channels; j++) {
937         vorbis_buffer[gst_vorbis_reorder_map[vorbisenc->channels - 1][j]][i] =
938             ptr[j];
939       }
940       ptr += vorbisenc->channels;
941     }
942   }
943 
944   /* tell the library how much we actually submitted */
945   vorbis_analysis_wrote (&vorbisenc->vd, size);
946   gst_buffer_unmap (buffer, &map);
947 
948   GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
949 
950   ret = gst_vorbis_enc_output_buffers (vorbisenc);
951 
952   return ret;
953 }
954 
955 static GstFlowReturn
gst_vorbis_enc_output_buffers(GstVorbisEnc * vorbisenc)956 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
957 {
958   GstFlowReturn ret;
959   gint64 duration;
960 
961   /* vorbis does some data preanalysis, then divides up blocks for
962      more involved (potentially parallel) processing.  Get a single
963      block for encoding now */
964   while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
965     ogg_packet op;
966 
967     GST_LOG_OBJECT (vorbisenc, "analysed to a block");
968 
969     /* analysis */
970     vorbis_analysis (&vorbisenc->vb, NULL);
971     vorbis_bitrate_addblock (&vorbisenc->vb);
972 
973     while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
974       GstBuffer *buf;
975 
976       GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
977       buf =
978           gst_audio_encoder_allocate_output_buffer (GST_AUDIO_ENCODER
979           (vorbisenc), op.bytes);
980       gst_buffer_fill (buf, 0, op.packet, op.bytes);
981 
982       /* we have to call this every packet, not just on e_o_s, since
983          each packet's duration depends on the previous one's */
984       duration = packet_duration_vorbis (vorbisenc, &op);
985       if (op.e_o_s) {
986         gint64 samples = op.granulepos - vorbisenc->samples_out;
987         if (samples < duration) {
988           gint64 trim_end = duration - samples;
989           GST_DEBUG_OBJECT (vorbisenc,
990               "Adding trim-end %" G_GUINT64_FORMAT, trim_end);
991           gst_buffer_add_audio_clipping_meta (buf, GST_FORMAT_DEFAULT, 0,
992               trim_end);
993         }
994       }
995       /* tracking granulepos should tell us samples accounted for */
996       ret =
997           gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER
998           (vorbisenc), buf, op.granulepos - vorbisenc->samples_out);
999       vorbisenc->samples_out = op.granulepos;
1000 
1001       if (ret != GST_FLOW_OK)
1002         return ret;
1003     }
1004   }
1005 
1006   return GST_FLOW_OK;
1007 }
1008 
1009 static void
gst_vorbis_enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1010 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
1011     GParamSpec * pspec)
1012 {
1013   GstVorbisEnc *vorbisenc;
1014 
1015   g_return_if_fail (GST_IS_VORBISENC (object));
1016 
1017   vorbisenc = GST_VORBISENC (object);
1018 
1019   switch (prop_id) {
1020     case ARG_MAX_BITRATE:
1021       g_value_set_int (value, vorbisenc->max_bitrate);
1022       break;
1023     case ARG_BITRATE:
1024       g_value_set_int (value, vorbisenc->bitrate);
1025       break;
1026     case ARG_MIN_BITRATE:
1027       g_value_set_int (value, vorbisenc->min_bitrate);
1028       break;
1029     case ARG_QUALITY:
1030       g_value_set_float (value, vorbisenc->quality);
1031       break;
1032     case ARG_MANAGED:
1033       g_value_set_boolean (value, vorbisenc->managed);
1034       break;
1035     case ARG_LAST_MESSAGE:
1036       g_value_set_string (value, vorbisenc->last_message);
1037       break;
1038     default:
1039       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1040       break;
1041   }
1042 }
1043 
1044 static void
gst_vorbis_enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1045 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
1046     const GValue * value, GParamSpec * pspec)
1047 {
1048   GstVorbisEnc *vorbisenc;
1049 
1050   g_return_if_fail (GST_IS_VORBISENC (object));
1051 
1052   vorbisenc = GST_VORBISENC (object);
1053 
1054   switch (prop_id) {
1055     case ARG_MAX_BITRATE:
1056     {
1057       gboolean old_value = vorbisenc->managed;
1058 
1059       vorbisenc->max_bitrate = g_value_get_int (value);
1060       if (vorbisenc->max_bitrate >= 0
1061           && vorbisenc->max_bitrate < LOWEST_BITRATE) {
1062         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1063         vorbisenc->max_bitrate = LOWEST_BITRATE;
1064       }
1065       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1066         vorbisenc->managed = TRUE;
1067       else
1068         vorbisenc->managed = FALSE;
1069 
1070       if (old_value != vorbisenc->managed)
1071         g_object_notify (object, "managed");
1072       break;
1073     }
1074     case ARG_BITRATE:
1075       vorbisenc->bitrate = g_value_get_int (value);
1076       if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
1077         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1078         vorbisenc->bitrate = LOWEST_BITRATE;
1079       }
1080       break;
1081     case ARG_MIN_BITRATE:
1082     {
1083       gboolean old_value = vorbisenc->managed;
1084 
1085       vorbisenc->min_bitrate = g_value_get_int (value);
1086       if (vorbisenc->min_bitrate >= 0
1087           && vorbisenc->min_bitrate < LOWEST_BITRATE) {
1088         g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1089         vorbisenc->min_bitrate = LOWEST_BITRATE;
1090       }
1091       if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1092         vorbisenc->managed = TRUE;
1093       else
1094         vorbisenc->managed = FALSE;
1095 
1096       if (old_value != vorbisenc->managed)
1097         g_object_notify (object, "managed");
1098       break;
1099     }
1100     case ARG_QUALITY:
1101       vorbisenc->quality = g_value_get_float (value);
1102       if (vorbisenc->quality >= 0.0)
1103         vorbisenc->quality_set = TRUE;
1104       else
1105         vorbisenc->quality_set = FALSE;
1106       break;
1107     case ARG_MANAGED:
1108       vorbisenc->managed = g_value_get_boolean (value);
1109       break;
1110     default:
1111       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1112       break;
1113   }
1114 }
1115