音频解码器的收集image.png

音频解码器的创建调用流程

image.png

解码器列表的传递

image.png

音频解码器的创建

image.png

NetEq与Decoder

image.png

创建音频解码器

image.png

代码分析接收音频并解码流程

DecoderDatabase::SetCodecs

设置编解码器
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\modules\audio_coding\neteq\decoder_database.cc

  1. std::vector<int> DecoderDatabase::SetCodecs(
  2. const std::map<int, SdpAudioFormat>& codecs) {
  3. // First collect all payload types that we'll remove or reassign, then remove
  4. // them from the database.
  5. std::vector<int> changed_payload_types;
  6. // 第一次decoders_是没有值的,不进入该循环
  7. for (const std::pair<uint8_t, const DecoderInfo&> kv : decoders_) {
  8. auto i = codecs.find(kv.first);
  9. if (i == codecs.end() || i->second != kv.second.GetFormat()) {
  10. changed_payload_types.push_back(kv.first);
  11. }
  12. }
  13. for (int pl_type : changed_payload_types) {
  14. Remove(pl_type);
  15. }
  16. // Enter the new and changed payload type mappings into the database.
  17. for (const auto& kv : codecs) {
  18. const int& rtp_payload_type = kv.first;
  19. const SdpAudioFormat& audio_format = kv.second;
  20. RTC_DCHECK_GE(rtp_payload_type, 0);
  21. RTC_DCHECK_LE(rtp_payload_type, 0x7f);
  22. if (decoders_.count(rtp_payload_type) == 0) {
  23. decoders_.insert(std::make_pair(
  24. rtp_payload_type,
  25. DecoderInfo(audio_format, codec_pair_id_, decoder_factory_.get())));
  26. } else {
  27. // The mapping for this payload type hasn't changed.
  28. }
  29. }
  30. return changed_payload_types;
  31. }

image.png
image.png
为何我电脑上没有打印这些值,只是显示指针。
image.png

设置好解码器后,就可以接收数据了。

ChannelReceive::OnRtpPacket

h:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\audio\channel_receive.cc
每次webrtc接收到数据,都会调用这个函数。

  1. // May be called on either worker thread or network thread.
  2. void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) {
  3. int64_t now_ms = rtc::TimeMillis();
  4. {
  5. MutexLock lock(&sync_info_lock_);
  6. last_received_rtp_timestamp_ = packet.Timestamp();
  7. last_received_rtp_system_time_ms_ = now_ms;
  8. }
  9. // Store playout timestamp for the received RTP packet
  10. UpdatePlayoutTimestamp(false, now_ms);
  11. const auto& it = payload_type_frequencies_.find(packet.PayloadType());
  12. if (it == payload_type_frequencies_.end())
  13. return;
  14. // TODO(nisse): Set payload_type_frequency earlier, when packet is parsed.
  15. RtpPacketReceived packet_copy(packet);
  16. packet_copy.set_payload_type_frequency(it->second);
  17. rtp_receive_statistics_->OnRtpPacket(packet_copy);
  18. RTPHeader header;
  19. packet_copy.GetHeader(&header);
  20. // Interpolates absolute capture timestamp RTP header extension.
  21. header.extension.absolute_capture_time =
  22. absolute_capture_time_receiver_.OnReceivePacket(
  23. AbsoluteCaptureTimeReceiver::GetSource(header.ssrc,
  24. header.arrOfCSRCs),
  25. header.timestamp,
  26. rtc::saturated_cast<uint32_t>(packet_copy.payload_type_frequency()),
  27. header.extension.absolute_capture_time);
  28. ReceivePacket(packet_copy.data(), packet_copy.size(), header);
  29. }

image.png
—》

