日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網(wǎng)站首頁 編程語言 正文

webrtc 測試video_loopback

作者:newrtc 更新時間: 2023-10-15 編程語言
  • webrtc版本5841-m110
    時間又過去了一年,再分析一下底層有什么改進,依然從video_loopback開始。
    我想先不去看信令及協(xié)商的過程,只看媒體層有什么變化。所以從這個demo開始

video_loopback

項目路徑 src/video/video_loopback
在video_loopback_main.cc 中就一個函數(shù)main,進入webrtc::RunLoopbackTest

video_loopback_lib

在這里插入圖片描述
這個文件里面主要是測試功能的一些配置,列出我測試修改的幾個

//修改編碼用h264
// Flags common with screenshare loopback, with equal default values.
ABSL_FLAG(std::string, codec, "H264" /*"VP8"*/, "Video codec to use.");
//修改起音頻測試
ABSL_FLAG(bool, audio, true, "Add audio stream");
//修改啟用真實音頻采集
ABSL_FLAG(bool,
          use_real_adm,
          true,/* false,*/
          "Use real ADM instead of fake (no effect if audio is false)");

通過修改參數(shù)配置 我們可以跟蹤調試,接下來跟蹤webrtc::test::RunTest(webrtc::Loopback);

  • Loopback() 這個函數(shù)就是初始化參數(shù),我們簡單看一下初始化的值是不是我們想要的,
  • 進入 fixture->RunWithRenderers(params);

video_quality_test

主要的流程在video_quality_test.cc 里面
跟蹤試試,運行就崩潰,和之前版本一樣的問題,解決方法參考之前的文章

https://newrtc.blog.csdn.net/article/details/118379956

在這里插入圖片描述
運行起來了,不過沒有聲音,哪里出了問題么,這demo越來越不負責了。我們先找找音頻的問題再分析代碼。

代碼在video_quality_tesy.cc
先解決沒有聲音的問題,查看代碼是使用了新的音頻采集模塊,不知道為什么沒有聲音,等有時間先去看看為什么要替換原來的coreaudio,莫非真的要刷kpi么。
上代碼

rtc::scoped_refptr<AudioDeviceModule> VideoQualityTest::CreateAudioDevice() {
//增加這句,初始化的是原來的coreaudio采集方式
  return AudioDeviceModule::Create(AudioDeviceModule::kPlatformDefaultAudio,
                                   task_queue_factory_.get());
//這是新版的測試代碼,大概跟蹤了一下                                   
#ifdef WEBRTC_WIN
  RTC_LOG(LS_INFO) << "Using latest version of ADM on Windows";
  // We must initialize the COM library on a thread before we calling any of
  // the library functions. All COM functions in the ADM will return
  // CO_E_NOTINITIALIZED otherwise. The legacy ADM for Windows used internal
  // COM initialization but the new ADM requires COM to be initialized
  // externally.
  com_initializer_ =
      std::make_unique<ScopedCOMInitializer>(ScopedCOMInitializer::kMTA);
  RTC_CHECK(com_initializer_->Succeeded());
  RTC_CHECK(webrtc_win::core_audio_utility::IsSupported());
  RTC_CHECK(webrtc_win::core_audio_utility::IsMMCSSSupported());
  return CreateWindowsCoreAudioAudioDeviceModule(task_queue_factory_.get());
#else
//這是原來的方式,可以正常使用
  // Use legacy factory method on all platforms except Windows.
  return AudioDeviceModule::Create(AudioDeviceModule::kPlatformDefaultAudio,
                                   task_queue_factory_.get());
#endif
}

到此,demo的音視頻都能夠測試通過了,接下來開始代碼流程

初始化過程

我們只看幾個重要的函數(shù)

