blob: 21eeac5a91f76783d928de78db8ac903fdf39217 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_MIRRORING_SERVICE_MEDIA_REMOTER_H_
#define COMPONENTS_MIRRORING_SERVICE_MEDIA_REMOTER_H_
#include <optional>
#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "media/cast/cast_config.h"
#include "media/mojo/mojom/remoting.mojom.h"
#include "media/mojo/mojom/remoting_common.mojom.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "third_party/openscreen/src/cast/streaming/public/sender.h"
namespace media::cast {
class CastEnvironment;
} // namespace media::cast
namespace mirroring {
class RpcDispatcher;
class RemotingSender;
// MediaRemoter remotes media content directly to a Cast Receiver. When
// MediaRemoter is started, it connects itself with a source tab in browser
// through the Mirroring Service mojo interface and allows the browser to access
// this MediaRemoter to start/stop individual remoting sessions, which are
// caused by user actions (i.e., when they somehow indicate a desire to
// enter/leave an immersive video-watching mode).
//
// When a remoting session is started, MediaRemoter will first request that tab
// mirroring be switched into content remoting mode. If granted, it will notify
// the browser that this has succeeded. At this point, two-way RPC binary
// messaging begins, and the MediaRemoter simply forwards messages between the
// browser and the Cast Receiver. The audio/video data streams are delivered
// from the media renderer to the Mirroring Service through mojo datapipes, and
// are then sent out to Cast Receiver through Cast Streaming.
class COMPONENT_EXPORT(MIRRORING_SERVICE) MediaRemoter final
: public media::mojom::Remoter {
public:
class Client {
public:
virtual ~Client() = default;
// Connects the |remoter| with a source tab.
virtual void ConnectToRemotingSource(
mojo::PendingRemote<media::mojom::Remoter> remoter,
mojo::PendingReceiver<media::mojom::RemotingSource>
source_receiver) = 0;
// Requests to start remoting. StartRpcMessaging() / OnRemotingStartFailed()
// will be called when starting succeeds / fails.
virtual void RequestRemotingStreaming() = 0;
// Requests to resume mirroring.
virtual void RestartMirroringStreaming() = 0;
};
MediaRemoter(Client& client,
const media::mojom::RemotingSinkMetadata& sink_metadata,
RpcDispatcher& message_dispatcher);
MediaRemoter(const MediaRemoter&) = delete;
MediaRemoter& operator=(const MediaRemoter&) = delete;
~MediaRemoter() override;
// Callback from |message_dispatcher_| for received RPC messages.
void OnMessageFromSink(const std::vector<uint8_t>& response);
// Called when OFFER/ANSWER exchange for a remoting session succeeds.
// New way using openscreen::cast::Sender objects.
// NOTE: either `audio_sender` or `video_sender` must not be nullptr,
// and must either outlive `this` or live until `Stop` is called. If
// either is nullptr, the associated config should be default constructed as
// it is ignored.
void StartRpcMessaging(
scoped_refptr<media::cast::CastEnvironment> cast_environment,
std::unique_ptr<openscreen::cast::Sender> audio_sender,
std::unique_ptr<openscreen::cast::Sender> video_sender,
std::optional<media::cast::FrameSenderConfig> audio_config,
std::optional<media::cast::FrameSenderConfig> video_config);
// Called when a mirroring session is successfully resumed.
void OnMirroringResumed(bool is_tab_switching = false);
// Error occurred either during the start of remoting or in the middle of
// remoting. In either case, this call fallbacks to mirroring, and prevents
// further starting of media remoting during this mirroring session.
void OnRemotingFailed();
// media::mojom::Remoter implementation.
// Stops the current remoting session with a given |reason|.
void Stop(media::mojom::RemotingStopReason reason) override;
private:
// media::mojom::Remoter implementation.
void Start() override;
void StartWithPermissionAlreadyGranted() override;
void StartDataStreams(
mojo::ScopedDataPipeConsumerHandle audio_pipe,
mojo::ScopedDataPipeConsumerHandle video_pipe,
mojo::PendingReceiver<media::mojom::RemotingDataStreamSender>
audio_sender_receiver,
mojo::PendingReceiver<media::mojom::RemotingDataStreamSender>
video_sender_receiver) override;
void SendMessageToSink(const std::vector<uint8_t>& message) override;
void EstimateTransmissionCapacity(
media::mojom::Remoter::EstimateTransmissionCapacityCallback callback)
override;
// Called by the public |StartRpcMessaging| methods.
void StartRpcMessagingInternal(
scoped_refptr<media::cast::CastEnvironment> cast_environment,
std::optional<media::cast::FrameSenderConfig> audio_config,
std::optional<media::cast::FrameSenderConfig> video_config);
// Called by RemotingSender when error occurred. Will stop this remoting
// session and fallback to mirroring.
void OnRemotingDataStreamError();
raw_ref<Client> client_;
const media::mojom::RemotingSinkMetadata sink_metadata_;
raw_ref<RpcDispatcher> rpc_dispatcher_;
mojo::Receiver<media::mojom::Remoter> receiver_{this};
mojo::Remote<media::mojom::RemotingSource> remoting_source_;
scoped_refptr<media::cast::CastEnvironment> cast_environment_;
std::unique_ptr<RemotingSender> audio_sender_;
std::unique_ptr<RemotingSender> video_sender_;
// Used only if StartRpcMessaging is called with openscreen::cast::Sender
// objects.
std::unique_ptr<openscreen::cast::Sender> openscreen_audio_sender_;
std::unique_ptr<openscreen::cast::Sender> openscreen_video_sender_;
std::optional<media::cast::FrameSenderConfig> audio_config_;
std::optional<media::cast::FrameSenderConfig> video_config_;
// State transition diagram:
//
// .-----------> MIRRORING
// | |
// | V
// | STARTING_REMOTING
// | |
// | V
// | .-----------------------------.
// | | | |
// | | V V
// | | REMOTING_STARTED ----> REMOTING_DISABLED
// | | |
// | V V
// .--STOPPING_REMOTING
enum {
MIRRORING, // In mirroring.
STARTING_REMOTING, // Starting a remoting session.
REMOTING_STARTED, // Remoting started successfully.
REMOTING_DISABLED, // Remoting was disabled (because of error).
STOPPING_REMOTING, // Stopping the remoting session.
} state_;
base::WeakPtrFactory<MediaRemoter> weak_factory_{this};
};
} // namespace mirroring
#endif // COMPONENTS_MIRRORING_SERVICE_MEDIA_REMOTER_H_