static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps) { GstOpusDec *dec = GST_OPUS_DEC (bdec); gboolean ret = TRUE; GstStructure *s; const GValue *streamheader; GST_DEBUG_OBJECT (dec, "set_format: %" GST_PTR_FORMAT, caps); s = gst_caps_get_structure (caps, 0); if ((streamheader = gst_structure_get_value (s, "streamheader")) && G_VALUE_HOLDS (streamheader, GST_TYPE_ARRAY) && gst_value_array_get_size (streamheader) >= 2) { const GValue *header, *vorbiscomment; GstBuffer *buf; GstFlowReturn res = GST_FLOW_OK; header = gst_value_array_get_value (streamheader, 0); if (header && G_VALUE_HOLDS (header, GST_TYPE_BUFFER)) { buf = gst_value_get_buffer (header); res = gst_opus_dec_parse_header (dec, buf); if (res != GST_FLOW_OK) goto done; gst_buffer_replace (&dec->streamheader, buf); } vorbiscomment = gst_value_array_get_value (streamheader, 1); if (vorbiscomment && G_VALUE_HOLDS (vorbiscomment, GST_TYPE_BUFFER)) { buf = gst_value_get_buffer (vorbiscomment); res = gst_opus_dec_parse_comments (dec, buf); if (res != GST_FLOW_OK) goto done; gst_buffer_replace (&dec->vorbiscomment, buf); } } done: return ret; }
static GstFlowReturn gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf) { GstFlowReturn res; GstOpusDec *dec; /* no fancy draining */ if (G_UNLIKELY (!buf)) return GST_FLOW_OK; dec = GST_OPUS_DEC (adec); GST_LOG_OBJECT (dec, "Got buffer ts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); /* If we have the streamheader and vorbiscomment from the caps already * ignore them here */ if (dec->streamheader && dec->vorbiscomment) { if (memcmp_buffers (dec->streamheader, buf)) { GST_DEBUG_OBJECT (dec, "found streamheader"); gst_audio_decoder_finish_frame (adec, NULL, 1); res = GST_FLOW_OK; } else if (memcmp_buffers (dec->vorbiscomment, buf)) { GST_DEBUG_OBJECT (dec, "found vorbiscomments"); gst_audio_decoder_finish_frame (adec, NULL, 1); res = GST_FLOW_OK; } else { res = opus_dec_chain_parse_data (dec, buf); } } else { /* Otherwise fall back to packet counting and assume that the * first two packets might be the headers, checking magic. */ switch (dec->packetno) { case 0: if (gst_opus_header_is_header (buf, "OpusHead", 8)) { GST_DEBUG_OBJECT (dec, "found streamheader"); res = gst_opus_dec_parse_header (dec, buf); gst_audio_decoder_finish_frame (adec, NULL, 1); } else { res = opus_dec_chain_parse_data (dec, buf); } break; case 1: if (gst_opus_header_is_header (buf, "OpusTags", 8)) { GST_DEBUG_OBJECT (dec, "counted vorbiscomments"); res = gst_opus_dec_parse_comments (dec, buf); gst_audio_decoder_finish_frame (adec, NULL, 1); } else { res = opus_dec_chain_parse_data (dec, buf); } break; default: { res = opus_dec_chain_parse_data (dec, buf); break; } } } dec->packetno++; return res; }
static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps) { GstOpusDec *dec = GST_OPUS_DEC (bdec); gboolean ret = TRUE; GstStructure *s; const GValue *streamheader; GstCaps *old_caps; GST_DEBUG_OBJECT (dec, "set_format: %" GST_PTR_FORMAT, caps); if ((old_caps = gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (bdec)))) { if (gst_caps_is_equal (caps, old_caps)) { gst_caps_unref (old_caps); GST_DEBUG_OBJECT (dec, "caps didn't change"); goto done; } GST_DEBUG_OBJECT (dec, "caps have changed, resetting decoder"); gst_opus_dec_reset (dec); gst_caps_unref (old_caps); } s = gst_caps_get_structure (caps, 0); if ((streamheader = gst_structure_get_value (s, "streamheader")) && G_VALUE_HOLDS (streamheader, GST_TYPE_ARRAY) && gst_value_array_get_size (streamheader) >= 2) { const GValue *header, *vorbiscomment; GstBuffer *buf; GstFlowReturn res = GST_FLOW_OK; header = gst_value_array_get_value (streamheader, 0); if (header && G_VALUE_HOLDS (header, GST_TYPE_BUFFER)) { buf = gst_value_get_buffer (header); res = gst_opus_dec_parse_header (dec, buf); if (res != GST_FLOW_OK) goto done; gst_buffer_replace (&dec->streamheader, buf); } vorbiscomment = gst_value_array_get_value (streamheader, 1); if (vorbiscomment && G_VALUE_HOLDS (vorbiscomment, GST_TYPE_BUFFER)) { buf = gst_value_get_buffer (vorbiscomment); res = gst_opus_dec_parse_comments (dec, buf); if (res != GST_FLOW_OK) goto done; gst_buffer_replace (&dec->vorbiscomment, buf); } } else { /* defaults if not in the caps */ dec->n_channels = 2; dec->sample_rate = 48000; gst_structure_get_int (s, "channels", &dec->n_channels); gst_structure_get_int (s, "rate", &dec->sample_rate); /* default stereo mapping */ dec->channel_mapping_family = 0; dec->channel_mapping[0] = 0; dec->channel_mapping[1] = 1; dec->n_streams = 1; dec->n_stereo_streams = 1; gst_opus_dec_negotiate (dec, NULL); } done: return ret; }
static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps) { GstOpusDec *dec = GST_OPUS_DEC (bdec); gboolean ret = TRUE; GstStructure *s; const GValue *streamheader; GstCaps *old_caps; GST_DEBUG_OBJECT (dec, "set_format: %" GST_PTR_FORMAT, caps); if ((old_caps = gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (bdec)))) { if (gst_caps_is_equal (caps, old_caps)) { gst_caps_unref (old_caps); GST_DEBUG_OBJECT (dec, "caps didn't change"); goto done; } GST_DEBUG_OBJECT (dec, "caps have changed, resetting decoder"); gst_opus_dec_reset (dec); gst_caps_unref (old_caps); } s = gst_caps_get_structure (caps, 0); if ((streamheader = gst_structure_get_value (s, "streamheader")) && G_VALUE_HOLDS (streamheader, GST_TYPE_ARRAY) && gst_value_array_get_size (streamheader) >= 2) { const GValue *header, *vorbiscomment; GstBuffer *buf; GstFlowReturn res = GST_FLOW_OK; header = gst_value_array_get_value (streamheader, 0); if (header && G_VALUE_HOLDS (header, GST_TYPE_BUFFER)) { buf = gst_value_get_buffer (header); res = gst_opus_dec_parse_header (dec, buf); if (res != GST_FLOW_OK) { ret = FALSE; goto done; } gst_buffer_replace (&dec->streamheader, buf); } vorbiscomment = gst_value_array_get_value (streamheader, 1); if (vorbiscomment && G_VALUE_HOLDS (vorbiscomment, GST_TYPE_BUFFER)) { buf = gst_value_get_buffer (vorbiscomment); res = gst_opus_dec_parse_comments (dec, buf); if (res != GST_FLOW_OK) { ret = FALSE; goto done; } gst_buffer_replace (&dec->vorbiscomment, buf); } } else { const GstAudioChannelPosition *posn = NULL; if (!gst_codec_utils_opus_parse_caps (caps, &dec->sample_rate, &dec->n_channels, &dec->channel_mapping_family, &dec->n_streams, &dec->n_stereo_streams, dec->channel_mapping)) { ret = FALSE; goto done; } if (dec->channel_mapping_family == 1 && dec->n_channels <= 8) posn = gst_opus_channel_positions[dec->n_channels - 1]; if (!gst_opus_dec_negotiate (dec, posn)) return FALSE; } done: return ret; }