#ifndef COMPONENTS_CAST_STREAMING_RENDERER_COMMON_BUFFER_REQUESTER_H_
#define COMPONENTS_CAST_STREAMING_RENDERER_COMMON_BUFFER_REQUESTER_H_
#include <memory>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "components/cast_streaming/common/frame/demuxer_stream_traits.h"
#include "components/cast_streaming/common/public/mojom/demuxer_connector.mojom.h"
#include "components/cast_streaming/renderer/common/decoder_buffer_provider_impl.h"
#include "components/cast_streaming/renderer/public/decoder_buffer_provider.h"
#include "media/mojo/mojom/media_types.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
namespace cast_streaming {
template <typename TMojoRemoteType>
class BufferRequester;
using AudioBufferRequester = BufferRequester<mojom::AudioBufferRequester>;
using VideoBufferRequester = BufferRequester<mojom::VideoBufferRequester>;
template <typename TMojoRemoteType>
class BufferRequester
: public DemuxerStreamTraits<TMojoRemoteType>,
public DecoderBufferProviderImpl<
typename DemuxerStreamTraits<TMojoRemoteType>::ConfigType>::Client {
public:
using Traits = DemuxerStreamTraits<TMojoRemoteType>;
using ConfigType = typename Traits::ConfigType;
class Client {
public:
virtual ~Client() = default;
virtual void OnNewBufferProvider(
base::WeakPtr<DecoderBufferProvider<ConfigType>> ptr) = 0;
virtual void OnMojoDisconnect() = 0;
};
BufferRequester(Client* client,
ConfigType config,
mojo::ScopedDataPipeConsumerHandle data_pipe,
mojo::PendingRemote<TMojoRemoteType> pending_remote,
scoped_refptr<base::SequencedTaskRunner> task_runner)
: client_(client),
task_runner_(std::move(task_runner)),
remote_(std::move(pending_remote)),
weak_factory_(this) {
DCHECK(client_);
DCHECK(task_runner_);
remote_.set_disconnect_handler(
base::BindOnce(&Client::OnMojoDisconnect, base::Unretained(client)));
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&BufferRequester<TMojoRemoteType>::OnNewConfig,
weak_factory_.GetWeakPtr(), std::move(config),
std::move(data_pipe)));
}
~BufferRequester() override = default;
using BufferProviderRequestCB =
typename DecoderBufferProviderImpl<typename DemuxerStreamTraits<
TMojoRemoteType>::ConfigType>::Client::BufferProviderRequestCB;
void RequestBufferAsync(BufferProviderRequestCB on_buffer_received) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!buffer_request_cb_);
buffer_request_cb_ = std::move(on_buffer_received);
remote_->GetBuffer(base::BindOnce(&BufferRequester::OnGetBufferDone,
weak_factory_.GetWeakPtr()));
}
void EnableBitstreamConverterAsync(base::OnceCallback<void(bool)> callback) {
remote_->EnableBitstreamConverter(std::move(callback));
}
private:
void OnGetBufferDone(
typename Traits::GetBufferResponseType get_buffer_response) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(buffer_provider_);
DCHECK(buffer_request_cb_);
if (!get_buffer_response) {
std::move(buffer_request_cb_).Run(nullptr);
return;
}
if (get_buffer_response->is_stream_info()) {
buffer_request_cb_ = BufferProviderRequestCB{};
typename Traits::StreamInfoType& data_stream_info =
get_buffer_response->get_stream_info();
OnNewConfig(std::move(data_stream_info->decoder_config),
std::move(data_stream_info->data_pipe));
} else {
DCHECK(get_buffer_response->is_buffer());
std::move(buffer_request_cb_)
.Run(std::move(get_buffer_response->get_buffer()));
}
}
void OnNewConfig(ConfigType config,
mojo::ScopedDataPipeConsumerHandle data_pipe) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
buffer_provider_ = std::make_unique<DecoderBufferProviderImpl<ConfigType>>(
std::move(config), std::move(data_pipe), this, task_runner_);
client_->OnNewBufferProvider(buffer_provider_->GetWeakPtr());
}
std::unique_ptr<DecoderBufferProviderImpl<ConfigType>> buffer_provider_;
BufferProviderRequestCB buffer_request_cb_;
const raw_ptr<Client> client_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
mojo::Remote<TMojoRemoteType> remote_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<BufferRequester<TMojoRemoteType>> weak_factory_;
};
}
#endif