调用堆栈
VideoChannel::SetLocalContent_w

bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
SdpType type,
std::string* error_desc) {
TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
RTC_DCHECK_RUN_ON(worker_thread());
RTC_LOG(LS_INFO) << "Setting local video description for " << ToString();
RTC_DCHECK(content);
if (!content) {
SafeSetError("Can't find video content in local description.", error_desc);
return false;
}
const VideoContentDescription* video = content->as_video();
if (type == SdpType::kAnswer)
SetNegotiatedHeaderExtensions_w(video->rtp_header_extensions());
RtpHeaderExtensions rtp_header_extensions =
GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
UpdateRtpHeaderExtensionMap(rtp_header_extensions);
media_channel()->SetExtmapAllowMixed(video->extmap_allow_mixed());
VideoRecvParameters recv_params = last_recv_params_;
RtpParametersFromMediaDescription(
video, rtp_header_extensions,
webrtc::RtpTransceiverDirectionHasRecv(video->direction()), &recv_params);
VideoSendParameters send_params = last_send_params_;
bool needs_send_params_update = false;
if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
for (auto& send_codec : send_params.codecs) {
auto* recv_codec = FindMatchingCodec(recv_params.codecs, send_codec);
if (recv_codec) {
if (!recv_codec->packetization && send_codec.packetization) {
send_codec.packetization.reset();
needs_send_params_update = true;
} else if (recv_codec->packetization != send_codec.packetization) {
SafeSetError(
"Failed to set local answer due to invalid codec packetization "
"specified in m-section with mid='" +
content_name() + "'.",
error_desc);
return false;
}
}
}
}
if (!media_channel()->SetRecvParameters(recv_params)) {
SafeSetError(
"Failed to set local video description recv parameters for m-section "
"with mid='" +
content_name() + "'.",
error_desc);
return false;
}
if (webrtc::RtpTransceiverDirectionHasRecv(video->direction())) {
for (const VideoCodec& codec : video->codecs()) {
MaybeAddHandledPayloadType(codec.id);
}
// Need to re-register the sink to update the handled payload.
if (!RegisterRtpDemuxerSink_w()) {
RTC_LOG(LS_ERROR) << "Failed to set up video demuxing for " << ToString();
return false;
}
}
last_recv_params_ = recv_params;
if (needs_send_params_update) {
if (!media_channel()->SetSendParameters(send_params)) {
SafeSetError("Failed to set send parameters for m-section with mid='" +
content_name() + "'.",
error_desc);
return false;
}
last_send_params_ = send_params;
}
// TODO(pthatcher): Move local streams into VideoSendParameters, and
// only give it to the media channel once we have a remote
// description too (without a remote description, we won't be able
// to send them anyway).
if (!UpdateLocalStreams_w(video->streams(), type, error_desc)) {
SafeSetError(
"Failed to set local video description streams for m-section with "
"mid='" +
content_name() + "'.",
error_desc);
return false;
}
set_local_content_direction(content->direction());
UpdateMediaSendRecvState_w();
return true;
}
BaseChannel::UpdateLocalStream_w

bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
SdpType type,
std::string* error_desc) {
// In the case of RIDs (where SSRCs are not negotiated), this method will
// generate an SSRC for each layer in StreamParams. That representation will
// be stored internally in |local_streams_|.
// In subsequent offers, the same stream can appear in |streams| again
// (without the SSRCs), so it should be looked up using RIDs (if available)
// and then by primary SSRC.
// In both scenarios, it is safe to assume that the media channel will be
// created with a StreamParams object with SSRCs. However, it is not safe to
// assume that |local_streams_| will always have SSRCs as there are scenarios
// in which niether SSRCs or RIDs are negotiated.
// Check for streams that have been removed.
bool ret = true;
for (const StreamParams& old_stream : local_streams_) {
if (!old_stream.has_ssrcs() ||
GetStream(streams, StreamFinder(&old_stream))) {
continue;
}
if (!media_channel()->RemoveSendStream(old_stream.first_ssrc())) {
rtc::StringBuilder desc;
desc << "Failed to remove send stream with ssrc "
<< old_stream.first_ssrc() << " from m-section with mid='"
<< content_name() << "'.";
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
// Check for new streams.
std::vector<StreamParams> all_streams;
for (const StreamParams& stream : streams) {
StreamParams* existing = GetStream(local_streams_, StreamFinder(&stream));
if (existing) {
// Parameters cannot change for an existing stream.
all_streams.push_back(*existing);
continue;
}
all_streams.push_back(stream);
StreamParams& new_stream = all_streams.back();
if (!new_stream.has_ssrcs() && !new_stream.has_rids()) {
continue;
}
RTC_DCHECK(new_stream.has_ssrcs() || new_stream.has_rids());
if (new_stream.has_ssrcs() && new_stream.has_rids()) {
rtc::StringBuilder desc;
desc << "Failed to add send stream: " << new_stream.first_ssrc()
<< " into m-section with mid='" << content_name()
<< "'. Stream has both SSRCs and RIDs.";
SafeSetError(desc.str(), error_desc);
ret = false;
continue;
}
// 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)) {
RTC_LOG(LS_INFO) << "Add send stream ssrc: " << new_stream.ssrcs[0]
<< " into " << ToString();
} else {
rtc::StringBuilder desc;
desc << "Failed to add send stream ssrc: " << new_stream.first_ssrc()
<< " into m-section with mid='" << content_name() << "'";
SafeSetError(desc.str(), error_desc);
ret = false;
}
}
local_streams_ = all_streams;
return ret;
}
WebRtcVideoChannel::AddSendStream

bool WebRtcVideoChannel::AddSendStream(const StreamParams& sp) {
RTC_DCHECK_RUN_ON(&thread_checker_);
RTC_LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
if (!ValidateStreamParams(sp))
return false;
if (!ValidateSendSsrcAvailability(sp))
return false;
for (uint32_t used_ssrc : sp.ssrcs)
send_ssrcs_.insert(used_ssrc);
webrtc::VideoSendStream::Config config(this);
for (const RidDescription& rid : sp.rids()) {
config.rtp.rids.push_back(rid.rid);
}
config.suspend_below_min_bitrate = video_config_.suspend_below_min_bitrate;
config.periodic_alr_bandwidth_probing =
video_config_.periodic_alr_bandwidth_probing;
config.encoder_settings.experiment_cpu_load_estimator =
video_config_.experiment_cpu_load_estimator;
config.encoder_settings.encoder_factory = encoder_factory_;
config.encoder_settings.bitrate_allocator_factory =
bitrate_allocator_factory_;
config.encoder_settings.encoder_switch_request_callback = this;
config.crypto_options = crypto_options_;
config.rtp.extmap_allow_mixed = ExtmapAllowMixed();
config.rtcp_report_interval_ms = video_config_.rtcp_report_interval_ms;
WebRtcVideoSendStream* stream = new WebRtcVideoSendStream(
call_, sp, std::move(config), default_send_options_,
video_config_.enable_cpu_adaptation, bitrate_config_.max_bitrate_bps,
send_codec_, send_rtp_extensions_, send_params_);
uint32_t ssrc = sp.first_ssrc();
RTC_DCHECK(ssrc != 0);
send_streams_[ssrc] = stream;
if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
rtcp_receiver_report_ssrc_ = ssrc;
RTC_LOG(LS_INFO)
<< "SetLocalSsrc on all the receive streams because we added "
"a send stream.";
for (auto& kv : receive_streams_)
kv.second->SetLocalSsrc(ssrc);
}
if (sending_) {
stream->SetSend(true);
}
return true;
}