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, 255 ], " "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,
109 static GstFlowReturn gst_vorbis_enc_pre_push (GstAudioEncoder * enc,
110 GstBuffer ** buffer);
112 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
114 static void gst_vorbis_enc_dispose (GObject * object);
115 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
116 GValue * value, GParamSpec * pspec);
117 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
118 const GValue * value, GParamSpec * pspec);
119 static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
121 GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstAudioEncoder,
122 GST_TYPE_AUDIO_ENCODER, gst_vorbis_enc_add_interfaces);
125 gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
127 static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
129 g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
134 gst_vorbis_enc_base_init (gpointer g_class)
136 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
138 gst_element_class_add_static_pad_template (element_class,
139 &vorbis_enc_src_factory);
140 gst_element_class_add_static_pad_template (element_class,
141 &vorbis_enc_sink_factory);
143 gst_element_class_set_details_simple (element_class,
144 "Vorbis audio encoder", "Codec/Encoder/Audio",
145 "Encodes audio in Vorbis format",
146 "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
150 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
152 GObjectClass *gobject_class;
153 GstAudioEncoderClass *base_class;
155 gobject_class = (GObjectClass *) klass;
156 base_class = (GstAudioEncoderClass *) (klass);
158 gobject_class->set_property = gst_vorbis_enc_set_property;
159 gobject_class->get_property = gst_vorbis_enc_get_property;
160 gobject_class->dispose = gst_vorbis_enc_dispose;
162 base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
163 base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
164 base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
165 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
166 base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
167 base_class->event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
168 base_class->pre_push = GST_DEBUG_FUNCPTR (gst_vorbis_enc_pre_push);
170 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
171 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
172 "Specify a maximum bitrate (in bps). Useful for streaming "
173 "applications. (-1 == disabled)",
174 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
175 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
176 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
177 g_param_spec_int ("bitrate", "Target Bitrate",
178 "Attempt to encode at a bitrate averaging this (in bps). "
179 "This uses the bitrate management engine, and is not recommended for most users. "
180 "Quality is a better alternative. (-1 == disabled)", -1,
181 HIGHEST_BITRATE, BITRATE_DEFAULT,
182 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
183 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
184 g_param_spec_int ("min-bitrate", "Minimum Bitrate",
185 "Specify a minimum bitrate (in bps). Useful for encoding for a "
186 "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
187 MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
188 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
189 g_param_spec_float ("quality", "Quality",
190 "Specify quality instead of specifying a particular bitrate.", -0.1,
191 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
192 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
193 g_param_spec_boolean ("managed", "Managed",
194 "Enable bitrate management engine", FALSE,
195 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
196 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
197 g_param_spec_string ("last-message", "last-message",
198 "The last status message", NULL,
199 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
203 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
205 GstAudioEncoder *enc = GST_AUDIO_ENCODER (vorbisenc);
207 vorbisenc->channels = -1;
208 vorbisenc->frequency = -1;
210 vorbisenc->managed = FALSE;
211 vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
212 vorbisenc->bitrate = BITRATE_DEFAULT;
213 vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
214 vorbisenc->quality = QUALITY_DEFAULT;
215 vorbisenc->quality_set = FALSE;
216 vorbisenc->last_message = NULL;
218 /* arrange granulepos marking (and required perfect ts) */
219 gst_audio_encoder_set_mark_granule (enc, TRUE);
220 gst_audio_encoder_set_perfect_timestamp (enc, TRUE);
224 gst_vorbis_enc_dispose (GObject * object)
226 GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
228 if (vorbisenc->sinkcaps) {
229 gst_caps_unref (vorbisenc->sinkcaps);
230 vorbisenc->sinkcaps = NULL;
233 G_OBJECT_CLASS (parent_class)->dispose (object);
237 gst_vorbis_enc_start (GstAudioEncoder * enc)
239 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
241 GST_DEBUG_OBJECT (enc, "start");
242 vorbisenc->tags = gst_tag_list_new ();
243 vorbisenc->header_sent = FALSE;
249 gst_vorbis_enc_stop (GstAudioEncoder * enc)
251 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
253 GST_DEBUG_OBJECT (enc, "stop");
254 vorbis_block_clear (&vorbisenc->vb);
255 vorbis_dsp_clear (&vorbisenc->vd);
256 vorbis_info_clear (&vorbisenc->vi);
257 g_free (vorbisenc->last_message);
258 vorbisenc->last_message = NULL;
259 gst_tag_list_free (vorbisenc->tags);
260 vorbisenc->tags = NULL;
261 g_slist_foreach (vorbisenc->headers, (GFunc) gst_buffer_unref, NULL);
262 vorbisenc->headers = NULL;
264 gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
270 gst_vorbis_enc_generate_sink_caps (void)
272 GstCaps *caps = gst_caps_new_empty ();
275 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
276 "rate", GST_TYPE_INT_RANGE, 1, 200000,
277 "channels", G_TYPE_INT, 1,
278 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
281 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
282 "rate", GST_TYPE_INT_RANGE, 1, 200000,
283 "channels", G_TYPE_INT, 2,
284 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
287 for (i = 3; i <= 8; i++) {
288 GValue chanpos = { 0 };
290 GstStructure *structure;
292 g_value_init (&chanpos, GST_TYPE_ARRAY);
293 g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
295 for (c = 0; c < i; c++) {
296 g_value_set_enum (&pos, gst_vorbis_channel_positions[i - 1][c]);
297 gst_value_array_append_value (&chanpos, &pos);
299 g_value_unset (&pos);
301 structure = gst_structure_new ("audio/x-raw-float",
302 "rate", GST_TYPE_INT_RANGE, 1, 200000,
303 "channels", G_TYPE_INT, i,
304 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
305 gst_structure_set_value (structure, "channel-positions", &chanpos);
306 g_value_unset (&chanpos);
308 gst_caps_append_structure (caps, structure);
311 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
312 "rate", GST_TYPE_INT_RANGE, 1, 200000,
313 "channels", GST_TYPE_INT_RANGE, 9, 255,
314 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
321 gst_vorbis_enc_getcaps (GstAudioEncoder * enc)
323 GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
325 if (vorbisenc->sinkcaps == NULL)
326 vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
328 return gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps);
332 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
334 /* FIXME, this probably depends on the bitrate and other setting but for now
335 * we return this value, which was obtained by totally unscientific
337 return 58 * GST_MSECOND;
341 gst_vorbis_enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
343 GstVorbisEnc *vorbisenc;
345 vorbisenc = GST_VORBISENC (enc);
347 vorbisenc->channels = GST_AUDIO_INFO_CHANNELS (info);
348 vorbisenc->frequency = GST_AUDIO_INFO_RATE (info);
350 /* if re-configured, we were drained and cleared already */
351 if (!gst_vorbis_enc_setup (vorbisenc))
354 /* feedback to base class */
355 gst_audio_encoder_set_latency (enc,
356 gst_vorbis_enc_get_latency (vorbisenc),
357 gst_vorbis_enc_get_latency (vorbisenc));
363 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
366 GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
369 vc_list = gst_tag_to_vorbis_comments (list, tag);
371 for (l = vc_list; l != NULL; l = l->next) {
372 const gchar *vc_string = (const gchar *) l->data;
373 gchar *key = NULL, *val = NULL;
375 GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
376 if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
377 vorbis_comment_add_tag (&enc->vc, key, val);
383 g_list_foreach (vc_list, (GFunc) g_free, NULL);
384 g_list_free (vc_list);
388 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
390 GstTagList *merged_tags;
391 const GstTagList *user_tags;
393 vorbis_comment_init (&enc->vc);
395 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
397 GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
398 GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
400 /* gst_tag_list_merge() will handle NULL for either or both lists fine */
401 merged_tags = gst_tag_list_merge (user_tags, enc->tags,
402 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
405 GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
406 gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
407 gst_tag_list_free (merged_tags);
412 get_constraints_string (GstVorbisEnc * vorbisenc)
414 gint min = vorbisenc->min_bitrate;
415 gint max = vorbisenc->max_bitrate;
418 if (min > 0 && max > 0)
419 result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
421 result = g_strdup_printf ("(min %d bps, no max)", min);
423 result = g_strdup_printf ("(no min, max %d bps)", max);
425 result = g_strdup_printf ("(no min or max)");
431 update_start_message (GstVorbisEnc * vorbisenc)
435 g_free (vorbisenc->last_message);
437 if (vorbisenc->bitrate > 0) {
438 if (vorbisenc->managed) {
439 constraints = get_constraints_string (vorbisenc);
440 vorbisenc->last_message =
441 g_strdup_printf ("encoding at average bitrate %d bps %s",
442 vorbisenc->bitrate, constraints);
443 g_free (constraints);
445 vorbisenc->last_message =
447 ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
451 if (vorbisenc->quality_set) {
452 if (vorbisenc->managed) {
453 constraints = get_constraints_string (vorbisenc);
454 vorbisenc->last_message =
456 ("encoding at quality level %2.2f using constrained VBR %s",
457 vorbisenc->quality, constraints);
458 g_free (constraints);
460 vorbisenc->last_message =
461 g_strdup_printf ("encoding at quality level %2.2f",
465 constraints = get_constraints_string (vorbisenc);
466 vorbisenc->last_message =
467 g_strdup_printf ("encoding using bitrate management %s", constraints);
468 g_free (constraints);
472 g_object_notify (G_OBJECT (vorbisenc), "last_message");
476 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
479 GST_LOG_OBJECT (vorbisenc, "setup");
481 if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
482 && vorbisenc->max_bitrate < 0) {
483 vorbisenc->quality_set = TRUE;
486 update_start_message (vorbisenc);
488 /* choose an encoding mode */
489 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
490 vorbis_info_init (&vorbisenc->vi);
492 if (vorbisenc->quality_set) {
493 if (vorbis_encode_setup_vbr (&vorbisenc->vi,
494 vorbisenc->channels, vorbisenc->frequency,
495 vorbisenc->quality) != 0) {
496 GST_ERROR_OBJECT (vorbisenc,
497 "vorbisenc: initialisation failed: invalid parameters for quality");
498 vorbis_info_clear (&vorbisenc->vi);
502 /* do we have optional hard quality restrictions? */
503 if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
504 struct ovectl_ratemanage_arg ai;
506 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
508 ai.bitrate_hard_min = vorbisenc->min_bitrate;
509 ai.bitrate_hard_max = vorbisenc->max_bitrate;
510 ai.management_active = 1;
512 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
515 long min_bitrate, max_bitrate;
517 min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
518 max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
520 if (vorbis_encode_setup_managed (&vorbisenc->vi,
522 vorbisenc->frequency,
523 max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
524 GST_ERROR_OBJECT (vorbisenc,
525 "vorbis_encode_setup_managed "
526 "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
527 vorbisenc->channels, vorbisenc->frequency, max_bitrate,
528 vorbisenc->bitrate, min_bitrate);
529 vorbis_info_clear (&vorbisenc->vi);
534 if (vorbisenc->managed && vorbisenc->bitrate < 0) {
535 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
536 } else if (!vorbisenc->managed) {
537 /* Turn off management entirely (if it was turned on). */
538 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
540 vorbis_encode_setup_init (&vorbisenc->vi);
542 /* set up the analysis state and auxiliary encoding storage */
543 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
544 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
546 /* samples == granulepos start at 0 again */
547 vorbisenc->samples_out = 0;
549 /* fresh encoder available */
550 vorbisenc->setup = TRUE;
556 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
558 GstFlowReturn ret = GST_FLOW_OK;
560 if (vorbisenc->setup) {
561 vorbis_analysis_wrote (&vorbisenc->vd, 0);
562 ret = gst_vorbis_enc_output_buffers (vorbisenc);
564 /* marked EOS to encoder, recreate if needed */
565 vorbisenc->setup = FALSE;
568 /* clean up and exit. vorbis_info_clear() must be called last */
569 vorbis_block_clear (&vorbisenc->vb);
570 vorbis_dsp_clear (&vorbisenc->vd);
571 vorbis_info_clear (&vorbisenc->vi);
577 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
582 outbuf = gst_buffer_new_and_alloc (packet->bytes);
583 memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
584 GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
585 GST_BUFFER_OFFSET_END (outbuf) = 0;
586 GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
587 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
589 GST_DEBUG ("created header packet buffer, %d bytes",
590 GST_BUFFER_SIZE (outbuf));
595 gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event)
597 GstVorbisEnc *vorbisenc;
599 vorbisenc = GST_VORBISENC (enc);
601 switch (GST_EVENT_TYPE (event)) {
603 if (vorbisenc->tags) {
606 gst_event_parse_tag (event, &list);
607 gst_tag_list_insert (vorbisenc->tags, list,
608 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
610 g_assert_not_reached ();
618 /* we only peeked, let base class handle it */
622 /* push out the buffer and do internal bookkeeping */
624 gst_vorbis_enc_push_header (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
626 GST_DEBUG_OBJECT (vorbisenc,
627 "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
628 GST_BUFFER_OFFSET_END (buffer),
629 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
630 gst_buffer_set_caps (buffer,
631 GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc)));
632 return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), buffer);
636 * (really really) FIXME: move into core (dixit tpm)
639 * _gst_caps_set_buffer_array:
641 * @field: field in caps to set
642 * @buf: header buffers
644 * Adds given buffers to an array of buffers set as the given @field
645 * on the given @caps. List of buffer arguments must be NULL-terminated.
647 * Returns: input caps with a streamheader field added, or NULL if some error
650 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
651 GstBuffer * buf, ...)
653 GstStructure *structure = NULL;
655 GValue array = { 0 };
656 GValue value = { 0 };
658 g_return_val_if_fail (caps != NULL, NULL);
659 g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
660 g_return_val_if_fail (field != NULL, NULL);
662 caps = gst_caps_make_writable (caps);
663 structure = gst_caps_get_structure (caps, 0);
665 g_value_init (&array, GST_TYPE_ARRAY);
668 /* put buffers in a fixed list */
670 g_assert (gst_buffer_is_metadata_writable (buf));
673 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
675 g_value_init (&value, GST_TYPE_BUFFER);
676 buf = gst_buffer_copy (buf);
677 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
678 gst_value_set_buffer (&value, buf);
679 gst_buffer_unref (buf);
680 gst_value_array_append_value (&array, &value);
681 g_value_unset (&value);
683 buf = va_arg (va, GstBuffer *);
686 gst_structure_set_value (structure, field, &array);
687 g_value_unset (&array);
693 gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
695 GstVorbisEnc *vorbisenc;
696 GstFlowReturn ret = GST_FLOW_OK;
700 float **vorbis_buffer;
701 GstBuffer *buf1, *buf2, *buf3;
703 vorbisenc = GST_VORBISENC (enc);
705 if (G_UNLIKELY (!vorbisenc->setup)) {
707 GST_DEBUG_OBJECT (vorbisenc, "forcing setup");
708 /* should not fail, as setup before same way */
709 if (!gst_vorbis_enc_setup (vorbisenc))
710 return GST_FLOW_ERROR;
713 GST_LOG_OBJECT (vorbisenc, "already drained");
718 if (!vorbisenc->header_sent) {
719 /* Vorbis streams begin with three headers; the initial header (with
720 most of the codec setup parameters) which is mandated by the Ogg
721 bitstream spec. The second header holds any comment fields. The
722 third header holds the bitstream codebook. We merely need to
723 make the headers, then pass them to libvorbis one at a time;
724 libvorbis handles the additional Ogg bitstream constraints */
726 ogg_packet header_comm;
727 ogg_packet header_code;
730 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
731 gst_vorbis_enc_set_metadata (vorbisenc);
732 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
733 &header_comm, &header_code);
734 vorbis_comment_clear (&vorbisenc->vc);
736 /* create header buffers */
737 buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
738 buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
739 buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
741 /* mark and put on caps */
742 caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
743 caps = _gst_caps_set_buffer_array (caps, "streamheader",
744 buf1, buf2, buf3, NULL);
746 /* negotiate with these caps */
747 GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
749 gst_buffer_set_caps (buf1, caps);
750 gst_buffer_set_caps (buf2, caps);
751 gst_buffer_set_caps (buf3, caps);
752 gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), caps);
753 gst_caps_unref (caps);
755 /* store buffers for later pre_push sending */
756 g_slist_foreach (vorbisenc->headers, (GFunc) gst_buffer_unref, NULL);
757 vorbisenc->headers = NULL;
758 GST_DEBUG_OBJECT (vorbisenc, "storing header buffers");
759 vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf3);
760 vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf2);
761 vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf1);
763 vorbisenc->header_sent = TRUE;
767 return gst_vorbis_enc_clear (vorbisenc);
770 data = (gfloat *) GST_BUFFER_DATA (buffer);
771 size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
773 /* expose the buffer to submit data */
774 vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
776 /* deinterleave samples, write the buffer data */
777 for (i = 0; i < size; i++) {
778 for (j = 0; j < vorbisenc->channels; j++) {
779 vorbis_buffer[j][i] = *data++;
783 /* tell the library how much we actually submitted */
784 vorbis_analysis_wrote (&vorbisenc->vd, size);
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 memcpy (GST_BUFFER_DATA (buf), 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);