编解码器类关系图

image.png
Add10MsData 用于向编码器输入数据
PlayoutData10Ms 用于从解码器获取数据
IncomingPacket用于从网络获取音频包,数据是没有rtp头的

创建音频编码器的步骤

image.png

创建音频编码器的函数调用过程

image.png
右边的第一步走完后,才会执行第二步。
最后调用SetEncoder将构造好的AudioEncoderOpusImpl赋值给创建好的AudioCodingModuleImpl。

音频编码器的选择

image.png

代码分析

ChannelSend::ChannelSend

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\audio\channel_send.cc

  1. ChannelSend::ChannelSend(
  2. Clock* clock,
  3. TaskQueueFactory* task_queue_factory,
  4. ProcessThread* module_process_thread,
  5. Transport* rtp_transport,
  6. RtcpRttStats* rtcp_rtt_stats,
  7. RtcEventLog* rtc_event_log,
  8. FrameEncryptorInterface* frame_encryptor,
  9. const webrtc::CryptoOptions& crypto_options,
  10. bool extmap_allow_mixed,
  11. int rtcp_report_interval_ms,
  12. uint32_t ssrc,
  13. rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
  14. TransportFeedbackObserver* feedback_observer)
  15. : event_log_(rtc_event_log),
  16. _timeStamp(0), // This is just an offset, RTP module will add it's own
  17. // random offset
  18. _moduleProcessThreadPtr(module_process_thread),
  19. input_mute_(false),
  20. previous_frame_muted_(false),
  21. _includeAudioLevelIndication(false),
  22. rtcp_observer_(new VoERtcpObserver(this)),
  23. feedback_observer_(feedback_observer),
  24. rtp_packet_pacer_proxy_(new RtpPacketSenderProxy()),
  25. retransmission_rate_limiter_(
  26. new RateLimiter(clock, kMaxRetransmissionWindowMs)),
  27. frame_encryptor_(frame_encryptor),
  28. crypto_options_(crypto_options),
  29. encoder_queue_(task_queue_factory->CreateTaskQueue(
  30. "AudioEncoder",
  31. TaskQueueFactory::Priority::NORMAL)),
  32. fixing_timestamp_stall_(
  33. !field_trial::IsDisabled("WebRTC-Audio-FixTimestampStall")) {
  34. RTC_DCHECK(module_process_thread);
  35. module_process_thread_checker_.Detach();
  36. // 创建音频编码器
  37. audio_coding_.reset(AudioCodingModule::Create(AudioCodingModule::Config()));
  38. RtpRtcpInterface::Configuration configuration;
  39. configuration.bandwidth_callback = rtcp_observer_.get();
  40. configuration.transport_feedback_callback = feedback_observer_;
  41. configuration.clock = (clock ? clock : Clock::GetRealTimeClock());
  42. configuration.audio = true;
  43. configuration.outgoing_transport = rtp_transport;
  44. configuration.paced_sender = rtp_packet_pacer_proxy_.get();
  45. configuration.event_log = event_log_;
  46. configuration.rtt_stats = rtcp_rtt_stats;
  47. configuration.retransmission_rate_limiter =
  48. retransmission_rate_limiter_.get();
  49. configuration.extmap_allow_mixed = extmap_allow_mixed;
  50. configuration.rtcp_report_interval_ms = rtcp_report_interval_ms;
  51. configuration.local_media_ssrc = ssrc;
  52. // 创建ModuleRtpRtcpImpl2
  53. rtp_rtcp_ = ModuleRtpRtcpImpl2::Create(configuration);
  54. rtp_rtcp_->SetSendingMediaStatus(false);
  55. rtp_sender_audio_ = std::make_unique<RTPSenderAudio>(configuration.clock,
  56. rtp_rtcp_->RtpSender());
  57. _moduleProcessThreadPtr->RegisterModule(rtp_rtcp_.get(), RTC_FROM_HERE);
  58. // Ensure that RTCP is enabled by default for the created channel.
  59. rtp_rtcp_->SetRTCPStatus(RtcpMode::kCompound);
  60. int error = audio_coding_->RegisterTransportCallback(this);
  61. RTC_DCHECK_EQ(0, error);
  62. if (frame_transformer)
  63. InitFrameTransformerDelegate(std::move(frame_transformer));
  64. }

