ADM与播放声音

image.png

播放声音的流程

image.png

重要流程

image.png

源码分析-音频播放流程

在h:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\media\engine\webrtc_voice_engine.cc
WebRtcVoiceMediaChannel::AddRecvStream 打断点调试

WebRtcVoiceMediaChannel::AddRecvStream

  1. bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
  2. TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddRecvStream");
  3. RTC_DCHECK_RUN_ON(worker_thread_);
  4. ***
  5. // Create a new channel for receiving audio data.
  6. // 创建一个新的通道去接收音频数据
  7. // 键值<ssrc, WebRtcAudioReceiveStream>
  8. recv_streams_.insert(std::make_pair(
  9. ssrc, new WebRtcAudioReceiveStream(
  10. ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
  11. recv_nack_enabled_, sp.stream_ids(), recv_rtp_extensions_,
  12. call_, this, engine()->decoder_factory_, decoder_map_,
  13. codec_pair_id_, engine()->audio_jitter_buffer_max_packets_,
  14. engine()->audio_jitter_buffer_fast_accelerate_,
  15. engine()->audio_jitter_buffer_min_delay_ms_,
  16. engine()->audio_jitter_buffer_enable_rtx_handling_,
  17. unsignaled_frame_decryptor_, crypto_options_, nullptr)));
  18. recv_streams_[ssrc]->SetPlayout(playout_);
  19. return true;
  20. }

调用堆栈

image.png

recvstreams[ssrc]->SetPlayout(playout_);

SetPlayout(bool playout)

  1. void SetPlayout(bool playout) {
  2. RTC_DCHECK_RUN_ON(&worker_thread_checker_);
  3. RTC_DCHECK(stream_);
  4. if (playout) {
  5. stream_->Start();
  6. } else {
  7. stream_->Stop();
  8. }
  9. }

stream->Start();
stream
->Stop();

AudioReceiveStream::Start

  1. void AudioReceiveStream::Start() {
  2. RTC_DCHECK_RUN_ON(&worker_thread_checker_);
  3. if (playing_) {
  4. return;
  5. }
  6. channel_receive_->StartPlayout();
  7. playing_ = true;
  8. audio_state()->AddReceivingStream(this);
  9. }
  10. void AudioReceiveStream::Stop() {
  11. RTC_DCHECK_RUN_ON(&worker_thread_checker_);
  12. if (!playing_) {
  13. return;
  14. }
  15. channel_receive_->StopPlayout();
  16. playing_ = false;
  17. audio_state()->RemoveReceivingStream(this);
  18. }

audio_state()->AddReceivingStream(this);

AudioState::AddReceivingStream

  1. void AudioState::AddReceivingStream(webrtc::AudioReceiveStream* stream) {
  2. RTC_DCHECK(thread_checker_.IsCurrent());
  3. RTC_DCHECK_EQ(0, receiving_streams_.count(stream));
  4. // 首先将该流插入到自己的管理中
  5. receiving_streams_.insert(stream);
  6. // 然后添加到audio_mixer的源中,后面就可以用它来进行混音了
  7. if (!config_.audio_mixer->AddSource(
  8. static_cast<internal::AudioReceiveStream*>(stream))) {
  9. RTC_DLOG(LS_ERROR) << "Failed to add source to mixer.";
  10. }
  11. // Make sure playback is initialized; start playing if enabled.
  12. UpdateNullAudioPollerState();
  13. // 判断是否正在播放,没有则调用adm->InitPlayout
  14. auto* adm = config_.audio_device_module.get();
  15. if (!adm->Playing()) {
  16. if (adm->InitPlayout() == 0) {
  17. if (playout_enabled_) {
  18. adm->StartPlayout();
  19. }
  20. } else {
  21. RTC_DLOG_F(LS_ERROR) << "Failed to initialize playout.";
  22. }
  23. }
  24. }

adm->InitPlayout

AudioDeviceModuleImpl::InitPlayout

  1. int32_t AudioDeviceModuleImpl::InitPlayout() {
  2. RTC_LOG(INFO) << __FUNCTION__;
  3. CHECKinitialized_();
  4. if (PlayoutIsInitialized()) {
  5. return 0;
  6. }
  7. // 又回到 AudioDeviceWindowsCore::InitPlayout
  8. int32_t result = audio_device_->InitPlayout();
  9. RTC_LOG(INFO) << "output: " << result;
  10. RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.InitPlayoutSuccess",
  11. static_cast<int>(result == 0));
  12. return result;
  13. }

image.png