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
26 * This element encodes raw float audio into a Vorbis stream.
27 * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
28 * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
31 * <title>Example pipelines</title>
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.
37 * gst-launch -v sinesrc num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sinesrc.ogg
40 * Record from a sound card using ALSA and encode to Ogg/Vorbis.
43 * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
50 * @short_description: an encoder that encodes to Ogg/Vorbis
62 #include <vorbis/vorbisenc.h>
64 #include <gst/gsttagsetter.h>
65 #include <gst/tag/tag.h>
66 #include "vorbisenc.h"
68 GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
69 #define GST_CAT_DEFAULT vorbisenc_debug
71 static GstPadTemplate *gst_vorbisenc_src_template, *gst_vorbisenc_sink_template;
73 /* elementfactory information */
74 GstElementDetails vorbisenc_details = {
76 "Codec/Encoder/Audio",
77 "Encodes audio in Vorbis format",
78 "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>",
81 /* GstVorbisEnc signals and args */
99 static void gst_vorbisenc_output_buffers (GstVorbisEnc * vorbisenc);
102 * vorbis_granule_time was added between 1.0 and 1.0.1; it's too silly
103 * to require a new version for such a simple function, but once we move
104 * beyond 1.0 for other reasons we can remove this copy */
107 vorbis_granule_time_copy (vorbis_dsp_state * v, ogg_int64_t granulepos)
110 return ((double) granulepos / v->vi->rate);
115 static const GstFormat *
116 gst_vorbisenc_get_formats (GstPad * pad)
118 static const GstFormat src_formats[] = {
123 static const GstFormat sink_formats[] = {
130 return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
134 #define MAX_BITRATE_DEFAULT -1
135 #define BITRATE_DEFAULT -1
136 #define MIN_BITRATE_DEFAULT -1
137 #define QUALITY_DEFAULT 0.3
138 #define LOWEST_BITRATE 6000 /* lowest allowed for a 8 kHz stream */
139 #define HIGHEST_BITRATE 250001 /* highest allowed for a 44 kHz stream */
141 static void gst_vorbisenc_base_init (gpointer g_class);
142 static void gst_vorbisenc_class_init (GstVorbisEncClass * klass);
143 static void gst_vorbisenc_init (GstVorbisEnc * vorbisenc);
145 static gboolean gst_vorbisenc_sink_event (GstPad * pad, GstEvent * event);
146 static GstFlowReturn gst_vorbisenc_chain (GstPad * pad, GstBuffer * buffer);
147 static gboolean gst_vorbisenc_setup (GstVorbisEnc * vorbisenc);
149 static void gst_vorbisenc_get_property (GObject * object, guint prop_id,
150 GValue * value, GParamSpec * pspec);
151 static void gst_vorbisenc_set_property (GObject * object, guint prop_id,
152 const GValue * value, GParamSpec * pspec);
153 static GstStateChangeReturn gst_vorbisenc_change_state (GstElement * element,
154 GstStateChange transition);
156 static GstElementClass *parent_class = NULL;
158 /*static guint gst_vorbisenc_signals[LAST_SIGNAL] = { 0 }; */
161 vorbisenc_get_type (void)
163 static GType vorbisenc_type = 0;
165 if (!vorbisenc_type) {
166 static const GTypeInfo vorbisenc_info = {
167 sizeof (GstVorbisEncClass),
168 gst_vorbisenc_base_init,
170 (GClassInitFunc) gst_vorbisenc_class_init,
173 sizeof (GstVorbisEnc),
175 (GInstanceInitFunc) gst_vorbisenc_init,
177 static const GInterfaceInfo tag_setter_info = {
184 g_type_register_static (GST_TYPE_ELEMENT, "GstVorbisEnc",
187 g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
190 return vorbisenc_type;
194 vorbis_caps_factory (void)
196 return gst_caps_new_simple ("audio/x-vorbis", NULL);
200 raw_caps_factory (void)
202 /* lowest sample rate is in vorbis/lib/modes/setup_8.h, 8000 Hz
203 * highest sample rate is in vorbis/lib/modes/setup_44.h, 50000 Hz */
205 gst_caps_new_simple ("audio/x-raw-float",
206 "rate", GST_TYPE_INT_RANGE, 8000, 50000,
207 "channels", GST_TYPE_INT_RANGE, 1, 2,
208 "endianness", G_TYPE_INT, G_BYTE_ORDER,
209 "width", G_TYPE_INT, 32, "buffer-frames", G_TYPE_INT, 0, NULL);
213 gst_vorbisenc_base_init (gpointer g_class)
215 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
216 GstCaps *raw_caps, *vorbis_caps;
218 raw_caps = raw_caps_factory ();
219 vorbis_caps = vorbis_caps_factory ();
221 gst_vorbisenc_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
222 GST_PAD_ALWAYS, raw_caps);
223 gst_vorbisenc_src_template = gst_pad_template_new ("src", GST_PAD_SRC,
224 GST_PAD_ALWAYS, vorbis_caps);
225 gst_element_class_add_pad_template (element_class,
226 gst_vorbisenc_sink_template);
227 gst_element_class_add_pad_template (element_class,
228 gst_vorbisenc_src_template);
229 gst_element_class_set_details (element_class, &vorbisenc_details);
233 gst_vorbisenc_class_init (GstVorbisEncClass * klass)
235 GObjectClass *gobject_class;
236 GstElementClass *gstelement_class;
238 gobject_class = (GObjectClass *) klass;
239 gstelement_class = (GstElementClass *) klass;
241 gobject_class->set_property = gst_vorbisenc_set_property;
242 gobject_class->get_property = gst_vorbisenc_get_property;
244 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
245 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
246 "Specify a maximum bitrate (in bps). Useful for streaming "
247 "applications. (-1 == disabled)",
248 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT, G_PARAM_READWRITE));
249 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
250 g_param_spec_int ("bitrate", "Target Bitrate",
251 "Attempt to encode at a bitrate averaging this (in bps). "
252 "This uses the bitrate management engine, and is not recommended for most users. "
253 "Quality is a better alternative. (-1 == disabled)",
254 -1, HIGHEST_BITRATE, BITRATE_DEFAULT, G_PARAM_READWRITE));
255 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
256 g_param_spec_int ("min_bitrate", "Minimum Bitrate",
257 "Specify a minimum bitrate (in bps). Useful for encoding for a "
258 "fixed-size channel. (-1 == disabled)",
259 -1, HIGHEST_BITRATE, MIN_BITRATE_DEFAULT, G_PARAM_READWRITE));
260 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
261 g_param_spec_float ("quality", "Quality",
262 "Specify quality instead of specifying a particular bitrate.",
263 -0.1, 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE));
264 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
265 g_param_spec_boolean ("managed", "Managed",
266 "Enable bitrate management engine", FALSE, G_PARAM_READWRITE));
267 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
268 g_param_spec_string ("last-message", "last-message",
269 "The last status message", NULL, G_PARAM_READABLE));
271 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
273 gstelement_class->change_state = gst_vorbisenc_change_state;
277 gst_vorbisenc_sink_setcaps (GstPad * pad, GstCaps * caps)
279 GstVorbisEnc *vorbisenc;
280 GstStructure *structure;
282 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
283 vorbisenc->setup = FALSE;
285 structure = gst_caps_get_structure (caps, 0);
286 gst_structure_get_int (structure, "channels", &vorbisenc->channels);
287 gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
289 gst_vorbisenc_setup (vorbisenc);
291 if (vorbisenc->setup)
298 gst_vorbisenc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
299 GstFormat * dest_format, gint64 * dest_value)
302 GstVorbisEnc *vorbisenc;
305 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
307 if (vorbisenc->samples_in == 0 ||
308 vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0)
311 avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in);
313 switch (src_format) {
314 case GST_FORMAT_BYTES:
315 switch (*dest_format) {
316 case GST_FORMAT_TIME:
317 *dest_value = src_value * GST_SECOND / avg;
323 case GST_FORMAT_TIME:
324 switch (*dest_format) {
325 case GST_FORMAT_BYTES:
326 *dest_value = src_value * avg / GST_SECOND;
339 gst_vorbisenc_convert_sink (GstPad * pad, GstFormat src_format,
340 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
344 gint bytes_per_sample;
345 GstVorbisEnc *vorbisenc;
347 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
349 bytes_per_sample = vorbisenc->channels * 2;
351 switch (src_format) {
352 case GST_FORMAT_BYTES:
353 switch (*dest_format) {
354 case GST_FORMAT_DEFAULT:
355 if (bytes_per_sample == 0)
357 *dest_value = src_value / bytes_per_sample;
359 case GST_FORMAT_TIME:
361 gint byterate = bytes_per_sample * vorbisenc->frequency;
365 *dest_value = src_value * GST_SECOND / byterate;
372 case GST_FORMAT_DEFAULT:
373 switch (*dest_format) {
374 case GST_FORMAT_BYTES:
375 *dest_value = src_value * bytes_per_sample;
377 case GST_FORMAT_TIME:
378 if (vorbisenc->frequency == 0)
380 *dest_value = src_value * GST_SECOND / vorbisenc->frequency;
386 case GST_FORMAT_TIME:
387 switch (*dest_format) {
388 case GST_FORMAT_BYTES:
389 scale = bytes_per_sample;
391 case GST_FORMAT_DEFAULT:
392 *dest_value = src_value * scale * vorbisenc->frequency / GST_SECOND;
404 static const GstQueryType *
405 gst_vorbisenc_get_query_types (GstPad * pad)
407 static const GstQueryType gst_vorbisenc_src_query_types[] = {
412 return gst_vorbisenc_src_query_types;
416 gst_vorbisenc_src_query (GstPad * pad, GstQuery * query)
419 GstVorbisEnc *vorbisenc;
421 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
423 switch (GST_QUERY_TYPE (query)) {
424 case GST_QUERY_POSITION:
428 case GST_FORMAT_BYTES:
429 case GST_FORMAT_TIME:
432 const GstFormat *peer_formats;
437 gst_pad_get_formats (GST_PAD_PEER (vorbisenc->sinkpad));
439 while (peer_formats && *peer_formats && !res) {
441 GstFormat peer_format = *peer_formats;
444 if (gst_pad_query (GST_PAD_PEER (vorbisenc->sinkpad),
445 GST_QUERY_TOTAL, &peer_format, &peer_value)) {
446 GstFormat conv_format;
448 /* convert to TIME */
449 conv_format = GST_FORMAT_TIME;
450 res = gst_vorbisenc_convert_sink (vorbisenc->sinkpad,
451 peer_format, peer_value, &conv_format, value);
452 /* and to final format */
453 res &= gst_vorbisenc_convert_src (pad,
454 GST_FORMAT_TIME, *value, format, value);
468 case GST_QUERY_CONVERT:
470 GstFormat src_fmt, dest_fmt;
471 gint64 src_val, dest_val;
473 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
475 gst_vorbisenc_convert_src (pad, src_fmt, src_val, &dest_fmt,
478 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
491 gst_vorbisenc_sink_query (GstPad * pad, GstQuery * query)
494 GstVorbisEnc *vorbisenc;
496 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
498 switch (GST_QUERY_TYPE (query)) {
499 case GST_QUERY_CONVERT:
501 GstFormat src_fmt, dest_fmt;
502 gint64 src_val, dest_val;
504 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
506 gst_vorbisenc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
509 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
522 gst_vorbisenc_init (GstVorbisEnc * vorbisenc)
525 gst_pad_new_from_template (gst_vorbisenc_sink_template, "sink");
526 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
527 gst_pad_set_event_function (vorbisenc->sinkpad, gst_vorbisenc_sink_event);
528 gst_pad_set_chain_function (vorbisenc->sinkpad, gst_vorbisenc_chain);
529 gst_pad_set_setcaps_function (vorbisenc->sinkpad, gst_vorbisenc_sink_setcaps);
530 gst_pad_set_query_function (vorbisenc->sinkpad,
531 GST_DEBUG_FUNCPTR (gst_vorbisenc_sink_query));
534 gst_pad_new_from_template (gst_vorbisenc_src_template, "src");
535 gst_pad_set_query_function (vorbisenc->srcpad,
536 GST_DEBUG_FUNCPTR (gst_vorbisenc_src_query));
537 gst_pad_set_query_type_function (vorbisenc->srcpad,
538 GST_DEBUG_FUNCPTR (gst_vorbisenc_get_query_types));
539 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
541 vorbisenc->channels = -1;
542 vorbisenc->frequency = -1;
544 vorbisenc->managed = FALSE;
545 vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
546 vorbisenc->bitrate = BITRATE_DEFAULT;
547 vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
548 vorbisenc->quality = QUALITY_DEFAULT;
549 vorbisenc->quality_set = FALSE;
550 vorbisenc->last_message = NULL;
552 vorbisenc->setup = FALSE;
553 vorbisenc->header_sent = FALSE;
558 gst_vorbisenc_get_tag_value (const GstTagList * list, const gchar * tag,
561 gchar *vorbisvalue = NULL;
567 /* get tag name right */
568 if ((strcmp (tag, GST_TAG_TRACK_NUMBER) == 0)
569 || (strcmp (tag, GST_TAG_ALBUM_VOLUME_NUMBER) == 0)
570 || (strcmp (tag, GST_TAG_TRACK_COUNT) == 0)
571 || (strcmp (tag, GST_TAG_ALBUM_VOLUME_COUNT) == 0)) {
574 if (!gst_tag_list_get_uint_index (list, tag, index, &track_no))
575 g_assert_not_reached ();
576 vorbisvalue = g_strdup_printf ("%u", track_no);
577 } else if (strcmp (tag, GST_TAG_DATE) == 0) {
578 /* FIXME: how are dates represented in vorbis files? */
582 if (!gst_tag_list_get_uint_index (list, tag, index, &u))
583 g_assert_not_reached ();
584 date = g_date_new_julian (u);
586 g_strdup_printf ("%04d-%02d-%02d", (gint) g_date_get_year (date),
587 (gint) g_date_get_month (date), (gint) g_date_get_day (date));
589 } else if (gst_tag_get_type (tag) == G_TYPE_STRING) {
590 if (!gst_tag_list_get_string_index (list, tag, index, &vorbisvalue))
591 g_assert_not_reached ();
598 gst_vorbisenc_metadata_set1 (const GstTagList * list, const gchar * tag,
601 const gchar *vorbistag = NULL;
602 gchar *vorbisvalue = NULL;
604 GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
606 vorbistag = gst_tag_to_vorbis_tag (tag);
607 if (vorbistag == NULL) {
611 count = gst_tag_list_get_tag_size (list, tag);
612 for (i = 0; i < count; i++) {
613 vorbisvalue = gst_vorbisenc_get_tag_value (list, tag, i);
615 if (vorbisvalue != NULL) {
616 vorbis_comment_add_tag (&enc->vc, g_strdup (vorbistag), vorbisvalue);
622 gst_vorbisenc_set_metadata (GstVorbisEnc * vorbisenc)
625 const GstTagList *user_tags;
627 user_tags = gst_tag_setter_get_list (GST_TAG_SETTER (vorbisenc));
628 if (!(vorbisenc->tags || user_tags))
632 gst_tag_list_merge (user_tags, vorbisenc->tags,
633 gst_tag_setter_get_merge_mode (GST_TAG_SETTER (vorbisenc)));
634 vorbis_comment_init (&vorbisenc->vc);
635 gst_tag_list_foreach (copy, gst_vorbisenc_metadata_set1, vorbisenc);
636 gst_tag_list_free (copy);
640 get_constraints_string (GstVorbisEnc * vorbisenc)
642 gint min = vorbisenc->min_bitrate;
643 gint max = vorbisenc->max_bitrate;
646 if (min > 0 && max > 0)
647 result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
649 result = g_strdup_printf ("(min %d bps, no max)", min);
651 result = g_strdup_printf ("(no min, max %d bps)", max);
653 result = g_strdup_printf ("(no min or max)");
659 update_start_message (GstVorbisEnc * vorbisenc)
663 g_free (vorbisenc->last_message);
665 if (vorbisenc->bitrate > 0) {
666 if (vorbisenc->managed) {
667 constraints = get_constraints_string (vorbisenc);
668 vorbisenc->last_message =
669 g_strdup_printf ("encoding at average bitrate %d bps %s",
670 vorbisenc->bitrate, constraints);
671 g_free (constraints);
673 vorbisenc->last_message =
675 ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
679 if (vorbisenc->quality_set) {
680 if (vorbisenc->managed) {
681 constraints = get_constraints_string (vorbisenc);
682 vorbisenc->last_message =
684 ("encoding at quality level %2.2f using constrained VBR %s",
685 vorbisenc->quality, constraints);
686 g_free (constraints);
688 vorbisenc->last_message =
689 g_strdup_printf ("encoding at quality level %2.2f",
693 constraints = get_constraints_string (vorbisenc);
694 vorbisenc->last_message =
695 g_strdup_printf ("encoding using bitrate management %s", constraints);
696 g_free (constraints);
700 g_object_notify (G_OBJECT (vorbisenc), "last_message");
704 gst_vorbisenc_setup (GstVorbisEnc * vorbisenc)
706 vorbisenc->setup = FALSE;
708 if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
709 && vorbisenc->max_bitrate < 0) {
710 vorbisenc->quality_set = TRUE;
713 update_start_message (vorbisenc);
715 /* choose an encoding mode */
716 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
717 vorbis_info_init (&vorbisenc->vi);
719 if (vorbisenc->quality_set) {
720 if (vorbis_encode_setup_vbr (&vorbisenc->vi,
721 vorbisenc->channels, vorbisenc->frequency,
722 vorbisenc->quality) != 0) {
723 GST_ERROR_OBJECT (vorbisenc,
724 "vorbisenc: initialisation failed: invalid parameters for quality");
725 vorbis_info_clear (&vorbisenc->vi);
729 /* do we have optional hard quality restrictions? */
730 if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
731 struct ovectl_ratemanage_arg ai;
733 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
735 /* the bitrates used by libvorbisenc are in kbit/sec, ours in bit/sec
736 * also remember that in telecom kbit/sec is 1000 bit/sec */
737 ai.bitrate_hard_min = vorbisenc->min_bitrate / 1000;
738 ai.bitrate_hard_max = vorbisenc->max_bitrate / 1000;
739 ai.management_active = 1;
741 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
744 long min_bitrate, max_bitrate;
746 min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
747 max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
749 if (vorbis_encode_setup_managed (&vorbisenc->vi,
751 vorbisenc->frequency,
752 max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
753 GST_ERROR_OBJECT (vorbisenc,
754 "vorbis_encode_setup_managed "
755 "(c %d, rate %d, max br %ld, br %ld, min br %ld) failed",
756 vorbisenc->channels, vorbisenc->frequency, max_bitrate,
757 vorbisenc->bitrate, min_bitrate);
758 vorbis_info_clear (&vorbisenc->vi);
763 if (vorbisenc->managed && vorbisenc->bitrate < 0) {
764 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
765 } else if (!vorbisenc->managed) {
766 /* Turn off management entirely (if it was turned on). */
767 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
769 vorbis_encode_setup_init (&vorbisenc->vi);
771 /* set up the analysis state and auxiliary encoding storage */
772 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
773 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
775 vorbisenc->setup = TRUE;
780 /* prepare a buffer for transmission by passing data through libvorbis */
782 gst_vorbisenc_buffer_from_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
786 outbuf = gst_buffer_new_and_alloc (packet->bytes);
787 memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
788 GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
789 GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos;
790 GST_BUFFER_TIMESTAMP (outbuf) =
791 vorbis_granule_time_copy (&vorbisenc->vd,
792 packet->granulepos) * GST_SECOND;
794 GST_DEBUG ("encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
798 /* push out the buffer and do internal bookkeeping */
800 gst_vorbisenc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
802 vorbisenc->bytes_out += GST_BUFFER_SIZE (buffer);
804 if (GST_PAD_IS_USABLE (vorbisenc->srcpad)) {
805 gst_pad_push (vorbisenc->srcpad, buffer);
807 gst_buffer_unref (buffer);
812 gst_vorbisenc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
816 outbuf = gst_vorbisenc_buffer_from_packet (vorbisenc, packet);
817 gst_vorbisenc_push_buffer (vorbisenc, outbuf);
821 gst_vorbisenc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
822 GstBuffer * buf2, GstBuffer * buf3)
824 GstStructure *structure;
826 GValue value = { 0 };
828 caps = gst_caps_make_writable (caps);
829 structure = gst_caps_get_structure (caps, 0);
832 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
833 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
834 GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
836 /* put buffers in a fixed list */
837 g_value_init (&list, GST_TYPE_ARRAY);
838 g_value_init (&value, GST_TYPE_BUFFER);
839 gst_value_set_buffer (&value, buf1);
840 gst_value_list_append_value (&list, &value);
841 g_value_unset (&value);
842 g_value_init (&value, GST_TYPE_BUFFER);
843 gst_value_set_buffer (&value, buf2);
844 gst_value_list_append_value (&list, &value);
845 g_value_unset (&value);
846 g_value_init (&value, GST_TYPE_BUFFER);
847 gst_value_set_buffer (&value, buf3);
848 gst_value_list_append_value (&list, &value);
849 gst_structure_set_value (structure, "streamheader", &list);
850 g_value_unset (&value);
851 g_value_unset (&list);
857 gst_vorbisenc_sink_event (GstPad * pad, GstEvent * event)
860 GstVorbisEnc *vorbisenc;
862 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
864 switch (GST_EVENT_TYPE (event)) {
866 /* Tell the library we're at end of stream so that it can handle
867 * the last frame and mark end of stream in the output properly */
868 GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on");
869 vorbis_analysis_wrote (&vorbisenc->vd, 0);
870 gst_vorbisenc_output_buffers (vorbisenc);
872 /* clean up and exit. vorbis_info_clear() must be called last */
873 vorbis_block_clear (&vorbisenc->vb);
874 vorbis_dsp_clear (&vorbisenc->vd);
875 vorbis_info_clear (&vorbisenc->vi);
877 res = gst_pad_event_default (pad, event);
880 if (vorbisenc->tags) {
883 gst_event_parse_tag (event, &list);
884 gst_tag_list_insert (vorbisenc->tags, list,
885 gst_tag_setter_get_merge_mode (GST_TAG_SETTER (vorbisenc)));
887 g_assert_not_reached ();
889 res = gst_pad_event_default (pad, event);
892 res = gst_pad_event_default (pad, event);
899 gst_vorbisenc_chain (GstPad * pad, GstBuffer * buffer)
901 GstBuffer *buf = GST_BUFFER (buffer);
902 GstVorbisEnc *vorbisenc;
904 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
912 if (!vorbisenc->setup) {
913 gst_buffer_unref (buf);
914 GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL),
915 ("encoder not initialized (input is not audio?)"));
916 return GST_FLOW_UNEXPECTED;
919 if (!vorbisenc->header_sent) {
920 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
923 /* Vorbis streams begin with three headers; the initial header (with
924 most of the codec setup parameters) which is mandated by the Ogg
925 bitstream spec. The second header holds any comment fields. The
926 third header holds the bitstream codebook. We merely need to
927 make the headers, then pass them to libvorbis one at a time;
928 libvorbis handles the additional Ogg bitstream constraints */
930 ogg_packet header_comm;
931 ogg_packet header_code;
932 GstBuffer *buf1, *buf2, *buf3;
935 gst_vorbisenc_set_metadata (vorbisenc);
936 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
937 &header_comm, &header_code);
939 /* create header buffers */
940 buf1 = gst_vorbisenc_buffer_from_packet (vorbisenc, &header);
941 buf2 = gst_vorbisenc_buffer_from_packet (vorbisenc, &header_comm);
942 buf3 = gst_vorbisenc_buffer_from_packet (vorbisenc, &header_code);
944 /* mark and put on caps */
945 caps = gst_pad_get_caps (vorbisenc->srcpad);
946 caps = gst_vorbisenc_set_header_on_caps (caps, buf1, buf2, buf3);
948 /* negotiate with these caps */
949 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
950 gst_pad_set_caps (vorbisenc->srcpad, caps);
952 gst_buffer_set_caps (buf1, caps);
953 gst_buffer_set_caps (buf2, caps);
954 gst_buffer_set_caps (buf3, caps);
956 /* push out buffers */
957 gst_vorbisenc_push_buffer (vorbisenc, buf1);
958 gst_vorbisenc_push_buffer (vorbisenc, buf2);
959 gst_vorbisenc_push_buffer (vorbisenc, buf3);
961 vorbisenc->header_sent = TRUE;
965 data = (gfloat *) GST_BUFFER_DATA (buf);
966 size = GST_BUFFER_SIZE (buf) / (vorbisenc->channels * sizeof (float));
968 /* expose the buffer to submit data */
969 buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
971 /* uninterleave samples */
972 for (i = 0; i < size; i++) {
973 for (j = 0; j < vorbisenc->channels; j++) {
974 buffer[j][i] = *data++;
978 /* tell the library how much we actually submitted */
979 vorbis_analysis_wrote (&vorbisenc->vd, size);
981 vorbisenc->samples_in += size;
983 gst_buffer_unref (buf);
986 gst_vorbisenc_output_buffers (vorbisenc);
992 gst_vorbisenc_output_buffers (GstVorbisEnc * vorbisenc)
994 /* vorbis does some data preanalysis, then divides up blocks for
995 more involved (potentially parallel) processing. Get a single
996 block for encoding now */
997 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
1000 GST_LOG_OBJECT (vorbisenc, "analysed to a block");
1003 vorbis_analysis (&vorbisenc->vb, NULL);
1004 vorbis_bitrate_addblock (&vorbisenc->vb);
1006 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
1007 GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
1008 gst_vorbisenc_push_packet (vorbisenc, &op);
1014 gst_vorbisenc_get_property (GObject * object, guint prop_id, GValue * value,
1017 GstVorbisEnc *vorbisenc;
1019 g_return_if_fail (GST_IS_VORBISENC (object));
1021 vorbisenc = GST_VORBISENC (object);
1024 case ARG_MAX_BITRATE:
1025 g_value_set_int (value, vorbisenc->max_bitrate);
1028 g_value_set_int (value, vorbisenc->bitrate);
1030 case ARG_MIN_BITRATE:
1031 g_value_set_int (value, vorbisenc->min_bitrate);
1034 g_value_set_float (value, vorbisenc->quality);
1037 g_value_set_boolean (value, vorbisenc->managed);
1039 case ARG_LAST_MESSAGE:
1040 g_value_set_string (value, vorbisenc->last_message);
1043 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1049 gst_vorbisenc_set_property (GObject * object, guint prop_id,
1050 const GValue * value, GParamSpec * pspec)
1052 GstVorbisEnc *vorbisenc;
1054 g_return_if_fail (GST_IS_VORBISENC (object));
1056 vorbisenc = GST_VORBISENC (object);
1059 case ARG_MAX_BITRATE:
1061 gboolean old_value = vorbisenc->managed;
1063 vorbisenc->max_bitrate = g_value_get_int (value);
1064 if (vorbisenc->max_bitrate >= 0
1065 && vorbisenc->max_bitrate < LOWEST_BITRATE) {
1066 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1067 vorbisenc->max_bitrate = LOWEST_BITRATE;
1069 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1070 vorbisenc->managed = TRUE;
1072 vorbisenc->managed = FALSE;
1074 if (old_value != vorbisenc->managed)
1075 g_object_notify (object, "managed");
1079 vorbisenc->bitrate = g_value_get_int (value);
1080 if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
1081 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1082 vorbisenc->bitrate = LOWEST_BITRATE;
1085 case ARG_MIN_BITRATE:
1087 gboolean old_value = vorbisenc->managed;
1089 vorbisenc->min_bitrate = g_value_get_int (value);
1090 if (vorbisenc->min_bitrate >= 0
1091 && vorbisenc->min_bitrate < LOWEST_BITRATE) {
1092 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1093 vorbisenc->min_bitrate = LOWEST_BITRATE;
1095 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1096 vorbisenc->managed = TRUE;
1098 vorbisenc->managed = FALSE;
1100 if (old_value != vorbisenc->managed)
1101 g_object_notify (object, "managed");
1105 vorbisenc->quality = g_value_get_float (value);
1106 if (vorbisenc->quality >= 0.0)
1107 vorbisenc->quality_set = TRUE;
1109 vorbisenc->quality_set = FALSE;
1112 vorbisenc->managed = g_value_get_boolean (value);
1115 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1120 static GstStateChangeReturn
1121 gst_vorbisenc_change_state (GstElement * element, GstStateChange transition)
1123 GstVorbisEnc *vorbisenc = GST_VORBISENC (element);
1124 GstStateChangeReturn res;
1127 switch (transition) {
1128 case GST_STATE_CHANGE_NULL_TO_READY:
1129 vorbisenc->tags = gst_tag_list_new ();
1131 case GST_STATE_CHANGE_READY_TO_PAUSED:
1132 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1137 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1139 switch (transition) {
1140 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1142 case GST_STATE_CHANGE_PAUSED_TO_READY:
1143 vorbisenc->setup = FALSE;
1144 vorbisenc->header_sent = FALSE;
1146 case GST_STATE_CHANGE_READY_TO_NULL:
1147 gst_tag_list_free (vorbisenc->tags);
1148 vorbisenc->tags = NULL;