2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
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.
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.
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.
21 * SECTION:element-vorbisenc
22 * @see_also: vorbisdec, oggmux
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
30 * <title>Example pipelines</title>
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.
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.
47 #include <vorbis/vorbisenc.h>
49 #include <gst/gsttagsetter.h>
50 #include <gst/tag/tag.h>
51 #include <gst/audio/audio.h>
52 #include "gstvorbisenc.h"
54 #include "gstvorbiscommon.h"
56 GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
57 #define GST_CAT_DEFAULT vorbisenc_debug
59 static GstStaticPadTemplate vorbis_enc_sink_factory =
60 GST_STATIC_PAD_TEMPLATE ("sink",
63 GST_STATIC_CAPS ("audio/x-raw, "
64 "format = (string) " GST_AUDIO_NE (F32) ", "
65 "layout = (string) interleaved, "
66 "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
69 static GstStaticPadTemplate vorbis_enc_src_factory =
70 GST_STATIC_PAD_TEMPLATE ("src",
73 GST_STATIC_CAPS ("audio/x-vorbis, "
74 "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
88 static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
91 #define MAX_BITRATE_DEFAULT -1
92 #define BITRATE_DEFAULT -1
93 #define MIN_BITRATE_DEFAULT -1
94 #define QUALITY_DEFAULT 0.3
95 #define LOWEST_BITRATE 6000 /* lowest allowed for a 8 kHz stream */
96 #define HIGHEST_BITRATE 250001 /* highest allowed for a 44 kHz stream */
98 static gboolean gst_vorbis_enc_start (GstAudioEncoder * enc);
99 static gboolean gst_vorbis_enc_stop (GstAudioEncoder * enc);
100 static gboolean gst_vorbis_enc_set_format (GstAudioEncoder * enc,
101 GstAudioInfo * info);
102 static GstFlowReturn gst_vorbis_enc_handle_frame (GstAudioEncoder * enc,
104 static GstCaps *gst_vorbis_enc_getcaps (GstAudioEncoder * enc,
106 static gboolean gst_vorbis_enc_sink_event (GstAudioEncoder * enc,
109 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
111 static void gst_vorbis_enc_dispose (GObject * object);
112 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
113 GValue * value, GParamSpec * pspec);
114 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
115 const GValue * value, GParamSpec * pspec);
116 static void gst_vorbis_enc_flush (GstAudioEncoder * vorbisenc);
118 #define gst_vorbis_enc_parent_class parent_class
119 G_DEFINE_TYPE_WITH_CODE (GstVorbisEnc, gst_vorbis_enc,
120 GST_TYPE_AUDIO_ENCODER, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
123 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
125 GObjectClass *gobject_class;
126 GstElementClass *gstelement_class;
127 GstAudioEncoderClass *base_class;
129 gobject_class = (GObjectClass *) klass;
130 gstelement_class = (GstElementClass *) klass;
131 base_class = (GstAudioEncoderClass *) (klass);
133 gobject_class->set_property = gst_vorbis_enc_set_property;
134 gobject_class->get_property = gst_vorbis_enc_get_property;
135 gobject_class->dispose = gst_vorbis_enc_dispose;
137 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
138 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
139 "Specify a maximum bitrate (in bps). Useful for streaming "
140 "applications. (-1 == disabled)",
141 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
142 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
143 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
144 g_param_spec_int ("bitrate", "Target Bitrate",
145 "Attempt to encode at a bitrate averaging this (in bps). "
146 "This uses the bitrate management engine, and is not recommended for most users. "
147 "Quality is a better alternative. (-1 == disabled)", -1,
148 HIGHEST_BITRATE, BITRATE_DEFAULT,
149 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
150 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
151 g_param_spec_int ("min-bitrate", "Minimum Bitrate",
152 "Specify a minimum bitrate (in bps). Useful for encoding for a "
153 "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
154 MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
155 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
156 g_param_spec_float ("quality", "Quality",
157 "Specify quality instead of specifying a particular bitrate.", -0.1,
158 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
159 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
160 g_param_spec_boolean ("managed", "Managed",
161 "Enable bitrate management engine", FALSE,
162 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
163 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
164 g_param_spec_string ("last-message", "last-message",
165 "The last status message", NULL,
166 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
168 gst_element_class_add_pad_template (gstelement_class,
169 gst_static_pad_template_get (&vorbis_enc_src_factory));
170 gst_element_class_add_pad_template (gstelement_class,
171 gst_static_pad_template_get (&vorbis_enc_sink_factory));
173 gst_element_class_set_static_metadata (gstelement_class,
174 "Vorbis audio encoder", "Codec/Encoder/Audio",
175 "Encodes audio in Vorbis format",
176 "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
178 base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
179 base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
180 base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
181 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
182 base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
183 base_class->sink_event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
184 base_class->flush = GST_DEBUG_FUNCPTR (gst_vorbis_enc_flush);
188 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc)
190 GstAudioEncoder *enc = GST_AUDIO_ENCODER (vorbisenc);
192 vorbisenc->channels = -1;
193 vorbisenc->frequency = -1;
195 vorbisenc->managed = FALSE;
196 vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
197 vorbisenc->bitrate = BITRATE_DEFAULT;
198 vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
199 vorbisenc->quality = QUALITY_DEFAULT;
200 vorbisenc->quality_set = FALSE;
201 vorbisenc->last_message = NULL;
203 /* arrange granulepos marking (and required perfect ts) */
204 gst_audio_encoder_set_mark_granule (enc, TRUE);
205 gst_audio_encoder_set_perfect_timestamp (enc, TRUE);
209 gst_vorbis_enc_dispose (GObject * object)
211 GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
213 if (vorbisenc->sinkcaps) {
214 gst_caps_unref (vorbisenc->sinkcaps);
215 vorbisenc->sinkcaps = NULL;
218 G_OBJECT_CLASS (parent_class)->dispose (object);
222 gst_vorbis_enc_start (GstAudioEncoder * enc)
224 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
226 GST_DEBUG_OBJECT (enc, "start");
227 vorbisenc->tags = gst_tag_list_new_empty ();
228 vorbisenc->header_sent = FALSE;
234 gst_vorbis_enc_stop (GstAudioEncoder * enc)
236 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
238 GST_DEBUG_OBJECT (enc, "stop");
239 vorbis_block_clear (&vorbisenc->vb);
240 vorbis_dsp_clear (&vorbisenc->vd);
241 vorbis_info_clear (&vorbisenc->vi);
242 g_free (vorbisenc->last_message);
243 vorbisenc->last_message = NULL;
244 gst_tag_list_unref (vorbisenc->tags);
245 vorbisenc->tags = NULL;
247 gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
253 gst_vorbis_enc_generate_sink_caps (void)
255 GstCaps *caps = gst_caps_new_empty ();
258 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
259 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
260 "layout", G_TYPE_STRING, "interleaved",
261 "rate", GST_TYPE_INT_RANGE, 1, 200000,
262 "channels", G_TYPE_INT, 1, NULL));
264 for (i = 2; i <= 8; i++) {
265 GstStructure *structure;
266 guint64 channel_mask = 0;
267 const GstAudioChannelPosition *pos = gst_vorbis_channel_positions[i - 1];
269 for (c = 0; c < i; c++) {
270 channel_mask |= G_GUINT64_CONSTANT (1) << pos[c];
273 structure = gst_structure_new ("audio/x-raw",
274 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
275 "layout", G_TYPE_STRING, "interleaved",
276 "rate", GST_TYPE_INT_RANGE, 1, 200000, "channels", G_TYPE_INT, i,
277 "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL);
279 gst_caps_append_structure (caps, structure);
282 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
283 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
284 "layout", G_TYPE_STRING, "interleaved",
285 "rate", GST_TYPE_INT_RANGE, 1, 200000,
286 "channels", GST_TYPE_INT_RANGE, 9, 255,
287 "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL));
293 gst_vorbis_enc_getcaps (GstAudioEncoder * enc, GstCaps * filter)
295 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
298 if (vorbisenc->sinkcaps == NULL)
299 vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
302 GstCaps *int_caps = gst_caps_intersect_full (filter, vorbisenc->sinkcaps,
303 GST_CAPS_INTERSECT_FIRST);
304 caps = gst_audio_encoder_proxy_getcaps (enc, int_caps, filter);
305 gst_caps_unref (int_caps);
307 caps = gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps, filter);
314 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
316 /* FIXME, this probably depends on the bitrate and other setting but for now
317 * we return this value, which was obtained by totally unscientific
319 return 58 * GST_MSECOND;
323 gst_vorbis_enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
325 GstVorbisEnc *vorbisenc;
327 vorbisenc = GST_VORBISENC (enc);
329 vorbisenc->channels = GST_AUDIO_INFO_CHANNELS (info);
330 vorbisenc->frequency = GST_AUDIO_INFO_RATE (info);
332 /* if re-configured, we were drained and cleared already */
333 if (!gst_vorbis_enc_setup (vorbisenc))
336 /* feedback to base class */
337 gst_audio_encoder_set_latency (enc,
338 gst_vorbis_enc_get_latency (vorbisenc),
339 gst_vorbis_enc_get_latency (vorbisenc));
345 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
348 GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
351 vc_list = gst_tag_to_vorbis_comments (list, tag);
353 for (l = vc_list; l != NULL; l = l->next) {
354 const gchar *vc_string = (const gchar *) l->data;
355 gchar *key = NULL, *val = NULL;
357 GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
358 if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
359 vorbis_comment_add_tag (&enc->vc, key, val);
365 g_list_foreach (vc_list, (GFunc) g_free, NULL);
366 g_list_free (vc_list);
370 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
372 GstTagList *merged_tags;
373 const GstTagList *user_tags;
375 vorbis_comment_init (&enc->vc);
377 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
379 GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
380 GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
382 /* gst_tag_list_merge() will handle NULL for either or both lists fine */
383 merged_tags = gst_tag_list_merge (user_tags, enc->tags,
384 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
387 GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
388 gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
389 gst_tag_list_unref (merged_tags);
394 get_constraints_string (GstVorbisEnc * vorbisenc)
396 gint min = vorbisenc->min_bitrate;
397 gint max = vorbisenc->max_bitrate;
400 if (min > 0 && max > 0)
401 result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
403 result = g_strdup_printf ("(min %d bps, no max)", min);
405 result = g_strdup_printf ("(no min, max %d bps)", max);
407 result = g_strdup_printf ("(no min or max)");
413 update_start_message (GstVorbisEnc * vorbisenc)
417 g_free (vorbisenc->last_message);
419 if (vorbisenc->bitrate > 0) {
420 if (vorbisenc->managed) {
421 constraints = get_constraints_string (vorbisenc);
422 vorbisenc->last_message =
423 g_strdup_printf ("encoding at average bitrate %d bps %s",
424 vorbisenc->bitrate, constraints);
425 g_free (constraints);
427 vorbisenc->last_message =
429 ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
433 if (vorbisenc->quality_set) {
434 if (vorbisenc->managed) {
435 constraints = get_constraints_string (vorbisenc);
436 vorbisenc->last_message =
438 ("encoding at quality level %2.2f using constrained VBR %s",
439 vorbisenc->quality, constraints);
440 g_free (constraints);
442 vorbisenc->last_message =
443 g_strdup_printf ("encoding at quality level %2.2f",
447 constraints = get_constraints_string (vorbisenc);
448 vorbisenc->last_message =
449 g_strdup_printf ("encoding using bitrate management %s", constraints);
450 g_free (constraints);
454 g_object_notify (G_OBJECT (vorbisenc), "last_message");
458 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
461 GST_LOG_OBJECT (vorbisenc, "setup");
463 if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
464 && vorbisenc->max_bitrate < 0) {
465 vorbisenc->quality_set = TRUE;
468 update_start_message (vorbisenc);
470 /* choose an encoding mode */
471 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
472 vorbis_info_init (&vorbisenc->vi);
474 if (vorbisenc->quality_set) {
475 if (vorbis_encode_setup_vbr (&vorbisenc->vi,
476 vorbisenc->channels, vorbisenc->frequency,
477 vorbisenc->quality) != 0) {
478 GST_ERROR_OBJECT (vorbisenc,
479 "vorbisenc: initialisation failed: invalid parameters for quality");
480 vorbis_info_clear (&vorbisenc->vi);
484 /* do we have optional hard quality restrictions? */
485 if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
486 struct ovectl_ratemanage_arg ai;
488 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
490 ai.bitrate_hard_min = vorbisenc->min_bitrate;
491 ai.bitrate_hard_max = vorbisenc->max_bitrate;
492 ai.management_active = 1;
494 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
497 long min_bitrate, max_bitrate;
499 min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
500 max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
502 if (vorbis_encode_setup_managed (&vorbisenc->vi,
504 vorbisenc->frequency,
505 max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
506 GST_ERROR_OBJECT (vorbisenc,
507 "vorbis_encode_setup_managed "
508 "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
509 vorbisenc->channels, vorbisenc->frequency, max_bitrate,
510 vorbisenc->bitrate, min_bitrate);
511 vorbis_info_clear (&vorbisenc->vi);
516 if (vorbisenc->managed && vorbisenc->bitrate < 0) {
517 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
518 } else if (!vorbisenc->managed) {
519 /* Turn off management entirely (if it was turned on). */
520 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
522 vorbis_encode_setup_init (&vorbisenc->vi);
524 /* set up the analysis state and auxiliary encoding storage */
525 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
526 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
528 /* samples == granulepos start at 0 again */
529 vorbisenc->samples_out = 0;
531 /* fresh encoder available */
532 vorbisenc->setup = TRUE;
538 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
540 GstFlowReturn ret = GST_FLOW_OK;
542 if (vorbisenc->setup) {
543 vorbis_analysis_wrote (&vorbisenc->vd, 0);
544 ret = gst_vorbis_enc_output_buffers (vorbisenc);
546 /* marked EOS to encoder, recreate if needed */
547 vorbisenc->setup = FALSE;
550 /* clean up and exit. vorbis_info_clear() must be called last */
551 vorbis_block_clear (&vorbisenc->vb);
552 vorbis_dsp_clear (&vorbisenc->vd);
553 vorbis_info_clear (&vorbisenc->vi);
559 gst_vorbis_enc_flush (GstAudioEncoder * enc)
561 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
563 gst_vorbis_enc_clear (vorbisenc);
564 vorbisenc->header_sent = FALSE;
568 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
574 gst_audio_encoder_allocate_output_buffer (GST_AUDIO_ENCODER (vorbisenc),
576 gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
577 GST_BUFFER_OFFSET (outbuf) = 0;
578 GST_BUFFER_OFFSET_END (outbuf) = 0;
579 GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
580 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
581 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_HEADER);
583 GST_DEBUG ("created header packet buffer, %" G_GSIZE_FORMAT " bytes",
584 gst_buffer_get_size (outbuf));
589 gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event)
591 GstVorbisEnc *vorbisenc;
593 vorbisenc = GST_VORBISENC (enc);
595 switch (GST_EVENT_TYPE (event)) {
597 if (vorbisenc->tags) {
600 gst_event_parse_tag (event, &list);
601 gst_tag_list_insert (vorbisenc->tags, list,
602 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
604 g_assert_not_reached ();
612 /* we only peeked, let base class handle it */
613 return GST_AUDIO_ENCODER_CLASS (parent_class)->sink_event (enc, event);
617 * (really really) FIXME: move into core (dixit tpm)
620 * _gst_caps_set_buffer_array:
622 * @field: field in caps to set
623 * @buf: header buffers
625 * Adds given buffers to an array of buffers set as the given @field
626 * on the given @caps. List of buffer arguments must be NULL-terminated.
628 * Returns: input caps with a streamheader field added, or NULL if some error
631 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
632 GstBuffer * buf, ...)
634 GstStructure *structure = NULL;
636 GValue array = { 0 };
637 GValue value = { 0 };
639 g_return_val_if_fail (caps != NULL, NULL);
640 g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
641 g_return_val_if_fail (field != NULL, NULL);
643 caps = gst_caps_make_writable (caps);
644 structure = gst_caps_get_structure (caps, 0);
646 g_value_init (&array, GST_TYPE_ARRAY);
649 /* put buffers in a fixed list */
651 g_value_init (&value, GST_TYPE_BUFFER);
652 gst_value_set_buffer (&value, buf);
653 gst_value_array_append_value (&array, &value);
654 g_value_unset (&value);
656 buf = va_arg (va, GstBuffer *);
659 gst_structure_take_value (structure, field, &array);
665 gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
667 GstVorbisEnc *vorbisenc;
668 GstFlowReturn ret = GST_FLOW_OK;
673 float **vorbis_buffer;
674 GstBuffer *buf1, *buf2, *buf3;
676 vorbisenc = GST_VORBISENC (enc);
678 if (G_UNLIKELY (!vorbisenc->setup)) {
680 GST_DEBUG_OBJECT (vorbisenc, "forcing setup");
681 /* should not fail, as setup before same way */
682 if (!gst_vorbis_enc_setup (vorbisenc))
683 return GST_FLOW_ERROR;
686 GST_LOG_OBJECT (vorbisenc, "already drained");
691 if (!vorbisenc->header_sent) {
692 /* Vorbis streams begin with three headers; the initial header (with
693 most of the codec setup parameters) which is mandated by the Ogg
694 bitstream spec. The second header holds any comment fields. The
695 third header holds the bitstream codebook. We merely need to
696 make the headers, then pass them to libvorbis one at a time;
697 libvorbis handles the additional Ogg bitstream constraints */
699 ogg_packet header_comm;
700 ogg_packet header_code;
704 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
705 gst_vorbis_enc_set_metadata (vorbisenc);
706 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
707 &header_comm, &header_code);
708 vorbis_comment_clear (&vorbisenc->vc);
710 /* create header buffers */
711 buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
712 buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
713 buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
715 /* mark and put on caps */
716 caps = gst_caps_new_simple ("audio/x-vorbis",
717 "rate", G_TYPE_INT, vorbisenc->frequency,
718 "channels", G_TYPE_INT, vorbisenc->channels, NULL);
719 caps = _gst_caps_set_buffer_array (caps, "streamheader",
720 buf1, buf2, buf3, NULL);
722 /* negotiate with these caps */
723 GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
724 gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (vorbisenc), caps);
725 gst_caps_unref (caps);
727 /* store buffers for later pre_push sending */
729 GST_DEBUG_OBJECT (vorbisenc, "storing header buffers");
730 headers = g_list_prepend (headers, buf3);
731 headers = g_list_prepend (headers, buf2);
732 headers = g_list_prepend (headers, buf1);
733 gst_audio_encoder_set_headers (enc, headers);
735 vorbisenc->header_sent = TRUE;
739 return gst_vorbis_enc_clear (vorbisenc);
741 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
744 size = map.size / (vorbisenc->channels * sizeof (float));
745 ptr = (gfloat *) map.data;
747 /* expose the buffer to submit data */
748 vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
750 /* deinterleave samples, write the buffer data */
751 if (vorbisenc->channels < 2 || vorbisenc->channels > 8) {
752 for (i = 0; i < size; i++) {
753 for (j = 0; j < vorbisenc->channels; j++) {
754 vorbis_buffer[j][i] = *ptr++;
761 for (i = 0; i < size; i++) {
762 for (j = 0; j < vorbisenc->channels; j++) {
763 vorbis_buffer[gst_vorbis_reorder_map[vorbisenc->channels - 1][j]][i] =
766 ptr += vorbisenc->channels;
770 /* tell the library how much we actually submitted */
771 vorbis_analysis_wrote (&vorbisenc->vd, size);
772 gst_buffer_unmap (buffer, &map);
774 GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
776 ret = gst_vorbis_enc_output_buffers (vorbisenc);
782 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
786 /* vorbis does some data preanalysis, then divides up blocks for
787 more involved (potentially parallel) processing. Get a single
788 block for encoding now */
789 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
792 GST_LOG_OBJECT (vorbisenc, "analysed to a block");
795 vorbis_analysis (&vorbisenc->vb, NULL);
796 vorbis_bitrate_addblock (&vorbisenc->vb);
798 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
801 GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
803 gst_audio_encoder_allocate_output_buffer (GST_AUDIO_ENCODER
804 (vorbisenc), op.bytes);
805 gst_buffer_fill (buf, 0, op.packet, op.bytes);
806 /* tracking granulepos should tell us samples accounted for */
808 gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER
809 (vorbisenc), buf, op.granulepos - vorbisenc->samples_out);
810 vorbisenc->samples_out = op.granulepos;
812 if (ret != GST_FLOW_OK)
821 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
824 GstVorbisEnc *vorbisenc;
826 g_return_if_fail (GST_IS_VORBISENC (object));
828 vorbisenc = GST_VORBISENC (object);
831 case ARG_MAX_BITRATE:
832 g_value_set_int (value, vorbisenc->max_bitrate);
835 g_value_set_int (value, vorbisenc->bitrate);
837 case ARG_MIN_BITRATE:
838 g_value_set_int (value, vorbisenc->min_bitrate);
841 g_value_set_float (value, vorbisenc->quality);
844 g_value_set_boolean (value, vorbisenc->managed);
846 case ARG_LAST_MESSAGE:
847 g_value_set_string (value, vorbisenc->last_message);
850 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
856 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
857 const GValue * value, GParamSpec * pspec)
859 GstVorbisEnc *vorbisenc;
861 g_return_if_fail (GST_IS_VORBISENC (object));
863 vorbisenc = GST_VORBISENC (object);
866 case ARG_MAX_BITRATE:
868 gboolean old_value = vorbisenc->managed;
870 vorbisenc->max_bitrate = g_value_get_int (value);
871 if (vorbisenc->max_bitrate >= 0
872 && vorbisenc->max_bitrate < LOWEST_BITRATE) {
873 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
874 vorbisenc->max_bitrate = LOWEST_BITRATE;
876 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
877 vorbisenc->managed = TRUE;
879 vorbisenc->managed = FALSE;
881 if (old_value != vorbisenc->managed)
882 g_object_notify (object, "managed");
886 vorbisenc->bitrate = g_value_get_int (value);
887 if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
888 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
889 vorbisenc->bitrate = LOWEST_BITRATE;
892 case ARG_MIN_BITRATE:
894 gboolean old_value = vorbisenc->managed;
896 vorbisenc->min_bitrate = g_value_get_int (value);
897 if (vorbisenc->min_bitrate >= 0
898 && vorbisenc->min_bitrate < LOWEST_BITRATE) {
899 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
900 vorbisenc->min_bitrate = LOWEST_BITRATE;
902 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
903 vorbisenc->managed = TRUE;
905 vorbisenc->managed = FALSE;
907 if (old_value != vorbisenc->managed)
908 g_object_notify (object, "managed");
912 vorbisenc->quality = g_value_get_float (value);
913 if (vorbisenc->quality >= 0.0)
914 vorbisenc->quality_set = TRUE;
916 vorbisenc->quality_set = FALSE;
919 vorbisenc->managed = g_value_get_boolean (value);
922 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);