void VideoQualityTest::RunWithRenderers(const Params& params) {
   //發(fā)送和接收的transport,繼承自Transport,實現(xiàn)SendRtp,SendRtcp接口
  std::unique_ptr<test::LayerFilteringTransport> send_transport;
  std::unique_ptr<test::DirectTransport> recv_transport;
  //渲染采集到的數(shù)據(jù)和解碼后的數(shù)據(jù)yuv420p
  std::unique_ptr<test::VideoRenderer> local_preview;
  std::vector<std::unique_ptr<test::VideoRenderer>> loopback_renderers;
  //初始化音頻模塊,這里創(chuàng)建了send call 和recv call兩個call,其實可以創(chuàng)建一個
  InitializeAudioDevice(&send_call_config, &recv_call_config,
                            params_.audio.use_real_adm);
  //創(chuàng)建發(fā)送call 接收call
  CreateCalls(send_call_config, recv_call_config);  
//創(chuàng)建transport
    send_transport = CreateSendTransport();
    recv_transport = CreateReceiveTransport();

    // TODO(ivica): Use two calls to be able to merge with RunWithAnalyzer or at
    // least share as much code as possible. That way this test would also match
    // the full stack tests better.
    //設置transport的receiver,模擬網(wǎng)絡接收的rtp,rtcp傳遞給call
    send_transport->SetReceiver(receiver_call_->Receiver());
    recv_transport->SetReceiver(sender_call_->Receiver());    
    //設置視頻相關,設置一些配置。后續(xù)仔細分析
    SetupVideo(send_transport.get(), recv_transport.get());  
    //創(chuàng)建視頻流
    CreateVideoStreams();    
    //創(chuàng)建視頻采集
    CreateCapturers();    
    //將采集關聯(lián)到視頻流
    ConnectVideoSourcesToStreams();       
    //音頻設置及創(chuàng)建音頻流
    SetupAudio(send_transport.get());
    //開始測試   
    Start();
}

重要函數(shù)分析

先看音頻的接收發(fā)送流程吧,視頻的類似
1、音頻設備初始化,在call 創(chuàng)建之前,
調用入口

InitializeAudioDevice(&send_call_config, &recv_call_config,
                           params_.audio.use_real_adm);
void VideoQualityTest::InitializeAudioDevice(Call::Config* send_call_config,
                                             Call::Config* recv_call_config,
                                             bool use_real_adm) {
  rtc::scoped_refptr<AudioDeviceModule> audio_device;
  if (use_real_adm) {
    // Run test with real ADM (using default audio devices) if user has
    // explicitly set the --audio and --use_real_adm command-line flags.
    //我們測試參數(shù)設置用實際的音頻設備,在此初始化
    audio_device = CreateAudioDevice();
  } else {
    // By default, create a test ADM which fakes audio.
    audio_device = TestAudioDeviceModule::Create(
        task_queue_factory_.get(),
        TestAudioDeviceModule::CreatePulsedNoiseCapturer(32000, 48000),
        TestAudioDeviceModule::CreateDiscardRenderer(48000), 1.f);
  }
  RTC_CHECK(audio_device);

  AudioState::Config audio_state_config;
  audio_state_config.audio_mixer = AudioMixerImpl::Create();
  audio_state_config.audio_processing = AudioProcessingBuilder().Create();
  audio_state_config.audio_device_module = audio_device;
  //把device設置為創(chuàng)建call的參數(shù),多個call可以共用一個device
  send_call_config->audio_state = AudioState::Create(audio_state_config);
  recv_call_config->audio_state = AudioState::Create(audio_state_config);
  if (use_real_adm) {
    // The real ADM requires extra initialization: setting default devices,
    // setting up number of channels etc. Helper class also calls
    // AudioDeviceModule::Init().
    //這里面是初始化設置,選取音頻采集,播放設備
    webrtc::adm_helpers::Init(audio_device.get());
  } else {
    audio_device->Init();
  }
  // Always initialize the ADM before injecting a valid audio transport.
  RTC_CHECK(audio_device->RegisterAudioCallback(
                send_call_config->audio_state->audio_transport()) == 0);
}

在CreateAudioDevice()中,調用AudioDeviceModule創(chuàng)建device

rtc::scoped_refptr<AudioDeviceModule> VideoQualityTest::CreateAudioDevice() {
  return AudioDeviceModule::Create(AudioDeviceModule::kPlatformDefaultAudio,
                                   task_queue_factory_.get());
 }

調用webrtc::adm_helpers::Init(audio_device.get()); 設置音頻設備

