webrtc代码走读一(视频参数配置汇总)

一、视频编码格式初始配置

webrtc\media\engine\internalencoderfactory.cc

1、按照Push顺序,优先选取第一个编解码格式。

2、屏蔽kUlpfecCodecName、kRedCodecName的codec,可以关闭FEC冗余。

3、开启FlexFEC功能。

二、视频分辨率初始配置

webrtc\pc\videocapturertracksource.cc

选取的原则是,在kVideoFormats里面找参数与kDefaultFormat默认值最接近的一组参数,作为本端的编码能力。

三、视频码率默认值

webrtc\media\engine\webrtcvideoengine.cc

EncoderStreamFactory::CreateEncoderStreams

四、默认QP、帧率最大值配置

webrtc\media\engine\webrtcvideoengine.cc

static const int kDefaultQpMax = 56;

const int kDefaultVideoMaxFramerate = 60;

五、使能SRTP

webrtc\src\webrtc\api\peerconnectioninterface.h

disable_encryption = true 取消SRTP

disable_encryption = false 开启SRTP

配置密钥:

bool Conductor::CreatePeerConnection(bool dtls)配置是否生成密钥。

六、生效新的帧率码率流程

在webrtc里面函数实现如下:
->VideoStreamEncoder::EncodeVideoFrame
->VideoSender::AddVideoFrame----在这个函数中读取全局变量encoder_params_,判断是否需要调整视频参数。
->VideoSender::SetEncoderParameters

->VCMGenericEncoder::SetEncoderParameters

->H264EncoderImpl::SetRateAllocation---传递新的帧率码率到编码器。

七、H264打包模式

codec.cc  VideoCodec::SetDefaultParameters

八、冗余模式配置

internalencoderfactory.cc

webrtc冗余打包方式有三种:Red(rfc2198)、Ulpfec(rfc5109)、Flexfec(草案)。其中Red和Ulpfec要成对使用。

九、MTU最大包长 

webrtcvideoengine.cc

kVideoMtu:该值用于配置一个MTU报文的最大包长。

十、BWE降码率最小阀值

webrtcvideoengine.cc

kMinVideoBitrateKbps:BWE检测网络异常,会通过降低码率保证视频流畅性,该值配置降低的最小阀值。

十一、NACK配置

webrtc支持RTPFB和PLI FB两种重传方式。
AssignPayloadTypesAndAddAssociatedRtxCodecs->AddDefaultFeedbackParams里面将两种方式都填写到SDP命令行里面。kRtcpFbParamNack

开启NACK可以使能高亮参数,关闭NACK可以屏蔽高亮参数。

初始化流程:

1、WebRtcVideoSendStream::SetCodec    kNackHistoryMs

2、VideoSendStreamImpl::ConfigureProtection

决定是否创建NACK类

3、ProtectionBitrateCalculator::SetProtectionMethod

4、VCMLossProtectionLogic::SetMethod

十二、协商音视频的PT值

一、视频PT值协商

webrtcvideoengine.cc  static std::vector<VideoCodec> AssignPayloadTypesAndAddAssociatedRtxCodecs

二、音频PT值协商

webrtcvoiceengine.cc   WebRtcVoiceMediaChannel::SetSendCodecs

