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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, 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.
40 * Last reviewed on 2006-03-01 (0.10.4)
49 #include <vorbis/vorbisenc.h>
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"
57 #include "gstvorbiscommon.h"
59 GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
60 #define GST_CAT_DEFAULT vorbisenc_debug
62 static GstStaticPadTemplate vorbis_enc_sink_factory =
63 GST_STATIC_PAD_TEMPLATE ("sink",
66 GST_STATIC_CAPS ("audio/x-raw-float, "
67 "rate = (int) [ 1, 200000 ], "
68 "channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, "
72 static GstStaticPadTemplate vorbis_enc_src_factory =
73 GST_STATIC_PAD_TEMPLATE ("src",
76 GST_STATIC_CAPS ("audio/x-vorbis")
90 static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
93 #define MAX_BITRATE_DEFAULT -1
94 #define BITRATE_DEFAULT -1
95 #define MIN_BITRATE_DEFAULT -1
96 #define QUALITY_DEFAULT 0.3
97 #define LOWEST_BITRATE 6000 /* lowest allowed for a 8 kHz stream */
98 #define HIGHEST_BITRATE 250001 /* highest allowed for a 44 kHz stream */
100 static gboolean gst_vorbis_enc_start (GstAudioEncoder * enc);
101 static gboolean gst_vorbis_enc_stop (GstAudioEncoder * enc);
102 static gboolean gst_vorbis_enc_set_format (GstAudioEncoder * enc,
103 GstAudioInfo * info);
104 static GstFlowReturn gst_vorbis_enc_handle_frame (GstAudioEncoder * enc,
106 static GstCaps *gst_vorbis_enc_getcaps (GstAudioEncoder * enc);
107 static gboolean gst_vorbis_enc_sink_event (GstAudioEncoder * enc,
110 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
112 static void gst_vorbis_enc_dispose (GObject * object);
113 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
114 GValue * value, GParamSpec * pspec);
115 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
116 const GValue * value, GParamSpec * pspec);
117 static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
119 GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstAudioEncoder,
120 GST_TYPE_AUDIO_ENCODER, gst_vorbis_enc_add_interfaces);
123 gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
125 static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
127 g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
132 gst_vorbis_enc_base_init (gpointer g_class)
134 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
136 gst_element_class_add_pad_template (element_class,
137 gst_static_pad_template_get (&vorbis_enc_src_factory));
138 gst_element_class_add_pad_template (element_class,
139 gst_static_pad_template_get (&vorbis_enc_sink_factory));
141 gst_element_class_set_details_simple (element_class,
142 "Vorbis audio encoder", "Codec/Encoder/Audio",
143 "Encodes audio in Vorbis format",
144 "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
148 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
150 GObjectClass *gobject_class;
151 GstAudioEncoderClass *base_class;
153 gobject_class = (GObjectClass *) klass;
154 base_class = (GstAudioEncoderClass *) (klass);
156 gobject_class->set_property = gst_vorbis_enc_set_property;
157 gobject_class->get_property = gst_vorbis_enc_get_property;
158 gobject_class->dispose = gst_vorbis_enc_dispose;
160 base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
161 base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
162 base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
163 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
164 base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
165 base_class->event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
167 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
168 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
169 "Specify a maximum bitrate (in bps). Useful for streaming "
170 "applications. (-1 == disabled)",
171 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
172 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
173 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
174 g_param_spec_int ("bitrate", "Target Bitrate",
175 "Attempt to encode at a bitrate averaging this (in bps). "
176 "This uses the bitrate management engine, and is not recommended for most users. "
177 "Quality is a better alternative. (-1 == disabled)", -1,
178 HIGHEST_BITRATE, BITRATE_DEFAULT,
179 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
180 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
181 g_param_spec_int ("min-bitrate", "Minimum Bitrate",
182 "Specify a minimum bitrate (in bps). Useful for encoding for a "
183 "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
184 MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
185 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
186 g_param_spec_float ("quality", "Quality",
187 "Specify quality instead of specifying a particular bitrate.", -0.1,
188 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
189 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
190 g_param_spec_boolean ("managed", "Managed",
191 "Enable bitrate management engine", FALSE,
192 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
193 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
194 g_param_spec_string ("last-message", "last-message",
195 "The last status message", NULL,
196 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
200 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
202 GstAudioEncoder *enc = GST_AUDIO_ENCODER (vorbisenc);
204 vorbisenc->channels = -1;
205 vorbisenc->frequency = -1;
207 vorbisenc->managed = FALSE;
208 vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
209 vorbisenc->bitrate = BITRATE_DEFAULT;
210 vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
211 vorbisenc->quality = QUALITY_DEFAULT;
212 vorbisenc->quality_set = FALSE;
213 vorbisenc->last_message = NULL;
215 /* arrange granulepos marking (and required perfect ts) */
216 gst_audio_encoder_set_mark_granule (enc, TRUE);
217 gst_audio_encoder_set_perfect_timestamp (enc, TRUE);
221 gst_vorbis_enc_dispose (GObject * object)
223 GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
225 if (vorbisenc->sinkcaps) {
226 gst_caps_unref (vorbisenc->sinkcaps);
227 vorbisenc->sinkcaps = NULL;
230 G_OBJECT_CLASS (parent_class)->dispose (object);
234 gst_vorbis_enc_start (GstAudioEncoder * enc)
236 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
238 GST_DEBUG_OBJECT (enc, "start");
239 vorbisenc->tags = gst_tag_list_new ();
240 vorbisenc->header_sent = FALSE;
246 gst_vorbis_enc_stop (GstAudioEncoder * enc)
248 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
250 GST_DEBUG_OBJECT (enc, "stop");
251 vorbis_block_clear (&vorbisenc->vb);
252 vorbis_dsp_clear (&vorbisenc->vd);
253 vorbis_info_clear (&vorbisenc->vi);
254 g_free (vorbisenc->last_message);
255 vorbisenc->last_message = NULL;
256 gst_tag_list_free (vorbisenc->tags);
257 vorbisenc->tags = NULL;
263 gst_vorbis_enc_generate_sink_caps (void)
265 GstCaps *caps = gst_caps_new_empty ();
268 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
269 "rate", GST_TYPE_INT_RANGE, 1, 200000,
270 "channels", G_TYPE_INT, 1,
271 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
274 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
275 "rate", GST_TYPE_INT_RANGE, 1, 200000,
276 "channels", G_TYPE_INT, 2,
277 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
280 for (i = 3; i <= 8; i++) {
281 GValue chanpos = { 0 };
283 GstStructure *structure;
285 g_value_init (&chanpos, GST_TYPE_ARRAY);
286 g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
288 for (c = 0; c < i; c++) {
289 g_value_set_enum (&pos, gst_vorbis_channel_positions[i - 1][c]);
290 gst_value_array_append_value (&chanpos, &pos);
292 g_value_unset (&pos);
294 structure = gst_structure_new ("audio/x-raw-float",
295 "rate", GST_TYPE_INT_RANGE, 1, 200000,
296 "channels", G_TYPE_INT, i,
297 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
298 gst_structure_set_value (structure, "channel-positions", &chanpos);
299 g_value_unset (&chanpos);
301 gst_caps_append_structure (caps, structure);
304 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
305 "rate", GST_TYPE_INT_RANGE, 1, 200000,
306 "channels", GST_TYPE_INT_RANGE, 9, 256,
307 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
314 gst_vorbis_enc_getcaps (GstAudioEncoder * enc)
316 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
318 if (vorbisenc->sinkcaps == NULL)
319 vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
321 return gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps);
325 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
327 /* FIXME, this probably depends on the bitrate and other setting but for now
328 * we return this value, which was obtained by totally unscientific
330 return 58 * GST_MSECOND;
334 gst_vorbis_enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
336 GstVorbisEnc *vorbisenc;
338 vorbisenc = GST_VORBISENC (enc);
340 vorbisenc->channels = GST_AUDIO_INFO_CHANNELS (info);
341 vorbisenc->frequency = GST_AUDIO_INFO_RATE (info);
343 /* if re-configured, we were drained and cleared already */
344 if (!gst_vorbis_enc_setup (vorbisenc))
347 /* feedback to base class */
348 gst_audio_encoder_set_latency (enc,
349 gst_vorbis_enc_get_latency (vorbisenc),
350 gst_vorbis_enc_get_latency (vorbisenc));
356 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
359 GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
362 vc_list = gst_tag_to_vorbis_comments (list, tag);
364 for (l = vc_list; l != NULL; l = l->next) {
365 const gchar *vc_string = (const gchar *) l->data;
366 gchar *key = NULL, *val = NULL;
368 GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
369 if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
370 vorbis_comment_add_tag (&enc->vc, key, val);
376 g_list_foreach (vc_list, (GFunc) g_free, NULL);
377 g_list_free (vc_list);
381 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
383 GstTagList *merged_tags;
384 const GstTagList *user_tags;
386 vorbis_comment_init (&enc->vc);
388 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
390 GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
391 GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
393 /* gst_tag_list_merge() will handle NULL for either or both lists fine */
394 merged_tags = gst_tag_list_merge (user_tags, enc->tags,
395 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
398 GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
399 gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
400 gst_tag_list_free (merged_tags);
405 get_constraints_string (GstVorbisEnc * vorbisenc)
407 gint min = vorbisenc->min_bitrate;
408 gint max = vorbisenc->max_bitrate;
411 if (min > 0 && max > 0)
412 result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
414 result = g_strdup_printf ("(min %d bps, no max)", min);
416 result = g_strdup_printf ("(no min, max %d bps)", max);
418 result = g_strdup_printf ("(no min or max)");
424 update_start_message (GstVorbisEnc * vorbisenc)
428 g_free (vorbisenc->last_message);
430 if (vorbisenc->bitrate > 0) {
431 if (vorbisenc->managed) {
432 constraints = get_constraints_string (vorbisenc);
433 vorbisenc->last_message =
434 g_strdup_printf ("encoding at average bitrate %d bps %s",
435 vorbisenc->bitrate, constraints);
436 g_free (constraints);
438 vorbisenc->last_message =
440 ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
444 if (vorbisenc->quality_set) {
445 if (vorbisenc->managed) {
446 constraints = get_constraints_string (vorbisenc);
447 vorbisenc->last_message =
449 ("encoding at quality level %2.2f using constrained VBR %s",
450 vorbisenc->quality, constraints);
451 g_free (constraints);
453 vorbisenc->last_message =
454 g_strdup_printf ("encoding at quality level %2.2f",
458 constraints = get_constraints_string (vorbisenc);
459 vorbisenc->last_message =
460 g_strdup_printf ("encoding using bitrate management %s", constraints);
461 g_free (constraints);
465 g_object_notify (G_OBJECT (vorbisenc), "last_message");
469 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
472 GST_LOG_OBJECT (vorbisenc, "setup");
474 if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
475 && vorbisenc->max_bitrate < 0) {
476 vorbisenc->quality_set = TRUE;
479 update_start_message (vorbisenc);
481 /* choose an encoding mode */
482 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
483 vorbis_info_init (&vorbisenc->vi);
485 if (vorbisenc->quality_set) {
486 if (vorbis_encode_setup_vbr (&vorbisenc->vi,
487 vorbisenc->channels, vorbisenc->frequency,
488 vorbisenc->quality) != 0) {
489 GST_ERROR_OBJECT (vorbisenc,
490 "vorbisenc: initialisation failed: invalid parameters for quality");
491 vorbis_info_clear (&vorbisenc->vi);
495 /* do we have optional hard quality restrictions? */
496 if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
497 struct ovectl_ratemanage_arg ai;
499 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
501 ai.bitrate_hard_min = vorbisenc->min_bitrate;
502 ai.bitrate_hard_max = vorbisenc->max_bitrate;
503 ai.management_active = 1;
505 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
508 long min_bitrate, max_bitrate;
510 min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
511 max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
513 if (vorbis_encode_setup_managed (&vorbisenc->vi,
515 vorbisenc->frequency,
516 max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
517 GST_ERROR_OBJECT (vorbisenc,
518 "vorbis_encode_setup_managed "
519 "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
520 vorbisenc->channels, vorbisenc->frequency, max_bitrate,
521 vorbisenc->bitrate, min_bitrate);
522 vorbis_info_clear (&vorbisenc->vi);
527 if (vorbisenc->managed && vorbisenc->bitrate < 0) {
528 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
529 } else if (!vorbisenc->managed) {
530 /* Turn off management entirely (if it was turned on). */
531 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
533 vorbis_encode_setup_init (&vorbisenc->vi);
535 /* set up the analysis state and auxiliary encoding storage */
536 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
537 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
539 /* samples == granulepos start at 0 again */
540 vorbisenc->samples_out = 0;
542 /* fresh encoder available */
543 vorbisenc->setup = TRUE;
549 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
551 GstFlowReturn ret = GST_FLOW_OK;
553 if (vorbisenc->setup) {
554 vorbis_analysis_wrote (&vorbisenc->vd, 0);
555 ret = gst_vorbis_enc_output_buffers (vorbisenc);
557 /* marked EOS to encoder, recreate if needed */
558 vorbisenc->setup = FALSE;
561 /* clean up and exit. vorbis_info_clear() must be called last */
562 vorbis_block_clear (&vorbisenc->vb);
563 vorbis_dsp_clear (&vorbisenc->vd);
564 vorbis_info_clear (&vorbisenc->vi);
570 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
575 outbuf = gst_buffer_new_and_alloc (packet->bytes);
576 memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
577 GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
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;
582 GST_DEBUG ("created header packet buffer, %d bytes",
583 GST_BUFFER_SIZE (outbuf));
588 gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event)
590 GstVorbisEnc *vorbisenc;
592 vorbisenc = GST_VORBISENC (enc);
594 switch (GST_EVENT_TYPE (event)) {
596 if (vorbisenc->tags) {
599 gst_event_parse_tag (event, &list);
600 gst_tag_list_insert (vorbisenc->tags, list,
601 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
603 g_assert_not_reached ();
611 /* we only peeked, let base class handle it */
615 /* push out the buffer and do internal bookkeeping */
617 gst_vorbis_enc_push_header (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
619 GST_DEBUG_OBJECT (vorbisenc,
620 "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
621 GST_BUFFER_OFFSET_END (buffer),
622 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
623 return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), buffer);
627 * (really really) FIXME: move into core (dixit tpm)
630 * _gst_caps_set_buffer_array:
632 * @field: field in caps to set
633 * @buf: header buffers
635 * Adds given buffers to an array of buffers set as the given @field
636 * on the given @caps. List of buffer arguments must be NULL-terminated.
638 * Returns: input caps with a streamheader field added, or NULL if some error
641 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
642 GstBuffer * buf, ...)
644 GstStructure *structure = NULL;
646 GValue array = { 0 };
647 GValue value = { 0 };
649 g_return_val_if_fail (caps != NULL, NULL);
650 g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
651 g_return_val_if_fail (field != NULL, NULL);
653 caps = gst_caps_make_writable (caps);
654 structure = gst_caps_get_structure (caps, 0);
656 g_value_init (&array, GST_TYPE_ARRAY);
659 /* put buffers in a fixed list */
661 g_assert (gst_buffer_is_metadata_writable (buf));
664 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
666 g_value_init (&value, GST_TYPE_BUFFER);
667 buf = gst_buffer_copy (buf);
668 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
669 gst_value_set_buffer (&value, buf);
670 gst_buffer_unref (buf);
671 gst_value_array_append_value (&array, &value);
672 g_value_unset (&value);
674 buf = va_arg (va, GstBuffer *);
677 gst_structure_set_value (structure, field, &array);
678 g_value_unset (&array);
684 gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
686 GstVorbisEnc *vorbisenc;
687 GstFlowReturn ret = GST_FLOW_OK;
691 float **vorbis_buffer;
692 GstBuffer *buf1, *buf2, *buf3;
694 vorbisenc = GST_VORBISENC (enc);
696 if (G_UNLIKELY (!vorbisenc->setup)) {
698 GST_DEBUG_OBJECT (vorbisenc, "forcing setup");
699 /* should not fail, as setup before same way */
700 if (!gst_vorbis_enc_setup (vorbisenc))
701 return GST_FLOW_ERROR;
704 GST_LOG_OBJECT (vorbisenc, "already drained");
709 if (!vorbisenc->header_sent) {
710 /* Vorbis streams begin with three headers; the initial header (with
711 most of the codec setup parameters) which is mandated by the Ogg
712 bitstream spec. The second header holds any comment fields. The
713 third header holds the bitstream codebook. We merely need to
714 make the headers, then pass them to libvorbis one at a time;
715 libvorbis handles the additional Ogg bitstream constraints */
717 ogg_packet header_comm;
718 ogg_packet header_code;
721 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
722 gst_vorbis_enc_set_metadata (vorbisenc);
723 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
724 &header_comm, &header_code);
725 vorbis_comment_clear (&vorbisenc->vc);
727 /* create header buffers */
728 buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
729 buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
730 buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
732 /* mark and put on caps */
733 caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
734 caps = _gst_caps_set_buffer_array (caps, "streamheader",
735 buf1, buf2, buf3, NULL);
737 /* negotiate with these caps */
738 GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
740 gst_buffer_set_caps (buf1, caps);
741 gst_buffer_set_caps (buf2, caps);
742 gst_buffer_set_caps (buf3, caps);
743 gst_caps_unref (caps);
745 /* push out buffers */
746 /* push_buffer takes the reference even for failure */
747 if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf1)) != GST_FLOW_OK)
748 goto failed_header_push;
749 if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf2)) != GST_FLOW_OK) {
751 goto failed_header_push;
753 if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf3)) != GST_FLOW_OK) {
755 goto failed_header_push;
758 vorbisenc->header_sent = TRUE;
762 return gst_vorbis_enc_clear (vorbisenc);
765 data = (gfloat *) GST_BUFFER_DATA (buffer);
766 size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
768 /* expose the buffer to submit data */
769 vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
771 /* deinterleave samples, write the buffer data */
772 for (i = 0; i < size; i++) {
773 for (j = 0; j < vorbisenc->channels; j++) {
774 vorbis_buffer[j][i] = *data++;
778 /* tell the library how much we actually submitted */
779 vorbis_analysis_wrote (&vorbisenc->vd, size);
781 GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
783 vorbisenc->samples_in += size;
785 ret = gst_vorbis_enc_output_buffers (vorbisenc);
792 GST_WARNING_OBJECT (vorbisenc, "Failed to push headers");
793 /* buf1 is always already unreffed */
795 gst_buffer_unref (buf2);
797 gst_buffer_unref (buf3);
803 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
807 /* vorbis does some data preanalysis, then divides up blocks for
808 more involved (potentially parallel) processing. Get a single
809 block for encoding now */
810 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
813 GST_LOG_OBJECT (vorbisenc, "analysed to a block");
816 vorbis_analysis (&vorbisenc->vb, NULL);
817 vorbis_bitrate_addblock (&vorbisenc->vb);
819 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
822 GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
823 buf = gst_buffer_new_and_alloc (op.bytes);
824 memcpy (GST_BUFFER_DATA (buf), op.packet, op.bytes);
825 /* tracking granulepos should tell us samples accounted for */
827 gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER
828 (vorbisenc), buf, op.granulepos - vorbisenc->samples_out);
829 vorbisenc->samples_out = op.granulepos;
831 if (ret != GST_FLOW_OK)
840 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
843 GstVorbisEnc *vorbisenc;
845 g_return_if_fail (GST_IS_VORBISENC (object));
847 vorbisenc = GST_VORBISENC (object);
850 case ARG_MAX_BITRATE:
851 g_value_set_int (value, vorbisenc->max_bitrate);
854 g_value_set_int (value, vorbisenc->bitrate);
856 case ARG_MIN_BITRATE:
857 g_value_set_int (value, vorbisenc->min_bitrate);
860 g_value_set_float (value, vorbisenc->quality);
863 g_value_set_boolean (value, vorbisenc->managed);
865 case ARG_LAST_MESSAGE:
866 g_value_set_string (value, vorbisenc->last_message);
869 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
875 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
876 const GValue * value, GParamSpec * pspec)
878 GstVorbisEnc *vorbisenc;
880 g_return_if_fail (GST_IS_VORBISENC (object));
882 vorbisenc = GST_VORBISENC (object);
885 case ARG_MAX_BITRATE:
887 gboolean old_value = vorbisenc->managed;
889 vorbisenc->max_bitrate = g_value_get_int (value);
890 if (vorbisenc->max_bitrate >= 0
891 && vorbisenc->max_bitrate < LOWEST_BITRATE) {
892 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
893 vorbisenc->max_bitrate = LOWEST_BITRATE;
895 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
896 vorbisenc->managed = TRUE;
898 vorbisenc->managed = FALSE;
900 if (old_value != vorbisenc->managed)
901 g_object_notify (object, "managed");
905 vorbisenc->bitrate = g_value_get_int (value);
906 if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
907 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
908 vorbisenc->bitrate = LOWEST_BITRATE;
911 case ARG_MIN_BITRATE:
913 gboolean old_value = vorbisenc->managed;
915 vorbisenc->min_bitrate = g_value_get_int (value);
916 if (vorbisenc->min_bitrate >= 0
917 && vorbisenc->min_bitrate < LOWEST_BITRATE) {
918 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
919 vorbisenc->min_bitrate = LOWEST_BITRATE;
921 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
922 vorbisenc->managed = TRUE;
924 vorbisenc->managed = FALSE;
926 if (old_value != vorbisenc->managed)
927 g_object_notify (object, "managed");
931 vorbisenc->quality = g_value_get_float (value);
932 if (vorbisenc->quality >= 0.0)
933 vorbisenc->quality_set = TRUE;
935 vorbisenc->quality_set = FALSE;
938 vorbisenc->managed = g_value_get_boolean (value);
941 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);