调用堆栈
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;}