simucast同一个视频使用不同码率,帧率,宽高发送多个视频流,接收方可以根据选择接受那一个视频
sdp表现:
//simucast 直播多个流,可以使用不同码率,宽度高度帧率等参数,webrtc内部有一固定算法进行转化
a=ssrc-group:SIM 2267484833 2714558033 2714558034
如何设置:
planb模式下:
RTCOfferAnswerOptions.num_simulcast_layer =3;
PeerConnection::CreateOffer();
unified plan模式下:
使用rid可以代替他的.
PeerConnection.GetSenders();
RtpParameters parma=RtpSender.GetParameters();
//设置param中编码参数的rid
...
RtpSender.SetParameters();
struct RtpParameters{
//多组编码参数 ,用于支持svc编码
std::vector<RtpEncodingParameters> encodings;
}
struct RtpEncodingParameters{
// Value to use for RID RTP header extension.
// Called "encodingId" in ORTC.
std::string rid;
}
webrtc m76中创建simulcast相关:
media_session.cc
static bool AddStreamParams(){
...
//这是对应的流的信息
StreamParams stream_param =
sender.rids.empty()
?
// Signal SSRCs and legacy simulcast (if requested).
//老版本planb. rids为空,使用num_simulcast_layer来创建,内部调用GenerateSsrcs
CreateStreamParamsForNewSenderWithSsrcs(
sender, rtcp_cname, include_rtx_streams,
include_flexfec_stream, ssrc_generator)
:
// Signal RIDs and spec-compliant simulcast (if requested).
CreateStreamParamsForNewSenderWithRids(sender, rtcp_cname);
...
}
planb 使用的函数:
//num_layers>1表示simulcast流
void StreamParams::GenerateSsrcs(int num_layers,
bool generate_fid,
bool generate_fec_fr,
rtc::UniqueRandomIdGenerator* ssrc_generator) {
RTC_DCHECK_GE(num_layers, 0);
RTC_DCHECK(ssrc_generator);
std::vector<uint32_t> primary_ssrcs;
for (int i = 0; i < num_layers; ++i) {
uint32_t ssrc = ssrc_generator->GenerateId();
primary_ssrcs.push_back(ssrc);
add_ssrc(ssrc);
}
if (num_layers > 1) {
SsrcGroup simulcast(kSimSsrcGroupSemantics, primary_ssrcs);
ssrc_groups.push_back(simulcast);
}
if (generate_fid) {
for (uint32_t ssrc : primary_ssrcs) {
AddFidSsrc(ssrc, ssrc_generator->GenerateId());
}
}
if (generate_fec_fr) {
for (uint32_t ssrc : primary_ssrcs) {
AddFecFrSsrc(ssrc, ssrc_generator->GenerateId());
}
}
}
...
验证ssrc和rid一系列参数
unimlucast plan 模式下:
BaseChannel::UpdateLocalStreams_w(){
ssrc应该是空的,用rid数量填充simulcast
// At this point we use the legacy simulcast group in StreamParams to
// indicate that we want multiple layers to the media channel.
if (!new_stream.has_ssrcs()) {
// TODO(bugs.webrtc.org/10250): Indicate if flex is desired here.
new_stream.GenerateSsrcs(new_stream.rids().size(), /* rtx = */ true,
/* flex_fec = */ false, ssrc_generator_);
}
if (media_channel()->AddSendStream(new_stream)){}
}
创建编码器配置,进行校验:
WebRtcVideoChannel ::WebRtcVideoSendStream::CreateVideoEncoderConfig(){
// By default, the stream count for the codec configuration should match the
// number of negotiated ssrcs. But if the codec is blacklisted for simulcast
// or a screencast (and not in simulcast screenshare experiment), only
// configure a single stream.
encoder_config.number_of_streams = parameters_.config.rtp.ssrcs.size();
if (IsCodecBlacklistedForSimulcast(codec.name) ||
(is_screencast && (!ScreenshareSimulcastFieldTrialEnabled() ||
!parameters_.conference_mode))) {
//如果编码器器在黑名单中,则强制设置单个流,不进行广播
encoder_config.number_of_streams = 1;
}