GST_STATIC_CAPS ("audio/x-vorbis")
);
-GST_BOILERPLATE (GstVorbisDec, gst_vorbis_dec, GstAudioDecoder,
- GST_TYPE_AUDIO_DECODER);
+#define gst_vorbis_dec_parent_class parent_class
+G_DEFINE_TYPE (GstVorbisDec, gst_vorbis_dec, GST_TYPE_AUDIO_DECODER);
static void vorbis_dec_finalize (GObject * object);
static void vorbis_dec_flush (GstAudioDecoder * dec, gboolean hard);
static void
-gst_vorbis_dec_base_init (gpointer g_class)
+gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GstPadTemplate *src_template, *sink_template;
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstAudioDecoderClass *base_class = GST_AUDIO_DECODER_CLASS (klass);
+
+ gobject_class->finalize = vorbis_dec_finalize;
src_template = gst_static_pad_template_get (&vorbis_dec_src_factory);
gst_element_class_add_pad_template (element_class, src_template);
"Vorbis audio decoder", "Codec/Decoder/Audio",
GST_VORBIS_DEC_DESCRIPTION,
"Benjamin Otte <otte@gnome.org>, Chris Lord <chris@openedhand.com>");
-}
-
-static void
-gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstAudioDecoderClass *base_class = GST_AUDIO_DECODER_CLASS (klass);
-
- gobject_class->finalize = vorbis_dec_finalize;
base_class->start = GST_DEBUG_FUNCPTR (vorbis_dec_start);
base_class->stop = GST_DEBUG_FUNCPTR (vorbis_dec_stop);
}
static void
-gst_vorbis_dec_init (GstVorbisDec * dec, GstVorbisDecClass * g_class)
+gst_vorbis_dec_init (GstVorbisDec * dec)
{
}
vorbis_handle_identification_packet (GstVorbisDec * vd)
{
GstCaps *caps;
- const GstAudioChannelPosition *pos = NULL;
- gint width = GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH;
+ GstAudioInfo info;
- switch (vd->vi.channels) {
+ gst_audio_info_set_format (&info, GST_VORBIS_AUDIO_FORMAT, vd->vi.rate,
+ vd->vi.channels);
+
+ switch (info.channels) {
case 1:
case 2:
/* nothing */
case 6:
case 7:
case 8:
- pos = gst_vorbis_channel_positions[vd->vi.channels - 1];
+ {
+ const GstAudioChannelPosition *pos;
+ gint i;
+
+ pos = gst_vorbis_channel_positions[info.channels - 1];
+ for (i = 0; i < info.channels; i++)
+ info.position[i] = pos[i];
break;
+ }
default:{
- gint i;
- GstAudioChannelPosition *posn =
- g_new (GstAudioChannelPosition, vd->vi.channels);
+ gint i, max_pos = MAX (info.channels, 64);
- GST_ELEMENT_WARNING (GST_ELEMENT (vd), STREAM, DECODE,
+ GST_ELEMENT_WARNING (vd, STREAM, DECODE,
(NULL), ("Using NONE channel layout for more than 8 channels"));
-
- for (i = 0; i < vd->vi.channels; i++)
- posn[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
-
- pos = posn;
+ for (i = 0; i < max_pos; i++)
+ info.position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+ break;
}
}
- /* negotiate width with downstream */
- caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (vd));
- if (caps) {
- if (!gst_caps_is_empty (caps)) {
- GstStructure *s;
-
- s = gst_caps_get_structure (caps, 0);
- /* template ensures 16 or 32 */
- gst_structure_get_int (s, "width", &width);
-
- GST_INFO_OBJECT (vd, "using %s with %d channels and %d bit audio depth",
- gst_structure_get_name (s), vd->vi.channels, width);
- }
- gst_caps_unref (caps);
- }
- vd->width = width >> 3;
+ caps = gst_audio_info_to_caps (&info);
+ gst_audio_decoder_set_outcaps (GST_AUDIO_DECODER (vd), caps);
+ gst_caps_unref (caps);
+ vd->info = info;
/* select a copy_samples function, this way we can have specialized versions
* for mono/stereo and avoid the depth switch in tremor case */
- vd->copy_samples = get_copy_sample_func (vd->vi.channels, vd->width);
-
- caps =
- gst_caps_copy (gst_pad_get_pad_template_caps
- (GST_AUDIO_DECODER_SRC_PAD (vd)));
- gst_caps_set_simple (caps, "rate", G_TYPE_INT, vd->vi.rate, "channels",
- G_TYPE_INT, vd->vi.channels, "width", G_TYPE_INT, width, NULL);
-
- if (pos) {
- gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
- }
-
- if (vd->vi.channels > 8) {
- g_free ((GstAudioChannelPosition *) pos);
- }
-
- gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (vd), caps);
- gst_caps_unref (caps);
+ vd->copy_samples = get_copy_sample_func (info.channels);
return GST_FLOW_OK;
}
guint bitrate = 0;
gchar *encoder = NULL;
GstTagList *list, *old_list;
- GstBuffer *buf;
+ guint8 *data;
+ gsize size;
GST_DEBUG_OBJECT (vd, "parsing comment packet");
- buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = gst_ogg_packet_data (packet);
- GST_BUFFER_SIZE (buf) = gst_ogg_packet_size (packet);
+ data = gst_ogg_packet_data (packet);
+ size = gst_ogg_packet_size (packet);
list =
- gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7,
+ gst_tag_list_from_vorbiscomment (data, size, (guint8 *) "\003vorbis", 7,
&encoder);
old_list = vd->taglist;
if (old_list)
gst_tag_list_free (old_list);
gst_tag_list_free (list);
- gst_buffer_unref (buf);
if (!vd->taglist) {
GST_ERROR_OBJECT (vd, "couldn't decode comments");
{
ogg_packet *packet;
ogg_packet_wrapper packet_wrapper;
+ GstFlowReturn ret;
- gst_ogg_packet_wrapper_from_buffer (&packet_wrapper, buffer);
+ gst_ogg_packet_wrapper_map (&packet_wrapper, buffer);
packet = gst_ogg_packet_from_wrapper (&packet_wrapper);
- return vorbis_handle_header_packet (vd, packet);
+ ret = vorbis_handle_header_packet (vd, packet);
+
+ gst_ogg_packet_wrapper_unmap (&packet_wrapper, buffer);
+
+ return ret;
}
#define MIN_NUM_HEADERS 3
GstStructure *s = NULL;
const GValue *array = NULL;
- caps = GST_PAD_CAPS (GST_AUDIO_DECODER_SINK_PAD (vd));
+ caps = gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (vd));
if (caps)
s = gst_caps_get_structure (caps, 0);
if (s)
array = gst_structure_get_value (s, "streamheader");
+ if (caps)
+ gst_caps_unref (caps);
+
if (array && (gst_value_array_get_size (array) >= MIN_NUM_HEADERS)) {
const GValue *value = NULL;
GstBuffer *buf = NULL;
guint sample_count;
GstBuffer *out = NULL;
GstFlowReturn result;
- gint size;
+ guint8 *data;
+ gsize size;
if (G_UNLIKELY (!vd->initialized)) {
result = vorbis_dec_handle_header_caps (vd);
goto done;
#endif
- size = sample_count * vd->vi.channels * vd->width;
+ size = sample_count * vd->info.bpf;
GST_LOG_OBJECT (vd, "%d samples ready for reading, size %d", sample_count,
size);
/* alloc buffer for it */
- result =
- gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (vd),
- GST_BUFFER_OFFSET_NONE, size,
- GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (vd)), &out);
- if (G_UNLIKELY (result != GST_FLOW_OK))
- goto done;
+ out = gst_buffer_new_allocate (NULL, size, 0);
+ data = gst_buffer_map (out, NULL, NULL, GST_MAP_WRITE);
/* get samples ready for reading now, should be sample_count */
#ifdef USE_TREMOLO
- pcm = GST_BUFFER_DATA (out);
- if (G_UNLIKELY (vorbis_dsp_pcmout (&vd->vd, pcm, sample_count) !=
+ if (G_UNLIKELY (vorbis_dsp_pcmout (&vd->vd, data, sample_count) !=
sample_count))
#else
if (G_UNLIKELY (vorbis_synthesis_pcmout (&vd->vd, &pcm) != sample_count))
#ifndef USE_TREMOLO
/* copy samples in buffer */
- vd->copy_samples ((vorbis_sample_t *) GST_BUFFER_DATA (out), pcm,
- sample_count, vd->vi.channels, vd->width);
+ vd->copy_samples ((vorbis_sample_t *) data, pcm,
+ sample_count, vd->info.channels);
#endif
GST_LOG_OBJECT (vd, "setting output size to %d", size);
- GST_BUFFER_SIZE (out) = size;
+ gst_buffer_unmap (out, data, size);
done:
/* whether or not data produced, consume one frame and advance time */
if (G_UNLIKELY (!buffer))
return GST_FLOW_OK;
+ GST_LOG_OBJECT (vd, "got buffer %p", buffer);
/* make ogg_packet out of the buffer */
- gst_ogg_packet_wrapper_from_buffer (&packet_wrapper, buffer);
+ gst_ogg_packet_wrapper_map (&packet_wrapper, buffer);
packet = gst_ogg_packet_from_wrapper (&packet_wrapper);
/* set some more stuff */
packet->granulepos = -1;
}
done:
+ GST_LOG_OBJECT (vd, "unmap buffer %p", buffer);
+ gst_ogg_packet_wrapper_unmap (&packet_wrapper, buffer);
+
return result;
empty_buffer: