aboutsummaryrefslogtreecommitdiff
path: root/cast/streaming
diff options
context:
space:
mode:
Diffstat (limited to 'cast/streaming')
-rw-r--r--cast/streaming/receiver_session.cc72
-rw-r--r--cast/streaming/receiver_session.h45
-rw-r--r--cast/streaming/sender_session.h5
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