blob: 789a24c2bea897ededb7346eb45aea419fdf48a7 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
namespace {
String TransceiverDirectionToString(
const webrtc::RtpTransceiverDirection& direction) {
switch (direction) {
case webrtc::RtpTransceiverDirection::kSendRecv:
return "sendrecv";
case webrtc::RtpTransceiverDirection::kSendOnly:
return "sendonly";
case webrtc::RtpTransceiverDirection::kRecvOnly:
return "recvonly";
case webrtc::RtpTransceiverDirection::kInactive:
return "inactive";
}
}
String OptionalTransceiverDirectionToString(
const base::Optional<webrtc::RtpTransceiverDirection>& direction) {
return direction ? TransceiverDirectionToString(*direction)
: String(); // null
}
bool TransceiverDirectionFromString(
const String& direction_string,
base::Optional<webrtc::RtpTransceiverDirection>* direction_out) {
if (!direction_string) {
*direction_out = base::nullopt;
return true;
}
if (direction_string == "sendrecv") {
*direction_out = webrtc::RtpTransceiverDirection::kSendRecv;
return true;
}
if (direction_string == "sendonly") {
*direction_out = webrtc::RtpTransceiverDirection::kSendOnly;
return true;
}
if (direction_string == "recvonly") {
*direction_out = webrtc::RtpTransceiverDirection::kRecvOnly;
return true;
}
if (direction_string == "inactive") {
*direction_out = webrtc::RtpTransceiverDirection::kInactive;
return true;
}
return false;
}
} // namespace
webrtc::RtpTransceiverInit ToRtpTransceiverInit(
const RTCRtpTransceiverInit& init) {
webrtc::RtpTransceiverInit webrtc_init;
base::Optional<webrtc::RtpTransceiverDirection> direction;
if (init.hasDirection() &&
TransceiverDirectionFromString(init.direction(), &direction) &&
direction) {
webrtc_init.direction = *direction;
}
DCHECK(init.hasStreams());
for (const auto& stream : init.streams()) {
webrtc_init.stream_ids.push_back(stream->id().Utf8().data());
}
DCHECK(init.hasSendEncodings());
// TODO(orphis,hbos): Pass the encodings down to the lower layer using
// ToRtpEncodingParameters() once implemented in third_party/webrtc.
// https://crbug.com/803494
return webrtc_init;
}
RTCRtpTransceiver::RTCRtpTransceiver(
RTCPeerConnection* pc,
std::unique_ptr<WebRTCRtpTransceiver> web_transceiver,
RTCRtpSender* sender,
RTCRtpReceiver* receiver)
: pc_(pc),
web_transceiver_(std::move(web_transceiver)),
sender_(sender),
receiver_(receiver),
fired_direction_(base::nullopt) {
DCHECK(pc_);
DCHECK(web_transceiver_);
DCHECK(sender_);
DCHECK(receiver_);
UpdateMembers();
}
String RTCRtpTransceiver::mid() const {
return web_transceiver_->Mid();
}
RTCRtpSender* RTCRtpTransceiver::sender() const {
return sender_;
}
RTCRtpReceiver* RTCRtpTransceiver::receiver() const {
return receiver_;
}
bool RTCRtpTransceiver::stopped() const {
return stopped_;
}
String RTCRtpTransceiver::direction() const {
return direction_;
}
void RTCRtpTransceiver::setDirection(String direction,
ExceptionState& exception_state) {
base::Optional<webrtc::RtpTransceiverDirection> webrtc_direction;
if (!TransceiverDirectionFromString(direction, &webrtc_direction) ||
!webrtc_direction) {
exception_state.ThrowTypeError("Invalid RTCRtpTransceiverDirection.");
return;
}
if (pc_->IsClosed()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The peer connection is closed.");
return;
}
if (stopped_) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The transceiver is stopped.");
return;
}
web_transceiver_->SetDirection(*webrtc_direction);
UpdateMembers();
}
String RTCRtpTransceiver::currentDirection() const {
return current_direction_;
}
void RTCRtpTransceiver::UpdateMembers() {
stopped_ = web_transceiver_->Stopped();
direction_ = TransceiverDirectionToString(web_transceiver_->Direction());
current_direction_ = OptionalTransceiverDirectionToString(
web_transceiver_->CurrentDirection());
fired_direction_ = web_transceiver_->FiredDirection();
}
void RTCRtpTransceiver::OnPeerConnectionClosed() {
receiver_->track()->Component()->Source()->SetReadyState(
MediaStreamSource::kReadyStateMuted);
stopped_ = true;
current_direction_ = String(); // null
}
WebRTCRtpTransceiver* RTCRtpTransceiver::web_transceiver() const {
return web_transceiver_.get();
}
base::Optional<webrtc::RtpTransceiverDirection>
RTCRtpTransceiver::fired_direction() const {
return fired_direction_;
}
bool RTCRtpTransceiver::DirectionHasSend() const {
auto direction = web_transceiver_->Direction();
return direction == webrtc::RtpTransceiverDirection::kSendRecv ||
direction == webrtc::RtpTransceiverDirection::kSendOnly;
}
bool RTCRtpTransceiver::DirectionHasRecv() const {
auto direction = web_transceiver_->Direction();
return direction == webrtc::RtpTransceiverDirection::kSendRecv ||
direction == webrtc::RtpTransceiverDirection::kRecvOnly;
}
bool RTCRtpTransceiver::FiredDirectionHasRecv() const {
return fired_direction_ &&
(*fired_direction_ == webrtc::RtpTransceiverDirection::kSendRecv ||
*fired_direction_ == webrtc::RtpTransceiverDirection::kRecvOnly);
}
void RTCRtpTransceiver::Trace(Visitor* visitor) {
visitor->Trace(pc_);
visitor->Trace(sender_);
visitor->Trace(receiver_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink