xref: /aosp_15_r20/external/openscreen/cast/streaming/sender_session.h (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2020 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #ifndef CAST_STREAMING_SENDER_SESSION_H_
6*3f982cf4SFabien Sanglard #define CAST_STREAMING_SENDER_SESSION_H_
7*3f982cf4SFabien Sanglard 
8*3f982cf4SFabien Sanglard #include <memory>
9*3f982cf4SFabien Sanglard #include <string>
10*3f982cf4SFabien Sanglard #include <utility>
11*3f982cf4SFabien Sanglard #include <vector>
12*3f982cf4SFabien Sanglard 
13*3f982cf4SFabien Sanglard #include "cast/common/public/message_port.h"
14*3f982cf4SFabien Sanglard #include "cast/streaming/answer_messages.h"
15*3f982cf4SFabien Sanglard #include "cast/streaming/capture_configs.h"
16*3f982cf4SFabien Sanglard #include "cast/streaming/capture_recommendations.h"
17*3f982cf4SFabien Sanglard #include "cast/streaming/offer_messages.h"
18*3f982cf4SFabien Sanglard #include "cast/streaming/remoting_capabilities.h"
19*3f982cf4SFabien Sanglard #include "cast/streaming/rpc_messenger.h"
20*3f982cf4SFabien Sanglard #include "cast/streaming/sender.h"
21*3f982cf4SFabien Sanglard #include "cast/streaming/sender_packet_router.h"
22*3f982cf4SFabien Sanglard #include "cast/streaming/session_config.h"
23*3f982cf4SFabien Sanglard #include "cast/streaming/session_messenger.h"
24*3f982cf4SFabien Sanglard #include "json/value.h"
25*3f982cf4SFabien Sanglard #include "util/json/json_serialization.h"
26*3f982cf4SFabien Sanglard 
27*3f982cf4SFabien Sanglard namespace openscreen {
28*3f982cf4SFabien Sanglard namespace cast {
29*3f982cf4SFabien Sanglard 
30*3f982cf4SFabien Sanglard class Environment;
31*3f982cf4SFabien Sanglard class Sender;
32*3f982cf4SFabien Sanglard 
33*3f982cf4SFabien Sanglard class SenderSession final {
34*3f982cf4SFabien Sanglard  public:
35*3f982cf4SFabien Sanglard   // Upon successful negotiation, a set of configured senders is constructed
36*3f982cf4SFabien Sanglard   // for handling audio and video. Note that either sender may be null.
37*3f982cf4SFabien Sanglard   struct ConfiguredSenders {
38*3f982cf4SFabien Sanglard     // In practice, we may have 0, 1, or 2 senders configured, depending
39*3f982cf4SFabien Sanglard     // on if the device supports audio and video, and if we were able to
40*3f982cf4SFabien Sanglard     // successfully negotiate a sender configuration.
41*3f982cf4SFabien Sanglard 
42*3f982cf4SFabien Sanglard     // If the sender is audio- or video-only, either of the senders
43*3f982cf4SFabien Sanglard     // may be nullptr. However, in the majority of cases they will be populated.
44*3f982cf4SFabien Sanglard     Sender* audio_sender = nullptr;
45*3f982cf4SFabien Sanglard     AudioCaptureConfig audio_config;
46*3f982cf4SFabien Sanglard 
47*3f982cf4SFabien Sanglard     Sender* video_sender = nullptr;
48*3f982cf4SFabien Sanglard     VideoCaptureConfig video_config;
49*3f982cf4SFabien Sanglard   };
50*3f982cf4SFabien Sanglard 
51*3f982cf4SFabien Sanglard   // This struct contains all of the information necessary to begin remoting
52*3f982cf4SFabien Sanglard   // after we receive the capabilities from the receiver.
53*3f982cf4SFabien Sanglard   struct RemotingNegotiation {
54*3f982cf4SFabien Sanglard     ConfiguredSenders senders;
55*3f982cf4SFabien Sanglard 
56*3f982cf4SFabien Sanglard     // The capabilities reported by the connected receiver. NOTE: SenderSession
57*3f982cf4SFabien Sanglard     // reports the capabilities as-is from the Receiver, so clients concerned
58*3f982cf4SFabien Sanglard     // about legacy devices, such as pre-1.27 Earth receivers should do
59*3f982cf4SFabien Sanglard     // a version check when using these capabilities to offer remoting.
60*3f982cf4SFabien Sanglard     RemotingCapabilities capabilities;
61*3f982cf4SFabien Sanglard   };
62*3f982cf4SFabien Sanglard 
63*3f982cf4SFabien Sanglard   // The embedder should provide a client for handling negotiation events.
64*3f982cf4SFabien Sanglard   // The client is required to implement a mirorring handler, and may choose
65*3f982cf4SFabien Sanglard   // to provide a remoting negotiation if it supports remoting.
66*3f982cf4SFabien Sanglard   // When the negotiation is complete, the appropriate |On*Negotiated| handler
67*3f982cf4SFabien Sanglard   // is called.
68*3f982cf4SFabien Sanglard   class Client {
69*3f982cf4SFabien Sanglard    public:
70*3f982cf4SFabien Sanglard     // Called when a new set of senders has been negotiated. This may be
71*3f982cf4SFabien Sanglard     // called multiple times during a session, once for every time Negotiate()
72*3f982cf4SFabien Sanglard     // is called on the SenderSession object. The negotiation call also includes
73*3f982cf4SFabien Sanglard     // capture recommendations that can be used by the sender to provide
74*3f982cf4SFabien Sanglard     // an optimal video stream for the receiver.
75*3f982cf4SFabien Sanglard     virtual void OnNegotiated(
76*3f982cf4SFabien Sanglard         const SenderSession* session,
77*3f982cf4SFabien Sanglard         ConfiguredSenders senders,
78*3f982cf4SFabien Sanglard         capture_recommendations::Recommendations capture_recommendations) = 0;
79*3f982cf4SFabien Sanglard 
80*3f982cf4SFabien Sanglard     // Called when a new set of remoting senders has been negotiated. Since
81*3f982cf4SFabien Sanglard     // remoting is an optional feature, the default behavior here is to leave
82*3f982cf4SFabien Sanglard     // this method unhandled.
OnRemotingNegotiated(const SenderSession * session,RemotingNegotiation negotiation)83*3f982cf4SFabien Sanglard     virtual void OnRemotingNegotiated(const SenderSession* session,
84*3f982cf4SFabien Sanglard                                       RemotingNegotiation negotiation) {}
85*3f982cf4SFabien Sanglard 
86*3f982cf4SFabien Sanglard     // Called whenever an error occurs. Ends the ongoing session, and the caller
87*3f982cf4SFabien Sanglard     // must call Negotiate() again if they wish to re-establish streaming.
88*3f982cf4SFabien Sanglard     virtual void OnError(const SenderSession* session, Error error) = 0;
89*3f982cf4SFabien Sanglard 
90*3f982cf4SFabien Sanglard    protected:
91*3f982cf4SFabien Sanglard     virtual ~Client();
92*3f982cf4SFabien Sanglard   };
93*3f982cf4SFabien Sanglard 
94*3f982cf4SFabien Sanglard   // The configuration information required to set up the session.
95*3f982cf4SFabien Sanglard   struct Configuration {
96*3f982cf4SFabien Sanglard     // The remote address of the receiver to connect to. NOTE: we do eventually
97*3f982cf4SFabien Sanglard     // set the remote endpoint on the |environment| object, but only after
98*3f982cf4SFabien Sanglard     // getting the port information from a successful ANSWER message.
99*3f982cf4SFabien Sanglard     IPAddress remote_address;
100*3f982cf4SFabien Sanglard 
101*3f982cf4SFabien Sanglard     // The client for notifying of successful negotiations and errors. Required.
102*3f982cf4SFabien Sanglard     Client* const client;
103*3f982cf4SFabien Sanglard 
104*3f982cf4SFabien Sanglard     // The cast environment used to access operating system resources, such
105*3f982cf4SFabien Sanglard     // as the UDP socket for RTP/RTCP messaging. Required.
106*3f982cf4SFabien Sanglard     Environment* environment;
107*3f982cf4SFabien Sanglard 
108*3f982cf4SFabien Sanglard     // The message port used to send streaming control protocol messages.
109*3f982cf4SFabien Sanglard     MessagePort* message_port;
110*3f982cf4SFabien Sanglard 
111*3f982cf4SFabien Sanglard     // The message source identifier (e.g. this sender).
112*3f982cf4SFabien Sanglard     std::string message_source_id;
113*3f982cf4SFabien Sanglard 
114*3f982cf4SFabien Sanglard     // The message destination identifier (e.g. the receiver we are connected
115*3f982cf4SFabien Sanglard     // to).
116*3f982cf4SFabien Sanglard     std::string message_destination_id;
117*3f982cf4SFabien Sanglard 
118*3f982cf4SFabien Sanglard     // Whether or not the android RTP value hack should be used (for legacy
119*3f982cf4SFabien Sanglard     // android devices). For more information, see https://crbug.com/631828.
120*3f982cf4SFabien Sanglard     bool use_android_rtp_hack = true;
121*3f982cf4SFabien Sanglard   };
122*3f982cf4SFabien Sanglard 
123*3f982cf4SFabien Sanglard   // The SenderSession assumes that the passed in client, environment, and
124*3f982cf4SFabien Sanglard   // message port persist for at least the lifetime of the SenderSession. If
125*3f982cf4SFabien Sanglard   // one of these classes needs to be reset, a new SenderSession should be
126*3f982cf4SFabien Sanglard   // created.
127*3f982cf4SFabien Sanglard   //
128*3f982cf4SFabien Sanglard   // |message_source_id| and |message_destination_id| are the local and remote
129*3f982cf4SFabien Sanglard   // ID, respectively, to use when sending or receiving control messages (e.g.,
130*3f982cf4SFabien Sanglard   // OFFERs or ANSWERs) over the |message_port|. |message_port|'s SetClient()
131*3f982cf4SFabien Sanglard   // method will be called.
132*3f982cf4SFabien Sanglard   explicit SenderSession(Configuration config);
133*3f982cf4SFabien Sanglard   SenderSession(const SenderSession&) = delete;
134*3f982cf4SFabien Sanglard   SenderSession(SenderSession&&) noexcept = delete;
135*3f982cf4SFabien Sanglard   SenderSession& operator=(const SenderSession&) = delete;
136*3f982cf4SFabien Sanglard   SenderSession& operator=(SenderSession&&) = delete;
137*3f982cf4SFabien Sanglard   ~SenderSession();
138*3f982cf4SFabien Sanglard 
139*3f982cf4SFabien Sanglard   // Starts a mirroring OFFER/ANSWER exchange with the already configured
140*3f982cf4SFabien Sanglard   // receiver over the message port. The caller should assume any configured
141*3f982cf4SFabien Sanglard   // senders become invalid when calling this method.
142*3f982cf4SFabien Sanglard   Error Negotiate(std::vector<AudioCaptureConfig> audio_configs,
143*3f982cf4SFabien Sanglard                   std::vector<VideoCaptureConfig> video_configs);
144*3f982cf4SFabien Sanglard 
145*3f982cf4SFabien Sanglard   // Remoting negotiation is actually very similar to mirroring negotiation--
146*3f982cf4SFabien Sanglard   // an OFFER/ANSWER exchange still occurs, however only one audio and video
147*3f982cf4SFabien Sanglard   // codec should be presented based on the encoding of the media element that
148*3f982cf4SFabien Sanglard   // should be remoted. Note: the codec fields in |audio_config| and
149*3f982cf4SFabien Sanglard   // |video_config| are ignored in favor of |kRemote|.
150*3f982cf4SFabien Sanglard   Error NegotiateRemoting(AudioCaptureConfig audio_config,
151*3f982cf4SFabien Sanglard                           VideoCaptureConfig video_config);
152*3f982cf4SFabien Sanglard 
153*3f982cf4SFabien Sanglard   // Get the current network usage (in bits per second). This includes all
154*3f982cf4SFabien Sanglard   // senders managed by this session, and is a best guess based on receiver
155*3f982cf4SFabien Sanglard   // feedback. Embedders may use this information to throttle capture devices.
156*3f982cf4SFabien Sanglard   int GetEstimatedNetworkBandwidth() const;
157*3f982cf4SFabien Sanglard 
158*3f982cf4SFabien Sanglard   // The RPC messenger for this session. NOTE: RPC messages may come at
159*3f982cf4SFabien Sanglard   // any time from the receiver, so subscriptions to RPC remoting messages
160*3f982cf4SFabien Sanglard   // should be done before calling |NegotiateRemoting|.
rpc_messenger()161*3f982cf4SFabien Sanglard   RpcMessenger* rpc_messenger() { return &rpc_messenger_; }
162*3f982cf4SFabien Sanglard 
163*3f982cf4SFabien Sanglard  private:
164*3f982cf4SFabien Sanglard   // We store the current negotiation, so that when we get an answer from the
165*3f982cf4SFabien Sanglard   // receiver we can line up the selected streams with the original
166*3f982cf4SFabien Sanglard   // configuration.
167*3f982cf4SFabien Sanglard   struct InProcessNegotiation {
168*3f982cf4SFabien Sanglard     // The offer, which should always be valid if we have an in process
169*3f982cf4SFabien Sanglard     // negotiation.
170*3f982cf4SFabien Sanglard     Offer offer;
171*3f982cf4SFabien Sanglard 
172*3f982cf4SFabien Sanglard     // The configs used to derive the offer.
173*3f982cf4SFabien Sanglard     std::vector<AudioCaptureConfig> audio_configs;
174*3f982cf4SFabien Sanglard     std::vector<VideoCaptureConfig> video_configs;
175*3f982cf4SFabien Sanglard 
176*3f982cf4SFabien Sanglard     // The answer message for this negotiation, which may be invalid if we
177*3f982cf4SFabien Sanglard     // haven't received an answer yet.
178*3f982cf4SFabien Sanglard     Answer answer;
179*3f982cf4SFabien Sanglard   };
180*3f982cf4SFabien Sanglard 
181*3f982cf4SFabien Sanglard   // The state of the session.
182*3f982cf4SFabien Sanglard   enum class State {
183*3f982cf4SFabien Sanglard     // Not sending content--may be in the middle of negotiation, or just
184*3f982cf4SFabien Sanglard     // waiting.
185*3f982cf4SFabien Sanglard     kIdle,
186*3f982cf4SFabien Sanglard 
187*3f982cf4SFabien Sanglard     // Currently mirroring content to a receiver.
188*3f982cf4SFabien Sanglard     kStreaming,
189*3f982cf4SFabien Sanglard 
190*3f982cf4SFabien Sanglard     // Currently remoting content to a receiver.
191*3f982cf4SFabien Sanglard     kRemoting
192*3f982cf4SFabien Sanglard   };
193*3f982cf4SFabien Sanglard 
194*3f982cf4SFabien Sanglard   // Reset the state and tear down the current negotiation/negotiated mirroring
195*3f982cf4SFabien Sanglard   // or remoting session. After reset, the SenderSession is still connected to
196*3f982cf4SFabien Sanglard   // the same |remote_address_|, and the |packet_router_| and sequence number
197*3f982cf4SFabien Sanglard   // will be unchanged.
198*3f982cf4SFabien Sanglard   void ResetState();
199*3f982cf4SFabien Sanglard 
200*3f982cf4SFabien Sanglard   // Uses the passed in configs and offer to send an OFFER/ANSWER negotiation
201*3f982cf4SFabien Sanglard   // and cache the new InProcessNavigation.
202*3f982cf4SFabien Sanglard   Error StartNegotiation(std::vector<AudioCaptureConfig> audio_configs,
203*3f982cf4SFabien Sanglard                          std::vector<VideoCaptureConfig> video_configs,
204*3f982cf4SFabien Sanglard                          Offer offer);
205*3f982cf4SFabien Sanglard 
206*3f982cf4SFabien Sanglard   // Specific message type handler methods.
207*3f982cf4SFabien Sanglard   void OnAnswer(ReceiverMessage message);
208*3f982cf4SFabien Sanglard   void OnCapabilitiesResponse(ReceiverMessage message);
209*3f982cf4SFabien Sanglard   void OnRpcMessage(ReceiverMessage message);
210*3f982cf4SFabien Sanglard   void HandleErrorMessage(ReceiverMessage message, const std::string& text);
211*3f982cf4SFabien Sanglard 
212*3f982cf4SFabien Sanglard   // Used by SpawnSenders to generate a sender for a specific stream.
213*3f982cf4SFabien Sanglard   std::unique_ptr<Sender> CreateSender(Ssrc receiver_ssrc,
214*3f982cf4SFabien Sanglard                                        const Stream& stream,
215*3f982cf4SFabien Sanglard                                        RtpPayloadType type);
216*3f982cf4SFabien Sanglard 
217*3f982cf4SFabien Sanglard   // Helper methods for spawning specific senders from the Answer message.
218*3f982cf4SFabien Sanglard   void SpawnAudioSender(ConfiguredSenders* senders,
219*3f982cf4SFabien Sanglard                         Ssrc receiver_ssrc,
220*3f982cf4SFabien Sanglard                         int send_index,
221*3f982cf4SFabien Sanglard                         int config_index);
222*3f982cf4SFabien Sanglard   void SpawnVideoSender(ConfiguredSenders* senders,
223*3f982cf4SFabien Sanglard                         Ssrc receiver_ssrc,
224*3f982cf4SFabien Sanglard                         int send_index,
225*3f982cf4SFabien Sanglard                         int config_index);
226*3f982cf4SFabien Sanglard 
227*3f982cf4SFabien Sanglard   // Spawn a set of configured senders from the currently stored negotiation.
228*3f982cf4SFabien Sanglard   ConfiguredSenders SpawnSenders(const Answer& answer);
229*3f982cf4SFabien Sanglard 
230*3f982cf4SFabien Sanglard   // Used by the RPC messenger to send outbound messages.
231*3f982cf4SFabien Sanglard   void SendRpcMessage(std::vector<uint8_t> message_body);
232*3f982cf4SFabien Sanglard 
233*3f982cf4SFabien Sanglard   // This session's configuration.
234*3f982cf4SFabien Sanglard   Configuration config_;
235*3f982cf4SFabien Sanglard 
236*3f982cf4SFabien Sanglard   // The session messenger, which uses the message port for sending control
237*3f982cf4SFabien Sanglard   // messages. For message formats, see
238*3f982cf4SFabien Sanglard   // cast/protocol/castv2/streaming_schema.json.
239*3f982cf4SFabien Sanglard   SenderSessionMessenger messenger_;
240*3f982cf4SFabien Sanglard 
241*3f982cf4SFabien Sanglard   // The RPC messenger, which uses the session messager for sending RPC messages
242*3f982cf4SFabien Sanglard   // and handles subscriptions to RPC messages.
243*3f982cf4SFabien Sanglard   RpcMessenger rpc_messenger_;
244*3f982cf4SFabien Sanglard 
245*3f982cf4SFabien Sanglard   // The packet router used for RTP/RTCP messaging across all senders.
246*3f982cf4SFabien Sanglard   SenderPacketRouter packet_router_;
247*3f982cf4SFabien Sanglard 
248*3f982cf4SFabien Sanglard   // Each negotiation has its own sequence number, and the receiver replies
249*3f982cf4SFabien Sanglard   // with the same sequence number that we send. Each message to the receiver
250*3f982cf4SFabien Sanglard   // advances our current sequence number.
251*3f982cf4SFabien Sanglard   int current_sequence_number_ = 0;
252*3f982cf4SFabien Sanglard 
253*3f982cf4SFabien Sanglard   // The current negotiation. If present, we are expected an ANSWER from
254*3f982cf4SFabien Sanglard   // the receiver. If not present, any provided ANSWERS are rejected.
255*3f982cf4SFabien Sanglard   std::unique_ptr<InProcessNegotiation> current_negotiation_;
256*3f982cf4SFabien Sanglard 
257*3f982cf4SFabien Sanglard   // The current state of the session. Note that the state is intentionally
258*3f982cf4SFabien Sanglard   // limited. |kStreaming| or |kRemoting| means that we are either starting
259*3f982cf4SFabien Sanglard   // a negotiation or actively sending to a receiver.
260*3f982cf4SFabien Sanglard   State state_ = State::kIdle;
261*3f982cf4SFabien Sanglard 
262*3f982cf4SFabien Sanglard   // If the negotiation has succeeded, we store the current audio and video
263*3f982cf4SFabien Sanglard   // senders used for this session. Either or both may be nullptr.
264*3f982cf4SFabien Sanglard   std::unique_ptr<Sender> current_audio_sender_;
265*3f982cf4SFabien Sanglard   std::unique_ptr<Sender> current_video_sender_;
266*3f982cf4SFabien Sanglard };  // namespace cast
267*3f982cf4SFabien Sanglard 
268*3f982cf4SFabien Sanglard }  // namespace cast
269*3f982cf4SFabien Sanglard }  // namespace openscreen
270*3f982cf4SFabien Sanglard 
271*3f982cf4SFabien Sanglard #endif  // CAST_STREAMING_SENDER_SESSION_H_
272