#ifndef COMPONENTS_CAST_STREAMING_BROWSER_CAST_STREAMING_SESSION_H_
#define COMPONENTS_CAST_STREAMING_BROWSER_CAST_STREAMING_SESSION_H_
#include <memory>
#include <optional>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/timer/timer.h"
#include "components/cast_streaming/browser/control/playback_command_dispatcher.h"
#include "components/cast_streaming/browser/control/remoting/remoting_session_client.h"
#include "components/cast_streaming/browser/control/renderer_controller_config.h"
#include "components/cast_streaming/browser/frame/demuxer_stream_data_provider.h"
#include "components/cast_streaming/browser/public/receiver_config.h"
#include "components/cast_streaming/browser/public/receiver_session.h"
#include "components/openscreen_platform/network_util.h"
#include "components/openscreen_platform/task_runner.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/video_decoder_config.h"
#include "media/mojo/mojom/media_types.mojom.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "third_party/openscreen/src/cast/streaming/public/receiver.h"
#include "third_party/openscreen/src/cast/streaming/public/receiver_constraints.h"
#include "third_party/openscreen/src/cast/streaming/public/receiver_session.h"
namespace cast_streaming {
class StreamConsumer;
class CastMessagePortConverter;
class CastStreamingSession {
public:
class Client {
public:
virtual void OnSessionInitialization(
StreamingInitializationInfo initialization_info,
std::optional<mojo::ScopedDataPipeConsumerHandle> audio_pipe_consumer,
std::optional<mojo::ScopedDataPipeConsumerHandle>
video_pipe_consumer) = 0;
virtual void OnAudioBufferReceived(
media::mojom::DecoderBufferPtr buffer) = 0;
virtual void OnVideoBufferReceived(
media::mojom::DecoderBufferPtr buffer) = 0;
virtual void OnSessionReinitializationPending() = 0;
virtual void OnSessionReinitialization(
StreamingInitializationInfo initialization_info,
std::optional<mojo::ScopedDataPipeConsumerHandle> audio_pipe_consumer,
std::optional<mojo::ScopedDataPipeConsumerHandle>
video_pipe_consumer) = 0;
virtual void OnSessionEnded() = 0;
protected:
virtual ~Client();
};
CastStreamingSession();
~CastStreamingSession();
CastStreamingSession(const CastStreamingSession&) = delete;
CastStreamingSession& operator=(const CastStreamingSession&) = delete;
void Start(Client* client,
std::optional<RendererControllerConfig> renderer_controls,
ReceiverConfig av_constraints,
ReceiverSession::MessagePortProvider message_port_provider,
scoped_refptr<base::SequencedTaskRunner> task_runner);
void Stop();
bool is_running() const { return !!receiver_session_; }
AudioDemuxerStreamDataProvider::RequestBufferCB GetAudioBufferRequester();
VideoDemuxerStreamDataProvider::RequestBufferCB GetVideoBufferRequester();
using PreloadBufferCB =
base::OnceCallback<void(media::mojom::DecoderBufferPtr)>;
PreloadBufferCB GetAudioBufferPreloader();
PreloadBufferCB GetVideoBufferPreloader();
private:
class ReceiverSessionClient final
: public openscreen::cast::ReceiverSession::Client,
public remoting::RemotingSessionClient::Dispatcher {
public:
ReceiverSessionClient(
CastStreamingSession::Client* client,
std::optional<RendererControllerConfig> renderer_controls,
ReceiverConfig av_constraints,
ReceiverSession::MessagePortProvider message_port_provider,
scoped_refptr<base::SequencedTaskRunner> task_runner);
~ReceiverSessionClient() override;
ReceiverSessionClient(const ReceiverSessionClient&) = delete;
ReceiverSessionClient& operator=(const ReceiverSessionClient&) = delete;
void GetAudioBuffer(base::OnceClosure no_frames_available_cb);
void GetVideoBuffer(base::OnceClosure no_frames_available_cb);
void PreloadAudioBuffer(media::mojom::DecoderBufferPtr buffer);
void PreloadVideoBuffer(media::mojom::DecoderBufferPtr buffer);
base::WeakPtr<ReceiverSessionClient> GetWeakPtr();
private:
bool ongoing_session_has_audio() const { return !!audio_consumer_; }
bool ongoing_session_has_video() const { return !!video_consumer_; }
void OnInitializationTimeout();
std::optional<mojo::ScopedDataPipeConsumerHandle> InitializeAudioConsumer(
const StreamingInitializationInfo& initialization_info);
std::optional<mojo::ScopedDataPipeConsumerHandle> InitializeVideoConsumer(
const StreamingInitializationInfo& initialization_info);
void OnFlushComplete();
void OnFlushUntil(uint32_t audio_count, uint32_t video_count);
void StartStreamingSession(
StreamingInitializationInfo initialization_info) override;
void OnNegotiated(const openscreen::cast::ReceiverSession* session,
openscreen::cast::ReceiverSession::ConfiguredReceivers
receivers) override;
void OnRemotingNegotiated(
const openscreen::cast::ReceiverSession* session,
openscreen::cast::ReceiverSession::RemotingNegotiation negotiation)
override;
void OnReceiversDestroying(const openscreen::cast::ReceiverSession* session,
ReceiversDestroyingReason reason) override;
void OnError(const openscreen::cast::ReceiverSession* session,
const openscreen::Error& error) override;
void OnDataTimeout();
void OnCastChannelClosed();
void EndSession();
openscreen_platform::TaskRunner task_runner_;
openscreen::cast::Environment environment_;
std::unique_ptr<CastMessagePortConverter> cast_message_port_converter_;
std::unique_ptr<openscreen::cast::ReceiverSession> receiver_session_;
base::OneShotTimer init_timeout_timer_;
std::unique_ptr<PlaybackCommandDispatcher> playback_command_dispatcher_;
base::OneShotTimer data_timeout_timer_;
bool is_flush_pending_ = false;
base::OnceCallback<void()> start_session_cb_;
bool is_initialized_ = false;
raw_ptr<CastStreamingSession::Client> client_;
std::unique_ptr<StreamConsumer> audio_consumer_;
std::unique_ptr<StreamConsumer> video_consumer_;
std::optional<media::mojom::DecoderBufferPtr> preloaded_audio_buffer_ =
std::nullopt;
std::optional<media::mojom::DecoderBufferPtr> preloaded_video_buffer_ =
std::nullopt;
base::WeakPtrFactory<ReceiverSessionClient> weak_factory_;
};
std::unique_ptr<ReceiverSessionClient> receiver_session_;
};
}
#endif