WebRtcVoiceMediaChannel::SetSendCodecs

  1. // Utility function called from SetSendParameters() to extract current send
  2. // codec settings from the given list of codecs (originally from SDP). Both send
  3. // and receive streams may be reconfigured based on the new settings.
  4. bool WebRtcVoiceMediaChannel::SetSendCodecs(
  5. const std::vector<AudioCodec>& codecs) {
  6. RTC_DCHECK_RUN_ON(worker_thread_);
  7. dtmf_payload_type_ = absl::nullopt;
  8. dtmf_payload_freq_ = -1;
  9. // Validate supplied codecs list.
  10. for (const AudioCodec& codec : codecs) {
  11. // TODO(solenberg): Validate more aspects of input - that payload types
  12. // don't overlap, remove redundant/unsupported codecs etc -
  13. // the same way it is done for RtpHeaderExtensions.
  14. if (codec.id < kMinPayloadType || codec.id > kMaxPayloadType) {
  15. RTC_LOG(LS_WARNING) << "Codec payload type out of range: "
  16. << ToString(codec);
  17. return false;
  18. }
  19. }
  20. // Find PT of telephone-event codec with lowest clockrate, as a fallback, in
  21. // case we don't have a DTMF codec with a rate matching the send codec's, or
  22. // if this function returns early.
  23. std::vector<AudioCodec> dtmf_codecs;
  24. for (const AudioCodec& codec : codecs) {
  25. if (IsCodec(codec, kDtmfCodecName)) {
  26. dtmf_codecs.push_back(codec);
  27. if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) {
  28. dtmf_payload_type_ = codec.id;
  29. dtmf_payload_freq_ = codec.clockrate;
  30. }
  31. }
  32. }
  33. // Scan through the list to figure out the codec to use for sending.
  34. absl::optional<webrtc::AudioSendStream::Config::SendCodecSpec>
  35. send_codec_spec;
  36. webrtc::BitrateConstraints bitrate_config;
  37. absl::optional<webrtc::AudioCodecInfo> voice_codec_info;
  38. size_t send_codec_position = 0;
  39. for (const AudioCodec& voice_codec : codecs) {
  40. if (!(IsCodec(voice_codec, kCnCodecName) ||
  41. IsCodec(voice_codec, kDtmfCodecName) ||
  42. IsCodec(voice_codec, kRedCodecName))) {
  43. webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
  44. voice_codec.channels, voice_codec.params);
  45. voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
  46. if (!voice_codec_info) {
  47. RTC_LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
  48. continue;
  49. }
  50. send_codec_spec = webrtc::AudioSendStream::Config::SendCodecSpec(
  51. voice_codec.id, format);
  52. if (voice_codec.bitrate > 0) {
  53. send_codec_spec->target_bitrate_bps = voice_codec.bitrate;
  54. }
  55. send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
  56. send_codec_spec->nack_enabled = HasNack(voice_codec);
  57. bitrate_config = GetBitrateConfigForCodec(voice_codec);
  58. break;
  59. }
  60. send_codec_position++;
  61. }
  62. if (!send_codec_spec) {
  63. return false;
  64. }
  65. RTC_DCHECK(voice_codec_info);
  66. if (voice_codec_info->allow_comfort_noise) {
  67. // Loop through the codecs list again to find the CN codec.
  68. // TODO(solenberg): Break out into a separate function?
  69. for (const AudioCodec& cn_codec : codecs) {
  70. if (IsCodec(cn_codec, kCnCodecName) &&
  71. cn_codec.clockrate == send_codec_spec->format.clockrate_hz &&
  72. cn_codec.channels == voice_codec_info->num_channels) {
  73. if (cn_codec.channels != 1) {
  74. RTC_LOG(LS_WARNING)
  75. << "CN #channels " << cn_codec.channels << " not supported.";
  76. } else if (cn_codec.clockrate != 8000 && cn_codec.clockrate != 16000 &&
  77. cn_codec.clockrate != 32000) {
  78. RTC_LOG(LS_WARNING)
  79. << "CN frequency " << cn_codec.clockrate << " not supported.";
  80. } else {
  81. send_codec_spec->cng_payload_type = cn_codec.id;
  82. }
  83. break;
  84. }
  85. }
  86. // Find the telephone-event PT exactly matching the preferred send codec.
  87. for (const AudioCodec& dtmf_codec : dtmf_codecs) {
  88. if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
  89. dtmf_payload_type_ = dtmf_codec.id;
  90. dtmf_payload_freq_ = dtmf_codec.clockrate;
  91. break;
  92. }
  93. }
  94. }
  95. if (audio_red_for_opus_trial_enabled_) {
  96. // Loop through the codecs to find the RED codec that matches opus
  97. // with respect to clockrate and number of channels.
  98. size_t red_codec_position = 0;
  99. for (const AudioCodec& red_codec : codecs) {
  100. if (red_codec_position < send_codec_position &&
  101. IsCodec(red_codec, kRedCodecName) &&
  102. red_codec.clockrate == send_codec_spec->format.clockrate_hz &&
  103. red_codec.channels == send_codec_spec->format.num_channels) {
  104. send_codec_spec->red_payload_type = red_codec.id;
  105. break;
  106. }
  107. red_codec_position++;
  108. }
  109. }
  110. if (send_codec_spec_ != send_codec_spec) {
  111. send_codec_spec_ = std::move(send_codec_spec);
  112. // Apply new settings to all streams.
  113. for (const auto& kv : send_streams_) {
  114. kv.second->SetSendCodecSpec(*send_codec_spec_);
  115. }
  116. } else {
  117. // If the codec isn't changing, set the start bitrate to -1 which means
  118. // "unchanged" so that BWE isn't affected.
  119. bitrate_config.start_bitrate_bps = -1;
  120. }
  121. call_->GetTransportControllerSend()->SetSdpBitrateParameters(bitrate_config);
  122. // Check if the transport cc feedback or NACK status has changed on the
  123. // preferred send codec, and in that case reconfigure all receive streams.
  124. if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
  125. recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
  126. RTC_LOG(LS_INFO) << "Recreate all the receive streams because the send "
  127. "codec has changed.";
  128. recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
  129. recv_nack_enabled_ = send_codec_spec_->nack_enabled;
  130. for (auto& kv : recv_streams_) {
  131. kv.second->SetUseTransportCcAndRecreateStream(recv_transport_cc_enabled_,
  132. recv_nack_enabled_);
  133. }
  134. }
  135. send_codecs_ = codecs;
  136. return true;
  137. }

image.png

总结

image.png