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/answer_messages.h"
15 #include "cast/streaming/capture_configs.h"
16 #include "cast/streaming/offer_messages.h"
17 #include "cast/streaming/receiver_packet_router.h"
18 #include "cast/streaming/sender_message.h"
19 #include "cast/streaming/session_config.h"
20 #include "cast/streaming/session_messager.h"
21 #include "util/json/json_serialization.h"
22 
23 namespace openscreen {
24 namespace cast {
25 
26 class Environment;
27 class Receiver;
28 
29 class ReceiverSession final : public Environment::SocketSubscriber {
30  public:
31   // Upon successful negotiation, a set of configured receivers is constructed
32   // for handling audio and video. Note that either receiver may be null.
33   struct ConfiguredReceivers {
34     // In practice, we may have 0, 1, or 2 receivers configured, depending
35     // on if the device supports audio and video, and if we were able to
36     // successfully negotiate a receiver configuration.
37 
38     // NOTES ON LIFETIMES: The audio and video Receiver pointers are owned by
39     // ReceiverSession, not the Client, and references to these pointers must be
40     // cleared before a call to Client::OnReceiversDestroying() returns.
41 
42     // If the receiver is audio- or video-only, or we failed to negotiate
43     // an acceptable session configuration with the sender, then either of the
44     // receivers may be nullptr. In this case, the associated config is default
45     // initialized and should be ignored.
46     Receiver* audio_receiver;
47     AudioCaptureConfig audio_config;
48 
49     Receiver* video_receiver;
50     VideoCaptureConfig video_config;
51   };
52 
53   // The embedder should provide a client for handling connections.
54   // When a connection is established, the OnMirroringNegotiated callback is
55   // called.
56   class Client {
57    public:
58     enum ReceiversDestroyingReason { kEndOfSession, kRenegotiated };
59 
60     // Called when a new set of receivers has been negotiated. This may be
61     // called multiple times during a session, as renegotiations occur.
62     virtual void OnMirroringNegotiated(const ReceiverSession* session,
63                                        ConfiguredReceivers receivers) = 0;
64 
65     // Called immediately preceding the destruction of this session's receivers.
66     // If |reason| is |kEndOfSession|, OnMirroringNegotiated() will never be
67     // called again; if it is |kRenegotiated|, OnMirroringNegotiated() will be
68     // called again soon with a new set of Receivers to use.
69     //
70     // Before returning, the implementation must ensure that all references to
71     // the Receivers, from the last call to OnMirroringNegotiated(), have been
72     // cleared.
73     virtual void OnReceiversDestroying(const ReceiverSession* session,
74                                        ReceiversDestroyingReason reason) = 0;
75 
76     virtual void OnError(const ReceiverSession* session, Error error) = 0;
77 
78    protected:
79     virtual ~Client();
80   };
81 
82   // Note: embedders are required to implement the following
83   // codecs to be Cast V2 compliant: H264, VP8, AAC, Opus.
84   struct Preferences {
85     Preferences();
86     Preferences(std::vector<VideoCodec> video_codecs,
87                 std::vector<AudioCodec> audio_codecs);
88     Preferences(std::vector<VideoCodec> video_codecs,
89                 std::vector<AudioCodec> audio_codecs,
90                 std::unique_ptr<Constraints> constraints,
91                 std::unique_ptr<DisplayDescription> description);
92 
93     Preferences(Preferences&&) noexcept;
94     Preferences(const Preferences&) = delete;
95     Preferences& operator=(Preferences&&) noexcept;
96     Preferences& operator=(const Preferences&) = delete;
97 
98     std::vector<VideoCodec> video_codecs{VideoCodec::kVp8, VideoCodec::kH264};
99     std::vector<AudioCodec> audio_codecs{AudioCodec::kOpus, AudioCodec::kAac};
100 
101     // The embedder has the option of directly specifying the display
102     // information and video/audio constraints that will be passed along to
103     // senders during the offer/answer exchange. If nullptr, these are ignored.
104     std::unique_ptr<Constraints> constraints;
105     std::unique_ptr<DisplayDescription> display_description;
106   };
107 
108   ReceiverSession(Client* const client,
109                   Environment* environment,
110                   MessagePort* message_port,
111                   Preferences preferences);
112   ReceiverSession(const ReceiverSession&) = delete;
113   ReceiverSession(ReceiverSession&&) noexcept = delete;
114   ReceiverSession& operator=(const ReceiverSession&) = delete;
115   ReceiverSession& operator=(ReceiverSession&&) = delete;
116   ~ReceiverSession();
117 
session_id()118   const std::string& session_id() const { return session_id_; }
119 
120   // Environment::SocketSubscriber event callbacks.
121   void OnSocketReady() override;
122   void OnSocketInvalid(Error error) override;
123 
124  private:
125   struct SessionProperties {
126     std::unique_ptr<AudioStream> selected_audio;
127     std::unique_ptr<VideoStream> selected_video;
128     int sequence_number;
129 
130     // To be valid either the audio or video must be selected, and we must
131     // have a sequence number we can reference.
132     bool IsValid() const;
133   };
134 
135   // Specific message type handler methods.
136   void OnOffer(SenderMessage message);
137 
138   // Creates receivers and sends an appropriate Answer message using the
139   // session properties.
140   void InitializeSession(const SessionProperties& properties);
141 
142   // Used by SpawnReceivers to generate a receiver for a specific stream.
143   std::unique_ptr<Receiver> ConstructReceiver(const Stream& stream);
144 
145   // Creates a set of configured receivers from a given pair of audio and
146   // video streams. NOTE: either audio or video may be null, but not both.
147   ConfiguredReceivers SpawnReceivers(const SessionProperties& properties);
148 
149   // Callers of this method should ensure at least one stream is non-null.
150   Answer ConstructAnswer(const SessionProperties& properties);
151 
152   // Handles resetting receivers and notifying the client.
153   void ResetReceivers(Client::ReceiversDestroyingReason reason);
154 
155   // Sends an error answer reply and notifies the client of the error.
156   void SendErrorAnswerReply(int sequence_number, const char* message);
157 
158   Client* const client_;
159   Environment* const environment_;
160   const Preferences preferences_;
161   // The sender_id of this session.
162   const std::string session_id_;
163   ReceiverSessionMessager messager_;
164 
165   // In some cases, the session initialization may be pending waiting for the
166   // UDP socket to be ready. In this case, the receivers and the answer
167   // message will not be configured and sent until the UDP socket has finished
168   // binding.
169   std::unique_ptr<SessionProperties> pending_session_;
170 
171   bool supports_wifi_status_reporting_ = false;
172   ReceiverPacketRouter packet_router_;
173 
174   std::unique_ptr<Receiver> current_audio_receiver_;
175   std::unique_ptr<Receiver> current_video_receiver_;
176 };
177 
178 }  // namespace cast
179 }  // namespace openscreen
180 
181 #endif  // CAST_STREAMING_RECEIVER_SESSION_H_
182