Commit 404c38dc authored by John Williams's avatar John Williams Committed by Commit Bot

[Cast MRP] Handle mirror playout delay and sender-side audio playback.

When Cast mirroring, check the media source for streamingCaptureAudio
and streamingTargetPlayoutDelayMillis query parameters, and reflect
them on the mirroring session launch parameters sent to the mirroring
service.

Bug: 1087961, b/156948625
Change-Id: I8b9a6eefa1fbdfdef23aa5866eed30be2b6047b7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2219595
Commit-Queue: John Williams <jrw@chromium.org>
Reviewed-by: default avatarTakumi Fujimoto <takumif@chromium.org>
Cr-Commit-Position: refs/heads/master@{#775188}
parent 774ea8b5
...@@ -165,9 +165,13 @@ void MirroringActivityRecord::CreateMojoBindings( ...@@ -165,9 +165,13 @@ void MirroringActivityRecord::CreateMojoBindings(
break; break;
} }
// Derive session type from capabilities. auto cast_source = CastMediaSource::FromMediaSource(route_.media_source());
DCHECK(cast_source);
// Derive session type from capabilities and media source.
const bool has_audio = (cast_data_.capabilities & const bool has_audio = (cast_data_.capabilities &
static_cast<uint8_t>(cast_channel::AUDIO_OUT)) != 0; static_cast<uint8_t>(cast_channel::AUDIO_OUT)) != 0 &&
cast_source->allow_audio_capture();
const bool has_video = (cast_data_.capabilities & const bool has_video = (cast_data_.capabilities &
static_cast<uint8_t>(cast_channel::VIDEO_OUT)) != 0; static_cast<uint8_t>(cast_channel::VIDEO_OUT)) != 0;
DCHECK(has_audio || has_video); DCHECK(has_audio || has_video);
...@@ -179,11 +183,9 @@ void MirroringActivityRecord::CreateMojoBindings( ...@@ -179,11 +183,9 @@ void MirroringActivityRecord::CreateMojoBindings(
// Arrange to start mirroring once the session is set. // Arrange to start mirroring once the session is set.
on_session_set_ = base::BindOnce( on_session_set_ = base::BindOnce(
&MirroringActivityRecord::StartMirroring, base::Unretained(this), &MirroringActivityRecord::StartMirroring, base::Unretained(this),
// TODO(jophba): update to pass target playout delay, once we are
// copmletely migrated to native MRP.
SessionParameters::New(session_type, cast_data_.ip_endpoint.address(), SessionParameters::New(session_type, cast_data_.ip_endpoint.address(),
cast_data_.model_name, cast_data_.model_name,
/*target_playout_delay*/ base::nullopt), cast_source->target_playout_delay()),
channel_to_service_.BindNewPipeAndPassReceiver()); channel_to_service_.BindNewPipeAndPassReceiver());
} }
......
...@@ -213,6 +213,8 @@ std::unique_ptr<CastMediaSource> CreateFromURLParams( ...@@ -213,6 +213,8 @@ std::unique_ptr<CastMediaSource> CreateFromURLParams(
const std::string& broadcast_namespace, const std::string& broadcast_namespace,
const std::string& encoded_broadcast_message, const std::string& encoded_broadcast_message,
const std::string& launch_timeout_str, const std::string& launch_timeout_str,
const std::string& target_playout_delay_millis_str,
const std::string& audio_capture_str,
const std::vector<ReceiverAppType>& supported_app_types, const std::vector<ReceiverAppType>& supported_app_types,
const std::string& app_params) { const std::string& app_params) {
if (app_infos.empty()) if (app_infos.empty())
...@@ -230,13 +232,24 @@ std::unique_ptr<CastMediaSource> CreateFromURLParams( ...@@ -230,13 +232,24 @@ std::unique_ptr<CastMediaSource> CreateFromURLParams(
broadcast_namespace, DecodeURLComponent(encoded_broadcast_message))); broadcast_namespace, DecodeURLComponent(encoded_broadcast_message)));
} }
int launch_timeout_millis; int launch_timeout_millis = 0;
if (base::StringToInt(launch_timeout_str, &launch_timeout_millis) && if (base::StringToInt(launch_timeout_str, &launch_timeout_millis) &&
launch_timeout_millis > 0) { launch_timeout_millis > 0) {
cast_source->set_launch_timeout( cast_source->set_launch_timeout(
base::TimeDelta::FromMilliseconds(launch_timeout_millis)); base::TimeDelta::FromMilliseconds(launch_timeout_millis));
} }
int target_playout_delay_millis = 0;
if (base::StringToInt(target_playout_delay_millis_str,
&target_playout_delay_millis) &&
target_playout_delay_millis > 0) {
cast_source->set_target_playout_delay(
base::TimeDelta::FromMilliseconds(target_playout_delay_millis));
}
if (audio_capture_str == "0")
cast_source->set_allow_audio_capture(false);
if (!supported_app_types.empty()) if (!supported_app_types.empty())
cast_source->set_supported_app_types(supported_app_types); cast_source->set_supported_app_types(supported_app_types);
cast_source->set_app_params(app_params); cast_source->set_app_params(app_params);
...@@ -262,6 +275,8 @@ std::unique_ptr<CastMediaSource> ParseCastUrl(const MediaSource::Id& source_id, ...@@ -262,6 +275,8 @@ std::unique_ptr<CastMediaSource> ParseCastUrl(const MediaSource::Id& source_id,
FindValueOr(params, "broadcastNamespace", ""), FindValueOr(params, "broadcastNamespace", ""),
FindValueOr(params, "broadcastMessage", ""), FindValueOr(params, "broadcastMessage", ""),
FindValueOr(params, "launchTimeout", ""), FindValueOr(params, "launchTimeout", ""),
FindValueOr(params, "streamingTargetPlayoutDelayMillis", ""),
FindValueOr(params, "streamingCaptureAudio", ""),
SupportedAppTypesFromString(FindValueOr(params, "supportedAppTypes", "")), SupportedAppTypesFromString(FindValueOr(params, "supportedAppTypes", "")),
FindValueOr(params, "appParams", "")); FindValueOr(params, "appParams", ""));
} }
...@@ -321,6 +336,8 @@ std::unique_ptr<CastMediaSource> ParseLegacyCastUrl( ...@@ -321,6 +336,8 @@ std::unique_ptr<CastMediaSource> ParseLegacyCastUrl(
FindValueOr(params, "__castBroadcastNamespace__", ""), FindValueOr(params, "__castBroadcastNamespace__", ""),
FindValueOr(params, "__castBroadcastMessage__", ""), FindValueOr(params, "__castBroadcastMessage__", ""),
FindValueOr(params, "__castLaunchTimeout__", ""), FindValueOr(params, "__castLaunchTimeout__", ""),
/* target_playout_delay_millis_str */ "",
/* audio_capture */ "",
/* supported_app_types */ {}, /* supported_app_types */ {},
/* appParams */ ""); /* appParams */ "");
} }
......
...@@ -165,6 +165,17 @@ class CastMediaSource { ...@@ -165,6 +165,17 @@ class CastMediaSource {
DefaultActionPolicy default_action_policy() const { DefaultActionPolicy default_action_policy() const {
return default_action_policy_; return default_action_policy_;
} }
base::Optional<base::TimeDelta> target_playout_delay() const {
return target_playout_delay_;
}
void set_target_playout_delay(
const base::Optional<base::TimeDelta>& target_playout_delay) {
target_playout_delay_ = target_playout_delay;
}
bool allow_audio_capture() const { return allow_audio_capture_; }
void set_allow_audio_capture(bool allow_audio_capture) {
allow_audio_capture_ = allow_audio_capture;
}
const std::string& app_params() const { return app_params_; } const std::string& app_params() const { return app_params_; }
void set_app_params(const std::string& app_params) { void set_app_params(const std::string& app_params) {
app_params_ = app_params; app_params_ = app_params;
...@@ -180,9 +191,11 @@ class CastMediaSource { ...@@ -180,9 +191,11 @@ class CastMediaSource {
AutoJoinPolicy auto_join_policy_; AutoJoinPolicy auto_join_policy_;
DefaultActionPolicy default_action_policy_; DefaultActionPolicy default_action_policy_;
base::TimeDelta launch_timeout_ = kDefaultLaunchTimeout; base::TimeDelta launch_timeout_ = kDefaultLaunchTimeout;
// Empty if not set. // Optional parameters.
std::string client_id_; std::string client_id_;
base::Optional<cast_channel::BroadcastRequest> broadcast_request_; base::Optional<cast_channel::BroadcastRequest> broadcast_request_;
base::Optional<base::TimeDelta> target_playout_delay_;
bool allow_audio_capture_ = true;
std::vector<ReceiverAppType> supported_app_types_ = {ReceiverAppType::kWeb}; std::vector<ReceiverAppType> supported_app_types_ = {ReceiverAppType::kWeb};
std::string app_params_; std::string app_params_;
}; };
......
...@@ -30,6 +30,8 @@ TEST(CastMediaSourceTest, FromCastURLWithDefaults) { ...@@ -30,6 +30,8 @@ TEST(CastMediaSourceTest, FromCastURLWithDefaults) {
EXPECT_EQ(DefaultActionPolicy::kCreateSession, EXPECT_EQ(DefaultActionPolicy::kCreateSession,
source->default_action_policy()); source->default_action_policy());
EXPECT_EQ(ReceiverAppType::kWeb, source->supported_app_types()[0]); EXPECT_EQ(ReceiverAppType::kWeb, source->supported_app_types()[0]);
EXPECT_EQ(base::nullopt, source->target_playout_delay());
EXPECT_EQ(true, source->allow_audio_capture());
} }
TEST(CastMediaSourceTest, FromCastURL) { TEST(CastMediaSourceTest, FromCastURL) {
...@@ -42,7 +44,9 @@ TEST(CastMediaSourceTest, FromCastURL) { ...@@ -42,7 +44,9 @@ TEST(CastMediaSourceTest, FromCastURL) {
"&autoJoinPolicy=tab_and_origin_scoped" "&autoJoinPolicy=tab_and_origin_scoped"
"&defaultActionPolicy=cast_this_tab" "&defaultActionPolicy=cast_this_tab"
"&appParams=appParams" "&appParams=appParams"
"&supportedAppTypes=ANDROID_TV,WEB"); "&supportedAppTypes=ANDROID_TV,WEB"
"&streamingTargetPlayoutDelayMillis=42"
"&streamingCaptureAudio=0");
std::unique_ptr<CastMediaSource> source = std::unique_ptr<CastMediaSource> source =
CastMediaSource::FromMediaSourceId(source_id); CastMediaSource::FromMediaSourceId(source_id);
ASSERT_TRUE(source); ASSERT_TRUE(source);
...@@ -64,6 +68,9 @@ TEST(CastMediaSourceTest, FromCastURL) { ...@@ -64,6 +68,9 @@ TEST(CastMediaSourceTest, FromCastURL) {
EXPECT_EQ(ReceiverAppType::kAndroidTv, source->supported_app_types()[0]); EXPECT_EQ(ReceiverAppType::kAndroidTv, source->supported_app_types()[0]);
EXPECT_EQ(ReceiverAppType::kWeb, source->supported_app_types()[1]); EXPECT_EQ(ReceiverAppType::kWeb, source->supported_app_types()[1]);
EXPECT_EQ("appParams", source->app_params()); EXPECT_EQ("appParams", source->app_params());
EXPECT_EQ(base::TimeDelta::FromMilliseconds(42),
source->target_playout_delay());
EXPECT_EQ(false, source->allow_audio_capture());
} }
TEST(CastMediaSourceTest, FromLegacyCastURL) { TEST(CastMediaSourceTest, FromLegacyCastURL) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment