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,
110 static GstFlowReturn gst_vorbis_enc_pre_push (GstAudioEncoder * enc,
111 GstBuffer ** buffer);
113 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
115 static void gst_vorbis_enc_dispose (GObject * object);
116 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
117 GValue * value, GParamSpec * pspec);
118 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
119 const GValue * value, GParamSpec * pspec);
121 #define gst_vorbis_enc_parent_class parent_class
122 G_DEFINE_TYPE_WITH_CODE (GstVorbisEnc, gst_vorbis_enc,
123 GST_TYPE_AUDIO_ENCODER, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
126 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
128 GObjectClass *gobject_class;
129 GstElementClass *gstelement_class;
130 GstAudioEncoderClass *base_class;
132 gobject_class = (GObjectClass *) klass;
133 gstelement_class = (GstElementClass *) klass;
134 base_class = (GstAudioEncoderClass *) (klass);
136 gobject_class->set_property = gst_vorbis_enc_set_property;
137 gobject_class->get_property = gst_vorbis_enc_get_property;
138 gobject_class->dispose = gst_vorbis_enc_dispose;
140 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
141 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
142 "Specify a maximum bitrate (in bps). Useful for streaming "
143 "applications. (-1 == disabled)",
144 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
145 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
146 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
147 g_param_spec_int ("bitrate", "Target Bitrate",
148 "Attempt to encode at a bitrate averaging this (in bps). "
149 "This uses the bitrate management engine, and is not recommended for most users. "
150 "Quality is a better alternative. (-1 == disabled)", -1,
151 HIGHEST_BITRATE, BITRATE_DEFAULT,
152 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
153 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
154 g_param_spec_int ("min-bitrate", "Minimum Bitrate",
155 "Specify a minimum bitrate (in bps). Useful for encoding for a "
156 "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
157 MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
158 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
159 g_param_spec_float ("quality", "Quality",
160 "Specify quality instead of specifying a particular bitrate.", -0.1,
161 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
162 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
163 g_param_spec_boolean ("managed", "Managed",
164 "Enable bitrate management engine", FALSE,
165 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
166 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
167 g_param_spec_string ("last-message", "last-message",
168 "The last status message", NULL,
169 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
171 gst_element_class_add_pad_template (gstelement_class,
172 gst_static_pad_template_get (&vorbis_enc_src_factory));
173 gst_element_class_add_pad_template (gstelement_class,
174 gst_static_pad_template_get (&vorbis_enc_sink_factory));
176 gst_element_class_set_details_simple (gstelement_class,
177 "Vorbis audio encoder", "Codec/Encoder/Audio",
178 "Encodes audio in Vorbis format",
179 "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
181 base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
182 base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
183 base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
184 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
185 base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
186 base_class->event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
187 base_class->pre_push = GST_DEBUG_FUNCPTR (gst_vorbis_enc_pre_push);
191 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc)
193 GstAudioEncoder *enc = GST_AUDIO_ENCODER (vorbisenc);
195 vorbisenc->channels = -1;
196 vorbisenc->frequency = -1;
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;
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);
212 gst_vorbis_enc_dispose (GObject * object)
214 GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
216 if (vorbisenc->sinkcaps) {
217 gst_caps_unref (vorbisenc->sinkcaps);
218 vorbisenc->sinkcaps = NULL;
221 G_OBJECT_CLASS (parent_class)->dispose (object);
225 gst_vorbis_enc_start (GstAudioEncoder * enc)
227 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
229 GST_DEBUG_OBJECT (enc, "start");
230 vorbisenc->tags = gst_tag_list_new_empty ();
231 vorbisenc->header_sent = FALSE;
237 gst_vorbis_enc_stop (GstAudioEncoder * enc)
239 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
241 GST_DEBUG_OBJECT (enc, "stop");
242 vorbis_block_clear (&vorbisenc->vb);
243 vorbis_dsp_clear (&vorbisenc->vd);
244 vorbis_info_clear (&vorbisenc->vi);
245 g_free (vorbisenc->last_message);
246 vorbisenc->last_message = NULL;
247 gst_tag_list_free (vorbisenc->tags);
248 vorbisenc->tags = NULL;
249 g_slist_foreach (vorbisenc->headers, (GFunc) gst_buffer_unref, NULL);
250 vorbisenc->headers = NULL;
252 gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
258 gst_vorbis_enc_generate_sink_caps (void)
260 GstCaps *caps = gst_caps_new_empty ();
263 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
264 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
265 "layout", G_TYPE_STRING, "interleaved",
266 "rate", GST_TYPE_INT_RANGE, 1, 200000,
267 "channels", G_TYPE_INT, 1, NULL));
269 for (i = 2; i <= 8; i++) {
270 GstStructure *structure;
271 guint64 channel_mask = 0;
272 const GstAudioChannelPosition *pos = gst_vorbis_channel_positions[i - 1];
274 for (c = 0; c < i; c++) {
275 channel_mask |= G_GUINT64_CONSTANT (1) << pos[i];
278 structure = gst_structure_new ("audio/x-raw",
279 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
280 "layout", G_TYPE_STRING, "interleaved",
281 "rate", GST_TYPE_INT_RANGE, 1, 200000, "channels", G_TYPE_INT, i,
282 "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL);
284 gst_caps_append_structure (caps, structure);
287 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
288 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
289 "layout", G_TYPE_STRING, "interleaved",
290 "rate", GST_TYPE_INT_RANGE, 1, 200000,
291 "channels", GST_TYPE_INT_RANGE, 9, 255,
292 "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL));
298 gst_vorbis_enc_getcaps (GstAudioEncoder * enc, GstCaps * filter)
300 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
303 if (vorbisenc->sinkcaps == NULL)
304 vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
307 GstCaps *int_caps = gst_caps_intersect_full (filter, vorbisenc->sinkcaps,
308 GST_CAPS_INTERSECT_FIRST);
309 caps = gst_audio_encoder_proxy_getcaps (enc, int_caps);
310 gst_caps_unref (int_caps);
312 caps = gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps);
319 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
321 /* FIXME, this probably depends on the bitrate and other setting but for now
322 * we return this value, which was obtained by totally unscientific
324 return 58 * GST_MSECOND;
328 gst_vorbis_enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
330 GstVorbisEnc *vorbisenc;
332 vorbisenc = GST_VORBISENC (enc);
334 vorbisenc->channels = GST_AUDIO_INFO_CHANNELS (info);
335 vorbisenc->frequency = GST_AUDIO_INFO_RATE (info);
337 /* if re-configured, we were drained and cleared already */
338 if (!gst_vorbis_enc_setup (vorbisenc))
341 /* feedback to base class */
342 gst_audio_encoder_set_latency (enc,
343 gst_vorbis_enc_get_latency (vorbisenc),
344 gst_vorbis_enc_get_latency (vorbisenc));
350 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
353 GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
356 vc_list = gst_tag_to_vorbis_comments (list, tag);
358 for (l = vc_list; l != NULL; l = l->next) {
359 const gchar *vc_string = (const gchar *) l->data;
360 gchar *key = NULL, *val = NULL;
362 GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
363 if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
364 vorbis_comment_add_tag (&enc->vc, key, val);
370 g_list_foreach (vc_list, (GFunc) g_free, NULL);
371 g_list_free (vc_list);
375 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
377 GstTagList *merged_tags;
378 const GstTagList *user_tags;
380 vorbis_comment_init (&enc->vc);
382 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
384 GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
385 GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
387 /* gst_tag_list_merge() will handle NULL for either or both lists fine */
388 merged_tags = gst_tag_list_merge (user_tags, enc->tags,
389 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
392 GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
393 gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
394 gst_tag_list_free (merged_tags);
399 get_constraints_string (GstVorbisEnc * vorbisenc)
401 gint min = vorbisenc->min_bitrate;
402 gint max = vorbisenc->max_bitrate;
405 if (min > 0 && max > 0)
406 result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
408 result = g_strdup_printf ("(min %d bps, no max)", min);
410 result = g_strdup_printf ("(no min, max %d bps)", max);
412 result = g_strdup_printf ("(no min or max)");
418 update_start_message (GstVorbisEnc * vorbisenc)
422 g_free (vorbisenc->last_message);
424 if (vorbisenc->bitrate > 0) {
425 if (vorbisenc->managed) {
426 constraints = get_constraints_string (vorbisenc);
427 vorbisenc->last_message =
428 g_strdup_printf ("encoding at average bitrate %d bps %s",
429 vorbisenc->bitrate, constraints);
430 g_free (constraints);
432 vorbisenc->last_message =
434 ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
438 if (vorbisenc->quality_set) {
439 if (vorbisenc->managed) {
440 constraints = get_constraints_string (vorbisenc);
441 vorbisenc->last_message =
443 ("encoding at quality level %2.2f using constrained VBR %s",
444 vorbisenc->quality, constraints);
445 g_free (constraints);
447 vorbisenc->last_message =
448 g_strdup_printf ("encoding at quality level %2.2f",
452 constraints = get_constraints_string (vorbisenc);
453 vorbisenc->last_message =
454 g_strdup_printf ("encoding using bitrate management %s", constraints);
455 g_free (constraints);
459 g_object_notify (G_OBJECT (vorbisenc), "last_message");
463 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
466 GST_LOG_OBJECT (vorbisenc, "setup");
468 if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
469 && vorbisenc->max_bitrate < 0) {
470 vorbisenc->quality_set = TRUE;
473 update_start_message (vorbisenc);
475 /* choose an encoding mode */
476 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
477 vorbis_info_init (&vorbisenc->vi);
479 if (vorbisenc->quality_set) {
480 if (vorbis_encode_setup_vbr (&vorbisenc->vi,
481 vorbisenc->channels, vorbisenc->frequency,
482 vorbisenc->quality) != 0) {
483 GST_ERROR_OBJECT (vorbisenc,
484 "vorbisenc: initialisation failed: invalid parameters for quality");
485 vorbis_info_clear (&vorbisenc->vi);
489 /* do we have optional hard quality restrictions? */
490 if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
491 struct ovectl_ratemanage_arg ai;
493 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
495 ai.bitrate_hard_min = vorbisenc->min_bitrate;
496 ai.bitrate_hard_max = vorbisenc->max_bitrate;
497 ai.management_active = 1;
499 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
502 long min_bitrate, max_bitrate;
504 min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
505 max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
507 if (vorbis_encode_setup_managed (&vorbisenc->vi,
509 vorbisenc->frequency,
510 max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
511 GST_ERROR_OBJECT (vorbisenc,
512 "vorbis_encode_setup_managed "
513 "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
514 vorbisenc->channels, vorbisenc->frequency, max_bitrate,
515 vorbisenc->bitrate, min_bitrate);
516 vorbis_info_clear (&vorbisenc->vi);
521 if (vorbisenc->managed && vorbisenc->bitrate < 0) {
522 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
523 } else if (!vorbisenc->managed) {
524 /* Turn off management entirely (if it was turned on). */
525 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
527 vorbis_encode_setup_init (&vorbisenc->vi);
529 /* set up the analysis state and auxiliary encoding storage */
530 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
531 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
533 /* samples == granulepos start at 0 again */
534 vorbisenc->samples_out = 0;
536 /* fresh encoder available */
537 vorbisenc->setup = TRUE;
543 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
545 GstFlowReturn ret = GST_FLOW_OK;
547 if (vorbisenc->setup) {
548 vorbis_analysis_wrote (&vorbisenc->vd, 0);
549 ret = gst_vorbis_enc_output_buffers (vorbisenc);
551 /* marked EOS to encoder, recreate if needed */
552 vorbisenc->setup = FALSE;
555 /* clean up and exit. vorbis_info_clear() must be called last */
556 vorbis_block_clear (&vorbisenc->vb);
557 vorbis_dsp_clear (&vorbisenc->vd);
558 vorbis_info_clear (&vorbisenc->vi);
564 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
569 outbuf = gst_buffer_new_and_alloc (packet->bytes);
570 gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
571 GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
572 GST_BUFFER_OFFSET_END (outbuf) = 0;
573 GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
574 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
576 GST_DEBUG ("created header packet buffer, %" G_GSIZE_FORMAT " bytes",
577 gst_buffer_get_size (outbuf));
582 gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event)
584 GstVorbisEnc *vorbisenc;
586 vorbisenc = GST_VORBISENC (enc);
588 switch (GST_EVENT_TYPE (event)) {
590 if (vorbisenc->tags) {
593 gst_event_parse_tag (event, &list);
594 gst_tag_list_insert (vorbisenc->tags, list,
595 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
597 g_assert_not_reached ();
605 /* we only peeked, let base class handle it */
606 return GST_AUDIO_ENCODER_CLASS (parent_class)->event (enc, event);
609 /* push out the buffer and do internal bookkeeping */
611 gst_vorbis_enc_push_header (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
613 GST_DEBUG_OBJECT (vorbisenc,
614 "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
615 GST_BUFFER_OFFSET_END (buffer),
616 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
617 return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), buffer);
621 * (really really) FIXME: move into core (dixit tpm)
624 * _gst_caps_set_buffer_array:
626 * @field: field in caps to set
627 * @buf: header buffers
629 * Adds given buffers to an array of buffers set as the given @field
630 * on the given @caps. List of buffer arguments must be NULL-terminated.
632 * Returns: input caps with a streamheader field added, or NULL if some error
635 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
636 GstBuffer * buf, ...)
638 GstStructure *structure = NULL;
640 GValue array = { 0 };
641 GValue value = { 0 };
643 g_return_val_if_fail (caps != NULL, NULL);
644 g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
645 g_return_val_if_fail (field != NULL, NULL);
647 caps = gst_caps_make_writable (caps);
648 structure = gst_caps_get_structure (caps, 0);
650 g_value_init (&array, GST_TYPE_ARRAY);
653 /* put buffers in a fixed list */
655 g_assert (gst_buffer_is_writable (buf));
658 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
660 g_value_init (&value, GST_TYPE_BUFFER);
661 buf = gst_buffer_copy (buf);
662 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
663 gst_value_set_buffer (&value, buf);
664 gst_buffer_unref (buf);
665 gst_value_array_append_value (&array, &value);
666 g_value_unset (&value);
668 buf = va_arg (va, GstBuffer *);
671 gst_structure_set_value (structure, field, &array);
672 g_value_unset (&array);
678 gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
680 GstVorbisEnc *vorbisenc;
681 GstFlowReturn ret = GST_FLOW_OK;
686 float **vorbis_buffer;
687 GstBuffer *buf1, *buf2, *buf3;
689 vorbisenc = GST_VORBISENC (enc);
691 if (G_UNLIKELY (!vorbisenc->setup)) {
693 GST_DEBUG_OBJECT (vorbisenc, "forcing setup");
694 /* should not fail, as setup before same way */
695 if (!gst_vorbis_enc_setup (vorbisenc))
696 return GST_FLOW_ERROR;
699 GST_LOG_OBJECT (vorbisenc, "already drained");
704 if (!vorbisenc->header_sent) {
705 /* Vorbis streams begin with three headers; the initial header (with
706 most of the codec setup parameters) which is mandated by the Ogg
707 bitstream spec. The second header holds any comment fields. The
708 third header holds the bitstream codebook. We merely need to
709 make the headers, then pass them to libvorbis one at a time;
710 libvorbis handles the additional Ogg bitstream constraints */
712 ogg_packet header_comm;
713 ogg_packet header_code;
716 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
717 gst_vorbis_enc_set_metadata (vorbisenc);
718 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
719 &header_comm, &header_code);
720 vorbis_comment_clear (&vorbisenc->vc);
722 /* create header buffers */
723 buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
724 buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
725 buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
727 /* mark and put on caps */
728 caps = gst_caps_new_simple ("audio/x-vorbis",
729 "rate", G_TYPE_INT, vorbisenc->frequency,
730 "channels", G_TYPE_INT, vorbisenc->channels, NULL);
731 caps = _gst_caps_set_buffer_array (caps, "streamheader",
732 buf1, buf2, buf3, NULL);
734 /* negotiate with these caps */
735 GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
736 gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (vorbisenc), caps);
737 gst_caps_unref (caps);
739 /* store buffers for later pre_push sending */
740 g_slist_foreach (vorbisenc->headers, (GFunc) gst_buffer_unref, NULL);
741 vorbisenc->headers = NULL;
742 GST_DEBUG_OBJECT (vorbisenc, "storing header buffers");
743 vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf3);
744 vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf2);
745 vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf1);
747 vorbisenc->header_sent = TRUE;
751 return gst_vorbis_enc_clear (vorbisenc);
753 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
756 size = map.size / (vorbisenc->channels * sizeof (float));
757 ptr = (gfloat *) map.data;
759 /* expose the buffer to submit data */
760 vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
762 /* deinterleave samples, write the buffer data */
763 if (vorbisenc->channels < 2 || vorbisenc->channels > 8) {
764 for (i = 0; i < size; i++) {
765 for (j = 0; j < vorbisenc->channels; j++) {
766 vorbis_buffer[j][i] = *ptr++;
773 for (i = 0; i < size; i++) {
774 for (j = 0; j < vorbisenc->channels; j++) {
775 vorbis_buffer[gst_vorbis_reorder_map[vorbisenc->channels - 1][j]][i] =
778 ptr += vorbisenc->channels;
782 /* tell the library how much we actually submitted */
783 vorbis_analysis_wrote (&vorbisenc->vd, size);
784 gst_buffer_unmap (buffer, &map);
786 GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
788 vorbisenc->samples_in += size;
790 ret = gst_vorbis_enc_output_buffers (vorbisenc);
796 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
800 /* vorbis does some data preanalysis, then divides up blocks for
801 more involved (potentially parallel) processing. Get a single
802 block for encoding now */
803 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
806 GST_LOG_OBJECT (vorbisenc, "analysed to a block");
809 vorbis_analysis (&vorbisenc->vb, NULL);
810 vorbis_bitrate_addblock (&vorbisenc->vb);
812 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
815 GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
816 buf = gst_buffer_new_and_alloc (op.bytes);
817 gst_buffer_fill (buf, 0, op.packet, op.bytes);
818 /* tracking granulepos should tell us samples accounted for */
820 gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER
821 (vorbisenc), buf, op.granulepos - vorbisenc->samples_out);
822 vorbisenc->samples_out = op.granulepos;
824 if (ret != GST_FLOW_OK)
833 gst_vorbis_enc_pre_push (GstAudioEncoder * enc, GstBuffer ** buffer)
835 GstVorbisEnc *vorbisenc;
836 GstFlowReturn ret = GST_FLOW_OK;
838 vorbisenc = GST_VORBISENC (enc);
840 /* FIXME 0.11 ? get rid of this special ogg stuff and have it
841 * put and use 'codec data' in caps like anything else,
842 * with all the usual out-of-band advantage etc */
843 if (G_UNLIKELY (vorbisenc->headers)) {
844 GSList *header = vorbisenc->headers;
846 /* try to push all of these, if we lose one, might as well lose all */
848 if (ret == GST_FLOW_OK)
849 ret = gst_vorbis_enc_push_header (vorbisenc, header->data);
851 gst_vorbis_enc_push_header (vorbisenc, header->data);
852 header = g_slist_next (header);
855 g_slist_free (vorbisenc->headers);
856 vorbisenc->headers = NULL;
863 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
866 GstVorbisEnc *vorbisenc;
868 g_return_if_fail (GST_IS_VORBISENC (object));
870 vorbisenc = GST_VORBISENC (object);
873 case ARG_MAX_BITRATE:
874 g_value_set_int (value, vorbisenc->max_bitrate);
877 g_value_set_int (value, vorbisenc->bitrate);
879 case ARG_MIN_BITRATE:
880 g_value_set_int (value, vorbisenc->min_bitrate);
883 g_value_set_float (value, vorbisenc->quality);
886 g_value_set_boolean (value, vorbisenc->managed);
888 case ARG_LAST_MESSAGE:
889 g_value_set_string (value, vorbisenc->last_message);
892 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
898 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
899 const GValue * value, GParamSpec * pspec)
901 GstVorbisEnc *vorbisenc;
903 g_return_if_fail (GST_IS_VORBISENC (object));
905 vorbisenc = GST_VORBISENC (object);
908 case ARG_MAX_BITRATE:
910 gboolean old_value = vorbisenc->managed;
912 vorbisenc->max_bitrate = g_value_get_int (value);
913 if (vorbisenc->max_bitrate >= 0
914 && vorbisenc->max_bitrate < LOWEST_BITRATE) {
915 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
916 vorbisenc->max_bitrate = LOWEST_BITRATE;
918 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
919 vorbisenc->managed = TRUE;
921 vorbisenc->managed = FALSE;
923 if (old_value != vorbisenc->managed)
924 g_object_notify (object, "managed");
928 vorbisenc->bitrate = g_value_get_int (value);
929 if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
930 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
931 vorbisenc->bitrate = LOWEST_BITRATE;
934 case ARG_MIN_BITRATE:
936 gboolean old_value = vorbisenc->managed;
938 vorbisenc->min_bitrate = g_value_get_int (value);
939 if (vorbisenc->min_bitrate >= 0
940 && vorbisenc->min_bitrate < LOWEST_BITRATE) {
941 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
942 vorbisenc->min_bitrate = LOWEST_BITRATE;
944 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
945 vorbisenc->managed = TRUE;
947 vorbisenc->managed = FALSE;
949 if (old_value != vorbisenc->managed)
950 g_object_notify (object, "managed");
954 vorbisenc->quality = g_value_get_float (value);
955 if (vorbisenc->quality >= 0.0)
956 vorbisenc->quality_set = TRUE;
958 vorbisenc->quality_set = FALSE;
961 vorbisenc->managed = g_value_get_boolean (value);
964 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);