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 audiotestsrc wave=sine num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sine.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 GstFlowReturn 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, "width", G_TYPE_INT, 32, NULL);
212 gst_vorbisenc_base_init (gpointer g_class)
214 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
215 GstCaps *raw_caps, *vorbis_caps;
217 raw_caps = raw_caps_factory ();
218 vorbis_caps = vorbis_caps_factory ();
220 gst_vorbisenc_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
221 GST_PAD_ALWAYS, raw_caps);
222 gst_vorbisenc_src_template = gst_pad_template_new ("src", GST_PAD_SRC,
223 GST_PAD_ALWAYS, vorbis_caps);
224 gst_element_class_add_pad_template (element_class,
225 gst_vorbisenc_sink_template);
226 gst_element_class_add_pad_template (element_class,
227 gst_vorbisenc_src_template);
228 gst_element_class_set_details (element_class, &vorbisenc_details);
232 gst_vorbisenc_class_init (GstVorbisEncClass * klass)
234 GObjectClass *gobject_class;
235 GstElementClass *gstelement_class;
237 gobject_class = (GObjectClass *) klass;
238 gstelement_class = (GstElementClass *) klass;
240 gobject_class->set_property = gst_vorbisenc_set_property;
241 gobject_class->get_property = gst_vorbisenc_get_property;
243 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
244 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
245 "Specify a maximum bitrate (in bps). Useful for streaming "
246 "applications. (-1 == disabled)",
247 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT, G_PARAM_READWRITE));
248 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
249 g_param_spec_int ("bitrate", "Target Bitrate",
250 "Attempt to encode at a bitrate averaging this (in bps). "
251 "This uses the bitrate management engine, and is not recommended for most users. "
252 "Quality is a better alternative. (-1 == disabled)",
253 -1, HIGHEST_BITRATE, BITRATE_DEFAULT, G_PARAM_READWRITE));
254 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
255 g_param_spec_int ("min_bitrate", "Minimum Bitrate",
256 "Specify a minimum bitrate (in bps). Useful for encoding for a "
257 "fixed-size channel. (-1 == disabled)",
258 -1, HIGHEST_BITRATE, MIN_BITRATE_DEFAULT, G_PARAM_READWRITE));
259 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
260 g_param_spec_float ("quality", "Quality",
261 "Specify quality instead of specifying a particular bitrate.",
262 -0.1, 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE));
263 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
264 g_param_spec_boolean ("managed", "Managed",
265 "Enable bitrate management engine", FALSE, G_PARAM_READWRITE));
266 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
267 g_param_spec_string ("last-message", "last-message",
268 "The last status message", NULL, G_PARAM_READABLE));
270 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
272 gstelement_class->change_state = gst_vorbisenc_change_state;
276 gst_vorbisenc_sink_setcaps (GstPad * pad, GstCaps * caps)
278 GstVorbisEnc *vorbisenc;
279 GstStructure *structure;
281 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
282 vorbisenc->setup = FALSE;
284 structure = gst_caps_get_structure (caps, 0);
285 gst_structure_get_int (structure, "channels", &vorbisenc->channels);
286 gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
288 gst_vorbisenc_setup (vorbisenc);
290 if (vorbisenc->setup)
297 gst_vorbisenc_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
298 GstFormat * dest_format, gint64 * dest_value)
301 GstVorbisEnc *vorbisenc;
304 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
306 if (vorbisenc->samples_in == 0 ||
307 vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0)
310 avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in);
312 switch (src_format) {
313 case GST_FORMAT_BYTES:
314 switch (*dest_format) {
315 case GST_FORMAT_TIME:
316 *dest_value = src_value * GST_SECOND / avg;
322 case GST_FORMAT_TIME:
323 switch (*dest_format) {
324 case GST_FORMAT_BYTES:
325 *dest_value = src_value * avg / GST_SECOND;
338 gst_vorbisenc_convert_sink (GstPad * pad, GstFormat src_format,
339 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
343 gint bytes_per_sample;
344 GstVorbisEnc *vorbisenc;
346 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
348 bytes_per_sample = vorbisenc->channels * 2;
350 switch (src_format) {
351 case GST_FORMAT_BYTES:
352 switch (*dest_format) {
353 case GST_FORMAT_DEFAULT:
354 if (bytes_per_sample == 0)
356 *dest_value = src_value / bytes_per_sample;
358 case GST_FORMAT_TIME:
360 gint byterate = bytes_per_sample * vorbisenc->frequency;
364 *dest_value = src_value * GST_SECOND / byterate;
371 case GST_FORMAT_DEFAULT:
372 switch (*dest_format) {
373 case GST_FORMAT_BYTES:
374 *dest_value = src_value * bytes_per_sample;
376 case GST_FORMAT_TIME:
377 if (vorbisenc->frequency == 0)
379 *dest_value = src_value * GST_SECOND / vorbisenc->frequency;
385 case GST_FORMAT_TIME:
386 switch (*dest_format) {
387 case GST_FORMAT_BYTES:
388 scale = bytes_per_sample;
390 case GST_FORMAT_DEFAULT:
391 *dest_value = src_value * scale * vorbisenc->frequency / GST_SECOND;
403 static const GstQueryType *
404 gst_vorbisenc_get_query_types (GstPad * pad)
406 static const GstQueryType gst_vorbisenc_src_query_types[] = {
413 return gst_vorbisenc_src_query_types;
417 gst_vorbisenc_src_query (GstPad * pad, GstQuery * query)
420 GstVorbisEnc *vorbisenc;
423 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
424 peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad));
426 switch (GST_QUERY_TYPE (query)) {
427 case GST_QUERY_POSITION:
429 GstFormat fmt, req_fmt;
432 gst_query_parse_position (query, &req_fmt, NULL);
433 if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
434 gst_query_set_position (query, req_fmt, val);
438 fmt = GST_FORMAT_TIME;
439 if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
442 if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
443 gst_query_set_position (query, req_fmt, val);
447 case GST_QUERY_DURATION:
449 GstFormat fmt, req_fmt;
452 gst_query_parse_duration (query, &req_fmt, NULL);
453 if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
454 gst_query_set_duration (query, req_fmt, val);
458 fmt = GST_FORMAT_TIME;
459 if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
462 if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
463 gst_query_set_duration (query, req_fmt, val);
467 case GST_QUERY_CONVERT:
469 GstFormat src_fmt, dest_fmt;
470 gint64 src_val, dest_val;
472 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
474 gst_vorbisenc_convert_src (pad, src_fmt, src_val, &dest_fmt,
477 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
486 gst_object_unref (peerpad);
487 gst_object_unref (vorbisenc);
492 gst_vorbisenc_sink_query (GstPad * pad, GstQuery * query)
495 GstVorbisEnc *vorbisenc;
497 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
499 switch (GST_QUERY_TYPE (query)) {
500 case GST_QUERY_CONVERT:
502 GstFormat src_fmt, dest_fmt;
503 gint64 src_val, dest_val;
505 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
507 gst_vorbisenc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
510 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
523 gst_vorbisenc_init (GstVorbisEnc * vorbisenc)
526 gst_pad_new_from_template (gst_vorbisenc_sink_template, "sink");
527 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
528 gst_pad_set_event_function (vorbisenc->sinkpad, gst_vorbisenc_sink_event);
529 gst_pad_set_chain_function (vorbisenc->sinkpad, gst_vorbisenc_chain);
530 gst_pad_set_setcaps_function (vorbisenc->sinkpad, gst_vorbisenc_sink_setcaps);
531 gst_pad_set_query_function (vorbisenc->sinkpad,
532 GST_DEBUG_FUNCPTR (gst_vorbisenc_sink_query));
535 gst_pad_new_from_template (gst_vorbisenc_src_template, "src");
536 gst_pad_set_query_function (vorbisenc->srcpad,
537 GST_DEBUG_FUNCPTR (gst_vorbisenc_src_query));
538 gst_pad_set_query_type_function (vorbisenc->srcpad,
539 GST_DEBUG_FUNCPTR (gst_vorbisenc_get_query_types));
540 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
542 vorbisenc->channels = -1;
543 vorbisenc->frequency = -1;
545 vorbisenc->managed = FALSE;
546 vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
547 vorbisenc->bitrate = BITRATE_DEFAULT;
548 vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
549 vorbisenc->quality = QUALITY_DEFAULT;
550 vorbisenc->quality_set = FALSE;
551 vorbisenc->last_message = NULL;
557 gst_vorbisenc_get_tag_value (const GstTagList * list, const gchar * tag,
561 gchar *vorbisvalue = NULL;
566 tag_type = gst_tag_get_type (tag);
568 /* get tag name right */
569 if ((strcmp (tag, GST_TAG_TRACK_NUMBER) == 0)
570 || (strcmp (tag, GST_TAG_ALBUM_VOLUME_NUMBER) == 0)
571 || (strcmp (tag, GST_TAG_TRACK_COUNT) == 0)
572 || (strcmp (tag, GST_TAG_ALBUM_VOLUME_COUNT) == 0)) {
575 if (!gst_tag_list_get_uint_index (list, tag, index, &track_no))
576 g_return_val_if_reached (NULL);
578 vorbisvalue = g_strdup_printf ("%u", track_no);
579 } else if (tag_type == GST_TYPE_DATE) {
582 if (!gst_tag_list_get_date_index (list, tag, index, &date))
583 g_return_val_if_reached (NULL);
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 (tag_type == G_TYPE_STRING) {
590 if (!gst_tag_list_get_string_index (list, tag, index, &vorbisvalue))
591 g_return_val_if_reached (NULL);
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_tag_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_tag_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 ai.bitrate_hard_min = vorbisenc->min_bitrate;
736 ai.bitrate_hard_max = vorbisenc->max_bitrate;
737 ai.management_active = 1;
739 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
742 long min_bitrate, max_bitrate;
744 min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
745 max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
747 if (vorbis_encode_setup_managed (&vorbisenc->vi,
749 vorbisenc->frequency,
750 max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
751 GST_ERROR_OBJECT (vorbisenc,
752 "vorbis_encode_setup_managed "
753 "(c %d, rate %d, max br %ld, br %ld, min br %ld) failed",
754 vorbisenc->channels, vorbisenc->frequency, max_bitrate,
755 vorbisenc->bitrate, min_bitrate);
756 vorbis_info_clear (&vorbisenc->vi);
761 if (vorbisenc->managed && vorbisenc->bitrate < 0) {
762 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
763 } else if (!vorbisenc->managed) {
764 /* Turn off management entirely (if it was turned on). */
765 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
767 vorbis_encode_setup_init (&vorbisenc->vi);
769 /* set up the analysis state and auxiliary encoding storage */
770 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
771 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
773 vorbisenc->prev_ts = 0;
775 vorbisenc->setup = TRUE;
781 gst_vorbisenc_clear (GstVorbisEnc * vorbisenc)
783 GstFlowReturn ret = GST_FLOW_OK;
785 if (vorbisenc->setup) {
786 vorbis_analysis_wrote (&vorbisenc->vd, 0);
787 ret = gst_vorbisenc_output_buffers (vorbisenc);
789 vorbisenc->setup = FALSE;
792 /* clean up and exit. vorbis_info_clear() must be called last */
793 vorbis_block_clear (&vorbisenc->vb);
794 vorbis_dsp_clear (&vorbisenc->vd);
795 vorbis_info_clear (&vorbisenc->vi);
797 vorbisenc->header_sent = FALSE;
802 /* prepare a buffer for transmission by passing data through libvorbis */
804 gst_vorbisenc_buffer_from_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
808 outbuf = gst_buffer_new_and_alloc (packet->bytes);
809 memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
810 GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
811 GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos;
812 GST_BUFFER_TIMESTAMP (outbuf) =
813 vorbis_granule_time_copy (&vorbisenc->vd,
814 packet->granulepos) * GST_SECOND;
815 GST_BUFFER_DURATION (outbuf) =
816 GST_BUFFER_TIMESTAMP (outbuf) - vorbisenc->prev_ts;
817 vorbisenc->prev_ts = GST_BUFFER_TIMESTAMP (outbuf);
819 GST_DEBUG ("encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
823 /* push out the buffer and do internal bookkeeping */
825 gst_vorbisenc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
827 vorbisenc->bytes_out += GST_BUFFER_SIZE (buffer);
829 return gst_pad_push (vorbisenc->srcpad, buffer);
833 gst_vorbisenc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
837 outbuf = gst_vorbisenc_buffer_from_packet (vorbisenc, packet);
838 return gst_vorbisenc_push_buffer (vorbisenc, outbuf);
842 gst_vorbisenc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
843 GstBuffer * buf2, GstBuffer * buf3)
845 GstStructure *structure;
846 GValue array = { 0 };
847 GValue value = { 0 };
849 caps = gst_caps_make_writable (caps);
850 structure = gst_caps_get_structure (caps, 0);
853 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
854 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
855 GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
857 /* put buffers in a fixed list */
858 g_value_init (&array, GST_TYPE_ARRAY);
859 g_value_init (&value, GST_TYPE_BUFFER);
860 gst_value_set_buffer (&value, buf1);
861 gst_value_array_append_value (&array, &value);
862 g_value_unset (&value);
863 g_value_init (&value, GST_TYPE_BUFFER);
864 gst_value_set_buffer (&value, buf2);
865 gst_value_array_append_value (&array, &value);
866 g_value_unset (&value);
867 g_value_init (&value, GST_TYPE_BUFFER);
868 gst_value_set_buffer (&value, buf3);
869 gst_value_array_append_value (&array, &value);
870 gst_structure_set_value (structure, "streamheader", &array);
871 g_value_unset (&value);
872 g_value_unset (&array);
878 gst_vorbisenc_sink_event (GstPad * pad, GstEvent * event)
881 GstVorbisEnc *vorbisenc;
883 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
885 switch (GST_EVENT_TYPE (event)) {
887 /* Tell the library we're at end of stream so that it can handle
888 * the last frame and mark end of stream in the output properly */
889 GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on");
890 gst_vorbisenc_clear (vorbisenc);
892 res = gst_pad_push_event (vorbisenc->srcpad, event);
895 if (vorbisenc->tags) {
898 gst_event_parse_tag (event, &list);
899 gst_tag_list_insert (vorbisenc->tags, list,
900 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
902 g_assert_not_reached ();
904 res = gst_pad_push_event (vorbisenc->srcpad, event);
907 res = gst_pad_push_event (vorbisenc->srcpad, event);
914 gst_vorbisenc_chain (GstPad * pad, GstBuffer * buffer)
916 GstBuffer *buf = GST_BUFFER (buffer);
917 GstVorbisEnc *vorbisenc;
918 GstFlowReturn ret = GST_FLOW_OK;
920 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
928 if (!vorbisenc->setup) {
929 gst_buffer_unref (buf);
930 GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL),
931 ("encoder not initialized (input is not audio?)"));
932 return GST_FLOW_UNEXPECTED;
935 if (!vorbisenc->header_sent) {
936 /* Vorbis streams begin with three headers; the initial header (with
937 most of the codec setup parameters) which is mandated by the Ogg
938 bitstream spec. The second header holds any comment fields. The
939 third header holds the bitstream codebook. We merely need to
940 make the headers, then pass them to libvorbis one at a time;
941 libvorbis handles the additional Ogg bitstream constraints */
943 ogg_packet header_comm;
944 ogg_packet header_code;
945 GstBuffer *buf1, *buf2, *buf3;
948 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
949 gst_vorbisenc_set_metadata (vorbisenc);
950 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
951 &header_comm, &header_code);
953 /* create header buffers */
954 buf1 = gst_vorbisenc_buffer_from_packet (vorbisenc, &header);
955 buf2 = gst_vorbisenc_buffer_from_packet (vorbisenc, &header_comm);
956 buf3 = gst_vorbisenc_buffer_from_packet (vorbisenc, &header_code);
958 /* mark and put on caps */
959 caps = gst_pad_get_caps (vorbisenc->srcpad);
960 caps = gst_vorbisenc_set_header_on_caps (caps, buf1, buf2, buf3);
962 /* negotiate with these caps */
963 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
964 gst_pad_set_caps (vorbisenc->srcpad, caps);
966 gst_buffer_set_caps (buf1, caps);
967 gst_buffer_set_caps (buf2, caps);
968 gst_buffer_set_caps (buf3, caps);
970 /* push out buffers */
971 if ((ret = gst_vorbisenc_push_buffer (vorbisenc, buf1)) != GST_FLOW_OK)
973 if ((ret = gst_vorbisenc_push_buffer (vorbisenc, buf2)) != GST_FLOW_OK)
975 if ((ret = gst_vorbisenc_push_buffer (vorbisenc, buf3)) != GST_FLOW_OK)
978 vorbisenc->header_sent = TRUE;
982 data = (gfloat *) GST_BUFFER_DATA (buf);
983 size = GST_BUFFER_SIZE (buf) / (vorbisenc->channels * sizeof (float));
985 /* expose the buffer to submit data */
986 buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
988 /* uninterleave samples */
989 for (i = 0; i < size; i++) {
990 for (j = 0; j < vorbisenc->channels; j++) {
991 buffer[j][i] = *data++;
995 /* tell the library how much we actually submitted */
996 vorbis_analysis_wrote (&vorbisenc->vd, size);
998 vorbisenc->samples_in += size;
1000 gst_buffer_unref (buf);
1003 ret = gst_vorbisenc_output_buffers (vorbisenc);
1009 static GstFlowReturn
1010 gst_vorbisenc_output_buffers (GstVorbisEnc * vorbisenc)
1014 /* vorbis does some data preanalysis, then divides up blocks for
1015 more involved (potentially parallel) processing. Get a single
1016 block for encoding now */
1017 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
1020 GST_LOG_OBJECT (vorbisenc, "analysed to a block");
1023 vorbis_analysis (&vorbisenc->vb, NULL);
1024 vorbis_bitrate_addblock (&vorbisenc->vb);
1026 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
1027 GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
1028 ret = gst_vorbisenc_push_packet (vorbisenc, &op);
1030 if (ret != GST_FLOW_OK)
1039 gst_vorbisenc_get_property (GObject * object, guint prop_id, GValue * value,
1042 GstVorbisEnc *vorbisenc;
1044 g_return_if_fail (GST_IS_VORBISENC (object));
1046 vorbisenc = GST_VORBISENC (object);
1049 case ARG_MAX_BITRATE:
1050 g_value_set_int (value, vorbisenc->max_bitrate);
1053 g_value_set_int (value, vorbisenc->bitrate);
1055 case ARG_MIN_BITRATE:
1056 g_value_set_int (value, vorbisenc->min_bitrate);
1059 g_value_set_float (value, vorbisenc->quality);
1062 g_value_set_boolean (value, vorbisenc->managed);
1064 case ARG_LAST_MESSAGE:
1065 g_value_set_string (value, vorbisenc->last_message);
1068 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1074 gst_vorbisenc_set_property (GObject * object, guint prop_id,
1075 const GValue * value, GParamSpec * pspec)
1077 GstVorbisEnc *vorbisenc;
1079 g_return_if_fail (GST_IS_VORBISENC (object));
1081 vorbisenc = GST_VORBISENC (object);
1084 case ARG_MAX_BITRATE:
1086 gboolean old_value = vorbisenc->managed;
1088 vorbisenc->max_bitrate = g_value_get_int (value);
1089 if (vorbisenc->max_bitrate >= 0
1090 && vorbisenc->max_bitrate < LOWEST_BITRATE) {
1091 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1092 vorbisenc->max_bitrate = LOWEST_BITRATE;
1094 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1095 vorbisenc->managed = TRUE;
1097 vorbisenc->managed = FALSE;
1099 if (old_value != vorbisenc->managed)
1100 g_object_notify (object, "managed");
1104 vorbisenc->bitrate = g_value_get_int (value);
1105 if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
1106 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1107 vorbisenc->bitrate = LOWEST_BITRATE;
1110 case ARG_MIN_BITRATE:
1112 gboolean old_value = vorbisenc->managed;
1114 vorbisenc->min_bitrate = g_value_get_int (value);
1115 if (vorbisenc->min_bitrate >= 0
1116 && vorbisenc->min_bitrate < LOWEST_BITRATE) {
1117 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1118 vorbisenc->min_bitrate = LOWEST_BITRATE;
1120 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1121 vorbisenc->managed = TRUE;
1123 vorbisenc->managed = FALSE;
1125 if (old_value != vorbisenc->managed)
1126 g_object_notify (object, "managed");
1130 vorbisenc->quality = g_value_get_float (value);
1131 if (vorbisenc->quality >= 0.0)
1132 vorbisenc->quality_set = TRUE;
1134 vorbisenc->quality_set = FALSE;
1137 vorbisenc->managed = g_value_get_boolean (value);
1140 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1145 static GstStateChangeReturn
1146 gst_vorbisenc_change_state (GstElement * element, GstStateChange transition)
1148 GstVorbisEnc *vorbisenc = GST_VORBISENC (element);
1149 GstStateChangeReturn res;
1152 switch (transition) {
1153 case GST_STATE_CHANGE_NULL_TO_READY:
1154 vorbisenc->tags = gst_tag_list_new ();
1156 case GST_STATE_CHANGE_READY_TO_PAUSED:
1157 vorbisenc->setup = FALSE;
1158 vorbisenc->header_sent = FALSE;
1160 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1166 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1168 switch (transition) {
1169 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1171 case GST_STATE_CHANGE_PAUSED_TO_READY:
1172 vorbis_block_clear (&vorbisenc->vb);
1173 vorbis_dsp_clear (&vorbisenc->vd);
1174 vorbis_info_clear (&vorbisenc->vi);
1175 g_free (vorbisenc->last_message);
1176 vorbisenc->last_message = NULL;
1178 case GST_STATE_CHANGE_READY_TO_NULL:
1179 gst_tag_list_free (vorbisenc->tags);
1180 vorbisenc->tags = NULL;