xref: /aosp_15_r20/external/openscreen/cast/streaming/receiver_session.h (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CAST_STREAMING_RECEIVER_SESSION_H_
6 #define CAST_STREAMING_RECEIVER_SESSION_H_
7 
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "cast/common/public/message_port.h"
14 #include "cast/streaming/capture_configs.h"
15 #include "cast/streaming/constants.h"
16 #include "cast/streaming/offer_messages.h"
17 #include "cast/streaming/receiver_packet_router.h"
18 #include "cast/streaming/resolution.h"
19 #include "cast/streaming/rpc_messenger.h"
20 #include "cast/streaming/sender_message.h"
21 #include "cast/streaming/session_config.h"
22 #include "cast/streaming/session_messenger.h"
23 
24 namespace openscreen {
25 namespace cast {
26 
27 class Environment;
28 class Receiver;
29 
30 // This class is responsible for listening for streaming requests from Cast
31 // Sender devices, then negotiating capture constraints and instantiating audio
32 // and video Receiver objects.
33 //   The owner of this session is expected to provide a client for
34 // updates, an environment for getting UDP socket information (as well as
35 // other OS dependencies), and a set of preferences to be used for
36 // negotiation.
37 //
38 // NOTE: In some cases, the session initialization may be pending waiting for
39 // the UDP socket to be ready. In this case, the receivers and the answer
40 // message will not be configured and sent until the UDP socket has finished
41 // binding.
42 class ReceiverSession final : public Environment::SocketSubscriber {
43  public:
44   // Upon successful negotiation, a set of configured receivers is constructed
45   // for handling audio and video. Note that either receiver may be null.
46   struct ConfiguredReceivers {
47     // In practice, we may have 0, 1, or 2 receivers configured, depending
48     // on if the device supports audio and video, and if we were able to
49     // successfully negotiate a receiver configuration.
50 
51     // NOTES ON LIFETIMES: The audio and video Receiver pointers are owned by
52     // ReceiverSession, not the Client, and references to these pointers must be
53     // cleared before a call to Client::OnReceiversDestroying() returns.
54 
55     // If the receiver is audio- or video-only, or we failed to negotiate
56     // an acceptable session configuration with the sender, then either of the
57     // receivers may be nullptr. In this case, the associated config is default
58     // initialized and should be ignored.
59     Receiver* audio_receiver;
60     AudioCaptureConfig audio_config;
61 
62     Receiver* video_receiver;
63     VideoCaptureConfig video_config;
64   };
65 
66   // This struct contains all of the information necessary to begin remoting
67   // once we get a remoting request from a Sender.
68   struct RemotingNegotiation {
69     // The configured receivers set to be used for handling audio and
70     // video streams. Unlike in the general streaming case, when we are remoting
71     // we don't know the codec and other information about the stream until
72     // the sender provices that information through the
73     // DemuxerStreamInitializeCallback RPC method.
74     ConfiguredReceivers receivers;
75 
76     // The RPC messenger to be used for subscribing to remoting proto messages.
77     // Unlike the SenderSession API, the RPC messenger is negotiation specific.
78     // The messenger is torn down when |OnReceiversDestroying| is called, and
79     // is owned by the ReceiverSession.
80     RpcMessenger* messenger;
81   };
82 
83   // The embedder should provide a client for handling connections.
84   // When a connection is established, the OnNegotiated callback is called.
85   class Client {
86    public:
87     // Currently we only care about the session ending or being renegotiated,
88     // which means that we don't have to tear down as much state.
89     enum ReceiversDestroyingReason { kEndOfSession, kRenegotiated };
90 
91     // Called when a set of streaming receivers has been negotiated. Both this
92     // and |OnRemotingNegotiated| may be called repeatedly as negotiations occur
93     // through the life of a session.
94     virtual void OnNegotiated(const ReceiverSession* session,
95                               ConfiguredReceivers receivers) = 0;
96 
97     // Called when a set of remoting receivers has been negotiated. This will
98     // only be called if |RemotingPreferences| are provided as part of
99     // constructing the ReceiverSession object.
OnRemotingNegotiated(const ReceiverSession * session,RemotingNegotiation negotiation)100     virtual void OnRemotingNegotiated(const ReceiverSession* session,
101                                       RemotingNegotiation negotiation) {}
102 
103     // Called immediately preceding the destruction of this session's receivers.
104     // If |reason| is |kEndOfSession|, OnNegotiated() will never be called
105     // again; if it is |kRenegotiated|, OnNegotiated() will be called again
106     // soon with a new set of Receivers to use.
107     //
108     // Before returning, the implementation must ensure that all references to
109     // the Receivers, from the last call to OnNegotiated(), have been cleared.
110     virtual void OnReceiversDestroying(const ReceiverSession* session,
111                                        ReceiversDestroyingReason reason) = 0;
112 
113     // Called whenever an error that the client may care about occurs.
114     // Recoverable errors are usually logged by the receiver session instead
115     // of reported here.
116     virtual void OnError(const ReceiverSession* session, Error error) = 0;
117 
118     // Called to verify whether a given codec parameter is supported by
119     // this client. If not overriden, this always assumes true.
120     // This method is used only for secondary matching, e.g.
121     // if you don't add VideoCodec::kHevc to the VideoCaptureConfig, then
122     // supporting codec parameter "hev1.1.6.L153.B0" does not matter.
123     //
124     // The codec parameter support callback is optional, however if provided
125     // then any offered streams that have a non-empty codec parameter field must
126     // match. If a stream does not have a codec parameter, this callback will
127     // not be called.
SupportsCodecParameter(const std::string & parameter)128     virtual bool SupportsCodecParameter(const std::string& parameter) {
129       return true;
130     }
131 
132    protected:
133     virtual ~Client();
134   };
135 
136   // Information about the display the receiver is attached to.
137   struct Display {
138     // Returns true if all configurations supported by |other| are also
139     // supported by this instance.
140     bool IsSupersetOf(const Display& other) const;
141 
142     // The display limitations of the actual screen, used to provide upper
143     // bounds on streams. For example, we will never
144     // send 60FPS if it is going to be displayed on a 30FPS screen.
145     // Note that we may exceed the display width and height for standard
146     // content sizes like 720p or 1080p.
147     Dimensions dimensions;
148 
149     // Whether the embedder is capable of scaling content. If set to false,
150     // the sender will manage the aspect ratio scaling.
151     bool can_scale_content = false;
152   };
153 
154   // Codec-specific audio limits for playback.
155   struct AudioLimits {
156     // Returns true if all configurations supported by |other| are also
157     // supported by this instance.
158     bool IsSupersetOf(const AudioLimits& other) const;
159 
160     // Whether or not these limits apply to all codecs.
161     bool applies_to_all_codecs = false;
162 
163     // Audio codec these limits apply to. Note that if |applies_to_all_codecs|
164     // is true this field is ignored.
165     AudioCodec codec;
166 
167     // Maximum audio sample rate.
168     int max_sample_rate = kDefaultAudioSampleRate;
169 
170     // Maximum audio channels, default is currently stereo.
171     int max_channels = kDefaultAudioChannels;
172 
173     // Minimum and maximum bitrates. Generally capture is done at the maximum
174     // bit rate, since audio bandwidth is much lower than video for most
175     // content.
176     int min_bit_rate = kDefaultAudioMinBitRate;
177     int max_bit_rate = kDefaultAudioMaxBitRate;
178 
179     // Max playout delay in milliseconds.
180     std::chrono::milliseconds max_delay = kDefaultMaxDelayMs;
181   };
182 
183   // Codec-specific video limits for playback.
184   struct VideoLimits {
185     // Returns true if all configurations supported by |other| are also
186     // supported by this instance.
187     bool IsSupersetOf(const VideoLimits& other) const;
188 
189     // Whether or not these limits apply to all codecs.
190     bool applies_to_all_codecs = false;
191 
192     // Video codec these limits apply to. Note that if |applies_to_all_codecs|
193     // is true this field is ignored.
194     VideoCodec codec;
195 
196     // Maximum pixels per second. Value is the standard amount of pixels
197     // for 1080P at 30FPS.
198     int max_pixels_per_second = 1920 * 1080 * 30;
199 
200     // Maximum dimensions. Minimum dimensions try to use the same aspect
201     // ratio and are generated from the spec.
202     Dimensions max_dimensions = {1920, 1080, {kDefaultFrameRate, 1}};
203 
204     // Minimum and maximum bitrates. Default values are based on default min and
205     // max dimensions, embedders that support different display dimensions
206     // should strongly consider setting these fields.
207     int min_bit_rate = kDefaultVideoMinBitRate;
208     int max_bit_rate = kDefaultVideoMaxBitRate;
209 
210     // Max playout delay in milliseconds.
211     std::chrono::milliseconds max_delay = kDefaultMaxDelayMs;
212   };
213 
214   // This struct is used to provide preferences for setting up and running
215   // remoting streams. These properties are based on the current control
216   // protocol and allow remoting with current senders.
217   struct RemotingPreferences {
218     // Returns true if all configurations supported by |other| are also
219     // supported by this instance.
220     bool IsSupersetOf(const RemotingPreferences& other) const;
221 
222     // Current remoting senders take an "all or nothing" support for audio
223     // codec support. While Opus and AAC support is handled in our Preferences'
224     // |audio_codecs| property, support for the following codecs must be
225     // enabled or disabled all together:
226     // MP3
227     // PCM, including Mu-Law, S16BE, S24BE, and ALAW variants
228     // Ogg Vorbis
229     // FLAC
230     // AMR, including narrow band (NB) and wide band (WB) variants
231     // GSM Mobile Station (MS)
232     // EAC3 (Dolby Digital Plus)
233     // ALAC (Apple Lossless)
234     // AC-3 (Dolby Digital)
235     // These properties are tied directly to what Chrome supports. See:
236     // https://source.chromium.org/chromium/chromium/src/+/master:media/base/audio_codecs.h
237     bool supports_chrome_audio_codecs = false;
238 
239     // Current remoting senders assume that the receiver supports 4K for all
240     // video codecs supplied in |video_codecs|, or none of them.
241     bool supports_4k = false;
242   };
243 
244   // Note: embedders are required to implement the following
245   // codecs to be Cast V2 compliant: H264, VP8, AAC, Opus.
246   struct Preferences {
247     Preferences();
248     Preferences(std::vector<VideoCodec> video_codecs,
249                 std::vector<AudioCodec> audio_codecs);
250     Preferences(std::vector<VideoCodec> video_codecs,
251                 std::vector<AudioCodec> audio_codecs,
252                 std::vector<AudioLimits> audio_limits,
253                 std::vector<VideoLimits> video_limits,
254                 std::unique_ptr<Display> description);
255 
256     Preferences(Preferences&&) noexcept;
257     Preferences(const Preferences&);
258     Preferences& operator=(Preferences&&) noexcept;
259     Preferences& operator=(const Preferences&);
260 
261     // Returns true if all configurations supported by |other| are also
262     // supported by this instance.
263     bool IsSupersetOf(const Preferences& other) const;
264 
265     // Audio and video codec preferences. Should be supplied in order of
266     // preference, e.g. in this example if we get both VP8 and H264 we will
267     // generally select the VP8 offer. If a codec is omitted from these fields
268     // it will never be selected in the OFFER/ANSWER negotiation.
269     std::vector<VideoCodec> video_codecs{VideoCodec::kVp8, VideoCodec::kH264};
270     std::vector<AudioCodec> audio_codecs{AudioCodec::kOpus, AudioCodec::kAac};
271 
272     // Optional limitation fields that help the sender provide a delightful
273     // cast experience. Although optional, highly recommended.
274     // NOTE: embedders that wish to apply the same limits for all codecs can
275     // pass a vector of size 1 with the |applies_to_all_codecs| field set to
276     // true.
277     std::vector<AudioLimits> audio_limits;
278     std::vector<VideoLimits> video_limits;
279     std::unique_ptr<Display> display_description;
280 
281     // Libcast remoting support is opt-in: embedders wishing to field remoting
282     // offers may provide a set of remoting preferences, or leave nullptr for
283     // all remoting OFFERs to be rejected in favor of continuing streaming.
284     std::unique_ptr<RemotingPreferences> remoting;
285   };
286 
287   ReceiverSession(Client* const client,
288                   Environment* environment,
289                   MessagePort* message_port,
290                   Preferences preferences);
291   ReceiverSession(const ReceiverSession&) = delete;
292   ReceiverSession(ReceiverSession&&) noexcept = delete;
293   ReceiverSession& operator=(const ReceiverSession&) = delete;
294   ReceiverSession& operator=(ReceiverSession&&) = delete;
295   ~ReceiverSession();
296 
session_id()297   const std::string& session_id() const { return session_id_; }
298 
299   // Environment::SocketSubscriber event callbacks.
300   void OnSocketReady() override;
301   void OnSocketInvalid(Error error) override;
302 
303  private:
304   // In some cases, such as waiting for the UDP socket to be bound, we
305   // may have a pending session that cannot start yet. This class provides
306   // all necessary info to instantiate a session.
307   struct SessionProperties {
308     // The cast mode the OFFER was sent for.
309     CastMode mode;
310 
311     // The selected audio and video streams from the original OFFER message.
312     std::unique_ptr<AudioStream> selected_audio;
313     std::unique_ptr<VideoStream> selected_video;
314 
315     // The sequence number of the OFFER that produced these properties.
316     int sequence_number;
317 
318     // To be valid either the audio or video must be selected, and we must
319     // have a sequence number we can reference.
320     bool IsValid() const;
321   };
322 
323   // Specific message type handler methods.
324   void OnOffer(SenderMessage message);
325   void OnCapabilitiesRequest(SenderMessage message);
326   void OnRpcMessage(SenderMessage message);
327 
328   // Selects streams from an offer based on its configuration, and sets
329   // them in the session properties.
330   void SelectStreams(const Offer& offer, SessionProperties* properties);
331 
332   // Creates receivers and sends an appropriate Answer message using the
333   // session properties.
334   void InitializeSession(const SessionProperties& properties);
335 
336   // Used by SpawnReceivers to generate a receiver for a specific stream.
337   std::unique_ptr<Receiver> ConstructReceiver(const Stream& stream);
338 
339   // Creates a set of configured receivers from a given pair of audio and
340   // video streams. NOTE: either audio or video may be null, but not both.
341   ConfiguredReceivers SpawnReceivers(const SessionProperties& properties);
342 
343   // Creates an ANSWER object. Assumes at least one stream is not nullptr.
344   Answer ConstructAnswer(const SessionProperties& properties);
345 
346   // Creates a ReceiverCapability version 2 object. This will be deprecated
347   // as part of https://issuetracker.google.com/184429130.
348   ReceiverCapability CreateRemotingCapabilityV2();
349 
350   // Handles resetting receivers and notifying the client.
351   void ResetReceivers(Client::ReceiversDestroyingReason reason);
352 
353   // Sends an error answer reply and notifies the client of the error.
354   void SendErrorAnswerReply(int sequence_number, const char* message);
355 
356   Client* const client_;
357   Environment* const environment_;
358   const Preferences preferences_;
359 
360   // The sender_id of this session.
361   const std::string session_id_;
362 
363   // The session messenger used for the lifetime of this session.
364   ReceiverSessionMessenger messenger_;
365 
366   // The packet router to be used for all Receivers spawned by this session.
367   ReceiverPacketRouter packet_router_;
368 
369   // Any session pending while the UDP socket is being bound.
370   std::unique_ptr<SessionProperties> pending_session_;
371 
372   // The negotiated receivers we own, clients are notified of destruction
373   // through |Client::OnReceiversDestroying|.
374   std::unique_ptr<Receiver> current_audio_receiver_;
375   std::unique_ptr<Receiver> current_video_receiver_;
376 
377   // If remoting, we store the RpcMessenger used by the embedder to send RPC
378   // messages from the remoting protobuf specification.
379   std::unique_ptr<RpcMessenger> rpc_messenger_;
380 };
381 
382 }  // namespace cast
383 }  // namespace openscreen
384 
385 #endif  // CAST_STREAMING_RECEIVER_SESSION_H_
386