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, 256 ], " "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);
92 /* this function takes into account the granulepos_offset and the subgranule
95 granulepos_to_timestamp_offset (GstVorbisEnc * vorbisenc,
96 ogg_int64_t granulepos)
99 return gst_util_uint64_scale ((guint64) granulepos
100 + vorbisenc->granulepos_offset, GST_SECOND, vorbisenc->frequency)
101 + vorbisenc->subgranule_offset;
102 return GST_CLOCK_TIME_NONE;
105 /* this function does a straight granulepos -> timestamp conversion */
107 granulepos_to_timestamp (GstVorbisEnc * vorbisenc, ogg_int64_t granulepos)
110 return gst_util_uint64_scale ((guint64) granulepos,
111 GST_SECOND, vorbisenc->frequency);
112 return GST_CLOCK_TIME_NONE;
115 #define MAX_BITRATE_DEFAULT -1
116 #define BITRATE_DEFAULT -1
117 #define MIN_BITRATE_DEFAULT -1
118 #define QUALITY_DEFAULT 0.3
119 #define LOWEST_BITRATE 6000 /* lowest allowed for a 8 kHz stream */
120 #define HIGHEST_BITRATE 250001 /* highest allowed for a 44 kHz stream */
122 static gboolean gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event);
123 static GstFlowReturn gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer);
124 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
126 static void gst_vorbis_enc_dispose (GObject * object);
127 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
128 GValue * value, GParamSpec * pspec);
129 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
130 const GValue * value, GParamSpec * pspec);
131 static GstStateChangeReturn gst_vorbis_enc_change_state (GstElement * element,
132 GstStateChange transition);
133 static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
135 GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstElement,
136 GST_TYPE_ELEMENT, gst_vorbis_enc_add_interfaces);
139 gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
141 static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
142 static const GInterfaceInfo preset_info = { NULL, NULL, NULL };
144 g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
146 g_type_add_interface_static (vorbisenc_type, GST_TYPE_PRESET, &preset_info);
150 gst_vorbis_enc_base_init (gpointer g_class)
152 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
153 GstPadTemplate *src_template, *sink_template;
156 src_template = gst_static_pad_template_get (&vorbis_enc_src_factory);
157 gst_element_class_add_pad_template (element_class, src_template);
159 sink_template = gst_static_pad_template_get (&vorbis_enc_sink_factory);
160 gst_element_class_add_pad_template (element_class, sink_template);
161 gst_element_class_set_details_simple (element_class,
162 "Vorbis audio encoder", "Codec/Encoder/Audio",
163 "Encodes audio in Vorbis format",
164 "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
168 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
170 GObjectClass *gobject_class;
171 GstElementClass *gstelement_class;
173 gobject_class = (GObjectClass *) klass;
174 gstelement_class = (GstElementClass *) klass;
176 gobject_class->set_property = gst_vorbis_enc_set_property;
177 gobject_class->get_property = gst_vorbis_enc_get_property;
178 gobject_class->dispose = gst_vorbis_enc_dispose;
180 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
181 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
182 "Specify a maximum bitrate (in bps). Useful for streaming "
183 "applications. (-1 == disabled)",
184 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
185 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
186 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
187 g_param_spec_int ("bitrate", "Target Bitrate",
188 "Attempt to encode at a bitrate averaging this (in bps). "
189 "This uses the bitrate management engine, and is not recommended for most users. "
190 "Quality is a better alternative. (-1 == disabled)", -1,
191 HIGHEST_BITRATE, BITRATE_DEFAULT,
192 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
193 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
194 g_param_spec_int ("min-bitrate", "Minimum Bitrate",
195 "Specify a minimum bitrate (in bps). Useful for encoding for a "
196 "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
197 MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
198 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
199 g_param_spec_float ("quality", "Quality",
200 "Specify quality instead of specifying a particular bitrate.", -0.1,
201 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
202 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
203 g_param_spec_boolean ("managed", "Managed",
204 "Enable bitrate management engine", FALSE,
205 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
206 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
207 g_param_spec_string ("last-message", "last-message",
208 "The last status message", NULL,
209 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
211 gstelement_class->change_state =
212 GST_DEBUG_FUNCPTR (gst_vorbis_enc_change_state);
216 gst_vorbis_enc_dispose (GObject * object)
218 GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
220 if (vorbisenc->sinkcaps) {
221 gst_caps_unref (vorbisenc->sinkcaps);
222 vorbisenc->sinkcaps = NULL;
225 G_OBJECT_CLASS (parent_class)->dispose (object);
229 gst_vorbis_enc_generate_sink_caps (void)
231 GstCaps *caps = gst_caps_new_empty ();
234 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
235 "rate", GST_TYPE_INT_RANGE, 1, 200000,
236 "channels", G_TYPE_INT, 1,
237 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
240 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
241 "rate", GST_TYPE_INT_RANGE, 1, 200000,
242 "channels", G_TYPE_INT, 2,
243 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
246 for (i = 3; i <= 8; i++) {
247 GValue chanpos = { 0 };
249 GstStructure *structure;
251 g_value_init (&chanpos, GST_TYPE_ARRAY);
252 g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
254 for (c = 0; c < i; c++) {
255 g_value_set_enum (&pos, gst_vorbis_channel_positions[i - 1][c]);
256 gst_value_array_append_value (&chanpos, &pos);
258 g_value_unset (&pos);
260 structure = gst_structure_new ("audio/x-raw-float",
261 "rate", GST_TYPE_INT_RANGE, 1, 200000,
262 "channels", G_TYPE_INT, i,
263 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
264 gst_structure_set_value (structure, "channel-positions", &chanpos);
265 g_value_unset (&chanpos);
267 gst_caps_append_structure (caps, structure);
270 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
271 "rate", GST_TYPE_INT_RANGE, 1, 200000,
272 "channels", GST_TYPE_INT_RANGE, 9, 256,
273 "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
280 gst_vorbis_enc_sink_getcaps (GstPad * pad)
282 GstVorbisEnc *vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
284 if (vorbisenc->sinkcaps == NULL)
285 vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
287 return gst_caps_ref (vorbisenc->sinkcaps);
291 gst_vorbis_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
293 GstVorbisEnc *vorbisenc;
294 GstStructure *structure;
296 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
297 vorbisenc->setup = FALSE;
299 structure = gst_caps_get_structure (caps, 0);
300 gst_structure_get_int (structure, "channels", &vorbisenc->channels);
301 gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
303 gst_vorbis_enc_setup (vorbisenc);
305 if (vorbisenc->setup)
312 gst_vorbis_enc_convert_src (GstPad * pad, GstFormat src_format,
313 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
316 GstVorbisEnc *vorbisenc;
319 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
321 if (vorbisenc->samples_in == 0 ||
322 vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0) {
323 gst_object_unref (vorbisenc);
327 avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in);
329 switch (src_format) {
330 case GST_FORMAT_BYTES:
331 switch (*dest_format) {
332 case GST_FORMAT_TIME:
333 *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, avg);
339 case GST_FORMAT_TIME:
340 switch (*dest_format) {
341 case GST_FORMAT_BYTES:
342 *dest_value = gst_util_uint64_scale_int (src_value, avg, GST_SECOND);
351 gst_object_unref (vorbisenc);
356 gst_vorbis_enc_convert_sink (GstPad * pad, GstFormat src_format,
357 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
361 gint bytes_per_sample;
362 GstVorbisEnc *vorbisenc;
364 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
366 bytes_per_sample = vorbisenc->channels * 2;
368 switch (src_format) {
369 case GST_FORMAT_BYTES:
370 switch (*dest_format) {
371 case GST_FORMAT_DEFAULT:
372 if (bytes_per_sample == 0)
374 *dest_value = src_value / bytes_per_sample;
376 case GST_FORMAT_TIME:
378 gint byterate = bytes_per_sample * vorbisenc->frequency;
383 gst_util_uint64_scale_int (src_value, GST_SECOND, byterate);
390 case GST_FORMAT_DEFAULT:
391 switch (*dest_format) {
392 case GST_FORMAT_BYTES:
393 *dest_value = src_value * bytes_per_sample;
395 case GST_FORMAT_TIME:
396 if (vorbisenc->frequency == 0)
399 gst_util_uint64_scale_int (src_value, GST_SECOND,
400 vorbisenc->frequency);
406 case GST_FORMAT_TIME:
407 switch (*dest_format) {
408 case GST_FORMAT_BYTES:
409 scale = bytes_per_sample;
411 case GST_FORMAT_DEFAULT:
413 gst_util_uint64_scale_int (src_value,
414 scale * vorbisenc->frequency, GST_SECOND);
423 gst_object_unref (vorbisenc);
428 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
430 /* FIXME, this probably depends on the bitrate and other setting but for now
431 * we return this value, which was obtained by totally unscientific
433 return 58 * GST_MSECOND;
436 static const GstQueryType *
437 gst_vorbis_enc_get_query_types (GstPad * pad)
439 static const GstQueryType gst_vorbis_enc_src_query_types[] = {
446 return gst_vorbis_enc_src_query_types;
450 gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query)
453 GstVorbisEnc *vorbisenc;
456 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
457 peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad));
459 switch (GST_QUERY_TYPE (query)) {
460 case GST_QUERY_POSITION:
462 GstFormat fmt, req_fmt;
465 gst_query_parse_position (query, &req_fmt, NULL);
466 if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
467 gst_query_set_position (query, req_fmt, val);
471 fmt = GST_FORMAT_TIME;
472 if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
475 if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
476 gst_query_set_position (query, req_fmt, val);
480 case GST_QUERY_DURATION:
482 GstFormat fmt, req_fmt;
485 gst_query_parse_duration (query, &req_fmt, NULL);
486 if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
487 gst_query_set_duration (query, req_fmt, val);
491 fmt = GST_FORMAT_TIME;
492 if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
495 if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
496 gst_query_set_duration (query, req_fmt, val);
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_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
510 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
513 case GST_QUERY_LATENCY:
516 GstClockTime min_latency, max_latency;
519 if ((res = gst_pad_query (peerpad, query))) {
520 gst_query_parse_latency (query, &live, &min_latency, &max_latency);
522 latency = gst_vorbis_enc_get_latency (vorbisenc);
524 /* add our latency */
525 min_latency += latency;
526 if (max_latency != -1)
527 max_latency += latency;
529 gst_query_set_latency (query, live, min_latency, max_latency);
534 res = gst_pad_query (peerpad, query);
539 gst_object_unref (peerpad);
540 gst_object_unref (vorbisenc);
545 gst_vorbis_enc_sink_query (GstPad * pad, GstQuery * query)
549 switch (GST_QUERY_TYPE (query)) {
550 case GST_QUERY_CONVERT:
552 GstFormat src_fmt, dest_fmt;
553 gint64 src_val, dest_val;
555 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
557 gst_vorbis_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
560 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
564 res = gst_pad_query_default (pad, query);
573 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
576 gst_pad_new_from_static_template (&vorbis_enc_sink_factory, "sink");
577 gst_pad_set_event_function (vorbisenc->sinkpad,
578 GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event));
579 gst_pad_set_chain_function (vorbisenc->sinkpad,
580 GST_DEBUG_FUNCPTR (gst_vorbis_enc_chain));
581 gst_pad_set_setcaps_function (vorbisenc->sinkpad,
582 GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_setcaps));
583 gst_pad_set_getcaps_function (vorbisenc->sinkpad,
584 GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_getcaps));
585 gst_pad_set_query_function (vorbisenc->sinkpad,
586 GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_query));
587 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
590 gst_pad_new_from_static_template (&vorbis_enc_src_factory, "src");
591 gst_pad_set_query_function (vorbisenc->srcpad,
592 GST_DEBUG_FUNCPTR (gst_vorbis_enc_src_query));
593 gst_pad_set_query_type_function (vorbisenc->srcpad,
594 GST_DEBUG_FUNCPTR (gst_vorbis_enc_get_query_types));
595 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
597 vorbisenc->channels = -1;
598 vorbisenc->frequency = -1;
600 vorbisenc->managed = FALSE;
601 vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
602 vorbisenc->bitrate = BITRATE_DEFAULT;
603 vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
604 vorbisenc->quality = QUALITY_DEFAULT;
605 vorbisenc->quality_set = FALSE;
606 vorbisenc->last_message = NULL;
610 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
613 GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
616 vc_list = gst_tag_to_vorbis_comments (list, tag);
618 for (l = vc_list; l != NULL; l = l->next) {
619 const gchar *vc_string = (const gchar *) l->data;
620 gchar *key = NULL, *val = NULL;
622 GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
623 if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
624 vorbis_comment_add_tag (&enc->vc, key, val);
630 g_list_foreach (vc_list, (GFunc) g_free, NULL);
631 g_list_free (vc_list);
635 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
637 GstTagList *merged_tags;
638 const GstTagList *user_tags;
640 vorbis_comment_init (&enc->vc);
642 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
644 GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
645 GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
647 /* gst_tag_list_merge() will handle NULL for either or both lists fine */
648 merged_tags = gst_tag_list_merge (user_tags, enc->tags,
649 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
652 GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
653 gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
654 gst_tag_list_free (merged_tags);
659 get_constraints_string (GstVorbisEnc * vorbisenc)
661 gint min = vorbisenc->min_bitrate;
662 gint max = vorbisenc->max_bitrate;
665 if (min > 0 && max > 0)
666 result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
668 result = g_strdup_printf ("(min %d bps, no max)", min);
670 result = g_strdup_printf ("(no min, max %d bps)", max);
672 result = g_strdup_printf ("(no min or max)");
678 update_start_message (GstVorbisEnc * vorbisenc)
682 g_free (vorbisenc->last_message);
684 if (vorbisenc->bitrate > 0) {
685 if (vorbisenc->managed) {
686 constraints = get_constraints_string (vorbisenc);
687 vorbisenc->last_message =
688 g_strdup_printf ("encoding at average bitrate %d bps %s",
689 vorbisenc->bitrate, constraints);
690 g_free (constraints);
692 vorbisenc->last_message =
694 ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
698 if (vorbisenc->quality_set) {
699 if (vorbisenc->managed) {
700 constraints = get_constraints_string (vorbisenc);
701 vorbisenc->last_message =
703 ("encoding at quality level %2.2f using constrained VBR %s",
704 vorbisenc->quality, constraints);
705 g_free (constraints);
707 vorbisenc->last_message =
708 g_strdup_printf ("encoding at quality level %2.2f",
712 constraints = get_constraints_string (vorbisenc);
713 vorbisenc->last_message =
714 g_strdup_printf ("encoding using bitrate management %s", constraints);
715 g_free (constraints);
719 g_object_notify (G_OBJECT (vorbisenc), "last_message");
723 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
725 vorbisenc->setup = FALSE;
727 if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
728 && vorbisenc->max_bitrate < 0) {
729 vorbisenc->quality_set = TRUE;
732 update_start_message (vorbisenc);
734 /* choose an encoding mode */
735 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
736 vorbis_info_init (&vorbisenc->vi);
738 if (vorbisenc->quality_set) {
739 if (vorbis_encode_setup_vbr (&vorbisenc->vi,
740 vorbisenc->channels, vorbisenc->frequency,
741 vorbisenc->quality) != 0) {
742 GST_ERROR_OBJECT (vorbisenc,
743 "vorbisenc: initialisation failed: invalid parameters for quality");
744 vorbis_info_clear (&vorbisenc->vi);
748 /* do we have optional hard quality restrictions? */
749 if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
750 struct ovectl_ratemanage_arg ai;
752 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
754 ai.bitrate_hard_min = vorbisenc->min_bitrate;
755 ai.bitrate_hard_max = vorbisenc->max_bitrate;
756 ai.management_active = 1;
758 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
761 long min_bitrate, max_bitrate;
763 min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
764 max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
766 if (vorbis_encode_setup_managed (&vorbisenc->vi,
768 vorbisenc->frequency,
769 max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
770 GST_ERROR_OBJECT (vorbisenc,
771 "vorbis_encode_setup_managed "
772 "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
773 vorbisenc->channels, vorbisenc->frequency, max_bitrate,
774 vorbisenc->bitrate, min_bitrate);
775 vorbis_info_clear (&vorbisenc->vi);
780 if (vorbisenc->managed && vorbisenc->bitrate < 0) {
781 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
782 } else if (!vorbisenc->managed) {
783 /* Turn off management entirely (if it was turned on). */
784 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
786 vorbis_encode_setup_init (&vorbisenc->vi);
788 /* set up the analysis state and auxiliary encoding storage */
789 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
790 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
792 vorbisenc->next_ts = 0;
794 vorbisenc->setup = TRUE;
800 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
802 GstFlowReturn ret = GST_FLOW_OK;
804 if (vorbisenc->setup) {
805 vorbis_analysis_wrote (&vorbisenc->vd, 0);
806 ret = gst_vorbis_enc_output_buffers (vorbisenc);
808 vorbisenc->setup = FALSE;
811 /* clean up and exit. vorbis_info_clear() must be called last */
812 vorbis_block_clear (&vorbisenc->vb);
813 vorbis_dsp_clear (&vorbisenc->vd);
814 vorbis_info_clear (&vorbisenc->vi);
816 vorbisenc->header_sent = FALSE;
821 /* prepare a buffer for transmission by passing data through libvorbis */
823 gst_vorbis_enc_buffer_from_packet (GstVorbisEnc * vorbisenc,
828 outbuf = gst_buffer_new_and_alloc (packet->bytes);
829 memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
830 /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
831 * time representation */
832 GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos +
833 vorbisenc->granulepos_offset;
834 GST_BUFFER_OFFSET (outbuf) = granulepos_to_timestamp (vorbisenc,
835 GST_BUFFER_OFFSET_END (outbuf));
836 GST_BUFFER_TIMESTAMP (outbuf) = vorbisenc->next_ts;
838 /* update the next timestamp, taking granulepos_offset and subgranule offset
841 granulepos_to_timestamp_offset (vorbisenc, packet->granulepos) +
842 vorbisenc->initial_ts;
843 GST_BUFFER_DURATION (outbuf) =
844 vorbisenc->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
846 if (vorbisenc->next_discont) {
847 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
848 vorbisenc->next_discont = FALSE;
851 gst_buffer_set_caps (outbuf, vorbisenc->srccaps);
853 GST_LOG_OBJECT (vorbisenc, "encoded buffer of %d bytes",
854 GST_BUFFER_SIZE (outbuf));
858 /* the same as above, but different logic for setting timestamp and granulepos
861 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
866 outbuf = gst_buffer_new_and_alloc (packet->bytes);
867 memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
868 GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
869 GST_BUFFER_OFFSET_END (outbuf) = 0;
870 GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
871 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
873 gst_buffer_set_caps (outbuf, vorbisenc->srccaps);
875 GST_DEBUG ("created header packet buffer, %d bytes",
876 GST_BUFFER_SIZE (outbuf));
880 /* push out the buffer and do internal bookkeeping */
882 gst_vorbis_enc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
884 vorbisenc->bytes_out += GST_BUFFER_SIZE (buffer);
886 GST_DEBUG_OBJECT (vorbisenc,
887 "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
888 GST_BUFFER_OFFSET_END (buffer),
889 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
890 return gst_pad_push (vorbisenc->srcpad, buffer);
894 gst_vorbis_enc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
898 outbuf = gst_vorbis_enc_buffer_from_packet (vorbisenc, packet);
899 return gst_vorbis_enc_push_buffer (vorbisenc, outbuf);
902 /* Set a copy of these buffers as 'streamheader' on the caps.
903 * We need a copy to avoid these buffers ending up with (indirect) refs on
907 gst_vorbis_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
908 GstBuffer * buf2, GstBuffer * buf3)
911 GstStructure *structure;
912 GValue array = { 0 };
913 GValue value = { 0 };
915 caps = gst_caps_make_writable (caps);
916 structure = gst_caps_get_structure (caps, 0);
919 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
920 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
921 GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
923 /* put buffers in a fixed list */
924 g_value_init (&array, GST_TYPE_ARRAY);
925 g_value_init (&value, GST_TYPE_BUFFER);
926 buf = gst_buffer_copy (buf1);
927 gst_value_set_buffer (&value, buf);
928 gst_buffer_unref (buf);
929 gst_value_array_append_value (&array, &value);
930 g_value_unset (&value);
931 g_value_init (&value, GST_TYPE_BUFFER);
932 buf = gst_buffer_copy (buf2);
933 gst_value_set_buffer (&value, buf);
934 gst_buffer_unref (buf);
935 gst_value_array_append_value (&array, &value);
936 g_value_unset (&value);
937 g_value_init (&value, GST_TYPE_BUFFER);
938 buf = gst_buffer_copy (buf3);
939 gst_value_set_buffer (&value, buf);
940 gst_buffer_unref (buf);
941 gst_value_array_append_value (&array, &value);
942 gst_structure_set_value (structure, "streamheader", &array);
943 g_value_unset (&value);
944 g_value_unset (&array);
950 gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event)
953 GstVorbisEnc *vorbisenc;
955 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
957 switch (GST_EVENT_TYPE (event)) {
959 /* Tell the library we're at end of stream so that it can handle
960 * the last frame and mark end of stream in the output properly */
961 GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on");
962 gst_vorbis_enc_clear (vorbisenc);
964 res = gst_pad_push_event (vorbisenc->srcpad, event);
967 if (vorbisenc->tags) {
970 gst_event_parse_tag (event, &list);
971 gst_tag_list_insert (vorbisenc->tags, list,
972 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
974 g_assert_not_reached ();
976 res = gst_pad_push_event (vorbisenc->srcpad, event);
978 case GST_EVENT_NEWSEGMENT:
981 gdouble rate, applied_rate;
983 gint64 start, stop, position;
985 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
986 &format, &start, &stop, &position);
987 if (format == GST_FORMAT_TIME) {
988 gst_segment_set_newsegment (&vorbisenc->segment, update, rate, format,
989 start, stop, position);
990 if (vorbisenc->initial_ts == GST_CLOCK_TIME_NONE) {
991 GST_DEBUG_OBJECT (vorbisenc, "Initial segment %" GST_SEGMENT_FORMAT,
992 &vorbisenc->segment);
993 vorbisenc->initial_ts = start;
999 res = gst_pad_push_event (vorbisenc->srcpad, event);
1006 gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
1007 GstClockTime timestamp, GstClockTime duration)
1009 gboolean ret = FALSE;
1011 if (timestamp != GST_CLOCK_TIME_NONE &&
1012 vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
1013 timestamp + duration != vorbisenc->expected_ts) {
1014 /* It turns out that a lot of elements don't generate perfect streams due
1015 * to rounding errors. So, we permit small errors (< 1/2 a sample) without
1016 * causing a discont.
1018 int halfsample = GST_SECOND / vorbisenc->frequency / 2;
1020 if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > halfsample) {
1021 GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
1022 ", buffer TS %" GST_TIME_FORMAT,
1023 GST_TIME_ARGS (vorbisenc->expected_ts), GST_TIME_ARGS (timestamp));
1028 if (timestamp != GST_CLOCK_TIME_NONE && duration != GST_CLOCK_TIME_NONE) {
1029 vorbisenc->expected_ts = timestamp + duration;
1031 vorbisenc->expected_ts = GST_CLOCK_TIME_NONE;
1036 static GstFlowReturn
1037 gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
1039 GstVorbisEnc *vorbisenc;
1040 GstFlowReturn ret = GST_FLOW_OK;
1044 float **vorbis_buffer;
1045 GstBuffer *buf1, *buf2, *buf3;
1046 gboolean first = FALSE;
1047 GstClockTime timestamp = GST_CLOCK_TIME_NONE;
1048 GstClockTime running_time = GST_CLOCK_TIME_NONE;
1050 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
1052 if (!vorbisenc->setup)
1055 buffer = gst_audio_buffer_clip (buffer, &vorbisenc->segment,
1056 vorbisenc->frequency, 4 * vorbisenc->channels);
1057 if (buffer == NULL) {
1058 GST_DEBUG_OBJECT (vorbisenc, "Dropping buffer, out of segment");
1062 gst_segment_to_running_time (&vorbisenc->segment, GST_FORMAT_TIME,
1063 GST_BUFFER_TIMESTAMP (buffer));
1064 timestamp = running_time + vorbisenc->initial_ts;
1065 GST_DEBUG_OBJECT (vorbisenc, "Initial ts is %" GST_TIME_FORMAT,
1066 GST_TIME_ARGS (vorbisenc->initial_ts));
1067 if (!vorbisenc->header_sent) {
1068 /* Vorbis streams begin with three headers; the initial header (with
1069 most of the codec setup parameters) which is mandated by the Ogg
1070 bitstream spec. The second header holds any comment fields. The
1071 third header holds the bitstream codebook. We merely need to
1072 make the headers, then pass them to libvorbis one at a time;
1073 libvorbis handles the additional Ogg bitstream constraints */
1075 ogg_packet header_comm;
1076 ogg_packet header_code;
1079 /* first, make sure header buffers get timestamp == 0 */
1080 vorbisenc->next_ts = 0;
1081 vorbisenc->granulepos_offset = 0;
1082 vorbisenc->subgranule_offset = 0;
1084 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
1085 gst_vorbis_enc_set_metadata (vorbisenc);
1086 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
1087 &header_comm, &header_code);
1088 vorbis_comment_clear (&vorbisenc->vc);
1090 /* create header buffers */
1091 buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
1092 buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
1093 buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
1095 /* mark and put on caps */
1096 vorbisenc->srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
1097 caps = vorbisenc->srccaps;
1098 caps = gst_vorbis_enc_set_header_on_caps (caps, buf1, buf2, buf3);
1100 /* negotiate with these caps */
1101 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
1102 gst_pad_set_caps (vorbisenc->srcpad, caps);
1104 gst_buffer_set_caps (buf1, caps);
1105 gst_buffer_set_caps (buf2, caps);
1106 gst_buffer_set_caps (buf3, caps);
1108 /* push out buffers */
1109 /* push_buffer takes the reference even for failure */
1110 if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf1)) != GST_FLOW_OK)
1111 goto failed_header_push;
1112 if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf2)) != GST_FLOW_OK) {
1114 goto failed_header_push;
1116 if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf3)) != GST_FLOW_OK) {
1118 goto failed_header_push;
1121 /* now adjust starting granulepos accordingly if the buffer's timestamp is
1123 vorbisenc->next_ts = timestamp;
1124 vorbisenc->expected_ts = timestamp;
1125 vorbisenc->granulepos_offset = gst_util_uint64_scale
1126 (running_time, vorbisenc->frequency, GST_SECOND);
1127 vorbisenc->subgranule_offset = 0;
1128 vorbisenc->subgranule_offset =
1129 (vorbisenc->next_ts - vorbisenc->initial_ts) -
1130 granulepos_to_timestamp_offset (vorbisenc, 0);
1132 vorbisenc->header_sent = TRUE;
1136 if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
1137 timestamp < vorbisenc->expected_ts) {
1138 guint64 diff = vorbisenc->expected_ts - timestamp;
1141 GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
1142 "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
1143 "), cannot handle. Clipping buffer.",
1144 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts));
1147 GST_CLOCK_TIME_TO_FRAMES (diff,
1148 vorbisenc->frequency) * vorbisenc->channels * sizeof (gfloat);
1149 if (diff_bytes >= GST_BUFFER_SIZE (buffer)) {
1150 gst_buffer_unref (buffer);
1153 buffer = gst_buffer_make_metadata_writable (buffer);
1154 GST_BUFFER_DATA (buffer) += diff_bytes;
1155 GST_BUFFER_SIZE (buffer) -= diff_bytes;
1157 GST_BUFFER_TIMESTAMP (buffer) += diff;
1158 if (GST_BUFFER_DURATION_IS_VALID (buffer))
1159 GST_BUFFER_DURATION (buffer) -= diff;
1162 if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, timestamp,
1163 GST_BUFFER_DURATION (buffer)) && !first) {
1164 GST_WARNING_OBJECT (vorbisenc,
1165 "Buffer is discontinuous, flushing encoder "
1166 "and restarting (Discont from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT
1167 ")", GST_TIME_ARGS (vorbisenc->next_ts), GST_TIME_ARGS (timestamp));
1168 /* Re-initialise encoder (there's unfortunately no API to flush it) */
1169 if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK)
1171 if (!gst_vorbis_enc_setup (vorbisenc))
1172 return GST_FLOW_ERROR; /* Should be impossible, we can only get here if
1173 we successfully initialised earlier */
1175 /* Now, set our granulepos offset appropriately. */
1176 vorbisenc->next_ts = timestamp;
1177 /* We need to round to the nearest whole number of samples, not just do
1178 * a truncating division here */
1179 vorbisenc->granulepos_offset = gst_util_uint64_scale
1180 (running_time + GST_SECOND / vorbisenc->frequency / 2
1181 - vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND);
1183 vorbisenc->header_sent = TRUE;
1185 /* And our next output buffer must have DISCONT set on it */
1186 vorbisenc->next_discont = TRUE;
1189 /* Sending zero samples to libvorbis marks EOS, so we mustn't do that */
1190 if (GST_BUFFER_SIZE (buffer) == 0) {
1191 gst_buffer_unref (buffer);
1195 /* data to encode */
1196 data = (gfloat *) GST_BUFFER_DATA (buffer);
1197 size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
1199 /* expose the buffer to submit data */
1200 vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
1202 /* deinterleave samples, write the buffer data */
1203 for (i = 0; i < size; i++) {
1204 for (j = 0; j < vorbisenc->channels; j++) {
1205 vorbis_buffer[j][i] = *data++;
1209 /* tell the library how much we actually submitted */
1210 vorbis_analysis_wrote (&vorbisenc->vd, size);
1212 GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
1214 vorbisenc->samples_in += size;
1216 gst_buffer_unref (buffer);
1218 ret = gst_vorbis_enc_output_buffers (vorbisenc);
1225 gst_buffer_unref (buffer);
1226 GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL),
1227 ("encoder not initialized (input is not audio?)"));
1228 return GST_FLOW_UNEXPECTED;
1232 GST_WARNING_OBJECT (vorbisenc, "Failed to push headers");
1233 /* buf1 is always already unreffed */
1235 gst_buffer_unref (buf2);
1237 gst_buffer_unref (buf3);
1238 gst_buffer_unref (buffer);
1243 static GstFlowReturn
1244 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
1248 /* vorbis does some data preanalysis, then divides up blocks for
1249 more involved (potentially parallel) processing. Get a single
1250 block for encoding now */
1251 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
1254 GST_LOG_OBJECT (vorbisenc, "analysed to a block");
1257 vorbis_analysis (&vorbisenc->vb, NULL);
1258 vorbis_bitrate_addblock (&vorbisenc->vb);
1260 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
1261 GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
1262 ret = gst_vorbis_enc_push_packet (vorbisenc, &op);
1264 if (ret != GST_FLOW_OK)
1273 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
1276 GstVorbisEnc *vorbisenc;
1278 g_return_if_fail (GST_IS_VORBISENC (object));
1280 vorbisenc = GST_VORBISENC (object);
1283 case ARG_MAX_BITRATE:
1284 g_value_set_int (value, vorbisenc->max_bitrate);
1287 g_value_set_int (value, vorbisenc->bitrate);
1289 case ARG_MIN_BITRATE:
1290 g_value_set_int (value, vorbisenc->min_bitrate);
1293 g_value_set_float (value, vorbisenc->quality);
1296 g_value_set_boolean (value, vorbisenc->managed);
1298 case ARG_LAST_MESSAGE:
1299 g_value_set_string (value, vorbisenc->last_message);
1302 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1308 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
1309 const GValue * value, GParamSpec * pspec)
1311 GstVorbisEnc *vorbisenc;
1313 g_return_if_fail (GST_IS_VORBISENC (object));
1315 vorbisenc = GST_VORBISENC (object);
1318 case ARG_MAX_BITRATE:
1320 gboolean old_value = vorbisenc->managed;
1322 vorbisenc->max_bitrate = g_value_get_int (value);
1323 if (vorbisenc->max_bitrate >= 0
1324 && vorbisenc->max_bitrate < LOWEST_BITRATE) {
1325 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1326 vorbisenc->max_bitrate = LOWEST_BITRATE;
1328 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1329 vorbisenc->managed = TRUE;
1331 vorbisenc->managed = FALSE;
1333 if (old_value != vorbisenc->managed)
1334 g_object_notify (object, "managed");
1338 vorbisenc->bitrate = g_value_get_int (value);
1339 if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
1340 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1341 vorbisenc->bitrate = LOWEST_BITRATE;
1344 case ARG_MIN_BITRATE:
1346 gboolean old_value = vorbisenc->managed;
1348 vorbisenc->min_bitrate = g_value_get_int (value);
1349 if (vorbisenc->min_bitrate >= 0
1350 && vorbisenc->min_bitrate < LOWEST_BITRATE) {
1351 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1352 vorbisenc->min_bitrate = LOWEST_BITRATE;
1354 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1355 vorbisenc->managed = TRUE;
1357 vorbisenc->managed = FALSE;
1359 if (old_value != vorbisenc->managed)
1360 g_object_notify (object, "managed");
1364 vorbisenc->quality = g_value_get_float (value);
1365 if (vorbisenc->quality >= 0.0)
1366 vorbisenc->quality_set = TRUE;
1368 vorbisenc->quality_set = FALSE;
1371 vorbisenc->managed = g_value_get_boolean (value);
1374 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1379 static GstStateChangeReturn
1380 gst_vorbis_enc_change_state (GstElement * element, GstStateChange transition)
1382 GstVorbisEnc *vorbisenc = GST_VORBISENC (element);
1383 GstStateChangeReturn res;
1386 switch (transition) {
1387 case GST_STATE_CHANGE_NULL_TO_READY:
1388 vorbisenc->tags = gst_tag_list_new ();
1390 case GST_STATE_CHANGE_READY_TO_PAUSED:
1391 vorbisenc->setup = FALSE;
1392 vorbisenc->next_discont = FALSE;
1393 vorbisenc->header_sent = FALSE;
1394 gst_segment_init (&vorbisenc->segment, GST_FORMAT_TIME);
1395 vorbisenc->initial_ts = GST_CLOCK_TIME_NONE;
1397 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1403 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1405 switch (transition) {
1406 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1408 case GST_STATE_CHANGE_PAUSED_TO_READY:
1409 vorbis_block_clear (&vorbisenc->vb);
1410 vorbis_dsp_clear (&vorbisenc->vd);
1411 vorbis_info_clear (&vorbisenc->vi);
1412 g_free (vorbisenc->last_message);
1413 vorbisenc->last_message = NULL;
1414 if (vorbisenc->srccaps) {
1415 gst_caps_unref (vorbisenc->srccaps);
1416 vorbisenc->srccaps = NULL;
1419 case GST_STATE_CHANGE_READY_TO_NULL:
1420 gst_tag_list_free (vorbisenc->tags);
1421 vorbisenc->tags = NULL;