Opus解码音频API
创建音频解码器
代码分析
AudioDecoderOpusImpl::AudioDecoderOpusImpl
AudioDecoderOpusImpl::AudioDecoderOpusImpl(size_t num_channels,int sample_rate_hz): channels_{num_channels}, sample_rate_hz_{sample_rate_hz} {RTC_DCHECK(num_channels == 1 || num_channels == 2);RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 48000);const int error =WebRtcOpus_DecoderCreate(&dec_state_, channels_, sample_rate_hz_);RTC_DCHECK(error == 0);WebRtcOpus_DecoderInit(dec_state_);}

NetEqImpl::DecodeLoop
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\modules\audio_coding\neteq\neteq_impl.cc
int NetEqImpl::DecodeLoop(PacketList* packet_list,const Operation& operation,AudioDecoder* decoder,int* decoded_length,AudioDecoder::SpeechType* speech_type) {RTC_DCHECK(last_decoded_timestamps_.empty());RTC_DCHECK(last_decoded_packet_infos_.empty());// Do decoding.while (!packet_list->empty() && !decoder_database_->IsComfortNoise(packet_list->front().payload_type)) {assert(decoder); // At this point, we must have a decoder object.// The number of channels in the |sync_buffer_| should be the same as the// number decoder channels.assert(sync_buffer_->Channels() == decoder->Channels());assert(decoded_buffer_length_ >= kMaxFrameSize * decoder->Channels());assert(operation == Operation::kNormal ||operation == Operation::kAccelerate ||operation == Operation::kFastAccelerate ||operation == Operation::kMerge ||operation == Operation::kPreemptiveExpand);// 对传入的音频进行解码操作auto opt_result = packet_list->front().frame->Decode(rtc::ArrayView<int16_t>(&decoded_buffer_[*decoded_length],decoded_buffer_length_ - *decoded_length));last_decoded_timestamps_.push_back(packet_list->front().timestamp);last_decoded_packet_infos_.push_back(std::move(packet_list->front().packet_info));packet_list->pop_front();if (opt_result) {const auto& result = *opt_result;*speech_type = result.speech_type;if (result.num_decoded_samples > 0) {*decoded_length += rtc::dchecked_cast<int>(result.num_decoded_samples);// Update |decoder_frame_length_| with number of samples per channel.decoder_frame_length_ =result.num_decoded_samples / decoder->Channels();}} else {// Error.// TODO(ossu): What to put here?RTC_LOG(LS_WARNING) << "Decode error";*decoded_length = -1;last_decoded_packet_infos_.clear();packet_list->clear();break;}if (*decoded_length > rtc::dchecked_cast<int>(decoded_buffer_length_)) {// Guard against overflow.RTC_LOG(LS_WARNING) << "Decoded too much.";packet_list->clear();return kDecodedTooMuch;}} // End of decode loop.// If the list is not empty at this point, either a decoding error terminated// the while-loop, or list must hold exactly one CNG packet.assert(packet_list->empty() || *decoded_length < 0 ||(packet_list->size() == 1 && decoder_database_->IsComfortNoise(packet_list->front().payload_type)));return 0;}

webrtc::OpusFrame::Decode
absl::optional<DecodeResult> Decode(rtc::ArrayView<int16_t> decoded) const override {AudioDecoder::SpeechType speech_type = AudioDecoder::kSpeech;int ret;if (is_primary_payload_) {ret = decoder_->Decode(payload_.data(), payload_.size(), decoder_->SampleRateHz(),decoded.size() * sizeof(int16_t), decoded.data(), &speech_type);} else {ret = decoder_->DecodeRedundant(payload_.data(), payload_.size(), decoder_->SampleRateHz(),decoded.size() * sizeof(int16_t), decoded.data(), &speech_type);}if (ret < 0)return absl::nullopt;return DecodeResult{static_cast<size_t>(ret), speech_type};}
AudioDecoder::Decode
int AudioDecoder::Decode(const uint8_t* encoded,size_t encoded_len,int sample_rate_hz,size_t max_decoded_bytes,int16_t* decoded,SpeechType* speech_type) {TRACE_EVENT0("webrtc", "AudioDecoder::Decode");rtc::MsanCheckInitialized(rtc::MakeArrayView(encoded, encoded_len));int duration = PacketDuration(encoded, encoded_len);if (duration >= 0 &&duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {return -1;}return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,speech_type);}
AudioDecoderOpusImpl::DecodeInternal
int AudioDecoderOpusImpl::DecodeInternal(const uint8_t* encoded,size_t encoded_len,int sample_rate_hz,int16_t* decoded,SpeechType* speech_type) {RTC_DCHECK_EQ(sample_rate_hz, sample_rate_hz_);int16_t temp_type = 1; // Default is speech.int ret =WebRtcOpus_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type);if (ret > 0)ret *= static_cast<int>(channels_); // Return total number of samples.// temp_type==0,返回 AudioDecoder::SpeechType::kSpeech*speech_type = ConvertSpeechType(temp_type);return ret;}


