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.
27 #include <vorbis/vorbisenc.h>
29 #include <gst/gsttaginterface.h>
30 #include "vorbisenc.h"
32 static GstPadTemplate *gst_vorbisenc_src_template, *gst_vorbisenc_sink_template;
34 /* elementfactory information */
35 GstElementDetails vorbisenc_details = {
37 "Codec/Encoder/Audio",
38 "Encodes audio in OGG Vorbis format",
39 "Monty <monty@xiph.org>, "
40 "Wim Taymans <wim.taymans@chello.be>",
43 /* VorbisEnc signals and args */
62 static const GstFormat*
63 gst_vorbisenc_get_formats (GstPad *pad)
65 static const GstFormat src_formats[] = {
70 static const GstFormat sink_formats[] = {
77 return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
80 #define MAX_BITRATE_DEFAULT -1
81 #define BITRATE_DEFAULT -1
82 #define MIN_BITRATE_DEFAULT -1
83 #define QUALITY_DEFAULT 0.3
85 static void gst_vorbisenc_base_init (gpointer g_class);
86 static void gst_vorbisenc_class_init (VorbisEncClass *klass);
87 static void gst_vorbisenc_init (VorbisEnc *vorbisenc);
89 static void gst_vorbisenc_chain (GstPad *pad, GstData *_data);
90 static gboolean gst_vorbisenc_setup (VorbisEnc *vorbisenc);
92 static void gst_vorbisenc_get_property (GObject *object, guint prop_id,
93 GValue *value, GParamSpec *pspec);
94 static void gst_vorbisenc_set_property (GObject *object, guint prop_id,
95 const GValue *value, GParamSpec *pspec);
96 static GstElementStateReturn
97 gst_vorbisenc_change_state (GstElement *element);
99 static GstElementClass *parent_class = NULL;
100 /*static guint gst_vorbisenc_signals[LAST_SIGNAL] = { 0 }; */
103 vorbisenc_get_type (void)
105 static GType vorbisenc_type = 0;
107 if (!vorbisenc_type) {
108 static const GTypeInfo vorbisenc_info = {
109 sizeof (VorbisEncClass),
110 gst_vorbisenc_base_init,
112 (GClassInitFunc) gst_vorbisenc_class_init,
117 (GInstanceInitFunc) gst_vorbisenc_init,
119 static const GInterfaceInfo tag_setter_info = {
125 vorbisenc_type = g_type_register_static (GST_TYPE_ELEMENT, "VorbisEnc", &vorbisenc_info, 0);
127 g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER, &tag_setter_info);
129 return vorbisenc_type;
133 vorbis_caps_factory (void)
135 return gst_caps_new_simple ("application/ogg", NULL);
139 raw_caps_factory (void)
142 gst_caps_new_simple ("audio/x-raw-int",
143 "endianness", G_TYPE_INT, G_BYTE_ORDER,
144 "signed", G_TYPE_BOOLEAN, TRUE,
145 "width", G_TYPE_INT, 16,
146 "depth", G_TYPE_INT, 16,
147 "rate", GST_TYPE_INT_RANGE, 11025, 48000,
148 "channels", GST_TYPE_INT_RANGE, 1, 2,
153 gst_vorbisenc_base_init (gpointer g_class)
155 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
156 GstCaps *raw_caps, *vorbis_caps;
158 raw_caps = raw_caps_factory ();
159 vorbis_caps = vorbis_caps_factory ();
161 gst_vorbisenc_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
164 gst_vorbisenc_src_template = gst_pad_template_new ("src", GST_PAD_SRC,
167 gst_element_class_add_pad_template (element_class, gst_vorbisenc_sink_template);
168 gst_element_class_add_pad_template (element_class, gst_vorbisenc_src_template);
169 gst_element_class_set_details (element_class, &vorbisenc_details);
173 gst_vorbisenc_class_init (VorbisEncClass * klass)
175 GObjectClass *gobject_class;
176 GstElementClass *gstelement_class;
178 gobject_class = (GObjectClass *) klass;
179 gstelement_class = (GstElementClass *) klass;
181 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
182 g_param_spec_int ("max_bitrate", "Max bitrate",
183 " Specify a minimum bitrate (in bps). Useful for encoding for a fixed-size channel",
184 -1, G_MAXINT, MAX_BITRATE_DEFAULT, G_PARAM_READWRITE));
185 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
186 g_param_spec_int ("bitrate", "Bitrate", "Choose a bitrate to encode at. "
187 "Attempt to encode at a bitrate averaging this. Takes an argument in kbps.",
188 -1, G_MAXINT, BITRATE_DEFAULT, G_PARAM_READWRITE));
189 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
190 g_param_spec_int ("min_bitrate", "Min bitrate",
191 "Specify a maximum bitrate in bps. Useful for streaming applications.",
192 -1, G_MAXINT, MIN_BITRATE_DEFAULT, G_PARAM_READWRITE));
193 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
194 g_param_spec_float ("quality", "Quality",
195 "Specify quality instead of specifying a particular bitrate.",
196 0.0, 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE));
197 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SERIAL,
198 g_param_spec_int ("serial", "Serial", "Specify a serial number for the stream. (-1 is random)",
199 -1, G_MAXINT, -1, G_PARAM_READWRITE));
200 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
201 g_param_spec_boolean ("managed", "Managed", "Enable bitrate management engine",
202 FALSE, G_PARAM_READWRITE));
203 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
204 g_param_spec_string ("last-message", "last-message", "The last status message",
205 NULL, G_PARAM_READABLE));
207 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
209 gobject_class->set_property = gst_vorbisenc_set_property;
210 gobject_class->get_property = gst_vorbisenc_get_property;
212 gstelement_class->change_state = gst_vorbisenc_change_state;
215 static GstPadLinkReturn
216 gst_vorbisenc_sinkconnect (GstPad * pad, const GstCaps * caps)
218 VorbisEnc *vorbisenc;
219 GstStructure *structure;
221 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
223 structure = gst_caps_get_structure (caps, 0);
224 gst_structure_get_int (structure, "channels", &vorbisenc->channels);
225 gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
227 gst_vorbisenc_setup (vorbisenc);
229 if (vorbisenc->setup)
230 return GST_PAD_LINK_OK;
232 return GST_PAD_LINK_REFUSED;
236 gst_vorbisenc_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
237 GstFormat *dest_format, gint64 *dest_value)
240 VorbisEnc *vorbisenc;
243 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
245 if (vorbisenc->samples_in == 0 ||
246 vorbisenc->bytes_out == 0 ||
247 vorbisenc->frequency == 0)
250 avg = (vorbisenc->bytes_out * vorbisenc->frequency)/
251 (vorbisenc->samples_in);
253 switch (src_format) {
254 case GST_FORMAT_BYTES:
255 switch (*dest_format) {
256 case GST_FORMAT_TIME:
257 *dest_value = src_value * GST_SECOND / avg;
263 case GST_FORMAT_TIME:
264 switch (*dest_format) {
265 case GST_FORMAT_BYTES:
266 *dest_value = src_value * avg / GST_SECOND;
279 gst_vorbisenc_convert_sink (GstPad *pad, GstFormat src_format, gint64 src_value,
280 GstFormat *dest_format, gint64 *dest_value)
284 gint bytes_per_sample;
285 VorbisEnc *vorbisenc;
287 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
289 bytes_per_sample = vorbisenc->channels * 2;
291 switch (src_format) {
292 case GST_FORMAT_BYTES:
293 switch (*dest_format) {
294 case GST_FORMAT_DEFAULT:
295 if (bytes_per_sample == 0)
297 *dest_value = src_value / bytes_per_sample;
299 case GST_FORMAT_TIME:
301 gint byterate = bytes_per_sample * vorbisenc->frequency;
305 *dest_value = src_value * GST_SECOND / byterate;
312 case GST_FORMAT_DEFAULT:
313 switch (*dest_format) {
314 case GST_FORMAT_BYTES:
315 *dest_value = src_value * bytes_per_sample;
317 case GST_FORMAT_TIME:
318 if (vorbisenc->frequency == 0)
320 *dest_value = src_value * GST_SECOND / vorbisenc->frequency;
326 case GST_FORMAT_TIME:
327 switch (*dest_format) {
328 case GST_FORMAT_BYTES:
329 scale = bytes_per_sample;
331 case GST_FORMAT_DEFAULT:
332 *dest_value = src_value * scale * vorbisenc->frequency / GST_SECOND;
344 static const GstQueryType*
345 gst_vorbisenc_get_query_types (GstPad *pad)
347 static const GstQueryType gst_vorbisenc_src_query_types[] = {
352 return gst_vorbisenc_src_query_types;
356 gst_vorbisenc_src_query (GstPad *pad, GstQueryType type,
357 GstFormat *format, gint64 *value)
360 VorbisEnc *vorbisenc;
362 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
365 case GST_QUERY_TOTAL:
368 case GST_FORMAT_BYTES:
369 case GST_FORMAT_TIME:
372 const GstFormat *peer_formats;
376 peer_formats = gst_pad_get_formats (GST_PAD_PEER (vorbisenc->sinkpad));
378 while (peer_formats && *peer_formats && !res) {
380 GstFormat peer_format = *peer_formats;
383 if (gst_pad_query (GST_PAD_PEER (vorbisenc->sinkpad), GST_QUERY_TOTAL,
384 &peer_format, &peer_value))
386 GstFormat conv_format;
387 /* convert to TIME */
388 conv_format = GST_FORMAT_TIME;
389 res = gst_pad_convert (vorbisenc->sinkpad,
390 peer_format, peer_value,
391 &conv_format, value);
392 /* and to final format */
393 res &= gst_pad_convert (pad,
394 GST_FORMAT_TIME, *value,
407 case GST_QUERY_POSITION:
411 /* we only know about our samples, convert to requested format */
412 res = gst_pad_convert (pad,
413 GST_FORMAT_BYTES, vorbisenc->bytes_out,
427 gst_vorbisenc_init (VorbisEnc * vorbisenc)
429 vorbisenc->sinkpad = gst_pad_new_from_template (gst_vorbisenc_sink_template, "sink");
430 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
431 gst_pad_set_chain_function (vorbisenc->sinkpad, gst_vorbisenc_chain);
432 gst_pad_set_link_function (vorbisenc->sinkpad, gst_vorbisenc_sinkconnect);
433 gst_pad_set_convert_function (vorbisenc->sinkpad, GST_DEBUG_FUNCPTR (gst_vorbisenc_convert_sink));
434 gst_pad_set_formats_function (vorbisenc->sinkpad, GST_DEBUG_FUNCPTR (gst_vorbisenc_get_formats));
436 vorbisenc->srcpad = gst_pad_new_from_template (gst_vorbisenc_src_template, "src");
437 gst_pad_set_query_function (vorbisenc->srcpad, GST_DEBUG_FUNCPTR (gst_vorbisenc_src_query));
438 gst_pad_set_query_type_function (vorbisenc->srcpad, GST_DEBUG_FUNCPTR (gst_vorbisenc_get_query_types));
439 gst_pad_set_convert_function (vorbisenc->srcpad, GST_DEBUG_FUNCPTR (gst_vorbisenc_convert_src));
440 gst_pad_set_formats_function (vorbisenc->srcpad, GST_DEBUG_FUNCPTR (gst_vorbisenc_get_formats));
441 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
443 vorbisenc->channels = -1;
444 vorbisenc->frequency = -1;
446 vorbisenc->managed = FALSE;
447 vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
448 vorbisenc->bitrate = BITRATE_DEFAULT;
449 vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
450 vorbisenc->quality = QUALITY_DEFAULT;
451 vorbisenc->quality_set = FALSE;
452 vorbisenc->serial = -1;
453 vorbisenc->last_message = NULL;
455 vorbisenc->setup = FALSE;
456 vorbisenc->eos = FALSE;
457 vorbisenc->header_sent = FALSE;
459 vorbisenc->tags = gst_tag_list_new ();
461 /* we're chained and we can deal with events */
462 GST_FLAG_SET (vorbisenc, GST_ELEMENT_EVENT_AWARE);
466 gst_vorbisenc_metadata_set1 (const GstTagList *list, const gchar *tag, gpointer vorbisenc)
468 gchar *vorbistag = NULL;
469 gchar *vorbisvalue = NULL;
471 VorbisEnc *enc = GST_VORBISENC (vorbisenc);
473 count = gst_tag_list_get_tag_size (list, tag);
474 for (i = 0; i < count; i++) {
475 /* get tag name right */
476 if (strcmp (tag, GST_TAG_TITLE) == 0) {
477 vorbistag = g_strdup ("TITLE");
478 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
479 } else if (strcmp (tag, GST_TAG_VERSION) == 0) {
480 vorbistag = g_strdup ("VERSION");
481 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
482 } else if (strcmp (tag, GST_TAG_ALBUM) == 0) {
483 vorbistag = g_strdup ("ALBUM");
484 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
485 } else if (strcmp (tag, GST_TAG_TRACK_NUMBER) == 0) {
487 vorbistag = g_strdup ("TRACKNUMBER");
488 g_assert (gst_tag_list_get_uint_index (list, tag, i, &track_no));
489 vorbisvalue = g_strdup_printf ("%u", track_no);
490 } else if (strcmp (tag, GST_TAG_ARTIST) == 0) {
491 vorbistag = g_strdup ("ARTIST");
492 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
493 } else if (strcmp (tag, GST_TAG_PERFORMER) == 0) {
494 vorbistag = g_strdup ("PERFORMER");
495 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
496 } else if (strcmp (tag, GST_TAG_COPYRIGHT) == 0) {
497 vorbistag = g_strdup ("COPYRIGHT");
498 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
499 } else if (strcmp (tag, GST_TAG_LICENSE) == 0) {
500 vorbistag = g_strdup ("LICENSE");
501 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
502 } else if (strcmp (tag, GST_TAG_ORGANIZATION) == 0) {
503 vorbistag = g_strdup ("ORGANIZATION");
504 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
505 } else if (strcmp (tag, GST_TAG_DESCRIPTION) == 0) {
506 vorbistag = g_strdup ("DESCRIPTION");
507 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
508 } else if (strcmp (tag, GST_TAG_GENRE) == 0) {
509 vorbistag = g_strdup ("GENRE");
510 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
511 } else if (strcmp (tag, GST_TAG_DATE) == 0) {
512 /* FIXME: how are dates represented in vorbis files? */
516 vorbistag = g_strdup ("DATE");
517 g_assert (gst_tag_list_get_uint_index (list, tag, i, &u));
518 date = g_date_new_julian (u);
519 vorbisvalue = g_strdup_printf ("%04d-%02d-%02d", (gint) g_date_get_year (date),
520 (gint) g_date_get_month (date), (gint) g_date_get_day (date));
522 /* NOTE: GST_TAG_LOCATION != vorbis' location
523 } else if (strcmp (tag, PLACE) == 0) {
524 vorbistag = g_strdup ("LOCATION");
525 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
527 } else if (strcmp (tag, GST_TAG_CONTACT) == 0) {
528 vorbistag = g_strdup ("CONTACT");
529 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
530 } else if (strcmp (tag, GST_TAG_ISRC) == 0) {
531 vorbistag = g_strdup ("ISRC");
532 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
534 vorbistag = g_ascii_strup (tag, -1);
535 if (gst_tag_get_type (tag) == G_TYPE_STRING) {
536 g_assert (gst_tag_list_get_string_index (list, tag, i, &vorbisvalue));
538 const GValue *value = gst_tag_list_get_value_index (list, tag, i);
539 vorbisvalue = g_strdup_value_contents (value);
544 vorbis_comment_add_tag (&enc->vc, vorbistag, vorbisvalue);
547 gst_vorbisenc_set_metadata (VorbisEnc *vorbisenc)
550 const GstTagList *user_tags;
552 user_tags = gst_tag_setter_get_list (GST_TAG_SETTER (vorbisenc));
553 if (!(vorbisenc->tags || user_tags))
556 copy = gst_tag_list_merge (user_tags, vorbisenc->tags, gst_tag_setter_get_merge_mode (GST_TAG_SETTER (vorbisenc)));
557 vorbis_comment_init (&vorbisenc->vc);
558 gst_tag_list_foreach (copy, gst_vorbisenc_metadata_set1, vorbisenc);
559 gst_tag_list_free (copy);
563 get_constraints_string (VorbisEnc *vorbisenc)
565 gint min = vorbisenc->min_bitrate;
566 gint max = vorbisenc->max_bitrate;
569 if (min > 0 && max > 0)
570 result = g_strdup_printf ("(min %d bps, max %d bps)", min,max);
572 result = g_strdup_printf ("(min %d bps, no max)", min);
574 result = g_strdup_printf ("(no min, max %d bps)", max);
576 result = g_strdup_printf ("(no min or max)");
582 update_start_message (VorbisEnc *vorbisenc)
586 g_free (vorbisenc->last_message);
588 if (vorbisenc->bitrate > 0) {
589 if (vorbisenc->managed) {
590 constraints = get_constraints_string (vorbisenc);
591 vorbisenc->last_message =
592 g_strdup_printf ("encoding at average bitrate %d bps %s",
593 vorbisenc->bitrate, constraints);
594 g_free (constraints);
597 vorbisenc->last_message =
598 g_strdup_printf ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
603 if (vorbisenc->quality_set) {
604 if (vorbisenc->managed) {
605 constraints = get_constraints_string (vorbisenc);
606 vorbisenc->last_message =
607 g_strdup_printf ("encoding at quality level %2.2f using constrained VBR %s",
608 vorbisenc->quality, constraints);
609 g_free (constraints);
612 vorbisenc->last_message =
613 g_strdup_printf ("encoding at quality level %2.2f",
618 constraints = get_constraints_string (vorbisenc);
619 vorbisenc->last_message =
620 g_strdup_printf ("encoding using bitrate management %s",
622 g_free (constraints);
626 g_object_notify (G_OBJECT (vorbisenc), "last_message");
630 gst_vorbisenc_setup (VorbisEnc *vorbisenc)
634 if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0 && vorbisenc->max_bitrate < 0) {
635 vorbisenc->quality_set = TRUE;
638 update_start_message (vorbisenc);
640 /* choose an encoding mode */
641 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
642 vorbis_info_init (&vorbisenc->vi);
644 if(vorbisenc->quality_set){
645 if (vorbis_encode_setup_vbr (&vorbisenc->vi,
647 vorbisenc->frequency,
650 g_warning ("vorbisenc: initialisation failed: invalid parameters for quality");
651 vorbis_info_clear(&vorbisenc->vi);
655 /* do we have optional hard quality restrictions? */
656 if(vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0){
657 struct ovectl_ratemanage_arg ai;
658 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
660 /* the bitrates are in kHz */
661 ai.bitrate_hard_min = vorbisenc->min_bitrate / 1000;
662 ai.bitrate_hard_max = vorbisenc->max_bitrate / 1000;
663 ai.management_active = 1;
665 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
669 if (vorbis_encode_setup_managed (&vorbisenc->vi,
671 vorbisenc->frequency,
672 vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1,
674 vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1))
676 g_warning("vorbisenc: initialisation failed: invalid parameters for bitrate\n");
677 vorbis_info_clear(&vorbisenc->vi);
682 if(vorbisenc->managed && vorbisenc->bitrate < 0) {
683 vorbis_encode_ctl(&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
685 else if(!vorbisenc->managed) {
686 /* Turn off management entirely (if it was turned on). */
687 vorbis_encode_ctl(&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
689 vorbis_encode_setup_init(&vorbisenc->vi);
691 /* set up the analysis state and auxiliary encoding storage */
692 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
693 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
695 /* set up our packet->stream encoder */
696 /* pick a random serial number; that way we can more likely build
697 chained streams just by concatenation */
698 if (vorbisenc->serial < 0) {
703 serial = vorbisenc->serial;
706 ogg_stream_init (&vorbisenc->os, serial);
708 vorbisenc->setup = TRUE;
714 gst_vorbisenc_write_page (VorbisEnc *vorbisenc, ogg_page *page)
718 outbuf = gst_buffer_new_and_alloc (page->header_len +
721 memcpy (GST_BUFFER_DATA (outbuf), page->header,
723 memcpy (GST_BUFFER_DATA (outbuf) + page->header_len,
727 GST_DEBUG ("vorbisenc: encoded buffer of %d bytes",
728 GST_BUFFER_SIZE (outbuf));
730 vorbisenc->bytes_out += GST_BUFFER_SIZE (outbuf);
732 if (GST_PAD_IS_USABLE (vorbisenc->srcpad)) {
733 gst_pad_push (vorbisenc->srcpad, GST_DATA (outbuf));
736 gst_buffer_unref (outbuf);
741 gst_vorbisenc_chain (GstPad * pad, GstData *_data)
743 GstBuffer *buf = GST_BUFFER (_data);
744 VorbisEnc *vorbisenc;
746 g_return_if_fail (pad != NULL);
747 g_return_if_fail (GST_IS_PAD (pad));
748 g_return_if_fail (buf != NULL);
750 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
752 if (GST_IS_EVENT (buf)) {
753 GstEvent *event = GST_EVENT (buf);
755 switch (GST_EVENT_TYPE (event)) {
757 /* end of file. this can be done implicitly in the mainline,
758 but it's easier to see here in non-clever fashion.
759 Tell the library we're at end of stream so that it can handle
760 the last frame and mark end of stream in the output properly */
761 vorbis_analysis_wrote (&vorbisenc->vd, 0);
762 gst_event_unref (event);
765 if (vorbisenc->tags) {
766 gst_tag_list_merge (vorbisenc->tags, gst_event_tag_get_list (event),
767 gst_tag_setter_get_merge_mode (GST_TAG_SETTER (vorbisenc)));
769 g_assert_not_reached ();
771 gst_pad_event_default (pad, event);
774 gst_pad_event_default (pad, event);
784 if (!vorbisenc->setup) {
785 gst_buffer_unref (buf);
786 GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL), ("encoder not initialized (input is not audio?)"));
790 if (!vorbisenc->header_sent) {
792 /* Vorbis streams begin with three headers; the initial header (with
793 most of the codec setup parameters) which is mandated by the Ogg
794 bitstream spec. The second header holds any comment fields. The
795 third header holds the bitstream codebook. We merely need to
796 make the headers, then pass them to libvorbis one at a time;
797 libvorbis handles the additional Ogg bitstream constraints */
799 ogg_packet header_comm;
800 ogg_packet header_code;
802 gst_vorbisenc_set_metadata (vorbisenc);
803 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header, &header_comm, &header_code);
804 ogg_stream_packetin (&vorbisenc->os, &header); /* automatically placed in its own page */
805 ogg_stream_packetin (&vorbisenc->os, &header_comm);
806 ogg_stream_packetin (&vorbisenc->os, &header_code);
808 while ((result = ogg_stream_flush(&vorbisenc->os, &vorbisenc->og))) {
809 gst_vorbisenc_write_page (vorbisenc, &vorbisenc->og);
811 vorbisenc->header_sent = TRUE;
815 data = (gint16 *) GST_BUFFER_DATA (buf);
816 size = GST_BUFFER_SIZE (buf) / (vorbisenc->channels * 2);
818 /* expose the buffer to submit data */
819 buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
821 /* uninterleave samples */
822 for (i = 0; i < size; i++) {
823 for (j = 0; j < vorbisenc->channels; j++) {
824 buffer[j][i] = data[i * vorbisenc->channels + j] / 32768.f;
828 /* tell the library how much we actually submitted */
829 vorbis_analysis_wrote (&vorbisenc->vd, size);
831 vorbisenc->samples_in += size;
833 gst_buffer_unref (buf);
836 /* vorbis does some data preanalysis, then divvies up blocks for
837 more involved (potentially parallel) processing. Get a single
838 block for encoding now */
839 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
842 vorbis_analysis (&vorbisenc->vb, NULL);
843 vorbis_bitrate_addblock(&vorbisenc->vb);
845 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &vorbisenc->op)) {
847 /* weld the packet into the bitstream */
848 ogg_stream_packetin (&vorbisenc->os, &vorbisenc->op);
850 /* write out pages (if any) */
851 while (!vorbisenc->eos) {
852 int result = ogg_stream_pageout (&vorbisenc->os, &vorbisenc->og);
857 gst_vorbisenc_write_page (vorbisenc, &vorbisenc->og);
859 /* this could be set above, but for illustrative purposes, I do
860 it here (to show that vorbis does know where the stream ends) */
861 if (ogg_page_eos (&vorbisenc->og)) {
868 if (vorbisenc->eos) {
869 /* clean up and exit. vorbis_info_clear() must be called last */
870 ogg_stream_clear (&vorbisenc->os);
871 vorbis_block_clear (&vorbisenc->vb);
872 vorbis_dsp_clear (&vorbisenc->vd);
873 vorbis_info_clear (&vorbisenc->vi);
874 gst_pad_push (vorbisenc->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
875 gst_element_set_eos (GST_ELEMENT (vorbisenc));
880 gst_vorbisenc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
882 VorbisEnc *vorbisenc;
884 /* it's not null if we got it, but it might not be ours */
885 g_return_if_fail (GST_IS_VORBISENC (object));
887 vorbisenc = GST_VORBISENC (object);
890 case ARG_MAX_BITRATE:
891 g_value_set_int (value, vorbisenc->max_bitrate);
894 g_value_set_int (value, vorbisenc->bitrate);
896 case ARG_MIN_BITRATE:
897 g_value_set_int (value, vorbisenc->min_bitrate);
900 g_value_set_float (value, vorbisenc->quality);
903 g_value_set_int (value, vorbisenc->serial);
906 g_value_set_boolean (value, vorbisenc->managed);
908 case ARG_LAST_MESSAGE:
909 g_value_set_string (value, vorbisenc->last_message);
912 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
918 gst_vorbisenc_set_property (GObject * object, guint prop_id, const GValue * value,
921 VorbisEnc *vorbisenc;
923 /* it's not null if we got it, but it might not be ours */
924 g_return_if_fail (GST_IS_VORBISENC (object));
926 vorbisenc = GST_VORBISENC (object);
929 case ARG_MAX_BITRATE:
931 gboolean old_value = vorbisenc->managed;
933 vorbisenc->max_bitrate = g_value_get_int (value);
934 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
935 vorbisenc->managed = TRUE;
937 vorbisenc->managed = FALSE;
939 if (old_value != vorbisenc->managed)
940 g_object_notify (object, "managed");
944 vorbisenc->bitrate = g_value_get_int (value);
946 case ARG_MIN_BITRATE:
948 gboolean old_value = vorbisenc->managed;
950 vorbisenc->min_bitrate = g_value_get_int (value);
951 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
952 vorbisenc->managed = TRUE;
954 vorbisenc->managed = FALSE;
956 if (old_value != vorbisenc->managed)
957 g_object_notify (object, "managed");
961 vorbisenc->quality = g_value_get_float (value);
962 if (vorbisenc->quality >= 0.0)
963 vorbisenc->quality_set = TRUE;
965 vorbisenc->quality_set = FALSE;
968 vorbisenc->serial = g_value_get_int (value);
971 vorbisenc->managed = g_value_get_boolean (value);
974 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
979 static GstElementStateReturn
980 gst_vorbisenc_change_state (GstElement *element)
982 VorbisEnc *vorbisenc = GST_VORBISENC (element);
984 switch (GST_STATE_TRANSITION (element)) {
985 case GST_STATE_NULL_TO_READY:
986 case GST_STATE_READY_TO_PAUSED:
987 vorbisenc->eos = FALSE;
989 case GST_STATE_PAUSED_TO_PLAYING:
990 case GST_STATE_PLAYING_TO_PAUSED:
992 case GST_STATE_PAUSED_TO_READY:
993 vorbisenc->setup = FALSE;
994 vorbisenc->header_sent = FALSE;
995 gst_tag_list_free (vorbisenc->tags);
996 vorbisenc->tags = gst_tag_list_new ();
998 case GST_STATE_READY_TO_NULL:
1003 if (GST_ELEMENT_CLASS (parent_class)->change_state)
1004 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
1006 return GST_STATE_SUCCESS;