aboutsummaryrefslogtreecommitdiff
path: root/cast/standalone_sender
diff options
context:
space:
mode:
Diffstat (limited to 'cast/standalone_sender')
-rw-r--r--cast/standalone_sender/looping_file_cast_agent.cc8
-rw-r--r--cast/standalone_sender/looping_file_cast_agent.h11
-rw-r--r--cast/standalone_sender/looping_file_sender.cc5
-rw-r--r--cast/standalone_sender/looping_file_sender.h4
-rw-r--r--cast/standalone_sender/remoting_sender.cc32
-rw-r--r--cast/standalone_sender/remoting_sender.h26
-rw-r--r--cast/standalone_sender/simulated_capturer.cc11
-rw-r--r--cast/standalone_sender/simulated_capturer.h6
8 files changed, 78 insertions, 25 deletions
diff --git a/cast/standalone_sender/looping_file_cast_agent.cc b/cast/standalone_sender/looping_file_cast_agent.cc
index 4ee2231a..0e17ecab 100644
--- a/cast/standalone_sender/looping_file_cast_agent.cc
+++ b/cast/standalone_sender/looping_file_cast_agent.cc
@@ -273,7 +273,7 @@ void LoopingFileCastAgent::CreateAndStartSession() {
if (connection_settings_->use_remoting) {
remoting_sender_ = std::make_unique<RemotingSender>(
current_session_->rpc_messenger(), AudioCodec::kOpus,
- connection_settings_->codec, [this]() { OnRemotingReceiverReady(); });
+ connection_settings_->codec, this);
negotiation_error =
current_session_->NegotiateRemoting(audio_config, video_config);
@@ -321,13 +321,17 @@ void LoopingFileCastAgent::OnError(const SenderSession* session, Error error) {
Shutdown();
}
-void LoopingFileCastAgent::OnRemotingReceiverReady() {
+void LoopingFileCastAgent::OnReady() {
is_ready_for_remoting_ = true;
if (current_negotiation_) {
StartRemotingSenders();
}
}
+void LoopingFileCastAgent::OnPlaybackRateChange(double rate) {
+ file_sender_->SetPlaybackRate(rate);
+}
+
void LoopingFileCastAgent::StartRemotingSenders() {
OSP_DCHECK(current_negotiation_);
file_sender_ = std::make_unique<LoopingFileSender>(
diff --git a/cast/standalone_sender/looping_file_cast_agent.h b/cast/standalone_sender/looping_file_cast_agent.h
index 895d1324..3ec2e8fa 100644
--- a/cast/standalone_sender/looping_file_cast_agent.h
+++ b/cast/standalone_sender/looping_file_cast_agent.h
@@ -70,7 +70,8 @@ class LoopingFileCastAgent final
public VirtualConnectionRouter::SocketErrorHandler,
public ConnectionNamespaceHandler::VirtualConnectionPolicy,
public CastMessageHandler,
- public SenderSession::Client {
+ public SenderSession::Client,
+ public RemotingSender::Client {
public:
using ShutdownCallback = std::function<void()>;
@@ -107,6 +108,10 @@ class LoopingFileCastAgent final
CastSocket* socket,
::cast::channel::CastMessage message) override;
+ // RemotingSender::Client overrides.
+ void OnReady() override;
+ void OnPlaybackRateChange(double rate) override;
+
// Returns the Cast application ID for either A/V mirroring or audio-only
// mirroring, as configured by the ConnectionSettings.
const char* GetMirroringAppId() const;
@@ -135,10 +140,6 @@ class LoopingFileCastAgent final
SenderSession::RemotingNegotiation negotiation) override;
void OnError(const SenderSession* session, Error error) override;
- // Callback for when the RemotingSender indicates that the receiver
- // is ready.
- void OnRemotingReceiverReady();
-
// Starts the remoting sender. This may occur when remoting is "ready" if the
// session is already negotiated, or upon session negotiation if the receiver
// is already ready.
diff --git a/cast/standalone_sender/looping_file_sender.cc b/cast/standalone_sender/looping_file_sender.cc
index 9f6137dc..7ed5e3fe 100644
--- a/cast/standalone_sender/looping_file_sender.cc
+++ b/cast/standalone_sender/looping_file_sender.cc
@@ -44,6 +44,11 @@ LoopingFileSender::LoopingFileSender(Environment* environment,
LoopingFileSender::~LoopingFileSender() = default;
+void LoopingFileSender::SetPlaybackRate(double rate) {
+ video_capturer_->SetPlaybackRate(rate);
+ audio_capturer_->SetPlaybackRate(rate);
+}
+
void LoopingFileSender::UpdateEncoderBitrates() {
if (bandwidth_being_utilized_ >= kHighBandwidthThreshold) {
audio_encoder_.UseHighQuality();
diff --git a/cast/standalone_sender/looping_file_sender.h b/cast/standalone_sender/looping_file_sender.h
index 56a8aa45..7ad784b9 100644
--- a/cast/standalone_sender/looping_file_sender.h
+++ b/cast/standalone_sender/looping_file_sender.h
@@ -33,6 +33,8 @@ class LoopingFileSender final : public SimulatedAudioCapturer::Client,
~LoopingFileSender() final;
+ void SetPlaybackRate(double rate);
+
private:
void UpdateEncoderBitrates();
void ControlForNetworkCongestion();
@@ -49,7 +51,7 @@ class LoopingFileSender final : public SimulatedAudioCapturer::Client,
void UpdateStatusOnConsole();
- // SimulatedCapturer overrides.
+ // SimulatedCapturer::Client overrides.
void OnEndOfFile(SimulatedCapturer* capturer) final;
void OnError(SimulatedCapturer* capturer, std::string message) final;
diff --git a/cast/standalone_sender/remoting_sender.cc b/cast/standalone_sender/remoting_sender.cc
index 1566f0a7..741fb190 100644
--- a/cast/standalone_sender/remoting_sender.cc
+++ b/cast/standalone_sender/remoting_sender.cc
@@ -41,19 +41,22 @@ AudioDecoderConfig::Codec ToProtoCodec(AudioCodec value) {
} // namespace
+RemotingSender::Client::~Client() = default;
+
RemotingSender::RemotingSender(RpcMessenger* messenger,
AudioCodec audio_codec,
VideoCodec video_codec,
- ReadyCallback ready_cb)
+ Client* client)
: messenger_(messenger),
audio_codec_(audio_codec),
video_codec_(video_codec),
- ready_cb_(std::move(ready_cb)) {
+ client_(client) {
+ OSP_DCHECK(client_);
messenger_->RegisterMessageReceiverCallback(
RpcMessenger::kAcquireRendererHandle,
[this](std::unique_ptr<RpcMessage> message) {
OSP_DCHECK(message);
- this->OnInitializeMessage(*message);
+ this->OnMessage(*message);
});
}
@@ -62,6 +65,19 @@ RemotingSender::~RemotingSender() {
RpcMessenger::kAcquireRendererHandle);
}
+void RemotingSender::OnMessage(const RpcMessage& message) {
+ if (!message.has_proc()) {
+ return;
+ }
+ if (message.proc() == RpcMessage_RpcProc_RPC_DS_INITIALIZE) {
+ OSP_VLOG << "Received initialize message";
+ OnInitializeMessage(message);
+ } else if (message.proc() == RpcMessage_RpcProc_RPC_R_SETPLAYBACKRATE) {
+ OSP_VLOG << "Received playback rate message: " << message.double_value();
+ OnPlaybackRateMessage(message);
+ }
+}
+
void RemotingSender::OnInitializeMessage(const RpcMessage& message) {
receiver_handle_ = message.integer_value();
@@ -84,11 +100,11 @@ void RemotingSender::OnInitializeMessage(const RpcMessage& message) {
<< " and video codec " << CodecToString(video_codec_);
messenger_->SendMessageToRemote(callback_message);
- if (ready_cb_) {
- ready_cb_();
- } else {
- OSP_DLOG_INFO << "Received a ready message, but no ready callback.";
- }
+ client_->OnReady();
+}
+
+void RemotingSender::OnPlaybackRateMessage(const RpcMessage& message) {
+ client_->OnPlaybackRateChange(message.double_value());
}
} // namespace cast
diff --git a/cast/standalone_sender/remoting_sender.h b/cast/standalone_sender/remoting_sender.h
index d331009b..7d09dc69 100644
--- a/cast/standalone_sender/remoting_sender.h
+++ b/cast/standalone_sender/remoting_sender.h
@@ -26,19 +26,29 @@ namespace cast {
// the public APIs.
class RemotingSender {
public:
- using ReadyCallback = std::function<void()>;
+ // The remoting sender expects a valid client to handle received messages.
+ class Client {
+ public:
+ virtual ~Client();
+
+ // Executed when we receive the initialize message from the receiver.
+ virtual void OnReady() = 0;
+
+ // Executed when we receive a playback rate message from the receiver.
+ virtual void OnPlaybackRateChange(double rate) = 0;
+ };
+
RemotingSender(RpcMessenger* messenger,
AudioCodec audio_codec,
VideoCodec video_codec,
- ReadyCallback ready_cb);
+ Client* client);
~RemotingSender();
private:
- // When the receiver indicates that it is ready for initialization, it will
- // The receiver sends us an "initialization" message that we respond to
- // here with an "initialization callback" message that contains codec
- // information.
+ // Helper for parsing any received RPC messages.
+ void OnMessage(const RpcMessage& message);
void OnInitializeMessage(const RpcMessage& message);
+ void OnPlaybackRateMessage(const RpcMessage& message);
// The messenger is the only caller of OnInitializeMessage, so there are no
// lifetime concerns. However, if this class outlives |messenger_|, it will
@@ -52,9 +62,7 @@ class RemotingSender {
const AudioCodec audio_codec_;
const VideoCodec video_codec_;
- // The callback method to be called once we get the initialization message
- // from the receiver.
- ReadyCallback ready_cb_;
+ Client* client_;
// The initialization message from the receiver contains the handle the
// callback should go to.
diff --git a/cast/standalone_sender/simulated_capturer.cc b/cast/standalone_sender/simulated_capturer.cc
index 87313010..713caa24 100644
--- a/cast/standalone_sender/simulated_capturer.cc
+++ b/cast/standalone_sender/simulated_capturer.cc
@@ -85,6 +85,14 @@ SimulatedCapturer::SimulatedCapturer(Environment* environment,
SimulatedCapturer::~SimulatedCapturer() = default;
+void SimulatedCapturer::SetPlaybackRate(double rate) {
+ playback_rate_is_non_zero_ = rate > 0;
+ if (playback_rate_is_non_zero_) {
+ // Restart playback now that playback rate is nonzero.
+ StartDecodingNextFrame();
+ }
+}
+
void SimulatedCapturer::SetAdditionalDecoderParameters(
AVCodecContext* decoder_context) {}
@@ -119,6 +127,9 @@ Clock::duration SimulatedCapturer::ToApproximateClockDuration(
}
void SimulatedCapturer::StartDecodingNextFrame() {
+ if (!playback_rate_is_non_zero_) {
+ return;
+ }
const int read_frame_result =
av_read_frame(format_context_.get(), packet_.get());
if (read_frame_result < 0) {
diff --git a/cast/standalone_sender/simulated_capturer.h b/cast/standalone_sender/simulated_capturer.h
index 8d32085a..61738e1f 100644
--- a/cast/standalone_sender/simulated_capturer.h
+++ b/cast/standalone_sender/simulated_capturer.h
@@ -40,6 +40,8 @@ class SimulatedCapturer {
virtual ~Observer();
};
+ void SetPlaybackRate(double rate);
+
protected:
SimulatedCapturer(Environment* environment,
const char* path,
@@ -103,6 +105,10 @@ class SimulatedCapturer {
// Used to schedule the next task to execute and when it should execute. There
// is only ever one task scheduled/running at any time.
Alarm next_task_;
+
+ // Used to determine playback rate. Currently, we only support "playing"
+ // at 1x speed, or "pausing" at 0x speed.
+ bool playback_rate_is_non_zero_ = true;
};
// Emits the primary audio stream from a file.