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