void Init(AudioDeviceModule* adm) {
  RTC_DCHECK(adm);

  RTC_CHECK_EQ(0, adm->Init()) << "Failed to initialize the ADM.";

  // Playout device.
  {
   //設置播放設備ID,adm可以遍歷有哪些設備的
    if (adm->SetPlayoutDevice(AUDIO_DEVICE_ID) != 0) {
      RTC_LOG(LS_ERROR) << "Unable to set playout device.";
      return;
    }
    //初始化音頻播放設備
    if (adm->InitSpeaker() != 0) {
      RTC_LOG(LS_ERROR) << "Unable to access speaker.";
    }

    // Set number of channels
    bool available = false;
    //雙聲道支持
    if (adm->StereoPlayoutIsAvailable(&available) != 0) {
      RTC_LOG(LS_ERROR) << "Failed to query stereo playout.";
    }
    if (adm->SetStereoPlayout(available) != 0) {
      RTC_LOG(LS_ERROR) << "Failed to set stereo playout mode.";
    }
  }

  // Recording device.
  {
  //設置麥克風id,同樣adm可以設置ID
    if (adm->SetRecordingDevice(AUDIO_DEVICE_ID) != 0) {
      RTC_LOG(LS_ERROR) << "Unable to set recording device.";
      return;
    }
    //初始化
    if (adm->InitMicrophone() != 0) {
      RTC_LOG(LS_ERROR) << "Unable to access microphone.";
    }

    // Set number of channels
    bool available = false;
    if (adm->StereoRecordingIsAvailable(&available) != 0) {
      RTC_LOG(LS_ERROR) << "Failed to query stereo recording.";
    }
    if (adm->SetStereoRecording(available) != 0) {
      RTC_LOG(LS_ERROR) << "Failed to set stereo recording mode.";
    }
  }

2、創(chuàng)建call
CreateCalls

void CallTest::CreateSenderCall(const Call::Config& config) {
  auto sender_config = config;
  sender_config.task_queue_factory = task_queue_factory_.get();
  sender_config.network_state_predictor_factory =
      network_state_predictor_factory_.get();
  sender_config.network_controller_factory = network_controller_factory_.get();
  sender_config.trials = &field_trials_;
  sender_call_.reset(Call::Create(sender_config));
}

void CallTest::CreateReceiverCall(const Call::Config& config) {
  auto receiver_config = config;
  receiver_config.task_queue_factory = task_queue_factory_.get();
  receiver_config.trials = &field_trials_;
  receiver_call_.reset(Call::Create(receiver_config));
}

3、音頻編碼器設置

void VideoQualityTest::SetupAudio(Transport* transport) {
  AudioSendStream::Config audio_send_config(transport);
  audio_send_config.rtp.ssrc = kAudioSendSsrc;

  // Add extension to enable audio send side BWE, and allow audio bit rate
  // adaptation.
  audio_send_config.rtp.extensions.clear();
  //采用opus48k 雙聲道
  audio_send_config.send_codec_spec = AudioSendStream::Config::SendCodecSpec(
      kAudioSendPayloadType,
      {"OPUS",
       48000,
       2,
       {{"usedtx", (params_.audio.dtx ? "1" : "0")}, {"stereo", "1"}}});

  if (params_.call.send_side_bwe) {
    audio_send_config.rtp.extensions.push_back(
        webrtc::RtpExtension(webrtc::RtpExtension::kTransportSequenceNumberUri,
                             kTransportSequenceNumberExtensionId));
    audio_send_config.min_bitrate_bps = kOpusMinBitrateBps;
    audio_send_config.max_bitrate_bps = kOpusBitrateFbBps;
    audio_send_config.send_codec_spec->transport_cc_enabled = true;
    // Only allow ANA when send-side BWE is enabled.
    audio_send_config.audio_network_adaptor_config = params_.audio.ana_config;
  }
  audio_send_config.encoder_factory = audio_encoder_factory_;
  SetAudioConfig(audio_send_config);

  std::string sync_group;
  if (params_.video[0].enabled && params_.audio.sync_video)
    sync_group = kSyncGroup;

  CreateMatchingAudioConfigs(transport, sync_group);
  CreateAudioStreams();
}

4 創(chuàng)建音頻stream

void CallTest::CreateAudioStreams() {
  RTC_DCHECK(audio_send_stream_ == nullptr);
  RTC_DCHECK(audio_receive_streams_.empty());
  //通過call創(chuàng)建音頻發(fā)送stream
  audio_send_stream_ = sender_call_->CreateAudioSendStream(audio_send_config_);
  for (size_t i = 0; i < audio_receive_configs_.size(); ++i) {
    audio_receive_streams_.push_back(
        //通過call創(chuàng)建音頻接收stream
        receiver_call_->CreateAudioReceiveStream(audio_receive_configs_[i]));
  }
}

5 start音視頻

void CallTest::Start() {
  StartVideoStreams();
  if (audio_send_stream_) {
   //開始音頻發(fā)送
    audio_send_stream_->Start();
  }
  for (AudioReceiveStreamInterface* audio_recv_stream : audio_receive_streams_)
  //開始音頻接收
    audio_recv_stream->Start();
}

原文鏈接:https://newrtc.blog.csdn.net/article/details/130601730

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新