Implement transceiver.stop()

This adds RtpTransceiver.StopStandard(), which behaves according to
the specification at
https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop

It modifies RTCPeerConnection.getTransceivers() to return only
transceivers that have not been stopped.

Rebase of armax' https://webrtc-review.googlesource.com/c/src/+/172762

Bug: chromium:980879
Change-Id: I7d383ee874ccc0a006fdcf280496b5d4235425ce
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/180580
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31893}
This commit is contained in:
Harald Alvestrand
2020-08-10 14:41:03 +02:00
committed by Commit Bot
parent 582102c9b7
commit 11dc6571cb
24 changed files with 604 additions and 253 deletions

View File

@ -97,10 +97,19 @@ RTCError VerifyCodecPreferences(const std::vector<RtpCodecCapability>& codecs,
return RTCError::OK();
}
TaskQueueBase* GetCurrentTaskQueueOrThread() {
TaskQueueBase* current = TaskQueueBase::Current();
if (!current)
current = rtc::ThreadManager::Instance()->CurrentThread();
return current;
}
} // namespace
RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
: unified_plan_(false), media_type_(media_type) {
: thread_(GetCurrentTaskQueueOrThread()),
unified_plan_(false),
media_type_(media_type) {
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
media_type == cricket::MEDIA_TYPE_VIDEO);
}
@ -111,7 +120,8 @@ RtpTransceiver::RtpTransceiver(
receiver,
cricket::ChannelManager* channel_manager,
std::vector<RtpHeaderExtensionCapability> header_extensions_offered)
: unified_plan_(true),
: thread_(GetCurrentTaskQueueOrThread()),
unified_plan_(true),
media_type_(sender->media_type()),
channel_manager_(channel_manager),
header_extensions_to_offer_(std::move(header_extensions_offered)) {
@ -123,7 +133,7 @@ RtpTransceiver::RtpTransceiver(
}
RtpTransceiver::~RtpTransceiver() {
Stop();
StopInternal();
}
void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
@ -277,23 +287,51 @@ bool RtpTransceiver::stopped() const {
return stopped_;
}
bool RtpTransceiver::stopping() const {
RTC_DCHECK_RUN_ON(thread_);
return stopping_;
}
RtpTransceiverDirection RtpTransceiver::direction() const {
if (unified_plan_ && stopping())
return webrtc::RtpTransceiverDirection::kStopped;
return direction_;
}
void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) {
if (stopped()) {
return;
// Catch internal usage of SetDirection without error.
// We cannot deprecate this function while it is being proxied, so
// settle for causing a runtime error instead.
RTC_NOTREACHED();
SetDirectionWithError(new_direction);
}
RTCError RtpTransceiver::SetDirectionWithError(
RtpTransceiverDirection new_direction) {
if (unified_plan_ && stopping()) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
"Cannot set direction on a stopping transceiver.");
}
if (new_direction == direction_) {
return;
if (new_direction == direction_)
return RTCError::OK();
if (new_direction == RtpTransceiverDirection::kStopped) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
"The set direction 'stopped' is invalid.");
}
direction_ = new_direction;
SignalNegotiationNeeded();
return RTCError::OK();
}
absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
const {
if (unified_plan_ && stopping())
return webrtc::RtpTransceiverDirection::kStopped;
return current_direction_;
}
@ -302,14 +340,69 @@ absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
return fired_direction_;
}
void RtpTransceiver::Stop() {
for (const auto& sender : senders_) {
void RtpTransceiver::StopSendingAndReceiving() {
// 1. Let sender be transceiver.[[Sender]].
// 2. Let receiver be transceiver.[[Receiver]].
//
// 3. Stop sending media with sender.
//
// 4. Send an RTCP BYE for each RTP stream that was being sent by sender, as
// specified in [RFC3550].
RTC_DCHECK_RUN_ON(thread_);
for (const auto& sender : senders_)
sender->internal()->Stop();
}
for (const auto& receiver : receivers_) {
// 5. Stop receiving media with receiver.
for (const auto& receiver : receivers_)
receiver->internal()->Stop();
stopping_ = true;
direction_ = webrtc::RtpTransceiverDirection::kInactive;
}
RTCError RtpTransceiver::StopStandard() {
RTC_DCHECK_RUN_ON(thread_);
RTC_DCHECK(unified_plan_);
// 1. Let transceiver be the RTCRtpTransceiver object on which the method is
// invoked.
//
// 2. Let connection be the RTCPeerConnection object associated with
// transceiver.
//
// 3. If connection.[[IsClosed]] is true, throw an InvalidStateError.
if (is_pc_closed_) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
"PeerConnection is closed.");
}
// 4. If transceiver.[[Stopping]] is true, abort these steps.
if (stopping_)
return RTCError::OK();
// 5. Stop sending and receiving given transceiver, and update the
// negotiation-needed flag for connection.
StopSendingAndReceiving();
SignalNegotiationNeeded();
return RTCError::OK();
}
void RtpTransceiver::StopInternal() {
RTC_DCHECK_RUN_ON(thread_);
// 1. If transceiver.[[Stopping]] is false, stop sending and receiving given
// transceiver.
if (!stopping_)
StopSendingAndReceiving();
// 2. Set transceiver.[[Stopped]] to true.
stopped_ = true;
// Signal the updated change to the senders.
for (const auto& sender : senders_)
sender->internal()->SetTransceiverAsStopped();
// 3. Set transceiver.[[Receptive]] to false.
// 4. Set transceiver.[[CurrentDirection]] to null.
current_direction_ = absl::nullopt;
}
@ -403,4 +496,8 @@ RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
return RTCError::OK();
}
void RtpTransceiver::SetPeerConnectionClosed() {
is_pc_closed_ = true;
}
} // namespace webrtc