blob: 9086130d3dc5a58fd813569b04bd5038e880a5a7 [file] [log] [blame]
// Copyright (c) 2017 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/public/web/modules/mediastream/remote_media_stream_track_adapter.h"
#include "base/single_thread_task_runner.h"
#include "media/base/limits.h"
#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
#include "third_party/blink/public/platform/modules/webrtc/track_observer.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
RemoteVideoTrackAdapter::RemoteVideoTrackAdapter(
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
webrtc::VideoTrackInterface* webrtc_track)
: RemoteMediaStreamTrackAdapter(main_thread, webrtc_track) {
std::unique_ptr<TrackObserver> observer(
new TrackObserver(main_thread, observed_track().get()));
// Here, we use CrossThreadUnretained() to avoid a circular reference.
//
// TODO(crbug.com/963574): Remove the use of ConvertToBaseOnceCallback here
// once the file that includes remote_media_stream_track_adapter.h (namely
// webrtc_media_stream_track_adapter.h) is Onion souped.
web_initialize_ = ConvertToBaseOnceCallback(
CrossThreadBindOnce(&RemoteVideoTrackAdapter::InitializeWebVideoTrack,
CrossThreadUnretained(this), std::move(observer),
observed_track()->enabled()));
}
RemoteVideoTrackAdapter::~RemoteVideoTrackAdapter() {
DCHECK(main_thread_->BelongsToCurrentThread());
if (initialized()) {
// TODO(crbug.com/704136): When moving RemoteVideoTrackAdapter out of the
// public API, make this managed by Oilpan. Note that, the destructor will
// not allowed to touch other on-heap objects like web_track().
static_cast<MediaStreamRemoteVideoSource*>(
web_track()->Source().GetPlatformSource())
->OnSourceTerminated();
}
}
void RemoteVideoTrackAdapter::InitializeWebVideoTrack(
std::unique_ptr<TrackObserver> observer,
bool enabled) {
DCHECK(main_thread_->BelongsToCurrentThread());
auto video_source_ptr =
std::make_unique<MediaStreamRemoteVideoSource>(std::move(observer));
MediaStreamRemoteVideoSource* video_source = video_source_ptr.get();
InitializeWebTrack(WebMediaStreamSource::kTypeVideo);
web_track()->Source().SetPlatformSource(std::move(video_source_ptr));
WebMediaStreamSource::Capabilities capabilities;
capabilities.device_id = id();
web_track()->Source().SetCapabilities(capabilities);
web_track()->SetPlatformTrack(std::make_unique<MediaStreamVideoTrack>(
video_source, MediaStreamVideoSource::ConstraintsCallback(), enabled));
}
RemoteAudioTrackAdapter::RemoteAudioTrackAdapter(
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
webrtc::AudioTrackInterface* webrtc_track)
: RemoteMediaStreamTrackAdapter(main_thread, webrtc_track),
#if DCHECK_IS_ON()
unregistered_(false),
#endif
state_(observed_track()->state()) {
// TODO(tommi): Use TrackObserver instead.
observed_track()->RegisterObserver(this);
// Here, we use CrossThreadUnretained() to avoid a circular reference.
//
// TODO(crbug.com/963574): Remove the use of ConvertToBaseOnceCallback here
// once the file that includes remote_media_stream_track_adapter.h (namely
// webrtc_media_stream_track_adapter.h) is Onion souped.
web_initialize_ = ConvertToBaseOnceCallback(
CrossThreadBindOnce(&RemoteAudioTrackAdapter::InitializeWebAudioTrack,
CrossThreadUnretained(this), main_thread));
}
RemoteAudioTrackAdapter::~RemoteAudioTrackAdapter() {
#if DCHECK_IS_ON()
DCHECK(unregistered_);
#endif
}
void RemoteAudioTrackAdapter::Unregister() {
#if DCHECK_IS_ON()
DCHECK(!unregistered_);
unregistered_ = true;
#endif
observed_track()->UnregisterObserver(this);
}
void RemoteAudioTrackAdapter::InitializeWebAudioTrack(
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread) {
InitializeWebTrack(WebMediaStreamSource::kTypeAudio);
auto source = std::make_unique<PeerConnectionRemoteAudioSource>(
observed_track().get(), main_thread);
auto* source_ptr = source.get();
web_track()->Source().SetPlatformSource(
std::move(source)); // Takes ownership.
WebMediaStreamSource::Capabilities capabilities;
capabilities.device_id = id();
bool values[] = {false};
capabilities.echo_cancellation = WebVector<bool>(values, 1u);
capabilities.auto_gain_control = WebVector<bool>(values, 1u);
capabilities.noise_suppression = WebVector<bool>(values, 1u);
capabilities.sample_size = {
media::SampleFormatToBitsPerChannel(media::kSampleFormatS16), // min
media::SampleFormatToBitsPerChannel(media::kSampleFormatS16) // max
};
web_track()->Source().SetCapabilities(capabilities);
source_ptr->ConnectToTrack(*(web_track()));
}
void RemoteAudioTrackAdapter::OnChanged() {
PostCrossThreadTask(
*main_thread_, FROM_HERE,
CrossThreadBindOnce(&RemoteAudioTrackAdapter::OnChangedOnMainThread,
WrapRefCounted(this), observed_track()->state()));
}
void RemoteAudioTrackAdapter::OnChangedOnMainThread(
webrtc::MediaStreamTrackInterface::TrackState state) {
DCHECK(main_thread_->BelongsToCurrentThread());
if (state == state_ || !initialized())
return;
state_ = state;
switch (state) {
case webrtc::MediaStreamTrackInterface::kLive:
web_track()->Source().SetReadyState(
WebMediaStreamSource::kReadyStateLive);
break;
case webrtc::MediaStreamTrackInterface::kEnded:
web_track()->Source().SetReadyState(
WebMediaStreamSource::kReadyStateEnded);
break;
default:
NOTREACHED();
break;
}
}
} // namespace blink