#include "media/mojo/services/interface_factory_impl.h"
#include <memory>
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
#include "media/base/media_switches.h"
#include "media/mojo/mojom/renderer_extensions.mojom.h"
#include "media/mojo/services/mojo_decryptor_service.h"
#include "media/mojo/services/mojo_media_client.h"
#if BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER)
#include "base/sequence_checker.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequence_bound.h"
#include "media/mojo/services/mojo_audio_decoder_service.h"
#endif
#if BUILDFLAG(ENABLE_MOJO_AUDIO_ENCODER)
#include "media/mojo/services/mojo_audio_encoder_service.h"
#endif
#if BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
#include "media/mojo/services/mojo_video_decoder_service.h"
#endif
#if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER) || \
BUILDFLAG(IS_WIN)
#include "base/functional/callback_helpers.h"
#include "media/base/renderer.h"
#include "media/mojo/services/mojo_renderer_service.h"
#endif
#if BUILDFLAG(ENABLE_MOJO_CDM)
#include "media/base/cdm_factory.h"
#include "media/mojo/services/mojo_cdm_service.h"
#endif
namespace media {
#if BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER)
class InterfaceFactoryImpl::AudioDecoderReceivers {
public:
AudioDecoderReceivers(MojoMediaClient* mojo_media_client,
MojoCdmServiceContext* mojo_cdm_service_context,
base::RepeatingClosure disconnect_handler)
: task_runner_(
base::FeatureList::IsEnabled(
kUseTaskRunnerForMojoAudioDecoderService)
? base::ThreadPool::CreateSingleThreadTaskRunner(
{base::TaskPriority::USER_BLOCKING, base::MayBlock()})
: base::SingleThreadTaskRunner::GetCurrentDefault()),
receivers_(task_runner_),
mojo_media_client_(mojo_media_client),
mojo_cdm_service_context_(mojo_cdm_service_context),
disconnect_handler_(disconnect_handler) {
DCHECK(mojo_media_client_);
DCHECK(mojo_cdm_service_context_);
base::RepeatingClosure disconnect_cb =
base::BindRepeating(&AudioDecoderReceivers::OnReceiverDisconnect,
weak_factory_.GetWeakPtr());
if (!task_runner_->RunsTasksInCurrentSequence()) {
disconnect_cb =
base::BindPostTaskToCurrentDefault(std::move(disconnect_cb));
}
receivers_
.AsyncCall(&mojo::UniqueReceiverSet<
mojom::AudioDecoder>::set_disconnect_handler)
.WithArgs(std::move(disconnect_cb));
}
~AudioDecoderReceivers() = default;
void CreateAudioDecoder(mojo::PendingReceiver<mojom::AudioDecoder> receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
typedef mojo::ReceiverId (
mojo::UniqueReceiverSet<mojom::AudioDecoder>::*AddFuncType)(
std::unique_ptr<mojom::AudioDecoder>,
mojo::PendingReceiver<mojom::AudioDecoder>,
scoped_refptr<base::SequencedTaskRunner>);
receivers_
.AsyncCall(base::IgnoreResult<AddFuncType>(
&mojo::UniqueReceiverSet<mojom::AudioDecoder>::Add))
.WithArgs(
std::make_unique<MojoAudioDecoderService>(
mojo_media_client_, mojo_cdm_service_context_, task_runner_),
std::move(receiver), task_runner_);
++receiver_count_;
}
bool IsEmpty() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return receiver_count_ == 0;
}
private:
void OnReceiverDisconnect() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
--receiver_count_;
disconnect_handler_.Run();
}
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::SequenceBound<mojo::UniqueReceiverSet<mojom::AudioDecoder>> receivers_;
const raw_ptr<MojoMediaClient> mojo_media_client_;
const raw_ptr<MojoCdmServiceContext> mojo_cdm_service_context_;
base::RepeatingClosure disconnect_handler_;
int receiver_count_ = 0;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<AudioDecoderReceivers> weak_factory_{this};
};
#endif
InterfaceFactoryImpl::InterfaceFactoryImpl(
mojo::PendingRemote<mojom::FrameInterfaceFactory> frame_interfaces,
MojoMediaClient* mojo_media_client)
: … { … }
InterfaceFactoryImpl::~InterfaceFactoryImpl() { … }
void InterfaceFactoryImpl::CreateAudioDecoder(
mojo::PendingReceiver<mojom::AudioDecoder> receiver) { … }
void InterfaceFactoryImpl::CreateVideoDecoder(
mojo::PendingReceiver<mojom::VideoDecoder> receiver,
mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>
dst_video_decoder) { … }
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void InterfaceFactoryImpl::CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) { … }
#endif
void InterfaceFactoryImpl::CreateAudioEncoder(
mojo::PendingReceiver<mojom::AudioEncoder> receiver) { … }
void InterfaceFactoryImpl::CreateDefaultRenderer(
const std::string& audio_device_id,
mojo::PendingReceiver<mojom::Renderer> receiver) { … }
#if BUILDFLAG(ENABLE_CAST_RENDERER)
void InterfaceFactoryImpl::CreateCastRenderer(
const base::UnguessableToken& overlay_plane_id,
mojo::PendingReceiver<media::mojom::Renderer> receiver) {
DVLOG(2) << __func__;
auto renderer = mojo_media_client_->CreateCastRenderer(
frame_interfaces_.get(),
base::SingleThreadTaskRunner::GetCurrentDefault(), &media_log_,
overlay_plane_id);
if (!renderer) {
DLOG(ERROR) << "Renderer creation failed.";
return;
}
AddRenderer(std::move(renderer), std::move(receiver));
}
#endif
#if BUILDFLAG(IS_ANDROID)
void InterfaceFactoryImpl::CreateMediaPlayerRenderer(
mojo::PendingRemote<mojom::MediaPlayerRendererClientExtension>
client_extension_ptr,
mojo::PendingReceiver<mojom::Renderer> receiver,
mojo::PendingReceiver<mojom::MediaPlayerRendererExtension>
renderer_extension_receiver) {
NOTREACHED_IN_MIGRATION();
}
void InterfaceFactoryImpl::CreateFlingingRenderer(
const std::string& audio_device_id,
mojo::PendingRemote<mojom::FlingingRendererClientExtension>
client_extension,
mojo::PendingReceiver<mojom::Renderer> receiver) {
NOTREACHED_IN_MIGRATION();
}
#endif
#if BUILDFLAG(IS_WIN)
void InterfaceFactoryImpl::CreateMediaFoundationRenderer(
mojo::PendingRemote<mojom::MediaLog> media_log_remote,
mojo::PendingReceiver<media::mojom::Renderer> receiver,
mojo::PendingReceiver<media::mojom::MediaFoundationRendererExtension>
renderer_extension_receiver,
mojo::PendingRemote<media::mojom::MediaFoundationRendererClientExtension>
client_extension_remote) {
DVLOG(2) << __func__;
auto renderer = mojo_media_client_->CreateMediaFoundationRenderer(
base::SingleThreadTaskRunner::GetCurrentDefault(),
frame_interfaces_.get(), std::move(media_log_remote),
std::move(renderer_extension_receiver),
std::move(client_extension_remote));
if (!renderer) {
DLOG(ERROR) << "MediaFoundationRenderer creation failed.";
return;
}
AddRenderer(std::move(renderer), std::move(receiver));
}
#endif
void InterfaceFactoryImpl::CreateCdm(const CdmConfig& cdm_config,
CreateCdmCallback callback) { … }
void InterfaceFactoryImpl::OnDestroyPending(base::OnceClosure destroy_cb) { … }
bool InterfaceFactoryImpl::IsEmpty() { … }
void InterfaceFactoryImpl::SetReceiverDisconnectHandler() { … }
void InterfaceFactoryImpl::OnReceiverDisconnect() { … }
#if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER) || \
BUILDFLAG(IS_WIN)
void InterfaceFactoryImpl::AddRenderer(
std::unique_ptr<media::Renderer> renderer,
mojo::PendingReceiver<mojom::Renderer> receiver) {
auto mojo_renderer_service = std::make_unique<MojoRendererService>(
&cdm_service_context_, std::move(renderer));
renderer_receivers_.Add(std::move(mojo_renderer_service),
std::move(receiver));
}
#endif
#if BUILDFLAG(ENABLE_MOJO_CDM)
CdmFactory* InterfaceFactoryImpl::GetCdmFactory() { … }
void InterfaceFactoryImpl::OnCdmServiceInitialized(
MojoCdmService* raw_mojo_cdm_service,
CreateCdmCallback callback,
mojom::CdmContextPtr cdm_context,
CreateCdmStatus status) { … }
#endif
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void InterfaceFactoryImpl::FinishCreatingVideoDecoder(
mojo::PendingReceiver<mojom::VideoDecoder> receiver,
mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>
dst_video_decoder) { … }
#endif
}