十三、ICE探测参数配置

  struct RTCConfiguration {
    // This struct is subject to reorganization, both for naming
    // consistency, and to group settings to match where they are used
    // in the implementation. To do that, we need getter and setter
    // methods for all settings which are of interest to applications,
    // Chrome in particular.

    RTCConfiguration() = default;
    explicit RTCConfiguration(RTCConfigurationType type) {
      if (type == RTCConfigurationType::kAggressive) {
        // These parameters are also defined in Java and IOS configurations,
        // so their values may be overwritten by the Java or IOS configuration.
        bundle_policy = kBundlePolicyMaxBundle;
        rtcp_mux_policy = kRtcpMuxPolicyRequire;
        ice_connection_receiving_timeout =
            kAggressiveIceConnectionReceivingTimeout;

        // These parameters are not defined in Java or IOS configuration,
        // so their values will not be overwritten.
        enable_ice_renomination = true;
        redetermine_role_on_ice_restart = false;
      }
    }


    static const int kUndefined = -1;
    // Default maximum number of packets in the audio jitter buffer.
    static const int kAudioJitterBufferMaxPackets = 50;
    // ICE connection receiving timeout for aggressive configuration.
    static const int kAggressiveIceConnectionReceivingTimeout = 1000;


    IceTransportsType type = kRelay;
    BundlePolicy bundle_policy = kBundlePolicyBalanced;
    RtcpMuxPolicy rtcp_mux_policy = kRtcpMuxPolicyRequire;
    std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
    int ice_candidate_pool_size = 0;

    // If set to true, don't gather IPv6 ICE candidates.
    // TODO(deadbeef): Remove this? IPv6 support has long stopped being
    // experimental
    bool disable_ipv6 = false;

    // If set to true, don't gather IPv6 ICE candidates on Wi-Fi.
    // Only intended to be used on specific devices. Certain phones disable IPv6
    // when the screen is turned off and it would be better to just disable the
    // IPv6 ICE candidates on Wi-Fi in those cases.
    bool disable_ipv6_on_wifi = false;

    // By default, the PeerConnection will use a limited number of IPv6 network
    // interfaces, in order to avoid too many ICE candidate pairs being created
    // and delaying ICE completion.
    //
    // Can be set to INT_MAX to effectively disable the limit.
    int max_ipv6_networks = cricket::kDefaultMaxIPv6Networks;

    // If set to true, use RTP data channels instead of SCTP.
    // TODO(deadbeef): Remove this. We no longer commit to supporting RTP data
    // channels, though some applications are still working on moving off of
    // them.
    bool enable_rtp_data_channel = false;

    // Minimum bitrate at which screencast video tracks will be encoded at.
    // This means adding padding bits up to this bitrate, which can help
    // when switching from a static scene to one with motion.
    rtc::Optional<int> screencast_min_bitrate;

    // Use new combined audio/video bandwidth estimation?
    rtc::Optional<bool> combined_audio_video_bwe;

    // Can be used to disable DTLS-SRTP. This should never be done, but can be
    // useful for testing purposes, for example in setting up a loopback call
    // with a single PeerConnection.
    rtc::Optional<bool> enable_dtls_srtp;

    /
    // The below fields are not part of the standard.
    /

    // Can be used to disable TCP candidate generation.
    TcpCandidatePolicy tcp_candidate_policy = kTcpCandidatePolicyEnabled;

    // Can be used to avoid gathering candidates for a "higher cost" network,
    // if a lower cost one exists. For example, if both Wi-Fi and cellular
    // interfaces are available, this could be used to avoid using the cellular
    // interface.
    CandidateNetworkPolicy candidate_network_policy =
        kCandidateNetworkPolicyAll;

    // The maximum number of packets that can be stored in the NetEq audio
    // jitter buffer. Can be reduced to lower tolerated audio latency.
    int audio_jitter_buffer_max_packets = kAudioJitterBufferMaxPackets;

    // Whether to use the NetEq "fast mode" which will accelerate audio quicker
    // if it falls behind.
    bool audio_jitter_buffer_fast_accelerate = false;

    // Timeout in milliseconds before an ICE candidate pair is considered to be
    // "not receiving", after which a lower priority candidate pair may be
    // selected.
    int ice_connection_receiving_timeout = kUndefined;

    // Interval in milliseconds at which an ICE "backup" candidate pair will be
    // pinged. This is a candidate pair which is not actively in use, but may
    // be switched to if the active candidate pair becomes unusable.
    //
    // This is relevant mainly to Wi-Fi/cell handoff; the application may not
    // want this backup cellular candidate pair pinged frequently, since it
    // consumes data/battery.
    int ice_backup_candidate_pair_ping_interval = kUndefined;

    // Can be used to enable continual gathering, which means new candidates
    // will be gathered as network interfaces change. Note that if continual
    // gathering is used, the candidate removal API should also be used, to
    // avoid an ever-growing list of candidates.
    ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE;

    // If set to true, candidate pairs will be pinged in order of most likely
    // to work (which means using a TURN server, generally), rather than in
    // standard priority order.
    bool prioritize_most_likely_ice_candidate_pairs = false;

    struct cricket::MediaConfig media_config;

    // This doesn't currently work. For a while we were working on adding QUIC
    // data channel support to PeerConnection, but decided on a different
    // approach, and that code hasn't been updated for a while.
    bool enable_quic = false;

    // If set to true, only one preferred TURN allocation will be used per
    // network interface. UDP is preferred over TCP and IPv6 over IPv4. This
    // can be used to cut down on the number of candidate pairings.
    bool prune_turn_ports = false;

    // If set to true, this means the ICE transport should presume TURN-to-TURN
    // candidate pairs will succeed, even before a binding response is received.
    // This can be used to optimize the initial connection time, since the DTLS
    // handshake can begin immediately.
    bool presume_writable_when_fully_relayed = false;

    // If true, "renomination" will be added to the ice options in the transport
    // description.
    // See: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00
    bool enable_ice_renomination = false;

    // If true, the ICE role is re-determined when the PeerConnection sets a
    // local transport description that indicates an ICE restart.
    //
    // This is standard RFC5245 ICE behavior, but causes unnecessary role
    // thrashing, so an application may wish to avoid it. This role
    // re-determining was removed in ICEbis (ICE v2).
    bool redetermine_role_on_ice_restart = true;

    // If set, the min interval (max rate) at which we will send ICE checks
    // (STUN pings), in milliseconds.
    rtc::Optional<int> ice_check_min_interval;

    // ICE Periodic Regathering
    // If set, WebRTC will periodically create and propose candidates without
    // starting a new ICE generation. The regathering happens continuously with
    // interval specified in milliseconds by the uniform distribution [a, b].
    rtc::Optional<rtc::IntervalRange> ice_regather_interval_range;

  };

十四、field_trial参数配置

webrtc::field_trial::InitFieldTrialsFromString()

通过config文件配置field_trial示例

