Opus解码音频API

image.png

创建音频解码器

image.png
本节主要讲右手边的音频播放线程的。

代码分析

AudioDecoderOpusImpl::AudioDecoderOpusImpl

  1. AudioDecoderOpusImpl::AudioDecoderOpusImpl(size_t num_channels,
  2. int sample_rate_hz)
  3. : channels_{num_channels}, sample_rate_hz_{sample_rate_hz} {
  4. RTC_DCHECK(num_channels == 1 || num_channels == 2);
  5. RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 48000);
  6. const int error =
  7. WebRtcOpus_DecoderCreate(&dec_state_, channels_, sample_rate_hz_);
  8. RTC_DCHECK(error == 0);
  9. WebRtcOpus_DecoderInit(dec_state_);
  10. }

image.png

NetEqImpl::DecodeLoop

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\modules\audio_coding\neteq\neteq_impl.cc

  1. int NetEqImpl::DecodeLoop(PacketList* packet_list,
  2. const Operation& operation,
  3. AudioDecoder* decoder,
  4. int* decoded_length,
  5. AudioDecoder::SpeechType* speech_type) {
  6. RTC_DCHECK(last_decoded_timestamps_.empty());
  7. RTC_DCHECK(last_decoded_packet_infos_.empty());
  8. // Do decoding.
  9. while (!packet_list->empty() && !decoder_database_->IsComfortNoise(
  10. packet_list->front().payload_type)) {
  11. assert(decoder); // At this point, we must have a decoder object.
  12. // The number of channels in the |sync_buffer_| should be the same as the
  13. // number decoder channels.
  14. assert(sync_buffer_->Channels() == decoder->Channels());
  15. assert(decoded_buffer_length_ >= kMaxFrameSize * decoder->Channels());
  16. assert(operation == Operation::kNormal ||
  17. operation == Operation::kAccelerate ||
  18. operation == Operation::kFastAccelerate ||
  19. operation == Operation::kMerge ||
  20. operation == Operation::kPreemptiveExpand);
  21. // 对传入的音频进行解码操作
  22. auto opt_result = packet_list->front().frame->Decode(
  23. rtc::ArrayView<int16_t>(&decoded_buffer_[*decoded_length],
  24. decoded_buffer_length_ - *decoded_length));
  25. last_decoded_timestamps_.push_back(packet_list->front().timestamp);
  26. last_decoded_packet_infos_.push_back(
  27. std::move(packet_list->front().packet_info));
  28. packet_list->pop_front();
  29. if (opt_result) {
  30. const auto& result = *opt_result;
  31. *speech_type = result.speech_type;
  32. if (result.num_decoded_samples > 0) {
  33. *decoded_length += rtc::dchecked_cast<int>(result.num_decoded_samples);
  34. // Update |decoder_frame_length_| with number of samples per channel.
  35. decoder_frame_length_ =
  36. result.num_decoded_samples / decoder->Channels();
  37. }
  38. } else {
  39. // Error.
  40. // TODO(ossu): What to put here?
  41. RTC_LOG(LS_WARNING) << "Decode error";
  42. *decoded_length = -1;
  43. last_decoded_packet_infos_.clear();
  44. packet_list->clear();
  45. break;
  46. }
  47. if (*decoded_length > rtc::dchecked_cast<int>(decoded_buffer_length_)) {
  48. // Guard against overflow.
  49. RTC_LOG(LS_WARNING) << "Decoded too much.";
  50. packet_list->clear();
  51. return kDecodedTooMuch;
  52. }
  53. } // End of decode loop.
  54. // If the list is not empty at this point, either a decoding error terminated
  55. // the while-loop, or list must hold exactly one CNG packet.
  56. assert(packet_list->empty() || *decoded_length < 0 ||
  57. (packet_list->size() == 1 && decoder_database_->IsComfortNoise(
  58. packet_list->front().payload_type)));
  59. return 0;
  60. }

image.png

-》

webrtc::OpusFrame::Decode

  1. absl::optional<DecodeResult> Decode(
  2. rtc::ArrayView<int16_t> decoded) const override {
  3. AudioDecoder::SpeechType speech_type = AudioDecoder::kSpeech;
  4. int ret;
  5. if (is_primary_payload_) {
  6. ret = decoder_->Decode(
  7. payload_.data(), payload_.size(), decoder_->SampleRateHz(),
  8. decoded.size() * sizeof(int16_t), decoded.data(), &speech_type);
  9. } else {
  10. ret = decoder_->DecodeRedundant(
  11. payload_.data(), payload_.size(), decoder_->SampleRateHz(),
  12. decoded.size() * sizeof(int16_t), decoded.data(), &speech_type);
  13. }
  14. if (ret < 0)
  15. return absl::nullopt;
  16. return DecodeResult{static_cast<size_t>(ret), speech_type};
  17. }

—》

AudioDecoder::Decode

  1. int AudioDecoder::Decode(const uint8_t* encoded,
  2. size_t encoded_len,
  3. int sample_rate_hz,
  4. size_t max_decoded_bytes,
  5. int16_t* decoded,
  6. SpeechType* speech_type) {
  7. TRACE_EVENT0("webrtc", "AudioDecoder::Decode");
  8. rtc::MsanCheckInitialized(rtc::MakeArrayView(encoded, encoded_len));
  9. int duration = PacketDuration(encoded, encoded_len);
  10. if (duration >= 0 &&
  11. duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
  12. return -1;
  13. }
  14. return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
  15. speech_type);
  16. }

AudioDecoderOpusImpl::DecodeInternal

  1. int AudioDecoderOpusImpl::DecodeInternal(const uint8_t* encoded,
  2. size_t encoded_len,
  3. int sample_rate_hz,
  4. int16_t* decoded,
  5. SpeechType* speech_type) {
  6. RTC_DCHECK_EQ(sample_rate_hz, sample_rate_hz_);
  7. int16_t temp_type = 1; // Default is speech.
  8. int ret =
  9. WebRtcOpus_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type);
  10. if (ret > 0)
  11. ret *= static_cast<int>(channels_); // Return total number of samples.
  12. // temp_type==0,返回 AudioDecoder::SpeechType::kSpeech
  13. *speech_type = ConvertSpeechType(temp_type);
  14. return ret;
  15. }

image.png