static void gst_dtsdec_init (GstDtsDec * dtsdec) { dtsdec->request_channels = DCA_CHANNEL; dtsdec->dynamic_range_compression = FALSE; /* retrieve and intercept base class chain. * Quite HACKish, but that's dvd specs for you, * since one buffer needs to be split into 2 frames */ dtsdec->base_chain = GST_PAD_CHAINFUNC (GST_AUDIO_DECODER_SINK_PAD (dtsdec)); gst_pad_set_chain_function (GST_AUDIO_DECODER_SINK_PAD (dtsdec), GST_DEBUG_FUNCPTR (gst_dtsdec_chain)); }
static void gst_a52dec_init (GstA52Dec * a52dec) { a52dec->request_channels = A52_CHANNEL; a52dec->dynamic_range_compression = FALSE; a52dec->state = NULL; a52dec->samples = NULL; /* retrieve and intercept base class chain. * Quite HACKish, but that's dvd specs/caps for you, * since one buffer needs to be split into 2 frames */ a52dec->base_chain = GST_PAD_CHAINFUNC (GST_AUDIO_DECODER_SINK_PAD (a52dec)); gst_pad_set_chain_function (GST_AUDIO_DECODER_SINK_PAD (a52dec), GST_DEBUG_FUNCPTR (gst_a52dec_chain)); }
static void gst_mulawdec_init (GstMuLawDec * mulawdec) { gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (mulawdec), TRUE); gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST (mulawdec), TRUE); GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (mulawdec)); }
static void gst_sbc_dec_init (GstSbcDec * dec) { gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (dec), TRUE); gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST (dec), TRUE); GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (dec)); dec->samples_per_frame = 0; dec->frame_len = 0; }
static void gst_speex_dec_init (GstSpeexDec * dec) { gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (dec), TRUE); gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST (dec), TRUE); GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (dec)); dec->enh = DEFAULT_ENH; gst_speex_dec_reset (dec); }
static void gst_wavpack_dec_init (GstWavpackDec * dec) { dec->context = NULL; dec->stream_reader = gst_wavpack_stream_reader_new (); gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (dec), TRUE); gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST (dec), TRUE); GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (dec)); gst_wavpack_dec_reset (dec); }
static void gst_opus_dec_init (GstOpusDec * dec) { dec->use_inband_fec = FALSE; dec->apply_gain = DEFAULT_APPLY_GAIN; gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (dec), TRUE); gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST (dec), TRUE); GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (dec)); gst_opus_dec_reset (dec); }
static GstFlowReturn vorbis_dec_handle_header_caps (GstVorbisDec * vd) { GstFlowReturn result = GST_FLOW_OK; GstCaps *caps; GstStructure *s = NULL; const GValue *array = NULL; 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; gint i = 0; while (result == GST_FLOW_OK && i < gst_value_array_get_size (array)) { value = gst_value_array_get_value (array, i); buf = gst_value_get_buffer (value); if (!buf) goto null_buffer; result = vorbis_dec_handle_header_buffer (vd, buf); i++; } } else goto array_error; done: return (result != GST_FLOW_OK ? GST_FLOW_NOT_NEGOTIATED : GST_FLOW_OK); /* ERRORS */ 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 void gst_wavpack_dec_post_tags (GstWavpackDec * dec) { GstTagList *list; GstFormat format_time = GST_FORMAT_TIME, format_bytes = GST_FORMAT_BYTES; gint64 duration, size; /* try to estimate the average bitrate */ if (gst_pad_peer_query_duration (GST_AUDIO_DECODER_SINK_PAD (dec), format_bytes, &size) && gst_pad_peer_query_duration (GST_AUDIO_DECODER_SINK_PAD (dec), format_time, &duration) && size > 0 && duration > 0) { guint64 bitrate; list = gst_tag_list_new_empty (); bitrate = gst_util_uint64_scale (size, 8 * GST_SECOND, duration); gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, (guint) bitrate, NULL); gst_audio_decoder_merge_tags (GST_AUDIO_DECODER (dec), list, GST_TAG_MERGE_REPLACE); } }
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 GstFlowReturn gst_mpg123_audio_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * input_buffer) { GstMpg123AudioDec *mpg123_decoder; int decode_error; unsigned char *decoded_bytes; size_t num_decoded_bytes; GstFlowReturn retval; mpg123_decoder = GST_MPG123_AUDIO_DEC (dec); g_assert (mpg123_decoder->handle != NULL); /* The actual decoding */ { /* feed input data (if there is any) */ if (G_LIKELY (input_buffer != NULL)) { GstMapInfo info; if (gst_buffer_map (input_buffer, &info, GST_MAP_READ)) { mpg123_feed (mpg123_decoder->handle, info.data, info.size); gst_buffer_unmap (input_buffer, &info); } else { GST_ERROR_OBJECT (mpg123_decoder, "gst_memory_map() failed"); return GST_FLOW_ERROR; } } /* Try to decode a frame */ decoded_bytes = NULL; num_decoded_bytes = 0; decode_error = mpg123_decode_frame (mpg123_decoder->handle, &mpg123_decoder->frame_offset, &decoded_bytes, &num_decoded_bytes); } retval = GST_FLOW_OK; switch (decode_error) { case MPG123_NEW_FORMAT: /* As mentioned in gst_mpg123_audio_dec_set_format(), the next audioinfo * is not set immediately; instead, the code waits for mpg123 to take * note of the new format, and then sets the audioinfo. This fixes glitches * with mp3s containing several format headers (for example, first half * using 44.1kHz, second half 32 kHz) */ GST_LOG_OBJECT (dec, "mpg123 reported a new format -> setting next srccaps"); gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes, num_decoded_bytes); /* If there is a next audioinfo, use it, then set has_next_audioinfo to * FALSE, to make sure gst_audio_decoder_set_output_format() isn't called * again until set_format is called by the base class */ if (mpg123_decoder->has_next_audioinfo) { if (!gst_audio_decoder_set_output_format (dec, &(mpg123_decoder->next_audioinfo))) { GST_WARNING_OBJECT (dec, "Unable to set output format"); retval = GST_FLOW_NOT_NEGOTIATED; } mpg123_decoder->has_next_audioinfo = FALSE; } break; case MPG123_NEED_MORE: case MPG123_OK: retval = gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes, num_decoded_bytes); break; case MPG123_DONE: /* If this happens, then the upstream parser somehow missed the ending * of the bitstream */ GST_LOG_OBJECT (dec, "mpg123 is done decoding"); gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes, num_decoded_bytes); retval = GST_FLOW_EOS; break; default: { /* Anything else is considered an error */ int errcode; switch (decode_error) { case MPG123_ERR: errcode = mpg123_errcode (mpg123_decoder->handle); break; default: errcode = decode_error; } switch (errcode) { case MPG123_BAD_OUTFORMAT:{ GstCaps *input_caps = gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (dec)); GST_ELEMENT_ERROR (dec, STREAM, FORMAT, (NULL), ("Output sample format could not be used when trying to decode frame. " "This is typically caused when the input caps (often the sample " "rate) do not match the actual format of the audio data. " "Input caps: %" GST_PTR_FORMAT, input_caps) ); gst_caps_unref (input_caps); break; } default:{ char const *errmsg = mpg123_plain_strerror (errcode); GST_ERROR_OBJECT (dec, "Reported error: %s", errmsg); } } retval = GST_FLOW_ERROR; } } return retval; }
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; }
static gboolean gst_droidadec_set_format (GstAudioDecoder * decoder, GstCaps * caps) { GstDroidADec *dec = GST_DROIDADEC (decoder); GstStructure *str = gst_caps_get_structure (caps, 0); const GValue *value = gst_structure_get_value (str, "codec_data"); GstBuffer *codec_data = value ? gst_value_get_buffer (value) : NULL; /* * destroying the droidmedia codec here will cause stagefright to call abort. * That is why we create it after we are sure that everything is correct */ GST_DEBUG_OBJECT (dec, "set format %" GST_PTR_FORMAT, caps); if (dec->codec) { /* If we get a format change then we stop */ GstCaps *current = gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (decoder)); gboolean equal = gst_caps_is_equal_fixed (caps, current); gst_caps_unref (current); GST_DEBUG_OBJECT (dec, "new format is similar to old format? %d", equal); if (!equal) { GST_ELEMENT_ERROR (dec, LIBRARY, SETTINGS, (NULL), ("codec already configured")); } return equal; } dec->codec_type = gst_droid_codec_new_from_caps (caps, GST_DROID_CODEC_DECODER_AUDIO); if (!dec->codec_type) { GST_ELEMENT_ERROR (dec, LIBRARY, FAILED, (NULL), ("Unknown codec type for caps %" GST_PTR_FORMAT, caps)); return FALSE; } if (!gst_structure_get_int (str, "channels", &dec->channels) || !gst_structure_get_int (str, "rate", &dec->rate)) { GST_ELEMENT_ERROR (dec, STREAM, FORMAT, (NULL), ("Failed to parse caps %" GST_PTR_FORMAT, caps)); return FALSE; } GST_INFO_OBJECT (dec, "configuring decoder. rate=%d, channels=%d", dec->rate, dec->channels); gst_buffer_replace (&dec->codec_data, codec_data); /* handle_frame will create the codec */ dec->dirty = TRUE; dec->spf = gst_droid_codec_get_samples_per_frane (caps); GST_INFO_OBJECT (dec, "samples per frame: %d", dec->spf); return TRUE; }