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/audio.h>
54 #include "gstvorbisenc.h"
56 #include "gstvorbiscommon.h"
58 GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
59 #define GST_CAT_DEFAULT vorbisenc_debug
61 static GstStaticPadTemplate vorbis_enc_sink_factory =
62 GST_STATIC_PAD_TEMPLATE ("sink",
65 GST_STATIC_CAPS ("audio/x-raw, "
66 "format = (string) " GST_AUDIO_NE (F32) ", "
67 "layout = (string) interleaved, "
68 "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
71 static GstStaticPadTemplate vorbis_enc_src_factory =
72 GST_STATIC_PAD_TEMPLATE ("src",
75 GST_STATIC_CAPS ("audio/x-vorbis, "
76 "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
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,
108 static gboolean gst_vorbis_enc_sink_event (GstAudioEncoder * enc,
111 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
113 static void gst_vorbis_enc_dispose (GObject * object);
114 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
115 GValue * value, GParamSpec * pspec);
116 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
117 const GValue * value, GParamSpec * pspec);
119 #define gst_vorbis_enc_parent_class parent_class
120 G_DEFINE_TYPE_WITH_CODE (GstVorbisEnc, gst_vorbis_enc,
121 GST_TYPE_AUDIO_ENCODER, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
124 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
126 GObjectClass *gobject_class;
127 GstElementClass *gstelement_class;
128 GstAudioEncoderClass *base_class;
130 gobject_class = (GObjectClass *) klass;
131 gstelement_class = (GstElementClass *) klass;
132 base_class = (GstAudioEncoderClass *) (klass);
134 gobject_class->set_property = gst_vorbis_enc_set_property;
135 gobject_class->get_property = gst_vorbis_enc_get_property;
136 gobject_class->dispose = gst_vorbis_enc_dispose;
138 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
139 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
140 "Specify a maximum bitrate (in bps). Useful for streaming "
141 "applications. (-1 == disabled)",
142 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
143 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
144 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
145 g_param_spec_int ("bitrate", "Target Bitrate",
146 "Attempt to encode at a bitrate averaging this (in bps). "
147 "This uses the bitrate management engine, and is not recommended for most users. "
148 "Quality is a better alternative. (-1 == disabled)", -1,
149 HIGHEST_BITRATE, BITRATE_DEFAULT,
150 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
151 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
152 g_param_spec_int ("min-bitrate", "Minimum Bitrate",
153 "Specify a minimum bitrate (in bps). Useful for encoding for a "
154 "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
155 MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
156 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
157 g_param_spec_float ("quality", "Quality",
158 "Specify quality instead of specifying a particular bitrate.", -0.1,
159 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
160 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
161 g_param_spec_boolean ("managed", "Managed",
162 "Enable bitrate management engine", FALSE,
163 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
164 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
165 g_param_spec_string ("last-message", "last-message",
166 "The last status message", NULL,
167 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
169 gst_element_class_add_pad_template (gstelement_class,
170 gst_static_pad_template_get (&vorbis_enc_src_factory));
171 gst_element_class_add_pad_template (gstelement_class,
172 gst_static_pad_template_get (&vorbis_enc_sink_factory));
174 gst_element_class_set_details_simple (gstelement_class,
175 "Vorbis audio encoder", "Codec/Encoder/Audio",
176 "Encodes audio in Vorbis format",
177 "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
179 base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
180 base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
181 base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
182 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
183 base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
184 base_class->sink_event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
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_free (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[i];
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);
305 gst_caps_unref (int_caps);
307 caps = gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps);
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_free (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_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
564 outbuf = gst_buffer_new_and_alloc (packet->bytes);
565 gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
566 GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
567 GST_BUFFER_OFFSET_END (outbuf) = 0;
568 GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
569 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
571 GST_DEBUG ("created header packet buffer, %" G_GSIZE_FORMAT " bytes",
572 gst_buffer_get_size (outbuf));
577 gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event)
579 GstVorbisEnc *vorbisenc;
581 vorbisenc = GST_VORBISENC (enc);
583 switch (GST_EVENT_TYPE (event)) {
585 if (vorbisenc->tags) {
588 gst_event_parse_tag (event, &list);
589 gst_tag_list_insert (vorbisenc->tags, list,
590 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
592 g_assert_not_reached ();
600 /* we only peeked, let base class handle it */
601 return GST_AUDIO_ENCODER_CLASS (parent_class)->sink_event (enc, event);
605 * (really really) FIXME: move into core (dixit tpm)
608 * _gst_caps_set_buffer_array:
610 * @field: field in caps to set
611 * @buf: header buffers
613 * Adds given buffers to an array of buffers set as the given @field
614 * on the given @caps. List of buffer arguments must be NULL-terminated.
616 * Returns: input caps with a streamheader field added, or NULL if some error
619 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
620 GstBuffer * buf, ...)
622 GstStructure *structure = NULL;
624 GValue array = { 0 };
625 GValue value = { 0 };
627 g_return_val_if_fail (caps != NULL, NULL);
628 g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
629 g_return_val_if_fail (field != NULL, NULL);
631 caps = gst_caps_make_writable (caps);
632 structure = gst_caps_get_structure (caps, 0);
634 g_value_init (&array, GST_TYPE_ARRAY);
637 /* put buffers in a fixed list */
639 g_assert (gst_buffer_is_writable (buf));
642 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
644 g_value_init (&value, GST_TYPE_BUFFER);
645 buf = gst_buffer_copy (buf);
646 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
647 gst_value_set_buffer (&value, buf);
648 gst_buffer_unref (buf);
649 gst_value_array_append_value (&array, &value);
650 g_value_unset (&value);
652 buf = va_arg (va, GstBuffer *);
655 gst_structure_set_value (structure, field, &array);
656 g_value_unset (&array);
662 gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
664 GstVorbisEnc *vorbisenc;
665 GstFlowReturn ret = GST_FLOW_OK;
670 float **vorbis_buffer;
671 GstBuffer *buf1, *buf2, *buf3;
673 vorbisenc = GST_VORBISENC (enc);
675 if (G_UNLIKELY (!vorbisenc->setup)) {
677 GST_DEBUG_OBJECT (vorbisenc, "forcing setup");
678 /* should not fail, as setup before same way */
679 if (!gst_vorbis_enc_setup (vorbisenc))
680 return GST_FLOW_ERROR;
683 GST_LOG_OBJECT (vorbisenc, "already drained");
688 if (!vorbisenc->header_sent) {
689 /* Vorbis streams begin with three headers; the initial header (with
690 most of the codec setup parameters) which is mandated by the Ogg
691 bitstream spec. The second header holds any comment fields. The
692 third header holds the bitstream codebook. We merely need to
693 make the headers, then pass them to libvorbis one at a time;
694 libvorbis handles the additional Ogg bitstream constraints */
696 ogg_packet header_comm;
697 ogg_packet header_code;
701 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
702 gst_vorbis_enc_set_metadata (vorbisenc);
703 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
704 &header_comm, &header_code);
705 vorbis_comment_clear (&vorbisenc->vc);
707 /* create header buffers */
708 buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
709 buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
710 buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
712 /* mark and put on caps */
713 caps = gst_caps_new_simple ("audio/x-vorbis",
714 "rate", G_TYPE_INT, vorbisenc->frequency,
715 "channels", G_TYPE_INT, vorbisenc->channels, NULL);
716 caps = _gst_caps_set_buffer_array (caps, "streamheader",
717 buf1, buf2, buf3, NULL);
719 /* negotiate with these caps */
720 GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
721 gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (vorbisenc), caps);
722 gst_caps_unref (caps);
724 /* store buffers for later pre_push sending */
726 GST_DEBUG_OBJECT (vorbisenc, "storing header buffers");
727 headers = g_list_prepend (headers, buf3);
728 headers = g_list_prepend (headers, buf2);
729 headers = g_list_prepend (headers, buf1);
730 gst_audio_encoder_set_headers (enc, headers);
732 vorbisenc->header_sent = TRUE;
736 return gst_vorbis_enc_clear (vorbisenc);
738 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
741 size = map.size / (vorbisenc->channels * sizeof (float));
742 ptr = (gfloat *) map.data;
744 /* expose the buffer to submit data */
745 vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
747 /* deinterleave samples, write the buffer data */
748 if (vorbisenc->channels < 2 || vorbisenc->channels > 8) {
749 for (i = 0; i < size; i++) {
750 for (j = 0; j < vorbisenc->channels; j++) {
751 vorbis_buffer[j][i] = *ptr++;
758 for (i = 0; i < size; i++) {
759 for (j = 0; j < vorbisenc->channels; j++) {
760 vorbis_buffer[gst_vorbis_reorder_map[vorbisenc->channels - 1][j]][i] =
763 ptr += vorbisenc->channels;
767 /* tell the library how much we actually submitted */
768 vorbis_analysis_wrote (&vorbisenc->vd, size);
769 gst_buffer_unmap (buffer, &map);
771 GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
773 vorbisenc->samples_in += size;
775 ret = gst_vorbis_enc_output_buffers (vorbisenc);
781 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
785 /* vorbis does some data preanalysis, then divides up blocks for
786 more involved (potentially parallel) processing. Get a single
787 block for encoding now */
788 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
791 GST_LOG_OBJECT (vorbisenc, "analysed to a block");
794 vorbis_analysis (&vorbisenc->vb, NULL);
795 vorbis_bitrate_addblock (&vorbisenc->vb);
797 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
800 GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
801 buf = gst_buffer_new_and_alloc (op.bytes);
802 gst_buffer_fill (buf, 0, op.packet, op.bytes);
803 /* tracking granulepos should tell us samples accounted for */
805 gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER
806 (vorbisenc), buf, op.granulepos - vorbisenc->samples_out);
807 vorbisenc->samples_out = op.granulepos;
809 if (ret != GST_FLOW_OK)
818 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
821 GstVorbisEnc *vorbisenc;
823 g_return_if_fail (GST_IS_VORBISENC (object));
825 vorbisenc = GST_VORBISENC (object);
828 case ARG_MAX_BITRATE:
829 g_value_set_int (value, vorbisenc->max_bitrate);
832 g_value_set_int (value, vorbisenc->bitrate);
834 case ARG_MIN_BITRATE:
835 g_value_set_int (value, vorbisenc->min_bitrate);
838 g_value_set_float (value, vorbisenc->quality);
841 g_value_set_boolean (value, vorbisenc->managed);
843 case ARG_LAST_MESSAGE:
844 g_value_set_string (value, vorbisenc->last_message);
847 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
853 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
854 const GValue * value, GParamSpec * pspec)
856 GstVorbisEnc *vorbisenc;
858 g_return_if_fail (GST_IS_VORBISENC (object));
860 vorbisenc = GST_VORBISENC (object);
863 case ARG_MAX_BITRATE:
865 gboolean old_value = vorbisenc->managed;
867 vorbisenc->max_bitrate = g_value_get_int (value);
868 if (vorbisenc->max_bitrate >= 0
869 && vorbisenc->max_bitrate < LOWEST_BITRATE) {
870 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
871 vorbisenc->max_bitrate = LOWEST_BITRATE;
873 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
874 vorbisenc->managed = TRUE;
876 vorbisenc->managed = FALSE;
878 if (old_value != vorbisenc->managed)
879 g_object_notify (object, "managed");
883 vorbisenc->bitrate = g_value_get_int (value);
884 if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
885 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
886 vorbisenc->bitrate = LOWEST_BITRATE;
889 case ARG_MIN_BITRATE:
891 gboolean old_value = vorbisenc->managed;
893 vorbisenc->min_bitrate = g_value_get_int (value);
894 if (vorbisenc->min_bitrate >= 0
895 && vorbisenc->min_bitrate < LOWEST_BITRATE) {
896 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
897 vorbisenc->min_bitrate = LOWEST_BITRATE;
899 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
900 vorbisenc->managed = TRUE;
902 vorbisenc->managed = FALSE;
904 if (old_value != vorbisenc->managed)
905 g_object_notify (object, "managed");
909 vorbisenc->quality = g_value_get_float (value);
910 if (vorbisenc->quality >= 0.0)
911 vorbisenc->quality_set = TRUE;
913 vorbisenc->quality_set = FALSE;
916 vorbisenc->managed = g_value_get_boolean (value);
919 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);