diff options
Diffstat (limited to 'cast/streaming')
-rw-r--r-- | cast/streaming/receiver_session.cc | 72 | ||||
-rw-r--r-- | cast/streaming/receiver_session.h | 45 | ||||
-rw-r--r-- | cast/streaming/sender_session.h | 5 |
3 files changed, 95 insertions, 27 deletions
diff --git a/cast/streaming/receiver_session.cc b/cast/streaming/receiver_session.cc index c2a06d01..9d267ada 100644 --- a/cast/streaming/receiver_session.cc +++ b/cast/streaming/receiver_session.cc @@ -74,6 +74,14 @@ MediaCapability ToCapability(VideoCodec codec) { ReceiverSession::Client::~Client() = default; +using RemotingPreferences = ReceiverSession::RemotingPreferences; + +RemotingPreferences::RemotingPreferences() = default; +RemotingPreferences::RemotingPreferences(RemotingPreferences&&) noexcept = + default; +RemotingPreferences& RemotingPreferences::operator=( + RemotingPreferences&&) noexcept = default; + using Preferences = ReceiverSession::Preferences; Preferences::Preferences() = default; @@ -172,25 +180,17 @@ void ReceiverSession::OnOffer(SenderMessage message) { auto properties = std::make_unique<SessionProperties>(); properties->sequence_number = message.sequence_number; - // TODO(issuetracker.google.com/184186390): ReceiverSession needs to support - // fielding remoting offers. const Offer& offer = absl::get<Offer>(message.body); if (offer.cast_mode == CastMode::kRemoting) { - SendErrorAnswerReply(message.sequence_number, - "Remoting support is not complete in libcast"); - return; - } - - if (!offer.audio_streams.empty() && !preferences_.audio_codecs.empty()) { - properties->selected_audio = - SelectStream(preferences_.audio_codecs, offer.audio_streams); - } - - if (!offer.video_streams.empty() && !preferences_.video_codecs.empty()) { - properties->selected_video = - SelectStream(preferences_.video_codecs, offer.video_streams); + if (!preferences_.remoting) { + SendErrorAnswerReply(message.sequence_number, + "This receiver does not have remoting enabled."); + return; + } } + properties->mode = offer.cast_mode; + SelectStreams(offer, properties.get()); if (!properties->IsValid()) { SendErrorAnswerReply(message.sequence_number, "Failed to select any streams from OFFER"); @@ -243,6 +243,31 @@ void ReceiverSession::OnCapabilitiesRequest(SenderMessage message) { } } +void ReceiverSession::SelectStreams(const Offer& offer, + SessionProperties* properties) { + if (offer.cast_mode == CastMode::kMirroring) { + if (!offer.audio_streams.empty() && !preferences_.audio_codecs.empty()) { + properties->selected_audio = + SelectStream(preferences_.audio_codecs, offer.audio_streams); + } + if (!offer.video_streams.empty() && !preferences_.video_codecs.empty()) { + properties->selected_video = + SelectStream(preferences_.video_codecs, offer.video_streams); + } + } else { + OSP_DCHECK(offer.cast_mode == CastMode::kRemoting); + + if (offer.audio_streams.size() == 1) { + properties->selected_audio = + std::make_unique<AudioStream>(offer.audio_streams[0]); + } + if (offer.video_streams.size() == 1) { + properties->selected_video = + std::make_unique<VideoStream>(offer.video_streams[0]); + } + } +} + void ReceiverSession::InitializeSession(const SessionProperties& properties) { Answer answer = ConstructAnswer(properties); if (!answer.IsValid()) { @@ -255,7 +280,22 @@ void ReceiverSession::InitializeSession(const SessionProperties& properties) { // Only spawn receivers if we know we have a valid answer message. ConfiguredReceivers receivers = SpawnReceivers(properties); - client_->OnNegotiated(this, std::move(receivers)); + if (properties.mode == CastMode::kMirroring) { + client_->OnNegotiated(this, std::move(receivers)); + } else { + // TODO(jophba): cleanup sequence number usage. + broker_ = std::make_unique<RpcBroker>([this](std::vector<uint8_t> message) { + Error error = this->messenger_.SendMessage( + ReceiverMessage{ReceiverMessage::Type::kRpc, -1, true /* valid */, + std::move(message)}); + + if (!error.ok()) { + OSP_LOG_WARN << "Failed to send RPC message: " << error; + } + }); + client_->OnRemotingNegotiated( + this, RemotingNegotiation{std::move(receivers), broker_.get()}); + } const Error result = messenger_.SendMessage(ReceiverMessage{ ReceiverMessage::Type::kAnswer, properties.sequence_number, true /* valid */, std::move(answer)}); diff --git a/cast/streaming/receiver_session.h b/cast/streaming/receiver_session.h index 3c341279..0f9f00cf 100644 --- a/cast/streaming/receiver_session.h +++ b/cast/streaming/receiver_session.h @@ -16,6 +16,7 @@ #include "cast/streaming/offer_messages.h" #include "cast/streaming/receiver_packet_router.h" #include "cast/streaming/resolution.h" +#include "cast/streaming/rpc_broker.h" #include "cast/streaming/sender_message.h" #include "cast/streaming/session_config.h" #include "cast/streaming/session_messenger.h" @@ -26,9 +27,9 @@ namespace cast { class Environment; class Receiver; -// This class is responsible for listening for streaming (both mirroring and -// remoting) requests from Cast Sender devices, then negotiating capture -// constraints and instantiating audio and video Receiver objects. +// This class is responsible for listening for streaming requests from Cast +// Sender devices, then negotiating capture constraints and instantiating audio +// and video Receiver objects. // The owner of this session is expected to provide a client for // updates, an environment for getting UDP socket information (as well as // other OS dependencies), and a set of preferences to be used for @@ -62,17 +63,33 @@ class ReceiverSession final : public Environment::SocketSubscriber { VideoCaptureConfig video_config; }; + // This struct contains all of the information necessary to begin remoting + // once we get a remoting request from a Sender. + struct RemotingNegotiation { + ConfiguredReceivers receivers; + + // The RPC broker to be used for subscribing to remoting proto messages. + RpcBroker* broker; + }; + // The embedder should provide a client for handling connections. // When a connection is established, the OnNegotiated callback is called. class Client { public: enum ReceiversDestroyingReason { kEndOfSession, kRenegotiated }; - // Called when a new set of receivers has been negotiated. This may be - // called multiple times during a session, as renegotiations occur. + // Called when a set of streaming receivers has been negotiated. Both this + // and |OnRemotingNegotiated| may be called repeatedly as negotiations occur + // through the life of a session. virtual void OnNegotiated(const ReceiverSession* session, ConfiguredReceivers receivers) = 0; + // Called when a set of remoting receivers has been negotiated. This will + // only be called if |RemotingPreferences| are provided as part of + // constructing the ReceiverSession object. + virtual void OnRemotingNegotiated(const ReceiverSession* session, + RemotingNegotiation negotiation) {} + // Called immediately preceding the destruction of this session's receivers. // If |reason| is |kEndOfSession|, OnNegotiated() will never be called // again; if it is |kRenegotiated|, OnNegotiated() will be called again @@ -92,7 +109,7 @@ class ReceiverSession final : public Environment::SocketSubscriber { // Information about the display the receiver is attached to. struct Display { // The display limitations of the actual screen, used to provide upper - // bounds on mirroring and remoting streams. For example, we will never + // bounds on streams. For example, we will never // send 60FPS if it is going to be displayed on a 30FPS screen. // Note that we may exceed the display width and height for standard // content sizes like 720p or 1080p. @@ -166,6 +183,12 @@ class ReceiverSession final : public Environment::SocketSubscriber { // TODO(issuetracker.google.com/184429130): the mirroring control // protocol needs to be updated to allow more discrete support. struct RemotingPreferences { + RemotingPreferences(); + RemotingPreferences(RemotingPreferences&&) noexcept; + RemotingPreferences(const RemotingPreferences&) = delete; + RemotingPreferences& operator=(RemotingPreferences&&) noexcept; + RemotingPreferences& operator=(const RemotingPreferences&) = delete; + // Current remoting senders take an "all or nothing" support for audio // codec support. While Opus and AAC support is handled in our Preferences' // |audio_codecs| property, support for the following codecs must be @@ -219,7 +242,7 @@ class ReceiverSession final : public Environment::SocketSubscriber { // Libcast remoting support is opt-in: embedders wishing to field remoting // offers may provide a set of remoting preferences, or leave nullptr for - // all remoting OFFERs to be rejected in favor of continuing mirroring. + // all remoting OFFERs to be rejected in favor of continuing streaming. std::unique_ptr<RemotingPreferences> remoting; }; @@ -263,6 +286,10 @@ class ReceiverSession final : public Environment::SocketSubscriber { void OnOffer(SenderMessage message); void OnCapabilitiesRequest(SenderMessage message); + // Selects streams from an offer based on its configuration, and sets + // them in the session properties. + void SelectStreams(const Offer& offer, SessionProperties* properties); + // Creates receivers and sends an appropriate Answer message using the // session properties. void InitializeSession(const SessionProperties& properties); @@ -307,6 +334,10 @@ class ReceiverSession final : public Environment::SocketSubscriber { // through |Client::OnReceiversDestroying|. std::unique_ptr<Receiver> current_audio_receiver_; std::unique_ptr<Receiver> current_video_receiver_; + + // If remoting, we store the RpcBroker used by the embedder to send RPC + // messages from the remoting protobuf specification. + std::unique_ptr<RpcBroker> broker_; }; } // namespace cast diff --git a/cast/streaming/sender_session.h b/cast/streaming/sender_session.h index 7702b490..d95c61aa 100644 --- a/cast/streaming/sender_session.h +++ b/cast/streaming/sender_session.h @@ -50,8 +50,6 @@ class SenderSession final { // This struct contains all of the information necessary to begin remoting // after we receive the capabilities from the receiver. - // TODO(issuetracker.google.com/184189241): capture recommendations should be - // exposed as part of the remoting negotiation. struct RemotingNegotiation { ConfiguredSenders senders; @@ -258,8 +256,7 @@ class SenderSession final { std::unique_ptr<Sender> current_video_sender_; // If remoting, we store the RpcBroker used by the embedder to send RPC - // messages from the remoting protobuf specification. For more information, - // see //cast/streaming/remoting.proto. + // messages from the remoting protobuf specification. std::unique_ptr<RpcBroker> broker_; }; // namespace cast |