You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
6.6 KiB
173 lines
6.6 KiB
// Copyright 2020 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef CAST_STREAMING_SENDER_SESSION_H_
|
|
#define CAST_STREAMING_SENDER_SESSION_H_
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "cast/common/public/message_port.h"
|
|
#include "cast/streaming/answer_messages.h"
|
|
#include "cast/streaming/capture_configs.h"
|
|
#include "cast/streaming/offer_messages.h"
|
|
#include "cast/streaming/sender.h"
|
|
#include "cast/streaming/sender_packet_router.h"
|
|
#include "cast/streaming/session_config.h"
|
|
#include "cast/streaming/session_messager.h"
|
|
#include "json/value.h"
|
|
#include "util/json/json_serialization.h"
|
|
|
|
namespace openscreen {
|
|
namespace cast {
|
|
|
|
namespace capture_recommendations {
|
|
struct Recommendations;
|
|
}
|
|
|
|
class Environment;
|
|
class Sender;
|
|
|
|
class SenderSession final {
|
|
public:
|
|
// Upon successful negotiation, a set of configured senders is constructed
|
|
// for handling audio and video. Note that either sender may be null.
|
|
struct ConfiguredSenders {
|
|
// In practice, we may have 0, 1, or 2 senders configured, depending
|
|
// on if the device supports audio and video, and if we were able to
|
|
// successfully negotiate a sender configuration.
|
|
|
|
// If the sender is audio- or video-only, either of the senders
|
|
// may be nullptr. However, in the majority of cases they will be populated.
|
|
Sender* audio_sender;
|
|
AudioCaptureConfig audio_config;
|
|
|
|
Sender* video_sender;
|
|
VideoCaptureConfig video_config;
|
|
};
|
|
|
|
// The embedder should provide a client for handling the negotiation.
|
|
// When the negotiation is complete, the OnMirroringNegotiated callback is
|
|
// called.
|
|
class Client {
|
|
public:
|
|
// Called when a new set of senders has been negotiated. This may be
|
|
// called multiple times during a session, once for every time
|
|
// NegotiateMirroring() is called on the SenderSession object. The
|
|
// negotiation call also includes capture recommendations that can be used
|
|
// by the sender to provide an optimal video stream for the receiver.
|
|
virtual void OnMirroringNegotiated(
|
|
const SenderSession* session,
|
|
ConfiguredSenders senders,
|
|
capture_recommendations::Recommendations capture_recommendations) = 0;
|
|
|
|
// Called whenever an error occurs. Ends the ongoing session, and the caller
|
|
// must call NegotiateMirroring() again if they wish to re-establish
|
|
// streaming.
|
|
virtual void OnError(const SenderSession* session, Error error) = 0;
|
|
|
|
protected:
|
|
virtual ~Client();
|
|
};
|
|
|
|
// The SenderSession assumes that the passed in client, environment, and
|
|
// message port persist for at least the lifetime of the SenderSession. If
|
|
// one of these classes needs to be reset, a new SenderSession should be
|
|
// created.
|
|
//
|
|
// |message_source_id| and |message_destination_id| are the local and remote
|
|
// ID, respectively, to use when sending or receiving control messages (e.g.,
|
|
// OFFERs or ANSWERs) over the |message_port|. |message_port|'s SetClient()
|
|
// method will be called.
|
|
SenderSession(IPAddress remote_address,
|
|
Client* const client,
|
|
Environment* environment,
|
|
MessagePort* message_port,
|
|
std::string message_source_id,
|
|
std::string message_destination_id);
|
|
SenderSession(const SenderSession&) = delete;
|
|
SenderSession(SenderSession&&) noexcept = delete;
|
|
SenderSession& operator=(const SenderSession&) = delete;
|
|
SenderSession& operator=(SenderSession&&) = delete;
|
|
~SenderSession();
|
|
|
|
// Starts an OFFER/ANSWER exchange with the already configured receiver
|
|
// over the message port. The caller should assume any configured senders
|
|
// become invalid when calling this method.
|
|
Error NegotiateMirroring(std::vector<AudioCaptureConfig> audio_configs,
|
|
std::vector<VideoCaptureConfig> video_configs);
|
|
|
|
// Get the current network usage (in bits per second). This includes all
|
|
// senders managed by this session, and is a best guess based on receiver
|
|
// feedback. Embedders may use this information to throttle capture devices.
|
|
int GetEstimatedNetworkBandwidth() const;
|
|
|
|
private:
|
|
// We store the current negotiation, so that when we get an answer from the
|
|
// receiver we can line up the selected streams with the original
|
|
// configuration.
|
|
struct Negotiation {
|
|
Offer offer;
|
|
|
|
std::vector<AudioCaptureConfig> audio_configs;
|
|
std::vector<VideoCaptureConfig> video_configs;
|
|
};
|
|
|
|
// Specific message type handler methods.
|
|
void OnAnswer(ReceiverMessage message);
|
|
|
|
// Used by SpawnSenders to generate a sender for a specific stream.
|
|
std::unique_ptr<Sender> CreateSender(Ssrc receiver_ssrc,
|
|
const Stream& stream,
|
|
RtpPayloadType type);
|
|
|
|
// Helper methods for spawning specific senders from the Answer message.
|
|
void SpawnAudioSender(ConfiguredSenders* senders,
|
|
Ssrc receiver_ssrc,
|
|
int send_index,
|
|
int config_index);
|
|
void SpawnVideoSender(ConfiguredSenders* senders,
|
|
Ssrc receiver_ssrc,
|
|
int send_index,
|
|
int config_index);
|
|
|
|
// Spawn a set of configured senders from the currently stored negotiation.
|
|
ConfiguredSenders SpawnSenders(const Answer& answer);
|
|
|
|
// The remote address of the receiver we are communicating with. Used
|
|
// for both TLS and UDP traffic.
|
|
const IPAddress remote_address_;
|
|
|
|
// The embedder is expected to provide us a client for notifications about
|
|
// negotiations and errors, a valid cast environment, and a messaging
|
|
// port for communicating to the Receiver over TLS.
|
|
Client* const client_;
|
|
Environment* const environment_;
|
|
SenderSessionMessager messager_;
|
|
|
|
// The packet router used for messaging across all senders.
|
|
SenderPacketRouter packet_router_;
|
|
|
|
// Each negotiation has its own sequence number, and the receiver replies
|
|
// with the same sequence number that we send. Each message to the receiver
|
|
// advances our current sequence number.
|
|
int current_sequence_number_ = 0;
|
|
|
|
// The current negotiation. If present, we are expected an ANSWER from
|
|
// the receiver. If not present, any provided ANSWERS are rejected.
|
|
std::unique_ptr<Negotiation> current_negotiation_;
|
|
|
|
// If the negotiation has succeeded, we store the current audio and video
|
|
// senders used for this session. Either or both may be nullptr.
|
|
std::unique_ptr<Sender> current_audio_sender_;
|
|
std::unique_ptr<Sender> current_video_sender_;
|
|
}; // namespace cast
|
|
|
|
} // namespace cast
|
|
} // namespace openscreen
|
|
|
|
#endif // CAST_STREAMING_SENDER_SESSION_H_
|