From acf18e34bedb68dbe927a32183b29eeac2023e4c Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 16 Nov 2011 13:26:35 +0000 Subject: [PATCH] opusdec: allow negotiation of rate/channels with downstream Since an opus stream may be decoded to any (sensible) rate, and either stereo or mono, we try to accomodate downstream. --- ext/opus/gstopusdec.c | 67 +++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c index d3528c85a9..5af378487f 100644 --- a/ext/opus/gstopusdec.c +++ b/ext/opus/gstopusdec.c @@ -121,8 +121,8 @@ gst_opus_dec_reset (GstOpusDec * dec) static void gst_opus_dec_init (GstOpusDec * dec) { - dec->sample_rate = 48000; - dec->n_channels = 2; + dec->sample_rate = 0; + dec->n_channels = 0; gst_opus_dec_reset (dec); } @@ -162,6 +162,46 @@ gst_opus_dec_parse_comments (GstOpusDec * dec, GstBuffer * buf) return GST_FLOW_OK; } +static void +gst_opus_dec_setup_from_peer_caps (GstOpusDec * dec) +{ + GstPad *srcpad, *peer; + GstStructure *s; + GstCaps *caps, *template_caps, *peer_caps; + + srcpad = GST_AUDIO_DECODER_SRC_PAD (dec); + peer = gst_pad_get_peer (srcpad); + + if (peer) { + template_caps = gst_pad_get_pad_template_caps (srcpad); + peer_caps = gst_pad_get_caps (peer, NULL); + GST_DEBUG_OBJECT (dec, "Peer caps: %" GST_PTR_FORMAT, peer_caps); + caps = gst_caps_intersect (template_caps, peer_caps); + gst_caps_fixate (caps); + GST_DEBUG_OBJECT (dec, "Fixated caps: %" GST_PTR_FORMAT, caps); + + s = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_int (s, "channels", &dec->n_channels)) { + dec->n_channels = 2; + GST_WARNING_OBJECT (dec, "Failed to get channels, using default %d", + dec->n_channels); + } else { + GST_DEBUG_OBJECT (dec, "Got channels %d", dec->n_channels); + } + if (!gst_structure_get_int (s, "rate", &dec->sample_rate)) { + dec->sample_rate = 48000; + GST_WARNING_OBJECT (dec, "Failed to get rate, using default %d", + dec->sample_rate); + } else { + GST_DEBUG_OBJECT (dec, "Got sample rate %d", dec->sample_rate); + } + + gst_audio_decoder_set_outcaps (GST_AUDIO_DECODER (dec), caps); + } else { + GST_WARNING_OBJECT (dec, "Failed to get src pad peer"); + } +} + static GstFlowReturn opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf, GstClockTime timestamp, GstClockTime duration) @@ -176,25 +216,11 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf, unsigned int packet_size; if (dec->state == NULL) { - GstCaps *caps; + gst_opus_dec_setup_from_peer_caps (dec); dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels, &err); if (!dec->state || err != OPUS_OK) goto creation_failed; - - /* set caps */ - caps = gst_caps_new_simple ("audio/x-raw", - "format", G_TYPE_STRING, "S16LE", - "rate", G_TYPE_INT, dec->sample_rate, - "channels", G_TYPE_INT, dec->n_channels, NULL); - - GST_DEBUG_OBJECT (dec, "rate=%d channels=%d", - dec->sample_rate, dec->n_channels); - - if (!gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), caps)) - GST_ERROR ("nego failure"); - - gst_caps_unref (caps); } if (buf) { @@ -302,13 +328,6 @@ gst_opus_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps) } } - caps = gst_caps_new_simple ("audio/x-raw", - "format", G_TYPE_STRING, "S16LE", - "rate", G_TYPE_INT, dec->sample_rate, - "channels", G_TYPE_INT, dec->n_channels, NULL); - gst_audio_decoder_set_outcaps (GST_AUDIO_DECODER (dec), caps); - gst_caps_unref (caps); - done: return ret; }