// Function to call back to the PeerConnection when negotiation is needed void RtpTransmissionManager::OnNegotiationNeeded() {
on_negotiation_needed_();
}
RTCErrorOr<scoped_refptr<RtpSenderInterface>>
RtpTransmissionManager::AddTrackUnifiedPlan( const MediaConfig& media_config, const AudioOptions& audio_options, const VideoOptions& video_options, const CryptoOptions& crypto_options,
VideoBitrateAllocatorFactory* video_bitrate_allocator_factory,
scoped_refptr<MediaStreamTrackInterface> track, const std::vector<std::string>& stream_ids, const std::vector<RtpEncodingParameters>* init_send_encodings) {
RTC_DCHECK(IsUnifiedPlan()); auto transceiver =
FindFirstTransceiverForAddedTrack(track, init_send_encodings);
if (transceiver) {
RTC_LOG(LS_INFO) << "Reusing an existing "
<< MediaTypeToString(transceiver->media_type())
<< " transceiver for AddTrack.";
if (transceiver->stopping()) { return LOG_ERROR(RTCError::InvalidParameter()
<< "The existing transceiver is stopping.");
}
if (transceiver->direction() == RtpTransceiverDirection::kRecvOnly) {
transceiver->internal()->set_direction(
RtpTransceiverDirection::kSendRecv);
} else if (transceiver->direction() == RtpTransceiverDirection::kInactive) {
transceiver->internal()->set_direction(
RtpTransceiverDirection::kSendOnly);
}
transceiver->sender()->SetTrack(track.get());
transceiver->internal()->sender_internal()->set_stream_ids(stream_ids);
transceiver->internal()->set_reused_for_addtrack(true);
} else {
MediaType media_type = TrackType(track);
RTC_LOG(LS_INFO) << "Adding " << MediaTypeToString(media_type)
<< " transceiver in response to a call to AddTrack.";
std::string sender_id = track->id(); // Avoid creating a sender with an existing ID by generating a random ID. // This can happen if this is the second time AddTrack has created a sender // for this track.
if (FindSenderById(sender_id)) {
sender_id = CreateRandomUuid();
}
ScopedOperationsBatcher worker_tasks(context_->worker_thread());
transceiver = CreateAndAddTransceiver(
media_config, audio_options, video_options, crypto_options,
video_bitrate_allocator_factory, media_type, track, stream_ids,
init_send_encodings
? *init_send_encodings
: std::vector<RtpEncodingParameters>(1, RtpEncodingParameters{}), /*header_extensions_to_negotiate=*/{}, /*simulcast_rejected=*/false, /*initial_simulcast_layers=*/{},
worker_tasks, sender_id, /*receiver_id=*/"");
RTCError error = worker_tasks.Run();
RTC_DCHECK(error.ok());
transceiver->internal()->set_created_by_addtrack(true);
transceiver->internal()->set_direction(RtpTransceiverDirection::kSendRecv);
} return transceiver->sender();
}
scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
RtpTransmissionManager::CreateAndAddTransceiver( const MediaConfig& media_config, const AudioOptions& audio_options, const VideoOptions& video_options, const CryptoOptions& crypto_options,
VideoBitrateAllocatorFactory* video_bitrate_allocator_factory,
MediaType media_type,
scoped_refptr<MediaStreamTrackInterface> track, const std::vector<std::string>& stream_ids, const std::vector<RtpEncodingParameters>& init_send_encodings, const std::vector<RtpHeaderExtensionCapability>&
header_extensions_to_negotiate, bool simulcast_rejected, const std::vector<SimulcastLayer>& initial_simulcast_layers,
ScopedOperationsBatcher& worker_tasks,
absl::string_view sender_id,
absl::string_view receiver_id) {
RTC_DCHECK_RUN_ON(signaling_thread()); // Ensure that the new sender does not have an ID that is already in use by // another sender. // Allow receiver IDs to conflict since those come from remote SDP (which // could be invalid, but should not cause a crash).
RTC_DCHECK(!FindSenderById(sender_id));
std::vector<RtpHeaderExtensionCapability> header_extensions =
std::move(header_extensions_to_negotiate);
if (!env_.field_trials().IsDisabled( "WebRTC-HeaderExtensionNegotiateMemory")) { // If we have already negotiated header extensions for this type, // and it is not stopped, // reuse the negotiated state for new transceivers of the same type.
for (constauto& transceiver : transceivers()->List()) {
if (transceiver->media_type() == media_type && !transceiver->stopping()) {
header_extensions = transceiver->GetHeaderExtensionsToNegotiate(); break;
}
}
}
if (header_extensions.empty()) {
header_extensions = GetDefaultHeaderExtensions(media_type);
}
PLAN_B_ONLY scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
RtpTransmissionManager::GetAudioTransceiver() const {
RTC_DCHECK_RUN_ON(signaling_thread()); // This method only works with Plan B SDP, where there is a single // audio/video transceiver.
RTC_DCHECK(!IsUnifiedPlan());
for (auto transceiver : transceivers_.List()) {
if (transceiver->media_type() == MediaType::AUDIO) { return transceiver;
}
}
RTC_DCHECK_NOTREACHED(); return nullptr;
}
PLAN_B_ONLY scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
RtpTransmissionManager::GetVideoTransceiver() const {
RTC_DCHECK_RUN_ON(signaling_thread()); // This method only works with Plan B SDP, where there is a single // audio/video transceiver.
RTC_DCHECK(!IsUnifiedPlan());
for (auto transceiver : transceivers_.List()) {
if (transceiver->media_type() == MediaType::VIDEO) { return transceiver;
}
}
RTC_DCHECK_NOTREACHED(); return nullptr;
}
PLAN_B_ONLY void RtpTransmissionManager::AddTrackPlanB(
MediaStreamTrackInterface* track,
MediaStreamInterface* stream) {
RTC_DCHECK_RUN_ON(signaling_thread());
RTC_DCHECK(track);
RTC_DCHECK(stream);
RTC_DCHECK(!IsUnifiedPlan()); auto sender = FindSenderForTrack(track);
if (sender) { // We already have a sender for this track, so just change the stream_id // so that it's correct in the next call to CreateOffer.
sender->internal()->set_stream_ids({stream->id()}); return;
}
// Normal case; we've never seen this track before.
MediaType media_type = TrackType(track);
RtpTransceiver* transceiver = media_type == MediaType::AUDIO
? GetAudioTransceiver()->internal()
: GetVideoTransceiver()->internal();
scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender =
transceiver->AddSenderPlanB(
scoped_refptr<MediaStreamTrackInterface>(track), track->id(),
{stream->id()}, {}); // If the sender has already been configured in SDP, we call SetSsrc, // which will connect the sender to the underlying transport. This can // occur if a local session description that contains the ID of the sender // is set before AddStream is called. It can also occur if the local // session description is not changed and RemoveStream is called, and // later AddStream is called again with the same stream.
std::optional<uint32_t> ssrc =
GetSenderSsrc(media_type == MediaType::AUDIO ? local_audio_sender_infos_
: local_video_sender_infos_,
stream->id(), track->id());
if (ssrc) {
new_sender->internal()->SetSsrc(*ssrc);
}
}
// TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around // indefinitely, when we have unified plan SDP.
PLAN_B_ONLY void RtpTransmissionManager::RemoveTrackPlanB(
MediaStreamTrackInterface* track,
MediaStreamInterface* stream) {
RTC_DCHECK_RUN_ON(signaling_thread());
RTC_DCHECK(!IsUnifiedPlan()); auto sender = FindSenderForTrack(track);
if (!sender) {
RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
<< " doesn't exist."; return;
}
RtpTransceiver* transceiver = TrackType(track) == MediaType::AUDIO
? GetAudioTransceiver()->internal()
: GetVideoTransceiver()->internal();
transceiver->RemoveSenderPlanB(sender.get());
}
PLAN_B_ONLY void RtpTransmissionManager::CreateAudioReceiverPlanB(
MediaStreamInterface* stream, const RtpSenderInfo& remote_sender_info) {
RTC_DCHECK(!IsUnifiedPlan());
RTC_DCHECK(!closed_);
std::vector<scoped_refptr<MediaStreamInterface>> streams;
streams.push_back(scoped_refptr<MediaStreamInterface>(stream)); // TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use // the constructor taking stream IDs instead. auto audio_receiver = make_ref_counted<AudioRtpReceiver>(
worker_thread(), remote_sender_info.sender_id, streams, false,
voice_media_receive_channel()); auto task = (remote_sender_info.sender_id == kDefaultAudioSenderId)
? audio_receiver->GetSetupForUnsignaledMediaChannel()
: audio_receiver->GetSetupForMediaChannel(
remote_sender_info.first_ssrc);
worker_thread()->BlockingCall([&]() mutable { std::move(task)(); });
scoped_refptr<RtpReceiverInterface> receiver;
if (media_type == MediaType::AUDIO) { // When the MediaEngine audio channel is destroyed, the RemoteAudioSource // will be notified which will end the AudioRtpReceiver::track().
receiver = RemoveAndStopReceiver(sender_info);
scoped_refptr<AudioTrackInterface> audio_track =
stream->FindAudioTrack(sender_info.sender_id);
if (audio_track) {
stream->RemoveTrack(audio_track);
}
} else if (media_type == MediaType::VIDEO) { // Stopping or destroying a VideoRtpReceiver will end the // VideoRtpReceiver::track().
receiver = RemoveAndStopReceiver(sender_info);
scoped_refptr<VideoTrackInterface> video_track =
stream->FindVideoTrack(sender_info.sender_id);
if (video_track) { // There's no guarantee the track is still available, e.g. the track may // have been removed from the stream by an application.
stream->RemoveTrack(video_track);
}
} else {
RTC_DCHECK_NOTREACHED() << "Invalid media type";
}
if (receiver) {
RTC_DCHECK(!closed_);
RunWithObserver([&](auto observer) { observer->OnRemoveTrack(receiver); });
}
}
PLAN_B_ONLY void RtpTransmissionManager::OnLocalSenderAdded( const RtpSenderInfo& sender_info,
MediaType media_type) {
RTC_DCHECK_RUN_ON(signaling_thread());
RTC_DCHECK(!IsUnifiedPlan()); auto sender = FindSenderById(sender_info.sender_id);
if (!sender) {
RTC_LOG(LS_WARNING) << "An unknown RtpSender with id "
<< sender_info.sender_id
<< " has been configured in the local description."; return;
}
if (sender->media_type() != media_type) {
RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local" " description with an unexpected media type."; return;
}
PLAN_B_ONLY void RtpTransmissionManager::OnLocalSenderRemoved( const RtpSenderInfo& sender_info,
MediaType media_type) {
RTC_DCHECK_RUN_ON(signaling_thread()); auto sender = FindSenderById(sender_info.sender_id);
if (!sender) { // This is the normal case. I.e., RemoveStream has been called and the // SessionDescriptions has been renegotiated. return;
}
// A sender has been removed from the SessionDescription but it's still // associated with the PeerConnection. This only occurs if the SDP doesn't // match with the calls to CreateSender, AddStream and RemoveStream.
if (sender->media_type() != media_type) {
RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local" " description with an unexpected media type."; return;
}
scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
RtpTransmissionManager::FindSenderById(absl::string_view sender_id) const {
RTC_DCHECK_RUN_ON(signaling_thread());
for (constauto& transceiver : transceivers_.List()) {
RTC_ALLOW_PLAN_B_DEPRECATION_BEGIN(); // Under Unified Plan, senders() always has exactly one entry, // and one can use sender() not senders(). // Since this function is used both in Plan B and Unified, this is // left as-is for now.
for (auto sender : transceiver->internal()->senders()) {
if (sender->id() == sender_id) { return sender;
}
}
RTC_ALLOW_PLAN_B_DEPRECATION_END();
} return nullptr;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.