int PASCAL wWinMain(HINSTANCE instance,
                    HINSTANCE prev_instance,
                    wchar_t* cmd_line,
                    int cmd_show) {
  rtc::WinsockInitializer winsock_init;
  rtc::Win32SocketServer w32_ss;
  rtc::Win32Thread w32_thread(&w32_ss);
  rtc::ThreadManager::Instance()->SetCurrentThread(&w32_thread);

  WindowsCommandLineArguments win_args;
  int argc = win_args.argc();
  char** argv = win_args.argv();

  absl::ParseCommandLine(argc, argv);

  // InitFieldTrialsFromString stores the char*, so the char array must outlive
  // the application.
  const std::string forced_field_trials =
      absl::GetFlag(FLAGS_force_fieldtrials);
  
  FileLog* _LogStream = new FileLog("");
  rtc::LogMessage::AddLogToStream(_LogStream, rtc::LS_VERBOSE); 
  FILE* file_ = NULL;
  char buffer[1024*4];

  file_ = fopen("config.txt", "rt");
  
  if (file_)
  {
      int filesize = 0, readCnt = 0;
      fseek(file_,0L,SEEK_END);
      filesize = ftell(file_);
      fseek(file_,0L,SEEK_SET);
      readCnt = fread(buffer,filesize,1,file_); 

      if (readCnt)
      {
          webrtc::field_trial::InitFieldTrialsFromString(buffer);
          RTC_LOG(LS_ERROR) << "config InitFieldTrialsFromString " << buffer;
      }
  }
  else
  {
      webrtc::field_trial::InitFieldTrialsFromString(forced_field_trials.c_str());
      RTC_LOG(LS_ERROR) << "defaut InitFieldTrialsFromString " << forced_field_trials.c_str();
  }
  
  // Abort if the user specifies a port that is outside the allowed
  // range [1, 65535].
  if ((absl::GetFlag(FLAGS_port) < 1) || (absl::GetFlag(FLAGS_port) > 65535)) {
    printf("Error: %i is not a valid port.\n", absl::GetFlag(FLAGS_port));
    return -1;
  }

  const std::string server = absl::GetFlag(FLAGS_server);
  const std::string cotrun_server = absl::GetFlag(FLAGS_coturn);
  const std::string cotrun_port = absl::GetFlag(FLAGS_coturnport);
  MainWnd wnd(server.c_str(), absl::GetFlag(FLAGS_port),cotrun_server.c_str(), cotrun_port.c_str(),
              absl::GetFlag(FLAGS_autoconnect), absl::GetFlag(FLAGS_autocall));
  if (!wnd.Create()) {
    RTC_NOTREACHED();
    return -1;
  }

  rtc::InitializeSSL();
  PeerConnectionClient client;
  rtc::scoped_refptr<Conductor> conductor(
      new rtc::RefCountedObject<Conductor>(&client, &wnd));

  // Main loop.
  MSG msg;
  BOOL gm;
  while ((gm = ::GetMessage(&msg, NULL, 0, 0)) != 0 && gm != -1) {
    if (!wnd.PreTranslateMessage(&msg)) {
      ::TranslateMessage(&msg);
      ::DispatchMessage(&msg);
    }
  }

  if (conductor->connection_active() || client.is_connected()) {
    while ((conductor->connection_active() || client.is_connected()) &&
           (gm = ::GetMessage(&msg, NULL, 0, 0)) != 0 && gm != -1) {
      if (!wnd.PreTranslateMessage(&msg)) {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
      }
    }
  }

  rtc::CleanupSSL();
  return 0;
}

抱歉,作为AI语言模型,我无法为您提供视频。但是,我可以提供一些关于WebRTC的信息和代码示例: WebRTC是一种用于实时通信的开放式网络技术,可以在浏览器和移动设备之间实现视频、音频和数据传输。以下是一个基本的WebRTC视频聊天代码示例: HTML代码: ``` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>WebRTC Video Chat</title> </head> <body> <div> <video id="localVideo" autoplay muted></video> <video id="remoteVideo" autoplay></video> </div> <script src="main.js"></script> </body> </html> ``` JavaScript代码: ``` const localVideo = document.getElementById('localVideo'); const remoteVideo = document.getElementById('remoteVideo'); let localStream, remoteStream; // 获取本地视频流 navigator.mediaDevices.getUserMedia({ video: true, audio: true }) .then(stream => { localStream = stream; localVideo.srcObject = stream; }) .catch(error => { console.error('Error getting user media', error); }); // 创建PeerConnection对象 const peerConnection = new RTCPeerConnection(); // 添加本地视频流到PeerConnection peerConnection.addStream(localStream); // 监听远程视频流 peerConnection.onaddstream = event => { remoteStream = event.stream; remoteVideo.srcObject = remoteStream; }; // 创建SDP交换 peerConnection.createOffer() .then(offer => { return peerConnection.setLocalDescription(offer); }) .then(() => { // 将SDP交换发送给另一个端点 }) .catch(error => { console.error('Error creating offer', error); }); ``` 这只是一个基本的示例,WebRTC还有许多其他功能和配置选项。如果您想深入了解WebRTC,请查看相关文档和教程。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值