一、视频编码格式初始配置
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;
}