blob: 68b57de3e4ab3f5ff3bb00f4b7d0b051510c741c [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 "content/renderer/media/webrtc/transceiver_state_surfacer.h"
#include "content/renderer/media/webrtc/webrtc_util.h"
#include "third_party/webrtc/api/rtp_transceiver_interface.h"
namespace content {
TransceiverStateSurfacer::TransceiverStateSurfacer(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner)
: main_task_runner_(std::move(main_task_runner)),
signaling_task_runner_(std::move(signaling_task_runner)),
is_initialized_(false),
states_obtained_(false) {
DCHECK(main_task_runner_);
DCHECK(signaling_task_runner_);
}
TransceiverStateSurfacer::TransceiverStateSurfacer(
TransceiverStateSurfacer&& other)
: main_task_runner_(other.main_task_runner_),
signaling_task_runner_(other.signaling_task_runner_),
is_initialized_(other.is_initialized_),
states_obtained_(other.states_obtained_),
transceiver_states_(std::move(other.transceiver_states_)) {
// Explicitly null |other|'s task runners for use in destructor.
other.main_task_runner_ = nullptr;
other.signaling_task_runner_ = nullptr;
}
TransceiverStateSurfacer::~TransceiverStateSurfacer() {
// It's OK to not be on the main thread if this object has been moved, in
// which case |main_task_runner_| is null.
DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread());
}
TransceiverStateSurfacer& TransceiverStateSurfacer::operator=(
TransceiverStateSurfacer&& other) {
main_task_runner_ = other.main_task_runner_;
signaling_task_runner_ = other.signaling_task_runner_;
states_obtained_ = other.states_obtained_;
transceiver_states_ = std::move(other.transceiver_states_);
// Explicitly null |other|'s task runners for use in destructor.
other.main_task_runner_ = nullptr;
other.signaling_task_runner_ = nullptr;
return *this;
}
void TransceiverStateSurfacer::Initialize(
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
webrtc_transceivers) {
DCHECK(signaling_task_runner_->BelongsToCurrentThread());
DCHECK(!is_initialized_);
for (auto& webrtc_transceiver : webrtc_transceivers) {
// Create the sender state.
base::Optional<RtpSenderState> sender_state;
auto webrtc_sender = webrtc_transceiver->sender();
if (webrtc_sender) {
std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
sender_track_ref;
if (webrtc_sender->track()) {
// The track adapter for this track must already exist for us to obtain
// it, since this cannot be created from the signaling thread.
// TODO(hbos): Consider either making it possible to create local track
// adapters on the signaling thread for initialization on the main
// thread or wait for Onion Souping to simplify this.
// https://crbug.com/787254
sender_track_ref =
track_adapter_map->GetLocalTrackAdapter(webrtc_sender->track());
CHECK(sender_track_ref);
}
sender_state = RtpSenderState(
main_task_runner_, signaling_task_runner_, webrtc_sender.get(),
std::move(sender_track_ref), webrtc_sender->stream_ids());
}
// Create the receiver state.
base::Optional<RtpReceiverState> receiver_state;
auto webrtc_receiver = webrtc_transceiver->receiver();
if (webrtc_receiver) {
DCHECK(webrtc_receiver->track());
auto receiver_track_ref =
track_adapter_map->GetOrCreateRemoteTrackAdapter(
webrtc_receiver->track().get());
DCHECK(receiver_track_ref);
std::vector<std::string> receiver_stream_ids;
for (auto& stream : webrtc_receiver->streams()) {
receiver_stream_ids.push_back(stream->id());
}
receiver_state = RtpReceiverState(
main_task_runner_, signaling_task_runner_, webrtc_receiver.get(),
std::move(receiver_track_ref), std::move(receiver_stream_ids));
}
// Create the transceiver state.
transceiver_states_.push_back(RtpTransceiverState(
main_task_runner_, signaling_task_runner_, webrtc_transceiver.get(),
std::move(sender_state), std::move(receiver_state),
ToBaseOptional(webrtc_transceiver->mid()),
webrtc_transceiver->stopped(), webrtc_transceiver->direction(),
ToBaseOptional(webrtc_transceiver->current_direction()),
ToBaseOptional(webrtc_transceiver->fired_direction())));
}
is_initialized_ = true;
}
std::vector<RtpTransceiverState> TransceiverStateSurfacer::ObtainStates() {
DCHECK(main_task_runner_->BelongsToCurrentThread());
DCHECK(is_initialized_);
for (auto& transceiver_state : transceiver_states_)
transceiver_state.Initialize();
states_obtained_ = true;
return std::move(transceiver_states_);
}
SurfaceSenderStateOnly::SurfaceSenderStateOnly(
rtc::scoped_refptr<webrtc::RtpSenderInterface> sender)
: sender_(std::move(sender)) {
DCHECK(sender_);
}
SurfaceSenderStateOnly::~SurfaceSenderStateOnly() {}
cricket::MediaType SurfaceSenderStateOnly::media_type() const {
return sender_->media_type();
}
absl::optional<std::string> SurfaceSenderStateOnly::mid() const {
return absl::nullopt;
}
rtc::scoped_refptr<webrtc::RtpSenderInterface> SurfaceSenderStateOnly::sender()
const {
return sender_;
}
rtc::scoped_refptr<webrtc::RtpReceiverInterface>
SurfaceSenderStateOnly::receiver() const {
return nullptr;
}
bool SurfaceSenderStateOnly::stopped() const {
return false;
}
webrtc::RtpTransceiverDirection SurfaceSenderStateOnly::direction() const {
return webrtc::RtpTransceiverDirection::kSendOnly;
}
void SurfaceSenderStateOnly::SetDirection(
webrtc::RtpTransceiverDirection new_direction) {
NOTIMPLEMENTED();
}
absl::optional<webrtc::RtpTransceiverDirection>
SurfaceSenderStateOnly::current_direction() const {
return absl::nullopt;
}
void SurfaceSenderStateOnly::Stop() {
NOTIMPLEMENTED();
}
SurfaceReceiverStateOnly::SurfaceReceiverStateOnly(
rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver)
: receiver_(std::move(receiver)) {
DCHECK(receiver_);
}
SurfaceReceiverStateOnly::~SurfaceReceiverStateOnly() {}
cricket::MediaType SurfaceReceiverStateOnly::media_type() const {
return receiver_->media_type();
}
absl::optional<std::string> SurfaceReceiverStateOnly::mid() const {
return absl::nullopt;
}
rtc::scoped_refptr<webrtc::RtpSenderInterface>
SurfaceReceiverStateOnly::sender() const {
return nullptr;
}
rtc::scoped_refptr<webrtc::RtpReceiverInterface>
SurfaceReceiverStateOnly::receiver() const {
return receiver_;
}
bool SurfaceReceiverStateOnly::stopped() const {
return false;
}
webrtc::RtpTransceiverDirection SurfaceReceiverStateOnly::direction() const {
return webrtc::RtpTransceiverDirection::kRecvOnly;
}
void SurfaceReceiverStateOnly::SetDirection(
webrtc::RtpTransceiverDirection new_direction) {
NOTIMPLEMENTED();
}
absl::optional<webrtc::RtpTransceiverDirection>
SurfaceReceiverStateOnly::current_direction() const {
return absl::nullopt;
}
void SurfaceReceiverStateOnly::Stop() {
NOTIMPLEMENTED();
}
} // namespace content