ChannelReceive::ReceivePacket

  1. void ChannelReceive::ReceivePacket(const uint8_t* packet,
  2. size_t packet_length,
  3. const RTPHeader& header) {
  4. const uint8_t* payload = packet + header.headerLength;
  5. assert(packet_length >= header.headerLength);
  6. size_t payload_length = packet_length - header.headerLength;
  7. size_t payload_data_length = payload_length - header.paddingLength;
  8. // E2EE Custom Audio Frame Decryption (This is optional).
  9. // Keep this buffer around for the lifetime of the OnReceivedPayloadData call.
  10. rtc::Buffer decrypted_audio_payload;
  11. if (frame_decryptor_ != nullptr) { // 如果frame_decryptor_为nullptr则表示该音频包没有加密
  12. const size_t max_plaintext_size = frame_decryptor_->GetMaxPlaintextByteSize(
  13. cricket::MEDIA_TYPE_AUDIO, payload_length);
  14. decrypted_audio_payload.SetSize(max_plaintext_size);
  15. const std::vector<uint32_t> csrcs(header.arrOfCSRCs,
  16. header.arrOfCSRCs + header.numCSRCs);
  17. const FrameDecryptorInterface::Result decrypt_result =
  18. frame_decryptor_->Decrypt(
  19. cricket::MEDIA_TYPE_AUDIO, csrcs,
  20. /*additional_data=*/nullptr,
  21. rtc::ArrayView<const uint8_t>(payload, payload_data_length),
  22. decrypted_audio_payload);
  23. if (decrypt_result.IsOk()) {
  24. decrypted_audio_payload.SetSize(decrypt_result.bytes_written);
  25. } else {
  26. // Interpret failures as a silent frame.
  27. decrypted_audio_payload.SetSize(0);
  28. }
  29. payload = decrypted_audio_payload.data();
  30. payload_data_length = decrypted_audio_payload.size();
  31. } else if (crypto_options_.sframe.require_frame_encryption) {
  32. RTC_DLOG(LS_ERROR)
  33. << "FrameDecryptor required but not set, dropping packet";
  34. payload_data_length = 0;
  35. }
  36. rtc::ArrayView<const uint8_t> payload_data(payload, payload_data_length);
  37. if (frame_transformer_delegate_) {
  38. // Asynchronously transform the received payload. After the payload is
  39. // transformed, the delegate will call OnReceivedPayloadData to handle it.
  40. frame_transformer_delegate_->Transform(payload_data, header, remote_ssrc_);
  41. } else {
  42. OnReceivedPayloadData(payload_data, header);
  43. }
  44. }

—》

ChannelReceive::OnReceivedPayloadData

  1. void ChannelReceive::OnReceivedPayloadData(
  2. rtc::ArrayView<const uint8_t> payload,
  3. const RTPHeader& rtpHeader) {
  4. if (!Playing()) {
  5. // Avoid inserting into NetEQ when we are not playing. Count the
  6. // packet as discarded.
  7. // If we have a source_tracker_, tell it that the frame has been
  8. // "delivered". Normally, this happens in AudioReceiveStream when audio
  9. // frames are pulled out, but when playout is muted, nothing is pulling
  10. // frames. The downside of this approach is that frames delivered this way
  11. // won't be delayed for playout, and therefore will be unsynchronized with
  12. // (a) audio delay when playing and (b) any audio/video synchronization. But
  13. // the alternative is that muting playout also stops the SourceTracker from
  14. // updating RtpSource information.
  15. if (source_tracker_) {
  16. RtpPacketInfos::vector_type packet_vector = {
  17. RtpPacketInfo(rtpHeader, clock_->TimeInMilliseconds())};
  18. source_tracker_->OnFrameDelivered(RtpPacketInfos(packet_vector));
  19. }
  20. return;
  21. }
  22. // Push the incoming payload (parsed and ready for decoding) into the ACM
  23. // acm2::AcmReceiver是持有neteq的。
  24. if (acm_receiver_.InsertPacket(rtpHeader, payload) != 0) {
  25. RTC_DLOG(LS_ERROR) << "ChannelReceive::OnReceivedPayloadData() unable to "
  26. "push data to the ACM";
  27. return;
  28. }
  29. int64_t round_trip_time = 0;
  30. rtp_rtcp_->RTT(remote_ssrc_, &round_trip_time, NULL, NULL, NULL);
  31. std::vector<uint16_t> nack_list = acm_receiver_.GetNackList(round_trip_time);
  32. if (!nack_list.empty()) {
  33. // Can't use nack_list.data() since it's not supported by all
  34. // compilers.
  35. ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
  36. }
  37. }

image.png
—》

AcmReceiver::InsertPacket

  1. int AcmReceiver::InsertPacket(const RTPHeader& rtp_header,
  2. rtc::ArrayView<const uint8_t> incoming_payload) {
  3. if (incoming_payload.empty()) {
  4. neteq_->InsertEmptyPacket(rtp_header);
  5. return 0;
  6. }
  7. int payload_type = rtp_header.payloadType;
  8. auto format = neteq_->GetDecoderFormat(payload_type);
  9. if (format && absl::EqualsIgnoreCase(format->sdp_format.name, "red")) {
  10. // This is a RED packet. Get the format of the audio codec.
  11. payload_type = incoming_payload[0] & 0x7f;
  12. format = neteq_->GetDecoderFormat(payload_type);
  13. }
  14. if (!format) {
  15. RTC_LOG_F(LS_ERROR) << "Payload-type " << payload_type
  16. << " is not registered.";
  17. return -1;
  18. }
  19. {
  20. MutexLock lock(&mutex_);
  21. if (absl::EqualsIgnoreCase(format->sdp_format.name, "cn")) {
  22. if (last_decoder_ && last_decoder_->num_channels > 1) {
  23. // This is a CNG and the audio codec is not mono, so skip pushing in
  24. // packets into NetEq.
  25. return 0;
  26. }
  27. } else {
  28. //会经常更新
  29. last_decoder_ = DecoderInfo{/*payload_type=*/payload_type,
  30. /*sample_rate_hz=*/format->sample_rate_hz,
  31. /*num_channels=*/format->num_channels,
  32. /*sdp_format=*/std::move(format->sdp_format)};
  33. }
  34. } // |mutex_| is released.
  35. if (neteq_->InsertPacket(rtp_header, incoming_payload) < 0) {
  36. RTC_LOG(LERROR) << "AcmReceiver::InsertPacket "
  37. << static_cast<int>(rtp_header.payloadType)
  38. << " Failed to insert packet";
  39. return -1;
  40. }
  41. return 0;
  42. }

—》 neteq_->GetDecoderFormat(payload_type);

NetEqImpl::GetDecoderFormat

获取解码器的格式信息。
先获取DecoderDatabase::DecoderInfo,然后根据该信息获取解码器。

  1. absl::optional<NetEq::DecoderFormat> NetEqImpl::GetDecoderFormat(
  2. int payload_type) const {
  3. MutexLock lock(&mutex_);
  4. const DecoderDatabase::DecoderInfo* const di =
  5. decoder_database_->GetDecoderInfo(payload_type);
  6. if (di) {
  7. const AudioDecoder* const decoder = di->GetDecoder();
  8. // TODO(kwiberg): Why the special case for RED?
  9. return DecoderFormat{
  10. /*sample_rate_hz=*/di->IsRed() ? 8000 : di->SampleRateHz(),
  11. /*num_channels=*/
  12. decoder ? rtc::dchecked_cast<int>(decoder->Channels()) : 1,
  13. /*sdp_format=*/di->GetFormat()};
  14. } else {
  15. // Payload type not registered.
  16. return absl::nullopt;
  17. }
  18. }

—》

DecoderDatabase::DecoderInfo::GetDecoder

这里会判断是否已经创建解码器,如果没有则会创建。

  1. AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
  2. if (subtype_ != Subtype::kNormal) {
  3. // These are handled internally, so they have no AudioDecoder objects.
  4. return nullptr;
  5. }
  6. if (!decoder_) {
  7. // TODO(ossu): Keep a check here for now, since a number of tests create
  8. // DecoderInfos without factories.
  9. RTC_DCHECK(factory_);
  10. decoder_ = factory_->MakeAudioDecoder(audio_format_, codec_pair_id_);
  11. }
  12. RTC_DCHECK(decoder_) << "Failed to create: " << rtc::ToString(audio_format_);
  13. return decoder_.get();
  14. }

image.png

—》

NetEqImpl::InsertPacket

  1. int NetEqImpl::InsertPacket(const RTPHeader& rtp_header,
  2. rtc::ArrayView<const uint8_t> payload) {
  3. rtc::MsanCheckInitialized(payload);
  4. TRACE_EVENT0("webrtc", "NetEqImpl::InsertPacket");
  5. MutexLock lock(&mutex_);
  6. if (InsertPacketInternal(rtp_header, payload) != 0) {
  7. return kFail;
  8. }
  9. return kOK;
  10. }

—》

NetEqImpl::InsertPacketInternal

  1. int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header,
  2. rtc::ArrayView<const uint8_t> payload) {
  3. if (payload.empty()) {
  4. RTC_LOG_F(LS_ERROR) << "payload is empty";
  5. return kInvalidPointer;
  6. }
  7. int64_t receive_time_ms = clock_->TimeInMilliseconds();
  8. stats_->ReceivedPacket();
  9. PacketList packet_list;
  10. // Insert packet in a packet list.
  11. packet_list.push_back([&rtp_header, &payload, &receive_time_ms] {
  12. // Convert to Packet.
  13. Packet packet;
  14. packet.payload_type = rtp_header.payloadType;
  15. packet.sequence_number = rtp_header.sequenceNumber;
  16. packet.timestamp = rtp_header.timestamp;
  17. packet.payload.SetData(payload.data(), payload.size());
  18. packet.packet_info = RtpPacketInfo(rtp_header, receive_time_ms);
  19. // Waiting time will be set upon inserting the packet in the buffer.
  20. RTC_DCHECK(!packet.waiting_time);
  21. return packet;
  22. }());
  23. ******
  24. }

这里主要是向packet_list插入一个任务,然后会从该链表读取任务取执行。