blob: 5f1faf25381fcd05c737cec64948927e53cef1ee [file] [log] [blame]
// Copyright 2014 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/mediastream/media_stream_video_capturer_source.h"
#include <utility>
#include "media/capture/video_capturer_source.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
LocalFrame* frame,
SourceStoppedCallback stop_callback,
std::unique_ptr<media::VideoCapturerSource> source)
: frame_(frame), source_(std::move(source)) {
media::VideoCaptureFormats preferred_formats = source_->GetPreferredFormats();
if (!preferred_formats.empty())
capture_params_.requested_format = preferred_formats.front();
SetStopCallback(std::move(stop_callback));
}
MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
LocalFrame* frame,
SourceStoppedCallback stop_callback,
const MediaStreamDevice& device,
const media::VideoCaptureParams& capture_params,
DeviceCapturerFactoryCallback device_capturer_factory_callback)
: frame_(frame),
source_(device_capturer_factory_callback.Run(device.session_id())),
capture_params_(capture_params),
device_capturer_factory_callback_(
std::move(device_capturer_factory_callback)) {
DCHECK(!device.session_id().is_empty());
SetStopCallback(std::move(stop_callback));
SetDevice(device);
SetDeviceRotationDetection(true /* enabled */);
}
MediaStreamVideoCapturerSource::~MediaStreamVideoCapturerSource() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
void MediaStreamVideoCapturerSource::SetDeviceCapturerFactoryCallbackForTesting(
DeviceCapturerFactoryCallback testing_factory_callback) {
device_capturer_factory_callback_ = std::move(testing_factory_callback);
}
void MediaStreamVideoCapturerSource::RequestRefreshFrame() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
source_->RequestRefreshFrame();
}
void MediaStreamVideoCapturerSource::OnFrameDropped(
media::VideoCaptureFrameDropReason reason) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
source_->OnFrameDropped(reason);
}
void MediaStreamVideoCapturerSource::OnLog(const std::string& message) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
source_->OnLog(message);
}
void MediaStreamVideoCapturerSource::OnHasConsumers(bool has_consumers) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (has_consumers)
source_->Resume();
else
source_->MaybeSuspend();
}
void MediaStreamVideoCapturerSource::OnCapturingLinkSecured(bool is_secure) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!frame_)
return;
GetMediaStreamDispatcherHost()->SetCapturingLinkSecured(
device().serializable_session_id(),
static_cast<mojom::blink::MediaStreamType>(device().type), is_secure);
}
void MediaStreamVideoCapturerSource::StartSourceImpl(
VideoCaptureDeliverFrameCB frame_callback,
EncodedVideoFrameCB encoded_frame_callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
state_ = STARTING;
frame_callback_ = std::move(frame_callback);
source_->StartCapture(
capture_params_, frame_callback_,
WTF::BindRepeating(&MediaStreamVideoCapturerSource::OnRunStateChanged,
WTF::Unretained(this), capture_params_));
}
media::VideoCaptureFeedbackCB
MediaStreamVideoCapturerSource::GetFeedbackCallback() const {
return source_->GetFeedbackCallback();
}
void MediaStreamVideoCapturerSource::StopSourceImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
source_->StopCapture();
}
void MediaStreamVideoCapturerSource::StopSourceForRestartImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (state_ != STARTED) {
OnStopForRestartDone(false);
return;
}
state_ = STOPPING_FOR_RESTART;
source_->StopCapture();
// Force state update for nondevice sources, since they do not
// automatically update state after StopCapture().
if (device().type == mojom::blink::MediaStreamType::NO_SERVICE)
OnRunStateChanged(capture_params_, false);
}
void MediaStreamVideoCapturerSource::RestartSourceImpl(
const media::VideoCaptureFormat& new_format) {
DCHECK(new_format.IsValid());
media::VideoCaptureParams new_capture_params = capture_params_;
new_capture_params.requested_format = new_format;
state_ = RESTARTING;
source_->StartCapture(
new_capture_params, frame_callback_,
WTF::BindRepeating(&MediaStreamVideoCapturerSource::OnRunStateChanged,
WTF::Unretained(this), new_capture_params));
}
base::Optional<media::VideoCaptureFormat>
MediaStreamVideoCapturerSource::GetCurrentFormat() const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return capture_params_.requested_format;
}
base::Optional<media::VideoCaptureParams>
MediaStreamVideoCapturerSource::GetCurrentCaptureParams() const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return capture_params_;
}
void MediaStreamVideoCapturerSource::ChangeSourceImpl(
const MediaStreamDevice& new_device) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(device_capturer_factory_callback_);
if (state_ != STARTED) {
return;
}
state_ = STOPPING_FOR_CHANGE_SOURCE;
source_->StopCapture();
SetDevice(new_device);
source_ = device_capturer_factory_callback_.Run(new_device.session_id());
source_->StartCapture(
capture_params_, frame_callback_,
WTF::BindRepeating(&MediaStreamVideoCapturerSource::OnRunStateChanged,
WTF::Unretained(this), capture_params_));
}
base::WeakPtr<MediaStreamVideoSource>
MediaStreamVideoCapturerSource::GetWeakPtr() const {
return weak_factory_.GetWeakPtr();
}
void MediaStreamVideoCapturerSource::OnRunStateChanged(
const media::VideoCaptureParams& new_capture_params,
bool is_running) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
switch (state_) {
case STARTING:
source_->OnLog("MediaStreamVideoCapturerSource sending OnStartDone");
if (is_running) {
state_ = STARTED;
DCHECK(capture_params_ == new_capture_params);
OnStartDone(mojom::blink::MediaStreamRequestResult::OK);
} else {
state_ = STOPPED;
OnStartDone(
mojom::blink::MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO);
}
break;
case STARTED:
if (!is_running) {
state_ = STOPPED;
StopSource();
}
break;
case STOPPING_FOR_RESTART:
source_->OnLog(
"MediaStreamVideoCapturerSource sending OnStopForRestartDone");
state_ = is_running ? STARTED : STOPPED;
OnStopForRestartDone(!is_running);
break;
case STOPPING_FOR_CHANGE_SOURCE:
state_ = is_running ? STARTED : STOPPED;
break;
case RESTARTING:
if (is_running) {
state_ = STARTED;
capture_params_ = new_capture_params;
} else {
state_ = STOPPED;
}
source_->OnLog("MediaStreamVideoCapturerSource sending OnRestartDone");
OnRestartDone(is_running);
break;
case STOPPED:
break;
}
}
mojom::blink::MediaStreamDispatcherHost*
MediaStreamVideoCapturerSource::GetMediaStreamDispatcherHost() {
DCHECK(frame_);
if (!host_) {
frame_->GetBrowserInterfaceBroker().GetInterface(
host_.BindNewPipeAndPassReceiver());
}
return host_.get();
}
void MediaStreamVideoCapturerSource::SetMediaStreamDispatcherHostForTesting(
mojo::PendingRemote<mojom::blink::MediaStreamDispatcherHost> host) {
host_.Bind(std::move(host));
}
media::VideoCapturerSource*
MediaStreamVideoCapturerSource::GetSourceForTesting() {
return source_.get();
}
} // namespace blink