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, "
67 "format = (string) " GST_AUDIO_NE (F32) ", "
68 "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 256 ]")
71 static GstStaticPadTemplate vorbis_enc_src_factory =
72 GST_STATIC_PAD_TEMPLATE ("src",
75 GST_STATIC_CAPS ("audio/x-vorbis")
89 static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
91 /* this function takes into account the granulepos_offset and the subgranule
94 granulepos_to_timestamp_offset (GstVorbisEnc * vorbisenc,
95 ogg_int64_t granulepos)
98 return gst_util_uint64_scale ((guint64) granulepos
99 + vorbisenc->granulepos_offset, GST_SECOND, vorbisenc->frequency)
100 + vorbisenc->subgranule_offset;
101 return GST_CLOCK_TIME_NONE;
104 /* this function does a straight granulepos -> timestamp conversion */
106 granulepos_to_timestamp (GstVorbisEnc * vorbisenc, ogg_int64_t granulepos)
109 return gst_util_uint64_scale ((guint64) granulepos,
110 GST_SECOND, vorbisenc->frequency);
111 return GST_CLOCK_TIME_NONE;
114 #define MAX_BITRATE_DEFAULT -1
115 #define BITRATE_DEFAULT -1
116 #define MIN_BITRATE_DEFAULT -1
117 #define QUALITY_DEFAULT 0.3
118 #define LOWEST_BITRATE 6000 /* lowest allowed for a 8 kHz stream */
119 #define HIGHEST_BITRATE 250001 /* highest allowed for a 44 kHz stream */
121 static gboolean gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event);
122 static GstFlowReturn gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer);
123 static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
125 static void gst_vorbis_enc_dispose (GObject * object);
126 static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
127 GValue * value, GParamSpec * pspec);
128 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
129 const GValue * value, GParamSpec * pspec);
130 static GstStateChangeReturn gst_vorbis_enc_change_state (GstElement * element,
131 GstStateChange transition);
132 static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
134 #define gst_vorbis_enc_parent_class parent_class
135 G_DEFINE_TYPE_WITH_CODE (GstVorbisEnc, gst_vorbis_enc,
136 GST_TYPE_ELEMENT, gst_vorbis_enc_add_interfaces (g_define_type_id));
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_class_init (GstVorbisEncClass * klass)
152 GObjectClass *gobject_class;
153 GstElementClass *gstelement_class;
155 gobject_class = (GObjectClass *) klass;
156 gstelement_class = (GstElementClass *) klass;
158 gobject_class->set_property = gst_vorbis_enc_set_property;
159 gobject_class->get_property = gst_vorbis_enc_get_property;
160 gobject_class->dispose = gst_vorbis_enc_dispose;
162 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
163 g_param_spec_int ("max-bitrate", "Maximum Bitrate",
164 "Specify a maximum bitrate (in bps). Useful for streaming "
165 "applications. (-1 == disabled)",
166 -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT,
167 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
168 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
169 g_param_spec_int ("bitrate", "Target Bitrate",
170 "Attempt to encode at a bitrate averaging this (in bps). "
171 "This uses the bitrate management engine, and is not recommended for most users. "
172 "Quality is a better alternative. (-1 == disabled)", -1,
173 HIGHEST_BITRATE, BITRATE_DEFAULT,
174 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
175 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
176 g_param_spec_int ("min-bitrate", "Minimum Bitrate",
177 "Specify a minimum bitrate (in bps). Useful for encoding for a "
178 "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE,
179 MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
180 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
181 g_param_spec_float ("quality", "Quality",
182 "Specify quality instead of specifying a particular bitrate.", -0.1,
183 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
184 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
185 g_param_spec_boolean ("managed", "Managed",
186 "Enable bitrate management engine", FALSE,
187 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
188 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
189 g_param_spec_string ("last-message", "last-message",
190 "The last status message", NULL,
191 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
193 gst_element_class_add_pad_template (gstelement_class,
194 gst_static_pad_template_get (&vorbis_enc_src_factory));
195 gst_element_class_add_pad_template (gstelement_class,
196 gst_static_pad_template_get (&vorbis_enc_sink_factory));
197 gst_element_class_set_details_simple (gstelement_class,
198 "Vorbis audio encoder", "Codec/Encoder/Audio",
199 "Encodes audio in Vorbis format",
200 "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
202 gstelement_class->change_state =
203 GST_DEBUG_FUNCPTR (gst_vorbis_enc_change_state);
207 gst_vorbis_enc_dispose (GObject * object)
209 GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
211 if (vorbisenc->sinkcaps) {
212 gst_caps_unref (vorbisenc->sinkcaps);
213 vorbisenc->sinkcaps = NULL;
216 G_OBJECT_CLASS (parent_class)->dispose (object);
220 gst_vorbis_enc_generate_sink_caps (void)
222 GstCaps *caps = gst_caps_new_empty ();
225 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
226 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
227 "rate", GST_TYPE_INT_RANGE, 1, 200000,
228 "channels", G_TYPE_INT, 1, NULL));
230 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
231 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
232 "rate", GST_TYPE_INT_RANGE, 1, 200000,
233 "channels", G_TYPE_INT, 2, NULL));
235 for (i = 3; i <= 8; i++) {
236 GValue chanpos = { 0 };
238 GstStructure *structure;
240 g_value_init (&chanpos, GST_TYPE_ARRAY);
241 g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
243 for (c = 0; c < i; c++) {
244 g_value_set_enum (&pos, gst_vorbis_channel_positions[i - 1][c]);
245 gst_value_array_append_value (&chanpos, &pos);
247 g_value_unset (&pos);
249 structure = gst_structure_new ("audio/x-raw",
250 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
251 "rate", GST_TYPE_INT_RANGE, 1, 200000, "channels", G_TYPE_INT, i, NULL);
252 gst_structure_set_value (structure, "channel-positions", &chanpos);
253 g_value_unset (&chanpos);
255 gst_caps_append_structure (caps, structure);
258 gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
259 "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
260 "rate", GST_TYPE_INT_RANGE, 1, 200000,
261 "channels", GST_TYPE_INT_RANGE, 9, 256, NULL));
267 gst_vorbis_enc_sink_getcaps (GstPad * pad, GstCaps * filter)
269 GstVorbisEnc *vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
271 if (vorbisenc->sinkcaps == NULL)
272 vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
275 return gst_caps_intersect_full (filter, vorbisenc->sinkcaps,
276 GST_CAPS_INTERSECT_FIRST);
278 return gst_caps_ref (vorbisenc->sinkcaps);
282 gst_vorbis_enc_sink_setcaps (GstVorbisEnc * vorbisenc, GstCaps * caps)
284 GstStructure *structure;
286 vorbisenc->setup = FALSE;
288 structure = gst_caps_get_structure (caps, 0);
289 gst_structure_get_int (structure, "channels", &vorbisenc->channels);
290 gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
292 gst_vorbis_enc_setup (vorbisenc);
294 if (vorbisenc->setup)
301 gst_vorbis_enc_convert_src (GstPad * pad, GstFormat src_format,
302 gint64 src_value, GstFormat dest_format, gint64 * dest_value)
305 GstVorbisEnc *vorbisenc;
308 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
310 if (vorbisenc->samples_in == 0 ||
311 vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0) {
312 gst_object_unref (vorbisenc);
316 avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in);
318 switch (src_format) {
319 case GST_FORMAT_BYTES:
320 switch (dest_format) {
321 case GST_FORMAT_TIME:
322 *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, avg);
328 case GST_FORMAT_TIME:
329 switch (dest_format) {
330 case GST_FORMAT_BYTES:
331 *dest_value = gst_util_uint64_scale_int (src_value, avg, GST_SECOND);
340 gst_object_unref (vorbisenc);
345 gst_vorbis_enc_convert_sink (GstPad * pad, GstFormat src_format,
346 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
350 gint bytes_per_sample;
351 GstVorbisEnc *vorbisenc;
353 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
355 bytes_per_sample = vorbisenc->channels * 2;
357 switch (src_format) {
358 case GST_FORMAT_BYTES:
359 switch (*dest_format) {
360 case GST_FORMAT_DEFAULT:
361 if (bytes_per_sample == 0)
363 *dest_value = src_value / bytes_per_sample;
365 case GST_FORMAT_TIME:
367 gint byterate = bytes_per_sample * vorbisenc->frequency;
372 gst_util_uint64_scale_int (src_value, GST_SECOND, byterate);
379 case GST_FORMAT_DEFAULT:
380 switch (*dest_format) {
381 case GST_FORMAT_BYTES:
382 *dest_value = src_value * bytes_per_sample;
384 case GST_FORMAT_TIME:
385 if (vorbisenc->frequency == 0)
388 gst_util_uint64_scale_int (src_value, GST_SECOND,
389 vorbisenc->frequency);
395 case GST_FORMAT_TIME:
396 switch (*dest_format) {
397 case GST_FORMAT_BYTES:
398 scale = bytes_per_sample;
400 case GST_FORMAT_DEFAULT:
402 gst_util_uint64_scale_int (src_value,
403 scale * vorbisenc->frequency, GST_SECOND);
412 gst_object_unref (vorbisenc);
417 gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc)
419 /* FIXME, this probably depends on the bitrate and other setting but for now
420 * we return this value, which was obtained by totally unscientific
422 return 58 * GST_MSECOND;
425 static const GstQueryType *
426 gst_vorbis_enc_get_query_types (GstPad * pad)
428 static const GstQueryType gst_vorbis_enc_src_query_types[] = {
435 return gst_vorbis_enc_src_query_types;
439 gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query)
442 GstVorbisEnc *vorbisenc;
445 vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
446 peerpad = gst_pad_get_peer (vorbisenc->sinkpad);
448 switch (GST_QUERY_TYPE (query)) {
449 case GST_QUERY_POSITION:
454 gst_query_parse_position (query, &req_fmt, NULL);
455 if ((res = gst_pad_query_position (peerpad, req_fmt, &val))) {
456 gst_query_set_position (query, req_fmt, val);
460 if (!(res = gst_pad_query_position (peerpad, GST_FORMAT_TIME, &pos)))
464 gst_pad_query_convert (peerpad, GST_FORMAT_TIME, pos, req_fmt,
466 gst_query_set_position (query, req_fmt, val);
470 case GST_QUERY_DURATION:
475 gst_query_parse_duration (query, &req_fmt, NULL);
476 if ((res = gst_pad_query_duration (peerpad, req_fmt, &val))) {
477 gst_query_set_duration (query, req_fmt, val);
481 if (!(res = gst_pad_query_duration (peerpad, GST_FORMAT_TIME, &dur)))
485 gst_pad_query_convert (peerpad, GST_FORMAT_TIME, dur, req_fmt,
487 gst_query_set_duration (query, req_fmt, val);
491 case GST_QUERY_CONVERT:
493 GstFormat src_fmt, dest_fmt;
494 gint64 src_val, dest_val;
496 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
498 gst_vorbis_enc_convert_src (pad, src_fmt, src_val, dest_fmt,
501 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
504 case GST_QUERY_LATENCY:
507 GstClockTime min_latency, max_latency;
510 if ((res = gst_pad_query (peerpad, query))) {
511 gst_query_parse_latency (query, &live, &min_latency, &max_latency);
513 latency = gst_vorbis_enc_get_latency (vorbisenc);
515 /* add our latency */
516 min_latency += latency;
517 if (max_latency != -1)
518 max_latency += latency;
520 gst_query_set_latency (query, live, min_latency, max_latency);
525 res = gst_pad_query (peerpad, query);
530 gst_object_unref (peerpad);
531 gst_object_unref (vorbisenc);
536 gst_vorbis_enc_sink_query (GstPad * pad, GstQuery * query)
540 switch (GST_QUERY_TYPE (query)) {
541 case GST_QUERY_CONVERT:
543 GstFormat src_fmt, dest_fmt;
544 gint64 src_val, dest_val;
546 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
548 gst_vorbis_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
551 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
555 res = gst_pad_query_default (pad, query);
564 gst_vorbis_enc_init (GstVorbisEnc * vorbisenc)
567 gst_pad_new_from_static_template (&vorbis_enc_sink_factory, "sink");
568 gst_pad_set_event_function (vorbisenc->sinkpad,
569 GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event));
570 gst_pad_set_chain_function (vorbisenc->sinkpad,
571 GST_DEBUG_FUNCPTR (gst_vorbis_enc_chain));
572 gst_pad_set_getcaps_function (vorbisenc->sinkpad,
573 GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_getcaps));
574 gst_pad_set_query_function (vorbisenc->sinkpad,
575 GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_query));
576 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
579 gst_pad_new_from_static_template (&vorbis_enc_src_factory, "src");
580 gst_pad_set_query_function (vorbisenc->srcpad,
581 GST_DEBUG_FUNCPTR (gst_vorbis_enc_src_query));
582 gst_pad_set_query_type_function (vorbisenc->srcpad,
583 GST_DEBUG_FUNCPTR (gst_vorbis_enc_get_query_types));
584 gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
586 vorbisenc->channels = -1;
587 vorbisenc->frequency = -1;
589 vorbisenc->managed = FALSE;
590 vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
591 vorbisenc->bitrate = BITRATE_DEFAULT;
592 vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
593 vorbisenc->quality = QUALITY_DEFAULT;
594 vorbisenc->quality_set = FALSE;
595 vorbisenc->last_message = NULL;
599 gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
602 GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
605 vc_list = gst_tag_to_vorbis_comments (list, tag);
607 for (l = vc_list; l != NULL; l = l->next) {
608 const gchar *vc_string = (const gchar *) l->data;
609 gchar *key = NULL, *val = NULL;
611 GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
612 if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
613 vorbis_comment_add_tag (&enc->vc, key, val);
619 g_list_foreach (vc_list, (GFunc) g_free, NULL);
620 g_list_free (vc_list);
624 gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
626 GstTagList *merged_tags;
627 const GstTagList *user_tags;
629 vorbis_comment_init (&enc->vc);
631 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
633 GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
634 GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
636 /* gst_tag_list_merge() will handle NULL for either or both lists fine */
637 merged_tags = gst_tag_list_merge (user_tags, enc->tags,
638 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
641 GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
642 gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
643 gst_tag_list_free (merged_tags);
648 get_constraints_string (GstVorbisEnc * vorbisenc)
650 gint min = vorbisenc->min_bitrate;
651 gint max = vorbisenc->max_bitrate;
654 if (min > 0 && max > 0)
655 result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
657 result = g_strdup_printf ("(min %d bps, no max)", min);
659 result = g_strdup_printf ("(no min, max %d bps)", max);
661 result = g_strdup_printf ("(no min or max)");
667 update_start_message (GstVorbisEnc * vorbisenc)
671 g_free (vorbisenc->last_message);
673 if (vorbisenc->bitrate > 0) {
674 if (vorbisenc->managed) {
675 constraints = get_constraints_string (vorbisenc);
676 vorbisenc->last_message =
677 g_strdup_printf ("encoding at average bitrate %d bps %s",
678 vorbisenc->bitrate, constraints);
679 g_free (constraints);
681 vorbisenc->last_message =
683 ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
687 if (vorbisenc->quality_set) {
688 if (vorbisenc->managed) {
689 constraints = get_constraints_string (vorbisenc);
690 vorbisenc->last_message =
692 ("encoding at quality level %2.2f using constrained VBR %s",
693 vorbisenc->quality, constraints);
694 g_free (constraints);
696 vorbisenc->last_message =
697 g_strdup_printf ("encoding at quality level %2.2f",
701 constraints = get_constraints_string (vorbisenc);
702 vorbisenc->last_message =
703 g_strdup_printf ("encoding using bitrate management %s", constraints);
704 g_free (constraints);
708 g_object_notify (G_OBJECT (vorbisenc), "last_message");
712 gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
714 vorbisenc->setup = FALSE;
716 if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
717 && vorbisenc->max_bitrate < 0) {
718 vorbisenc->quality_set = TRUE;
721 update_start_message (vorbisenc);
723 /* choose an encoding mode */
724 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
725 vorbis_info_init (&vorbisenc->vi);
727 if (vorbisenc->quality_set) {
728 if (vorbis_encode_setup_vbr (&vorbisenc->vi,
729 vorbisenc->channels, vorbisenc->frequency,
730 vorbisenc->quality) != 0) {
731 GST_ERROR_OBJECT (vorbisenc,
732 "vorbisenc: initialisation failed: invalid parameters for quality");
733 vorbis_info_clear (&vorbisenc->vi);
737 /* do we have optional hard quality restrictions? */
738 if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
739 struct ovectl_ratemanage_arg ai;
741 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
743 ai.bitrate_hard_min = vorbisenc->min_bitrate;
744 ai.bitrate_hard_max = vorbisenc->max_bitrate;
745 ai.management_active = 1;
747 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
750 long min_bitrate, max_bitrate;
752 min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
753 max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
755 if (vorbis_encode_setup_managed (&vorbisenc->vi,
757 vorbisenc->frequency,
758 max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
759 GST_ERROR_OBJECT (vorbisenc,
760 "vorbis_encode_setup_managed "
761 "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
762 vorbisenc->channels, vorbisenc->frequency, max_bitrate,
763 vorbisenc->bitrate, min_bitrate);
764 vorbis_info_clear (&vorbisenc->vi);
769 if (vorbisenc->managed && vorbisenc->bitrate < 0) {
770 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
771 } else if (!vorbisenc->managed) {
772 /* Turn off management entirely (if it was turned on). */
773 vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
775 vorbis_encode_setup_init (&vorbisenc->vi);
777 /* set up the analysis state and auxiliary encoding storage */
778 vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
779 vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
781 vorbisenc->next_ts = 0;
783 vorbisenc->setup = TRUE;
789 gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
791 GstFlowReturn ret = GST_FLOW_OK;
793 if (vorbisenc->setup) {
794 vorbis_analysis_wrote (&vorbisenc->vd, 0);
795 ret = gst_vorbis_enc_output_buffers (vorbisenc);
797 vorbisenc->setup = FALSE;
800 /* clean up and exit. vorbis_info_clear() must be called last */
801 vorbis_block_clear (&vorbisenc->vb);
802 vorbis_dsp_clear (&vorbisenc->vd);
803 vorbis_info_clear (&vorbisenc->vi);
805 vorbisenc->header_sent = FALSE;
810 /* prepare a buffer for transmission by passing data through libvorbis */
812 gst_vorbis_enc_buffer_from_packet (GstVorbisEnc * vorbisenc,
817 outbuf = gst_buffer_new_and_alloc (packet->bytes);
818 gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
819 /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
820 * time representation */
821 GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos +
822 vorbisenc->granulepos_offset;
823 GST_BUFFER_OFFSET (outbuf) = granulepos_to_timestamp (vorbisenc,
824 GST_BUFFER_OFFSET_END (outbuf));
825 GST_BUFFER_TIMESTAMP (outbuf) = vorbisenc->next_ts;
827 /* update the next timestamp, taking granulepos_offset and subgranule offset
830 granulepos_to_timestamp_offset (vorbisenc, packet->granulepos);
831 GST_BUFFER_DURATION (outbuf) =
832 vorbisenc->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
834 if (vorbisenc->next_discont) {
835 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
836 vorbisenc->next_discont = FALSE;
839 GST_LOG_OBJECT (vorbisenc, "encoded buffer of %" G_GSIZE_FORMAT " bytes",
840 gst_buffer_get_size (outbuf));
844 /* the same as above, but different logic for setting timestamp and granulepos
847 gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
852 outbuf = gst_buffer_new_and_alloc (packet->bytes);
853 gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
854 GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
855 GST_BUFFER_OFFSET_END (outbuf) = 0;
856 GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
857 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
859 GST_DEBUG ("created header packet buffer, %" G_GSIZE_FORMAT " bytes",
860 gst_buffer_get_size (outbuf));
864 /* push out the buffer and do internal bookkeeping */
866 gst_vorbis_enc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
868 vorbisenc->bytes_out += gst_buffer_get_size (buffer);
870 GST_DEBUG_OBJECT (vorbisenc,
871 "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
872 GST_BUFFER_OFFSET_END (buffer),
873 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
874 return gst_pad_push (vorbisenc->srcpad, buffer);
878 gst_vorbis_enc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
882 outbuf = gst_vorbis_enc_buffer_from_packet (vorbisenc, packet);
883 return gst_vorbis_enc_push_buffer (vorbisenc, outbuf);
886 /* Set a copy of these buffers as 'streamheader' on the caps.
887 * We need a copy to avoid these buffers ending up with (indirect) refs on
891 gst_vorbis_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
892 GstBuffer * buf2, GstBuffer * buf3)
895 GstStructure *structure;
896 GValue array = { 0 };
897 GValue value = { 0 };
899 caps = gst_caps_make_writable (caps);
900 structure = gst_caps_get_structure (caps, 0);
903 GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
904 GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
905 GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
907 /* put buffers in a fixed list */
908 g_value_init (&array, GST_TYPE_ARRAY);
909 g_value_init (&value, GST_TYPE_BUFFER);
910 buf = gst_buffer_copy (buf1);
911 gst_value_set_buffer (&value, buf);
912 gst_buffer_unref (buf);
913 gst_value_array_append_value (&array, &value);
914 g_value_unset (&value);
915 g_value_init (&value, GST_TYPE_BUFFER);
916 buf = gst_buffer_copy (buf2);
917 gst_value_set_buffer (&value, buf);
918 gst_buffer_unref (buf);
919 gst_value_array_append_value (&array, &value);
920 g_value_unset (&value);
921 g_value_init (&value, GST_TYPE_BUFFER);
922 buf = gst_buffer_copy (buf3);
923 gst_value_set_buffer (&value, buf);
924 gst_buffer_unref (buf);
925 gst_value_array_append_value (&array, &value);
926 gst_structure_set_value (structure, "streamheader", &array);
927 g_value_unset (&value);
928 g_value_unset (&array);
934 gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event)
937 GstVorbisEnc *vorbisenc;
939 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
941 switch (GST_EVENT_TYPE (event)) {
946 gst_event_parse_caps (event, &caps);
947 res = gst_vorbis_enc_sink_setcaps (vorbisenc, caps);
948 gst_event_unref (event);
952 /* Tell the library we're at end of stream so that it can handle
953 * the last frame and mark end of stream in the output properly */
954 GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on");
955 gst_vorbis_enc_clear (vorbisenc);
957 res = gst_pad_push_event (vorbisenc->srcpad, event);
960 if (vorbisenc->tags) {
963 gst_event_parse_tag (event, &list);
964 gst_tag_list_insert (vorbisenc->tags, list,
965 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
967 g_assert_not_reached ();
969 res = gst_pad_push_event (vorbisenc->srcpad, event);
971 case GST_EVENT_SEGMENT:
973 const GstSegment *segment;
975 gst_event_parse_segment (event, &segment);
977 if (segment->format == GST_FORMAT_TIME) {
978 gst_segment_copy_into (segment, &vorbisenc->segment);
983 res = gst_pad_push_event (vorbisenc->srcpad, event);
990 gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
991 GstClockTime timestamp, GstClockTime duration)
993 gboolean ret = FALSE;
995 GST_DEBUG_OBJECT (vorbisenc, "exp %" GST_TIME_FORMAT " time %" GST_TIME_FORMAT
996 "dur %" GST_TIME_FORMAT, GST_TIME_ARGS (vorbisenc->expected_ts),
997 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
999 if (timestamp != GST_CLOCK_TIME_NONE &&
1000 vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
1001 timestamp + duration != vorbisenc->expected_ts) {
1002 /* It turns out that a lot of elements don't generate perfect streams due
1003 * to rounding errors. So, we permit small errors (< 3 samples) without
1004 * causing a discont.
1006 int threesample = GST_SECOND / vorbisenc->frequency * 3;
1008 if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > threesample) {
1009 GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
1010 ", buffer TS %" GST_TIME_FORMAT,
1011 GST_TIME_ARGS (vorbisenc->expected_ts), GST_TIME_ARGS (timestamp));
1016 if (timestamp != GST_CLOCK_TIME_NONE && duration != GST_CLOCK_TIME_NONE) {
1017 vorbisenc->expected_ts = timestamp + duration;
1019 vorbisenc->expected_ts = GST_CLOCK_TIME_NONE;
1024 static GstFlowReturn
1025 gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
1027 GstVorbisEnc *vorbisenc;
1028 GstFlowReturn ret = GST_FLOW_OK;
1032 float **vorbis_buffer;
1033 GstBuffer *buf1, *buf2, *buf3;
1034 gboolean first = FALSE;
1035 GstClockTime timestamp = GST_CLOCK_TIME_NONE;
1036 GstClockTime running_time = GST_CLOCK_TIME_NONE;
1039 vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
1041 if (!vorbisenc->setup)
1044 buffer = gst_audio_buffer_clip (buffer, &vorbisenc->segment,
1045 vorbisenc->frequency, 4 * vorbisenc->channels);
1046 if (buffer == NULL) {
1047 GST_DEBUG_OBJECT (vorbisenc, "Dropping buffer, out of segment");
1051 gst_segment_to_running_time (&vorbisenc->segment, GST_FORMAT_TIME,
1052 GST_BUFFER_TIMESTAMP (buffer));
1053 timestamp = running_time;
1054 GST_DEBUG_OBJECT (vorbisenc, " timestamp %" GST_TIME_FORMAT,
1055 GST_TIME_ARGS (timestamp));
1056 if (!vorbisenc->header_sent) {
1057 /* Vorbis streams begin with three headers; the initial header (with
1058 most of the codec setup parameters) which is mandated by the Ogg
1059 bitstream spec. The second header holds any comment fields. The
1060 third header holds the bitstream codebook. We merely need to
1061 make the headers, then pass them to libvorbis one at a time;
1062 libvorbis handles the additional Ogg bitstream constraints */
1064 ogg_packet header_comm;
1065 ogg_packet header_code;
1068 /* first, make sure header buffers get timestamp == 0 */
1069 vorbisenc->next_ts = 0;
1070 vorbisenc->granulepos_offset = 0;
1071 vorbisenc->subgranule_offset = 0;
1073 GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
1074 gst_vorbis_enc_set_metadata (vorbisenc);
1075 vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
1076 &header_comm, &header_code);
1077 vorbis_comment_clear (&vorbisenc->vc);
1079 /* create header buffers */
1080 buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
1081 buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
1082 buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
1084 /* mark and put on caps */
1085 vorbisenc->srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
1086 caps = vorbisenc->srccaps;
1087 caps = gst_vorbis_enc_set_header_on_caps (caps, buf1, buf2, buf3);
1089 /* negotiate with these caps */
1090 GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
1091 gst_pad_set_caps (vorbisenc->srcpad, caps);
1093 /* push out buffers */
1094 /* push_buffer takes the reference even for failure */
1095 if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf1)) != GST_FLOW_OK)
1096 goto failed_header_push;
1097 if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf2)) != GST_FLOW_OK) {
1099 goto failed_header_push;
1101 if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf3)) != GST_FLOW_OK) {
1103 goto failed_header_push;
1106 /* now adjust starting granulepos accordingly if the buffer's timestamp is
1108 vorbisenc->next_ts = timestamp;
1109 vorbisenc->expected_ts = timestamp;
1110 vorbisenc->granulepos_offset = gst_util_uint64_scale
1111 (running_time, vorbisenc->frequency, GST_SECOND);
1112 vorbisenc->subgranule_offset = 0;
1113 vorbisenc->subgranule_offset =
1114 vorbisenc->next_ts - granulepos_to_timestamp_offset (vorbisenc, 0);
1116 vorbisenc->header_sent = TRUE;
1120 if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
1121 timestamp < vorbisenc->expected_ts) {
1122 int threesample = GST_SECOND / vorbisenc->frequency * 3;
1123 guint64 diff = vorbisenc->expected_ts - timestamp;
1127 /* Don't freak out on tiny jitters; use the same < 3 sample
1128 tolerance as in the discontinuous detection */
1129 if ((GstClockTimeDiff) (vorbisenc->expected_ts - timestamp) > threesample) {
1131 GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
1132 "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
1133 "), cannot handle. Clipping buffer.",
1134 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts));
1136 size = gst_buffer_get_size (buffer);
1139 GST_CLOCK_TIME_TO_FRAMES (diff,
1140 vorbisenc->frequency) * vorbisenc->channels * sizeof (gfloat);
1141 if (diff_bytes >= size) {
1142 gst_buffer_unref (buffer);
1145 buffer = gst_buffer_make_writable (buffer);
1146 gst_buffer_resize (buffer, diff_bytes, size - diff_bytes);
1148 if (GST_BUFFER_DURATION_IS_VALID (buffer))
1149 GST_BUFFER_DURATION (buffer) -= diff;
1152 /* adjust the input timestamp in either case */
1153 GST_BUFFER_TIMESTAMP (buffer) += diff;
1156 if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, timestamp,
1157 GST_BUFFER_DURATION (buffer)) && !first) {
1158 GST_WARNING_OBJECT (vorbisenc,
1159 "Buffer is discontinuous, flushing encoder "
1160 "and restarting (Discont from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT
1161 ")", GST_TIME_ARGS (vorbisenc->next_ts), GST_TIME_ARGS (timestamp));
1162 /* Re-initialise encoder (there's unfortunately no API to flush it) */
1163 if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK)
1165 if (!gst_vorbis_enc_setup (vorbisenc))
1166 return GST_FLOW_ERROR; /* Should be impossible, we can only get here if
1167 we successfully initialised earlier */
1169 /* Now, set our granulepos offset appropriately. */
1170 vorbisenc->next_ts = timestamp;
1171 /* We need to round to the nearest whole number of samples, not just do
1172 * a truncating division here */
1173 vorbisenc->granulepos_offset = gst_util_uint64_scale
1174 (running_time + GST_SECOND / vorbisenc->frequency / 2
1175 - vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND);
1177 vorbisenc->header_sent = TRUE;
1179 /* And our next output buffer must have DISCONT set on it */
1180 vorbisenc->next_discont = TRUE;
1183 /* Sending zero samples to libvorbis marks EOS, so we mustn't do that */
1184 data = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_WRITE);
1186 gst_buffer_unmap (buffer, data, bsize);
1187 gst_buffer_unref (buffer);
1191 /* data to encode */
1192 size = bsize / (vorbisenc->channels * sizeof (float));
1196 /* expose the buffer to submit data */
1197 vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
1199 /* deinterleave samples, write the buffer data */
1200 for (i = 0; i < size; i++) {
1201 for (j = 0; j < vorbisenc->channels; j++) {
1202 vorbis_buffer[j][i] = *ptr++;
1206 /* tell the library how much we actually submitted */
1207 vorbis_analysis_wrote (&vorbisenc->vd, size);
1208 gst_buffer_unmap (buffer, data, bsize);
1210 GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
1212 vorbisenc->samples_in += size;
1214 gst_buffer_unref (buffer);
1216 ret = gst_vorbis_enc_output_buffers (vorbisenc);
1223 gst_buffer_unref (buffer);
1224 GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL),
1225 ("encoder not initialized (input is not audio?)"));
1226 return GST_FLOW_UNEXPECTED;
1230 GST_WARNING_OBJECT (vorbisenc, "Failed to push headers");
1231 /* buf1 is always already unreffed */
1233 gst_buffer_unref (buf2);
1235 gst_buffer_unref (buf3);
1236 gst_buffer_unref (buffer);
1241 static GstFlowReturn
1242 gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
1246 /* vorbis does some data preanalysis, then divides up blocks for
1247 more involved (potentially parallel) processing. Get a single
1248 block for encoding now */
1249 while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
1252 GST_LOG_OBJECT (vorbisenc, "analysed to a block");
1255 vorbis_analysis (&vorbisenc->vb, NULL);
1256 vorbis_bitrate_addblock (&vorbisenc->vb);
1258 while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
1259 GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
1260 ret = gst_vorbis_enc_push_packet (vorbisenc, &op);
1262 if (ret != GST_FLOW_OK)
1271 gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
1274 GstVorbisEnc *vorbisenc;
1276 g_return_if_fail (GST_IS_VORBISENC (object));
1278 vorbisenc = GST_VORBISENC (object);
1281 case ARG_MAX_BITRATE:
1282 g_value_set_int (value, vorbisenc->max_bitrate);
1285 g_value_set_int (value, vorbisenc->bitrate);
1287 case ARG_MIN_BITRATE:
1288 g_value_set_int (value, vorbisenc->min_bitrate);
1291 g_value_set_float (value, vorbisenc->quality);
1294 g_value_set_boolean (value, vorbisenc->managed);
1296 case ARG_LAST_MESSAGE:
1297 g_value_set_string (value, vorbisenc->last_message);
1300 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1306 gst_vorbis_enc_set_property (GObject * object, guint prop_id,
1307 const GValue * value, GParamSpec * pspec)
1309 GstVorbisEnc *vorbisenc;
1311 g_return_if_fail (GST_IS_VORBISENC (object));
1313 vorbisenc = GST_VORBISENC (object);
1316 case ARG_MAX_BITRATE:
1318 gboolean old_value = vorbisenc->managed;
1320 vorbisenc->max_bitrate = g_value_get_int (value);
1321 if (vorbisenc->max_bitrate >= 0
1322 && vorbisenc->max_bitrate < LOWEST_BITRATE) {
1323 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1324 vorbisenc->max_bitrate = LOWEST_BITRATE;
1326 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1327 vorbisenc->managed = TRUE;
1329 vorbisenc->managed = FALSE;
1331 if (old_value != vorbisenc->managed)
1332 g_object_notify (object, "managed");
1336 vorbisenc->bitrate = g_value_get_int (value);
1337 if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
1338 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1339 vorbisenc->bitrate = LOWEST_BITRATE;
1342 case ARG_MIN_BITRATE:
1344 gboolean old_value = vorbisenc->managed;
1346 vorbisenc->min_bitrate = g_value_get_int (value);
1347 if (vorbisenc->min_bitrate >= 0
1348 && vorbisenc->min_bitrate < LOWEST_BITRATE) {
1349 g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
1350 vorbisenc->min_bitrate = LOWEST_BITRATE;
1352 if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
1353 vorbisenc->managed = TRUE;
1355 vorbisenc->managed = FALSE;
1357 if (old_value != vorbisenc->managed)
1358 g_object_notify (object, "managed");
1362 vorbisenc->quality = g_value_get_float (value);
1363 if (vorbisenc->quality >= 0.0)
1364 vorbisenc->quality_set = TRUE;
1366 vorbisenc->quality_set = FALSE;
1369 vorbisenc->managed = g_value_get_boolean (value);
1372 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1377 static GstStateChangeReturn
1378 gst_vorbis_enc_change_state (GstElement * element, GstStateChange transition)
1380 GstVorbisEnc *vorbisenc = GST_VORBISENC (element);
1381 GstStateChangeReturn res;
1384 switch (transition) {
1385 case GST_STATE_CHANGE_NULL_TO_READY:
1386 vorbisenc->tags = gst_tag_list_new ();
1388 case GST_STATE_CHANGE_READY_TO_PAUSED:
1389 vorbisenc->setup = FALSE;
1390 vorbisenc->next_discont = FALSE;
1391 vorbisenc->header_sent = FALSE;
1392 gst_segment_init (&vorbisenc->segment, GST_FORMAT_TIME);
1394 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1400 res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1402 switch (transition) {
1403 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1405 case GST_STATE_CHANGE_PAUSED_TO_READY:
1406 vorbis_block_clear (&vorbisenc->vb);
1407 vorbis_dsp_clear (&vorbisenc->vd);
1408 vorbis_info_clear (&vorbisenc->vi);
1409 g_free (vorbisenc->last_message);
1410 vorbisenc->last_message = NULL;
1411 if (vorbisenc->srccaps) {
1412 gst_caps_unref (vorbisenc->srccaps);
1413 vorbisenc->srccaps = NULL;
1416 case GST_STATE_CHANGE_READY_TO_NULL:
1417 gst_tag_list_free (vorbisenc->tags);
1418 vorbisenc->tags = NULL;