#include "services/video_capture/video_source_provider_impl.h"
#include "base/functional/bind.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "services/video_capture/public/mojom/producer.mojom.h"
#include "services/video_capture/video_source_impl.h"
#include "services/video_capture/virtual_device_enabled_device_factory.h"
namespace video_capture {
VideoSourceProviderImpl::VideoSourceProviderImpl(
DeviceFactory* device_factory,
base::RepeatingClosure on_last_client_disconnected_cb)
: device_factory_(device_factory),
on_last_client_disconnected_cb_(
std::move(on_last_client_disconnected_cb)) {
receivers_.set_disconnect_handler(base::BindRepeating(
&VideoSourceProviderImpl::OnClientDisconnected, base::Unretained(this)));
}
VideoSourceProviderImpl::~VideoSourceProviderImpl() = default;
void VideoSourceProviderImpl::AddClient(
mojo::PendingReceiver<mojom::VideoSourceProvider> receiver) {
receivers_.Add(this, std::move(receiver));
client_count_++;
}
void VideoSourceProviderImpl::GetSourceInfos(GetSourceInfosCallback callback) {
GetSourceInfosCallback callback_with_default =
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
std::move(callback),
VideoSourceProvider::GetSourceInfosResult::kErrorDroppedRequest,
std::vector<media::VideoCaptureDeviceInfo>());
device_factory_->GetDeviceInfos(
base::BindOnce(std::move(callback_with_default),
VideoSourceProvider::GetSourceInfosResult::kSuccess));
}
void VideoSourceProviderImpl::GetVideoSource(
const std::string& device_id,
mojo::PendingReceiver<mojom::VideoSource> source_receiver) {
auto source_iter = sources_.find(device_id);
if (source_iter == sources_.end()) {
auto video_source = std::make_unique<VideoSourceImpl>(
device_factory_, device_id,
base::BindRepeating(
&VideoSourceProviderImpl::OnVideoSourceLastClientDisconnected,
base::Unretained(this), device_id));
source_iter =
sources_.insert(std::make_pair(device_id, std::move(video_source)))
.first;
}
source_iter->second->AddToReceiverSet(std::move(source_receiver));
}
void VideoSourceProviderImpl::AddSharedMemoryVirtualDevice(
const media::VideoCaptureDeviceInfo& device_info,
mojo::PendingRemote<mojom::Producer> producer,
mojo::PendingReceiver<mojom::SharedMemoryVirtualDevice>
virtual_device_receiver) {
device_factory_->AddSharedMemoryVirtualDevice(
device_info, std::move(producer), std::move(virtual_device_receiver));
}
void VideoSourceProviderImpl::AddTextureVirtualDevice(
const media::VideoCaptureDeviceInfo& device_info,
mojo::PendingReceiver<mojom::TextureVirtualDevice>
virtual_device_receiver) {
device_factory_->AddTextureVirtualDevice(device_info,
std::move(virtual_device_receiver));
}
void VideoSourceProviderImpl::RegisterVirtualDevicesChangedObserver(
mojo::PendingRemote<mojom::DevicesChangedObserver> observer,
bool raise_event_if_virtual_devices_already_present) {
device_factory_->RegisterVirtualDevicesChangedObserver(
std::move(observer), raise_event_if_virtual_devices_already_present);
}
void VideoSourceProviderImpl::RegisterDevicesChangedObserver(
mojo::PendingRemote<mojom::DevicesChangedObserver> observer) {
if (!devices_changed_notifier_) {
devices_changed_notifier_.emplace();
}
devices_changed_notifier_->RegisterObserver(std::move(observer));
}
void VideoSourceProviderImpl::Close(CloseCallback callback) {
closed_but_not_yet_disconnected_client_count_++;
std::move(callback).Run();
OnClientDisconnectedOrClosed();
}
void VideoSourceProviderImpl::OnClientDisconnected() {
if (closed_but_not_yet_disconnected_client_count_ > 0) {
closed_but_not_yet_disconnected_client_count_--;
return;
}
OnClientDisconnectedOrClosed();
}
void VideoSourceProviderImpl::OnClientDisconnectedOrClosed() {
client_count_--;
if (client_count_ == 0) {
on_last_client_disconnected_cb_.Run();
}
}
void VideoSourceProviderImpl::OnVideoSourceLastClientDisconnected(
const std::string& device_id) {
sources_.erase(device_id);
}
}