aboutsummaryrefslogtreecommitdiff
path: root/cast
diff options
context:
space:
mode:
authorJordan Bayles <jophba@chromium.org>2021-06-28 16:46:18 -0700
committerOpenscreen LUCI CQ <openscreen-scoped@luci-project-accounts.iam.gserviceaccount.com>2021-06-29 00:07:41 +0000
commit8ac28e195414974bf38a249270e4e842790c82f7 (patch)
treebf860be47c013cd8cba8ba8a43f65c680184ed39 /cast
parent43bb3ea9ad8731ac539b299b77b71ba98b0a2767 (diff)
downloadopenscreen-8ac28e195414974bf38a249270e4e842790c82f7.tar.gz
[Cast Streaming] Allow playing file only once
Currently, the looping file sender plays the video over and over again. In some cases, like testing, we want to only play the video once. This patch adds a new command line argument that stops the sender after the video finishes playing. Bug: b/191492654 Change-Id: I97a2f1e211037abd09ac21ee482c9f95502ba821 Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2986060 Commit-Queue: Jordan Bayles <jophba@chromium.org> Reviewed-by: Ryan Keane <rwkeane@google.com>
Diffstat (limited to 'cast')
-rw-r--r--cast/standalone_sender/BUILD.gn1
-rw-r--r--cast/standalone_sender/connection_settings.h48
-rw-r--r--cast/standalone_sender/looping_file_cast_agent.cc8
-rw-r--r--cast/standalone_sender/looping_file_cast_agent.h24
-rw-r--r--cast/standalone_sender/looping_file_sender.cc37
-rw-r--r--cast/standalone_sender/looping_file_sender.h15
-rw-r--r--cast/standalone_sender/main.cc15
7 files changed, 99 insertions, 49 deletions
diff --git a/cast/standalone_sender/BUILD.gn b/cast/standalone_sender/BUILD.gn
index d2d3619b..afa73d7d 100644
--- a/cast/standalone_sender/BUILD.gn
+++ b/cast/standalone_sender/BUILD.gn
@@ -40,6 +40,7 @@ if (!build_with_chromium) {
libs = []
if (have_ffmpeg && have_libopus && have_libvpx) {
sources += [
+ "connection_settings.h",
"ffmpeg_glue.cc",
"ffmpeg_glue.h",
"looping_file_cast_agent.cc",
diff --git a/cast/standalone_sender/connection_settings.h b/cast/standalone_sender/connection_settings.h
new file mode 100644
index 00000000..f42842c3
--- /dev/null
+++ b/cast/standalone_sender/connection_settings.h
@@ -0,0 +1,48 @@
+// Copyright 2021 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_STANDALONE_SENDER_CONNECTION_SETTINGS_H_
+#define CAST_STANDALONE_SENDER_CONNECTION_SETTINGS_H_
+
+#include <string>
+
+#include "platform/base/interface_info.h"
+
+namespace openscreen {
+namespace cast {
+
+// The connection settings for a given standalone sender instance. These fields
+// are used throughout the standalone sender component to initialize state from
+// the command line parameters.
+struct ConnectionSettings {
+ // The endpoint of the receiver we wish to connect to.
+ IPEndpoint receiver_endpoint;
+
+ // The path to the file that we want to play.
+ std::string path_to_file;
+
+ // The maximum bitrate. Default value means a reasonable default will be
+ // selected.
+ int max_bitrate = 0;
+
+ // Whether the stream should include video, or just be audio only.
+ bool should_include_video = true;
+
+ // Whether we should use the hacky RTP stream IDs for legacy android
+ // receivers, or if we should use the proper values. For more information,
+ // see https://issuetracker.google.com/184438154.
+ bool use_android_rtp_hack = true;
+
+ // Whether we should use remoting for the video, instead of the default of
+ // mirroring.
+ bool use_remoting = false;
+
+ // Whether we should loop the video when it is completed.
+ bool should_loop_video = true;
+};
+
+} // namespace cast
+} // namespace openscreen
+
+#endif // CAST_STANDALONE_SENDER_CONNECTION_SETTINGS_H_
diff --git a/cast/standalone_sender/looping_file_cast_agent.cc b/cast/standalone_sender/looping_file_cast_agent.cc
index 70d489de..ce9826de 100644
--- a/cast/standalone_sender/looping_file_cast_agent.cc
+++ b/cast/standalone_sender/looping_file_cast_agent.cc
@@ -291,8 +291,8 @@ void LoopingFileCastAgent::OnNegotiated(
}
file_sender_ = std::make_unique<LoopingFileSender>(
- environment_.get(), connection_settings_->path_to_file.c_str(), session,
- std::move(senders), connection_settings_->max_bitrate);
+ environment_.get(), connection_settings_.value(), session,
+ std::move(senders), [this]() { shutdown_callback_(); });
}
void LoopingFileCastAgent::OnRemotingNegotiated(
@@ -307,8 +307,8 @@ void LoopingFileCastAgent::OnRemotingNegotiated(
}
file_sender_ = std::make_unique<LoopingFileSender>(
- environment_.get(), connection_settings_->path_to_file.c_str(), session,
- std::move(negotiation.senders), connection_settings_->max_bitrate);
+ environment_.get(), connection_settings_.value(), session,
+ std::move(negotiation.senders), [this]() { shutdown_callback_(); });
}
void LoopingFileCastAgent::OnError(const SenderSession* session, Error error) {
diff --git a/cast/standalone_sender/looping_file_cast_agent.h b/cast/standalone_sender/looping_file_cast_agent.h
index d1d6b6ce..cff0f6ba 100644
--- a/cast/standalone_sender/looping_file_cast_agent.h
+++ b/cast/standalone_sender/looping_file_cast_agent.h
@@ -19,6 +19,7 @@
#include "cast/common/channel/virtual_connection_router.h"
#include "cast/common/public/cast_socket.h"
#include "cast/sender/public/sender_socket_factory.h"
+#include "cast/standalone_sender/connection_settings.h"
#include "cast/standalone_sender/looping_file_sender.h"
#include "cast/streaming/environment.h"
#include "cast/streaming/sender_session.h"
@@ -78,29 +79,6 @@ class LoopingFileCastAgent final
ShutdownCallback shutdown_callback);
~LoopingFileCastAgent();
- struct ConnectionSettings {
- // The endpoint of the receiver we wish to connect to.
- IPEndpoint receiver_endpoint;
-
- // The path to the file that we want to play.
- std::string path_to_file;
-
- // The maximum bitrate. Default value means a reasonable default will be
- // selected.
- int max_bitrate = 0;
-
- // Whether the stream should include video, or just be audio only.
- bool should_include_video = true;
-
- // Whether we should use the hacky RTP stream IDs for legacy android
- // receivers, or if we should use the proper values.
- bool use_android_rtp_hack = true;
-
- // Whether we should use remoting for the video, instead of the default of
- // mirroring.
- bool use_remoting = false;
- };
-
// Connect to a Cast Receiver, and start the workflow to establish a
// mirroring/streaming session. Destroy the LoopingFileCastAgent to shutdown
// and disconnect.
diff --git a/cast/standalone_sender/looping_file_sender.cc b/cast/standalone_sender/looping_file_sender.cc
index c66722f5..1392c413 100644
--- a/cast/standalone_sender/looping_file_sender.cc
+++ b/cast/standalone_sender/looping_file_sender.cc
@@ -4,20 +4,22 @@
#include "cast/standalone_sender/looping_file_sender.h"
+#include <utility>
+
#include "util/trace_logging.h"
namespace openscreen {
namespace cast {
LoopingFileSender::LoopingFileSender(Environment* environment,
- const char* path,
+ ConnectionSettings settings,
const SenderSession* session,
SenderSession::ConfiguredSenders senders,
- int max_bitrate)
+ ShutdownCallback shutdown_callback)
: env_(environment),
- path_(path),
+ settings_(std::move(settings)),
session_(session),
- max_bitrate_(max_bitrate),
+ shutdown_callback_(std::move(shutdown_callback)),
audio_encoder_(senders.audio_sender->config().channels,
StreamingOpusEncoder::kDefaultCastAudioFramesPerSecond,
senders.audio_sender),
@@ -32,8 +34,8 @@ LoopingFileSender::LoopingFileSender(Environment* environment,
OSP_CHECK(senders.audio_config.codec == AudioCodec::kOpus);
OSP_CHECK(senders.video_config.codec == VideoCodec::kVp8);
OSP_LOG_INFO << "Max allowed media bitrate (audio + video) will be "
- << max_bitrate_;
- bandwidth_being_utilized_ = max_bitrate_ / 2;
+ << settings_.max_bitrate;
+ bandwidth_being_utilized_ = settings_.max_bitrate / 2;
UpdateEncoderBitrates();
next_task_.Schedule([this] { SendFileAgain(); }, Alarm::kImmediately);
@@ -72,7 +74,7 @@ void LoopingFileSender::ControlForNetworkCongestion() {
// Repsect the user's maximum bitrate setting.
bandwidth_being_utilized_ =
- std::min(bandwidth_being_utilized_, max_bitrate_);
+ std::min(bandwidth_being_utilized_, settings_.max_bitrate);
UpdateEncoderBitrates();
} else {
@@ -84,16 +86,18 @@ void LoopingFileSender::ControlForNetworkCongestion() {
}
void LoopingFileSender::SendFileAgain() {
- OSP_LOG_INFO << "Sending " << path_ << " (starts in one second)...";
+ OSP_LOG_INFO << "Sending " << settings_.path_to_file
+ << " (starts in one second)...";
TRACE_DEFAULT_SCOPED(TraceCategory::kStandaloneSender);
OSP_DCHECK_EQ(num_capturers_running_, 0);
num_capturers_running_ = 2;
capture_start_time_ = latest_frame_time_ = env_->now() + seconds(1);
- audio_capturer_.emplace(env_, path_, audio_encoder_.num_channels(),
- audio_encoder_.sample_rate(), capture_start_time_,
- this);
- video_capturer_.emplace(env_, path_, capture_start_time_, this);
+ audio_capturer_.emplace(
+ env_, settings_.path_to_file.c_str(), audio_encoder_.num_channels(),
+ audio_encoder_.sample_rate(), capture_start_time_, this);
+ video_capturer_.emplace(env_, settings_.path_to_file.c_str(),
+ capture_start_time_, this);
next_task_.ScheduleFromNow([this] { ControlForNetworkCongestion(); },
kCongestionCheckInterval);
@@ -156,7 +160,14 @@ void LoopingFileSender::OnEndOfFile(SimulatedCapturer* capturer) {
--num_capturers_running_;
if (num_capturers_running_ == 0) {
console_update_task_.Cancel();
- next_task_.Schedule([this] { SendFileAgain(); }, Alarm::kImmediately);
+
+ if (settings_.should_loop_video) {
+ OSP_DLOG_INFO << "Starting the media stream over again.";
+ next_task_.Schedule([this] { SendFileAgain(); }, Alarm::kImmediately);
+ } else {
+ OSP_DLOG_INFO << "Video complete. Exiting...";
+ shutdown_callback_();
+ }
}
}
diff --git a/cast/standalone_sender/looping_file_sender.h b/cast/standalone_sender/looping_file_sender.h
index e55a4a7e..ef283dc3 100644
--- a/cast/standalone_sender/looping_file_sender.h
+++ b/cast/standalone_sender/looping_file_sender.h
@@ -8,6 +8,7 @@
#include <algorithm>
#include <string>
+#include "cast/standalone_sender/connection_settings.h"
#include "cast/standalone_sender/constants.h"
#include "cast/standalone_sender/simulated_capturer.h"
#include "cast/standalone_sender/streaming_opus_encoder.h"
@@ -22,11 +23,13 @@ namespace cast {
class LoopingFileSender final : public SimulatedAudioCapturer::Client,
public SimulatedVideoCapturer::Client {
public:
+ using ShutdownCallback = std::function<void()>;
+
LoopingFileSender(Environment* environment,
- const char* path,
+ ConnectionSettings settings,
const SenderSession* session,
SenderSession::ConfiguredSenders senders,
- int max_bitrate);
+ ShutdownCallback shutdown_callback);
~LoopingFileSender() final;
@@ -57,14 +60,14 @@ class LoopingFileSender final : public SimulatedAudioCapturer::Client,
// the remote's Receivers.
Environment* const env_;
- // The path to the media file to stream over and over.
- const char* const path_;
+ // The connection settings used for this session.
+ const ConnectionSettings settings_;
// Session to query for bandwidth information.
const SenderSession* session_;
- // User provided maximum bitrate (from command line argument).
- const int max_bitrate_;
+ // Callback for tearing down the sender process.
+ ShutdownCallback shutdown_callback_;
int bandwidth_estimate_ = 0;
int bandwidth_being_utilized_;
diff --git a/cast/standalone_sender/main.cc b/cast/standalone_sender/main.cc
index dd606c00..b7757d97 100644
--- a/cast/standalone_sender/main.cc
+++ b/cast/standalone_sender/main.cc
@@ -54,6 +54,10 @@ usage: %s <options> addr[:port] media_file
Specifies the maximum bits per second for the media streams.
Default if not set: %d
+
+ -n, --no-looping
+ Disable looping the passed in video after it finishes playing.
+
)"
#if defined(CAST_ALLOW_DEVELOPER_CERTIFICATE)
R"(
@@ -109,6 +113,7 @@ int StandaloneSenderMain(int argc, char* argv[]) {
// standalone sender, osp demo, and test_main argument options.
const struct option kArgumentOptions[] = {
{"max-bitrate", required_argument, nullptr, 'm'},
+ {"no-looping", no_argument, nullptr, 'n'},
#if defined(CAST_ALLOW_DEVELOPER_CERTIFICATE)
{"developer-certificate", required_argument, nullptr, 'd'},
#endif
@@ -120,14 +125,15 @@ int StandaloneSenderMain(int argc, char* argv[]) {
{nullptr, 0, nullptr, 0}
};
- bool is_verbose = false;
+ int max_bitrate = kDefaultMaxBitrate;
+ bool should_loop_video = true;
std::string developer_certificate_path;
bool use_android_rtp_hack = false;
bool use_remoting = false;
- int max_bitrate = kDefaultMaxBitrate;
+ bool is_verbose = false;
std::unique_ptr<TextTraceLoggingPlatform> trace_logger;
int ch = -1;
- while ((ch = getopt_long(argc, argv, "m:d:artvh", kArgumentOptions,
+ while ((ch = getopt_long(argc, argv, "m:nd:artvh", kArgumentOptions,
nullptr)) != -1) {
switch (ch) {
case 'm':
@@ -139,6 +145,9 @@ int StandaloneSenderMain(int argc, char* argv[]) {
return 1;
}
break;
+ case 'n':
+ should_loop_video = false;
+ break;
#if defined(CAST_ALLOW_DEVELOPER_CERTIFICATE)
case 'd':
developer_certificate_path = optarg;