From 0f7522e44994048cf60636b2d1725467d450bff6 Mon Sep 17 00:00:00 2001 From: Aleix Conchillo Flaque Date: Wed, 18 May 2011 22:07:58 +0200 Subject: [PATCH] vorbisdec: Handle headers in caps --- ext/vorbis/gstvorbisdec.c | 89 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/ext/vorbis/gstvorbisdec.c b/ext/vorbis/gstvorbisdec.c index 645c27d690..ee90661489 100644 --- a/ext/vorbis/gstvorbisdec.c +++ b/ext/vorbis/gstvorbisdec.c @@ -929,7 +929,8 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet, /* 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)) != sample_count)) + if (G_UNLIKELY ((vorbis_dsp_pcmout (&vd->vd, pcm, + sample_count)) != sample_count)) #else if (G_UNLIKELY ((vorbis_synthesis_pcmout (&vd->vd, &pcm)) != sample_count)) #endif @@ -960,7 +961,6 @@ done: /* no output, still keep track of timestamps */ vorbis_do_timestamps (vd, NULL, FALSE, timestamp, duration); } - #ifdef USE_TREMOLO vorbis_dsp_read (&vd->vd, sample_count); #else @@ -997,6 +997,77 @@ wrong_samples: } } +static GstFlowReturn +vorbis_dec_handle_header_buffer (GstVorbisDec * vd, GstBuffer * buffer) +{ + ogg_packet *packet; + ogg_packet_wrapper packet_wrapper; + + gst_ogg_packet_wrapper_from_buffer (&packet_wrapper, buffer); + packet = gst_ogg_packet_from_wrapper (&packet_wrapper); + + return vorbis_handle_header_packet (vd, packet); +} + + +#define MIN_NUM_HEADERS 3 +static GstFlowReturn +vorbis_dec_handle_header_caps (GstVorbisDec * vd, GstBuffer * buffer) +{ + GstFlowReturn result = GST_FLOW_OK; + GstCaps *caps = GST_PAD_CAPS (vd->sinkpad); + GstStructure *s = gst_caps_get_structure (caps, 0); + const GValue *array = gst_structure_get_value (s, "streamheader"); + + if (array && (gst_value_array_get_size (array) >= MIN_NUM_HEADERS)) { + const GValue *value = NULL; + GstBuffer *buf = NULL; + + /* initial header */ + value = gst_value_array_get_value (array, 0); + buf = gst_value_get_buffer (value); + if (!buf) + goto null_buffer; + result = vorbis_dec_handle_header_buffer (vd, buf); + + /* comment header */ + if (result == GST_FLOW_OK) { + value = gst_value_array_get_value (array, 1); + buf = gst_value_get_buffer (value); + if (!buf) + goto null_buffer; + result = vorbis_dec_handle_header_buffer (vd, buf); + } + + /* bitstream codebook header */ + if (result == GST_FLOW_OK) { + value = gst_value_array_get_value (array, 2); + buf = gst_value_get_buffer (value); + if (!buf) + goto null_buffer; + result = vorbis_dec_handle_header_buffer (vd, buf); + } + } else + goto array_error; + +done: + return (result != GST_FLOW_OK ? GST_FLOW_NOT_NEGOTIATED : GST_FLOW_OK); + +array_error: + { + GST_WARNING_OBJECT (vd, "streamheader array not found"); + result = GST_FLOW_ERROR; + goto done; + } + +null_buffer: + { + GST_WARNING_OBJECT (vd, "streamheader with null buffer received"); + result = GST_FLOW_ERROR; + goto done; + } +} + static GstFlowReturn vorbis_dec_decode_buffer (GstVorbisDec * vd, GstBuffer * buffer) { @@ -1034,6 +1105,13 @@ vorbis_dec_decode_buffer (GstVorbisDec * vd, GstBuffer * buffer) } else { GstClockTime timestamp, duration; + /* try to find header in caps so we can initialize the decoder */ + if (!vd->initialized) { + result = vorbis_dec_handle_header_caps (vd, buffer); + if (result != GST_FLOW_OK) + goto invalid_caps_header; + } + timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); @@ -1060,6 +1138,13 @@ empty_header: vd->discont = TRUE; goto done; } + +invalid_caps_header: + { + GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), + ("invalid streamheader in caps")); + goto done; + } } /*