Expose AV Settings outside cast_streaming Component
For use with other embedders aside from Fuchsia, the AV Settings (such as valid codecs, screen dimensions, etc...) must be exposed and set-able. This CL makes the following changes: - Expose the openscreen::cast::Preferences object as a top-level parameter for the embedder to provide. - Expose conversion utilities to be used by embedders in creating the above object - Add unit tests to the config conversions file. Bug: 1207721, internal b/182429089 Change-Id: I3af458b0491d2c413b1feee4801542c88e83bdb9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2935034 Reviewed-by: Matthew Wolenetz <wolenetz@chromium.org> Reviewed-by: Fabrice de Gans <fdegans@chromium.org> Reviewed-by: Avi Drissman <avi@chromium.org> Reviewed-by: Mike West <mkwst@chromium.org> Commit-Queue: Ryan Keane <rwkeane@google.com> Cr-Commit-Position: refs/heads/master@{#893086}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
f9e2951503
commit
3381995478
components/cast_streaming
browser
BUILD.gncast_streaming_session.cccast_streaming_session.hconfig_conversions.ccconfig_conversions.h
public
receiver_session_impl.ccreceiver_session_impl.htest
public
fuchsia/engine
@ -22,16 +22,28 @@ source_set("core") {
|
|||||||
sources = [
|
sources = [
|
||||||
"cast_message_port_impl.cc",
|
"cast_message_port_impl.cc",
|
||||||
"cast_message_port_impl.h",
|
"cast_message_port_impl.h",
|
||||||
"config_conversions.cc",
|
|
||||||
"config_conversions.h",
|
|
||||||
"message_serialization.cc",
|
"message_serialization.cc",
|
||||||
"message_serialization.h",
|
"message_serialization.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source_set("receiver_session_public") {
|
||||||
|
deps = [
|
||||||
|
"//base",
|
||||||
|
"//mojo/public/cpp/system",
|
||||||
|
]
|
||||||
|
public_deps = [
|
||||||
|
"//components/cast_streaming/public/mojom",
|
||||||
|
"//third_party/openscreen/src/cast/streaming:receiver",
|
||||||
|
]
|
||||||
|
visibility = [ ":*" ]
|
||||||
|
sources = [ "public/receiver_session.h" ]
|
||||||
|
}
|
||||||
|
|
||||||
source_set("receiver_session") {
|
source_set("receiver_session") {
|
||||||
deps = [
|
deps = [
|
||||||
":core",
|
":core",
|
||||||
|
":receiver_session_public",
|
||||||
":streaming_session",
|
":streaming_session",
|
||||||
"//base",
|
"//base",
|
||||||
"//media",
|
"//media",
|
||||||
@ -41,10 +53,9 @@ source_set("receiver_session") {
|
|||||||
]
|
]
|
||||||
public_deps = [
|
public_deps = [
|
||||||
"//components/cast_streaming/public/mojom",
|
"//components/cast_streaming/public/mojom",
|
||||||
"//third_party/openscreen/src/cast/common:channel",
|
"//third_party/openscreen/src/cast/streaming:receiver",
|
||||||
]
|
]
|
||||||
visibility = [ ":*" ]
|
visibility = [ ":*" ]
|
||||||
public = [ "public/receiver_session.h" ]
|
|
||||||
sources = [
|
sources = [
|
||||||
"receiver_session_impl.cc",
|
"receiver_session_impl.cc",
|
||||||
"receiver_session_impl.h",
|
"receiver_session_impl.h",
|
||||||
@ -54,7 +65,9 @@ source_set("receiver_session") {
|
|||||||
source_set("streaming_session") {
|
source_set("streaming_session") {
|
||||||
deps = [
|
deps = [
|
||||||
":core",
|
":core",
|
||||||
|
":receiver_session_public",
|
||||||
"//base",
|
"//base",
|
||||||
|
"//components/cast_streaming/public",
|
||||||
"//components/openscreen_platform",
|
"//components/openscreen_platform",
|
||||||
"//media",
|
"//media",
|
||||||
"//media/mojo/common",
|
"//media/mojo/common",
|
||||||
@ -84,13 +97,12 @@ source_set("network_context") {
|
|||||||
sources = [ "network_context_getter.cc" ]
|
sources = [ "network_context_getter.cc" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO(crbug.com/1208194): Also move cast_streaming_session_client here from
|
|
||||||
# //fuchsia.
|
|
||||||
source_set("browser") {
|
source_set("browser") {
|
||||||
public_deps = [
|
public_deps = [
|
||||||
":network_context",
|
":network_context",
|
||||||
":receiver_session",
|
":receiver_session_public",
|
||||||
]
|
]
|
||||||
|
deps = [ ":receiver_session" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO(crbug.com/1207715): Move to /tests directory.
|
# TODO(crbug.com/1207715): Move to /tests directory.
|
||||||
@ -98,6 +110,7 @@ source_set("test_sender") {
|
|||||||
testonly = true
|
testonly = true
|
||||||
deps = [
|
deps = [
|
||||||
":core",
|
":core",
|
||||||
|
"//components/cast_streaming/public",
|
||||||
"//media/mojo/common",
|
"//media/mojo/common",
|
||||||
"//media/mojo/mojom",
|
"//media/mojo/mojom",
|
||||||
"//mojo/public/cpp/system",
|
"//mojo/public/cpp/system",
|
||||||
@ -125,6 +138,7 @@ source_set("test_receiver") {
|
|||||||
deps = [
|
deps = [
|
||||||
":streaming_session",
|
":streaming_session",
|
||||||
"//base",
|
"//base",
|
||||||
|
"//components/cast_streaming/public",
|
||||||
"//components/openscreen_platform",
|
"//components/openscreen_platform",
|
||||||
"//media",
|
"//media",
|
||||||
"//media/mojo/common",
|
"//media/mojo/common",
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/time/time.h"
|
#include "base/time/time.h"
|
||||||
#include "components/cast_streaming/browser/config_conversions.h"
|
|
||||||
#include "components/cast_streaming/browser/stream_consumer.h"
|
#include "components/cast_streaming/browser/stream_consumer.h"
|
||||||
|
#include "components/cast_streaming/public/config_conversions.h"
|
||||||
#include "media/base/timestamp_constants.h"
|
#include "media/base/timestamp_constants.h"
|
||||||
#include "media/mojo/common/mojo_decoder_buffer_converter.h"
|
#include "media/mojo/common/mojo_decoder_buffer_converter.h"
|
||||||
#include "mojo/public/cpp/system/data_pipe.h"
|
#include "mojo/public/cpp/system/data_pipe.h"
|
||||||
@ -38,6 +38,7 @@ namespace cast_streaming {
|
|||||||
|
|
||||||
CastStreamingSession::ReceiverSessionClient::ReceiverSessionClient(
|
CastStreamingSession::ReceiverSessionClient::ReceiverSessionClient(
|
||||||
CastStreamingSession::Client* client,
|
CastStreamingSession::Client* client,
|
||||||
|
std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
|
||||||
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
|
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner)
|
scoped_refptr<base::SequencedTaskRunner> task_runner)
|
||||||
: task_runner_(task_runner),
|
: task_runner_(task_runner),
|
||||||
@ -51,15 +52,9 @@ CastStreamingSession::ReceiverSessionClient::ReceiverSessionClient(
|
|||||||
DCHECK(task_runner);
|
DCHECK(task_runner);
|
||||||
DCHECK(client_);
|
DCHECK(client_);
|
||||||
|
|
||||||
// TODO(crbug.com/1087520): Add streaming session Constraints and
|
|
||||||
// DisplayDescription.
|
|
||||||
receiver_session_ = std::make_unique<openscreen::cast::ReceiverSession>(
|
receiver_session_ = std::make_unique<openscreen::cast::ReceiverSession>(
|
||||||
this, &environment_, &cast_message_port_impl_,
|
this, &environment_, &cast_message_port_impl_,
|
||||||
openscreen::cast::ReceiverSession::Preferences(
|
std::move(*av_constraints));
|
||||||
{openscreen::cast::VideoCodec::kH264,
|
|
||||||
openscreen::cast::VideoCodec::kVp8},
|
|
||||||
{openscreen::cast::AudioCodec::kAac,
|
|
||||||
openscreen::cast::AudioCodec::kOpus}));
|
|
||||||
|
|
||||||
init_timeout_timer_.Start(
|
init_timeout_timer_.Start(
|
||||||
FROM_HERE, kInitTimeout,
|
FROM_HERE, kInitTimeout,
|
||||||
@ -102,9 +97,8 @@ CastStreamingSession::ReceiverSessionClient::InitializeAudioConsumer(
|
|||||||
base::BindRepeating(&base::OneShotTimer::Reset,
|
base::BindRepeating(&base::OneShotTimer::Reset,
|
||||||
base::Unretained(&data_timeout_timer_)));
|
base::Unretained(&data_timeout_timer_)));
|
||||||
|
|
||||||
return AudioStreamInfo{
|
return AudioStreamInfo{ToAudioDecoderConfig(audio_capture_config),
|
||||||
AudioCaptureConfigToAudioDecoderConfig(audio_capture_config),
|
std::move(data_pipe_consumer)};
|
||||||
std::move(data_pipe_consumer)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<CastStreamingSession::VideoStreamInfo>
|
absl::optional<CastStreamingSession::VideoStreamInfo>
|
||||||
@ -137,9 +131,8 @@ CastStreamingSession::ReceiverSessionClient::InitializeVideoConsumer(
|
|||||||
base::BindRepeating(&base::OneShotTimer::Reset,
|
base::BindRepeating(&base::OneShotTimer::Reset,
|
||||||
base::Unretained(&data_timeout_timer_)));
|
base::Unretained(&data_timeout_timer_)));
|
||||||
|
|
||||||
return VideoStreamInfo{
|
return VideoStreamInfo{ToVideoDecoderConfig(video_capture_config),
|
||||||
VideoCaptureConfigToVideoDecoderConfig(video_capture_config),
|
std::move(data_pipe_consumer)};
|
||||||
std::move(data_pipe_consumer)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastStreamingSession::ReceiverSessionClient::OnNegotiated(
|
void CastStreamingSession::ReceiverSessionClient::OnNegotiated(
|
||||||
@ -266,13 +259,14 @@ CastStreamingSession::~CastStreamingSession() = default;
|
|||||||
|
|
||||||
void CastStreamingSession::Start(
|
void CastStreamingSession::Start(
|
||||||
Client* client,
|
Client* client,
|
||||||
|
std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
|
||||||
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
|
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
||||||
DVLOG(1) << __func__;
|
DVLOG(1) << __func__;
|
||||||
DCHECK(client);
|
DCHECK(client);
|
||||||
DCHECK(!receiver_session_);
|
DCHECK(!receiver_session_);
|
||||||
receiver_session_ = std::make_unique<ReceiverSessionClient>(
|
receiver_session_ = std::make_unique<ReceiverSessionClient>(
|
||||||
client, std::move(message_port), task_runner);
|
client, std::move(av_constraints), std::move(message_port), task_runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastStreamingSession::Stop() {
|
void CastStreamingSession::Stop() {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "base/timer/timer.h"
|
#include "base/timer/timer.h"
|
||||||
#include "components/cast/message_port/message_port.h"
|
#include "components/cast/message_port/message_port.h"
|
||||||
#include "components/cast_streaming/browser/cast_message_port_impl.h"
|
#include "components/cast_streaming/browser/cast_message_port_impl.h"
|
||||||
|
#include "components/cast_streaming/browser/public/receiver_session.h"
|
||||||
#include "components/openscreen_platform/network_util.h"
|
#include "components/openscreen_platform/network_util.h"
|
||||||
#include "components/openscreen_platform/task_runner.h"
|
#include "components/openscreen_platform/task_runner.h"
|
||||||
#include "media/base/audio_decoder_config.h"
|
#include "media/base/audio_decoder_config.h"
|
||||||
@ -85,7 +86,11 @@ class CastStreamingSession {
|
|||||||
// * On failure, OnSessionEnded() will be called.
|
// * On failure, OnSessionEnded() will be called.
|
||||||
// * When a new offer is sent by the Cast Streaming Sender,
|
// * When a new offer is sent by the Cast Streaming Sender,
|
||||||
// OnSessionReinitialization() will be called.
|
// OnSessionReinitialization() will be called.
|
||||||
|
//
|
||||||
|
// |av_constraints| specifies the supported media codecs and limitations
|
||||||
|
// surrounding this support.
|
||||||
void Start(Client* client,
|
void Start(Client* client,
|
||||||
|
std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
|
||||||
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
|
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
||||||
|
|
||||||
@ -101,6 +106,7 @@ class CastStreamingSession {
|
|||||||
public:
|
public:
|
||||||
ReceiverSessionClient(
|
ReceiverSessionClient(
|
||||||
CastStreamingSession::Client* client,
|
CastStreamingSession::Client* client,
|
||||||
|
std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
|
||||||
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
|
std::unique_ptr<cast_api_bindings::MessagePort> message_port,
|
||||||
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
||||||
~ReceiverSessionClient() final;
|
~ReceiverSessionClient() final;
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
#include "components/cast_streaming/browser/config_conversions.h"
|
|
||||||
|
|
||||||
#include "base/notreached.h"
|
|
||||||
#include "media/base/media_util.h"
|
|
||||||
|
|
||||||
namespace cast_streaming {
|
|
||||||
|
|
||||||
openscreen::cast::AudioCaptureConfig AudioDecoderConfigToAudioCaptureConfig(
|
|
||||||
const media::AudioDecoderConfig& audio_config) {
|
|
||||||
openscreen::cast::AudioCaptureConfig audio_capture_config;
|
|
||||||
|
|
||||||
switch (audio_config.codec()) {
|
|
||||||
case media::AudioCodec::kCodecAAC:
|
|
||||||
audio_capture_config.codec = openscreen::cast::AudioCodec::kAac;
|
|
||||||
break;
|
|
||||||
case media::AudioCodec::kCodecOpus:
|
|
||||||
audio_capture_config.codec = openscreen::cast::AudioCodec::kOpus;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NOTREACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_capture_config.channels =
|
|
||||||
media::ChannelLayoutToChannelCount(audio_config.channel_layout());
|
|
||||||
audio_capture_config.sample_rate = audio_config.samples_per_second();
|
|
||||||
|
|
||||||
return audio_capture_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
openscreen::cast::VideoCaptureConfig VideoDecoderConfigToVideoCaptureConfig(
|
|
||||||
const media::VideoDecoderConfig& video_config) {
|
|
||||||
openscreen::cast::VideoCaptureConfig video_capture_config;
|
|
||||||
|
|
||||||
switch (video_config.codec()) {
|
|
||||||
case media::VideoCodec::kCodecH264:
|
|
||||||
video_capture_config.codec = openscreen::cast::VideoCodec::kH264;
|
|
||||||
break;
|
|
||||||
case media::VideoCodec::kCodecVP8:
|
|
||||||
video_capture_config.codec = openscreen::cast::VideoCodec::kVp8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NOTREACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
video_capture_config.resolutions.push_back(
|
|
||||||
{video_config.visible_rect().width(),
|
|
||||||
video_config.visible_rect().height()});
|
|
||||||
return video_capture_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
media::AudioDecoderConfig AudioCaptureConfigToAudioDecoderConfig(
|
|
||||||
const openscreen::cast::AudioCaptureConfig& audio_capture_config) {
|
|
||||||
// Gather data for the audio decoder config.
|
|
||||||
media::AudioCodec media_audio_codec = media::AudioCodec::kUnknownAudioCodec;
|
|
||||||
switch (audio_capture_config.codec) {
|
|
||||||
case openscreen::cast::AudioCodec::kAac:
|
|
||||||
media_audio_codec = media::AudioCodec::kCodecAAC;
|
|
||||||
break;
|
|
||||||
case openscreen::cast::AudioCodec::kOpus:
|
|
||||||
media_audio_codec = media::AudioCodec::kCodecOpus;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NOTREACHED();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return media::AudioDecoderConfig(
|
|
||||||
media_audio_codec, media::SampleFormat::kSampleFormatF32,
|
|
||||||
media::GuessChannelLayout(audio_capture_config.channels),
|
|
||||||
audio_capture_config.sample_rate /* samples_per_second */,
|
|
||||||
media::EmptyExtraData(), media::EncryptionScheme::kUnencrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
media::VideoDecoderConfig VideoCaptureConfigToVideoDecoderConfig(
|
|
||||||
const openscreen::cast::VideoCaptureConfig& video_capture_config) {
|
|
||||||
// Gather data for the video decoder config.
|
|
||||||
uint32_t video_width = video_capture_config.resolutions[0].width;
|
|
||||||
uint32_t video_height = video_capture_config.resolutions[0].height;
|
|
||||||
gfx::Size video_size(video_width, video_height);
|
|
||||||
gfx::Rect video_rect(video_width, video_height);
|
|
||||||
|
|
||||||
media::VideoCodec media_video_codec = media::VideoCodec::kUnknownVideoCodec;
|
|
||||||
media::VideoCodecProfile video_codec_profile =
|
|
||||||
media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
|
|
||||||
switch (video_capture_config.codec) {
|
|
||||||
case openscreen::cast::VideoCodec::kH264:
|
|
||||||
media_video_codec = media::VideoCodec::kCodecH264;
|
|
||||||
video_codec_profile = media::VideoCodecProfile::H264PROFILE_BASELINE;
|
|
||||||
break;
|
|
||||||
case openscreen::cast::VideoCodec::kVp8:
|
|
||||||
media_video_codec = media::VideoCodec::kCodecVP8;
|
|
||||||
video_codec_profile = media::VideoCodecProfile::VP8PROFILE_MIN;
|
|
||||||
break;
|
|
||||||
case openscreen::cast::VideoCodec::kHevc:
|
|
||||||
case openscreen::cast::VideoCodec::kVp9:
|
|
||||||
default:
|
|
||||||
NOTREACHED();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return media::VideoDecoderConfig(
|
|
||||||
media_video_codec, video_codec_profile,
|
|
||||||
media::VideoDecoderConfig::AlphaMode::kIsOpaque, media::VideoColorSpace(),
|
|
||||||
media::VideoTransformation(), video_size, video_rect, video_size,
|
|
||||||
media::EmptyExtraData(), media::EncryptionScheme::kUnencrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace cast_streaming
|
|
@ -1,30 +0,0 @@
|
|||||||
// 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 COMPONENTS_CAST_STREAMING_BROWSER_CONFIG_CONVERSIONS_H_
|
|
||||||
#define COMPONENTS_CAST_STREAMING_BROWSER_CONFIG_CONVERSIONS_H_
|
|
||||||
|
|
||||||
#include "media/base/audio_decoder_config.h"
|
|
||||||
#include "media/base/video_decoder_config.h"
|
|
||||||
#include "third_party/openscreen/src/cast/streaming/capture_configs.h"
|
|
||||||
|
|
||||||
namespace cast_streaming {
|
|
||||||
|
|
||||||
// Utility functions to convert between media and Open Screen types.
|
|
||||||
|
|
||||||
openscreen::cast::AudioCaptureConfig AudioDecoderConfigToAudioCaptureConfig(
|
|
||||||
const media::AudioDecoderConfig& audio_config);
|
|
||||||
|
|
||||||
openscreen::cast::VideoCaptureConfig VideoDecoderConfigToVideoCaptureConfig(
|
|
||||||
const media::VideoDecoderConfig& video_config);
|
|
||||||
|
|
||||||
media::AudioDecoderConfig AudioCaptureConfigToAudioDecoderConfig(
|
|
||||||
const openscreen::cast::AudioCaptureConfig& audio_capture_config);
|
|
||||||
|
|
||||||
media::VideoDecoderConfig VideoCaptureConfigToVideoDecoderConfig(
|
|
||||||
const openscreen::cast::VideoCaptureConfig& video_capture_config);
|
|
||||||
|
|
||||||
} // namespace cast_streaming
|
|
||||||
|
|
||||||
#endif // COMPONENTS_CAST_STREAMING_BROWSER_CONFIG_CONVERSIONS_H_
|
|
@ -10,6 +10,7 @@
|
|||||||
#include "base/callback.h"
|
#include "base/callback.h"
|
||||||
#include "components/cast_streaming/public/mojom/cast_streaming_session.mojom.h"
|
#include "components/cast_streaming/public/mojom/cast_streaming_session.mojom.h"
|
||||||
#include "mojo/public/cpp/bindings/associated_remote.h"
|
#include "mojo/public/cpp/bindings/associated_remote.h"
|
||||||
|
#include "third_party/openscreen/src/cast/streaming/receiver_session.h"
|
||||||
|
|
||||||
namespace cast_api_bindings {
|
namespace cast_api_bindings {
|
||||||
class MessagePort;
|
class MessagePort;
|
||||||
@ -21,14 +22,25 @@ namespace cast_streaming {
|
|||||||
// |message_port| and with a given |cast_streaming_receiver|. On destruction,
|
// |message_port| and with a given |cast_streaming_receiver|. On destruction,
|
||||||
// the Cast Streaming Receiver Session will be terminated if it was ever
|
// the Cast Streaming Receiver Session will be terminated if it was ever
|
||||||
// started.
|
// started.
|
||||||
|
// TODO(1220176): Forward declare ReceiverSession::Preferences instead of
|
||||||
|
// requiring the import above.
|
||||||
class ReceiverSession {
|
class ReceiverSession {
|
||||||
public:
|
public:
|
||||||
using MessagePortProvider =
|
using MessagePortProvider =
|
||||||
base::OnceCallback<std::unique_ptr<cast_api_bindings::MessagePort>()>;
|
base::OnceCallback<std::unique_ptr<cast_api_bindings::MessagePort>()>;
|
||||||
|
using AVConstraints = openscreen::cast::ReceiverSession::Preferences;
|
||||||
|
|
||||||
virtual ~ReceiverSession() = default;
|
virtual ~ReceiverSession() = default;
|
||||||
|
|
||||||
|
// |av_constraints| specifies the supported media codecs, an ordering to
|
||||||
|
// signify the receiver's preferences of which codecs should be used, and any
|
||||||
|
// limitations surrounding this support.
|
||||||
|
// |message_port_provider| creates a new MessagePort to be used for sending
|
||||||
|
// and receiving Cast messages.
|
||||||
|
// TODO(crbug.com/1219079): Add conversion functions to create the
|
||||||
|
// ReceiverSession::Preferences object from //media types.
|
||||||
static std::unique_ptr<ReceiverSession> Create(
|
static std::unique_ptr<ReceiverSession> Create(
|
||||||
|
std::unique_ptr<AVConstraints> av_constraints,
|
||||||
MessagePortProvider message_port_provider);
|
MessagePortProvider message_port_provider);
|
||||||
|
|
||||||
// Sets up the CastStreamingReceiver mojo remote. This will immediately call
|
// Sets up the CastStreamingReceiver mojo remote. This will immediately call
|
||||||
|
@ -13,14 +13,19 @@ namespace cast_streaming {
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
std::unique_ptr<ReceiverSession> ReceiverSession::Create(
|
std::unique_ptr<ReceiverSession> ReceiverSession::Create(
|
||||||
|
std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
|
||||||
ReceiverSession::MessagePortProvider message_port_provider) {
|
ReceiverSession::MessagePortProvider message_port_provider) {
|
||||||
return std::make_unique<ReceiverSessionImpl>(
|
return std::make_unique<ReceiverSessionImpl>(
|
||||||
std::move(message_port_provider));
|
std::move(av_constraints), std::move(message_port_provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReceiverSessionImpl::ReceiverSessionImpl(
|
ReceiverSessionImpl::ReceiverSessionImpl(
|
||||||
|
std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
|
||||||
ReceiverSession::MessagePortProvider message_port_provider)
|
ReceiverSession::MessagePortProvider message_port_provider)
|
||||||
: message_port_provider_(std::move(message_port_provider)) {
|
: message_port_provider_(std::move(message_port_provider)),
|
||||||
|
av_constraints_(std::move(av_constraints)) {
|
||||||
|
// TODO(crbug.com/1218495): Validate the provided codecs against build flags.
|
||||||
|
DCHECK(av_constraints_);
|
||||||
DCHECK(message_port_provider_);
|
DCHECK(message_port_provider_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +49,8 @@ void ReceiverSessionImpl::SetCastStreamingReceiver(
|
|||||||
void ReceiverSessionImpl::OnReceiverEnabled() {
|
void ReceiverSessionImpl::OnReceiverEnabled() {
|
||||||
DVLOG(1) << __func__;
|
DVLOG(1) << __func__;
|
||||||
DCHECK(message_port_provider_);
|
DCHECK(message_port_provider_);
|
||||||
cast_streaming_session_.Start(this, std::move(message_port_provider_).Run(),
|
cast_streaming_session_.Start(this, std::move(av_constraints_),
|
||||||
|
std::move(message_port_provider_).Run(),
|
||||||
base::SequencedTaskRunnerHandle::Get());
|
base::SequencedTaskRunnerHandle::Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +134,7 @@ void ReceiverSessionImpl::OnMojoDisconnect() {
|
|||||||
|
|
||||||
// Close the underlying connection.
|
// Close the underlying connection.
|
||||||
if (message_port_provider_) {
|
if (message_port_provider_) {
|
||||||
|
av_constraints_ = std::make_unique<ReceiverSession::AVConstraints>();
|
||||||
std::move(message_port_provider_).Run().reset();
|
std::move(message_port_provider_).Run().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,11 @@ namespace cast_streaming {
|
|||||||
class ReceiverSessionImpl : public cast_streaming::CastStreamingSession::Client,
|
class ReceiverSessionImpl : public cast_streaming::CastStreamingSession::Client,
|
||||||
public ReceiverSession {
|
public ReceiverSession {
|
||||||
public:
|
public:
|
||||||
explicit ReceiverSessionImpl(MessagePortProvider message_port_provider);
|
// |av_constraints| specifies the supported media codecs and limitations
|
||||||
|
// surrounding this support.
|
||||||
|
ReceiverSessionImpl(
|
||||||
|
std::unique_ptr<ReceiverSession::AVConstraints> av_constraints,
|
||||||
|
MessagePortProvider message_port_provider);
|
||||||
~ReceiverSessionImpl() final;
|
~ReceiverSessionImpl() final;
|
||||||
|
|
||||||
ReceiverSessionImpl(const ReceiverSessionImpl&) = delete;
|
ReceiverSessionImpl(const ReceiverSessionImpl&) = delete;
|
||||||
@ -55,6 +59,7 @@ class ReceiverSessionImpl : public cast_streaming::CastStreamingSession::Client,
|
|||||||
// Populated in the ctor, and empty following a call to either
|
// Populated in the ctor, and empty following a call to either
|
||||||
// OnReceiverEnabled() or OnMojoDisconnect().
|
// OnReceiverEnabled() or OnMojoDisconnect().
|
||||||
MessagePortProvider message_port_provider_;
|
MessagePortProvider message_port_provider_;
|
||||||
|
std::unique_ptr<ReceiverSession::AVConstraints> av_constraints_;
|
||||||
|
|
||||||
mojo::AssociatedRemote<mojom::CastStreamingReceiver> cast_streaming_receiver_;
|
mojo::AssociatedRemote<mojom::CastStreamingReceiver> cast_streaming_receiver_;
|
||||||
cast_streaming::CastStreamingSession cast_streaming_session_;
|
cast_streaming::CastStreamingSession cast_streaming_session_;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/run_loop.h"
|
#include "base/run_loop.h"
|
||||||
#include "base/threading/sequenced_task_runner_handle.h"
|
#include "base/threading/sequenced_task_runner_handle.h"
|
||||||
|
#include "components/cast_streaming/public/config_conversions.h"
|
||||||
|
|
||||||
namespace cast_streaming {
|
namespace cast_streaming {
|
||||||
|
|
||||||
@ -16,7 +17,14 @@ CastStreamingTestReceiver::~CastStreamingTestReceiver() = default;
|
|||||||
void CastStreamingTestReceiver::Start(
|
void CastStreamingTestReceiver::Start(
|
||||||
std::unique_ptr<cast_api_bindings::MessagePort> message_port) {
|
std::unique_ptr<cast_api_bindings::MessagePort> message_port) {
|
||||||
VLOG(1) << __func__;
|
VLOG(1) << __func__;
|
||||||
receiver_session_.Start(this, std::move(message_port),
|
auto stream_config =
|
||||||
|
std::make_unique<cast_streaming::ReceiverSession::AVConstraints>(
|
||||||
|
ToVideoCaptureConfigCodecs(media::VideoCodec::kCodecH264,
|
||||||
|
media::VideoCodec::kCodecVP8),
|
||||||
|
ToAudioCaptureConfigCodecs(media::AudioCodec::kCodecAAC,
|
||||||
|
media::AudioCodec::kCodecOpus));
|
||||||
|
receiver_session_.Start(this, std::move(stream_config),
|
||||||
|
std::move(message_port),
|
||||||
base::SequencedTaskRunnerHandle::Get());
|
base::SequencedTaskRunnerHandle::Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/run_loop.h"
|
#include "base/run_loop.h"
|
||||||
#include "base/threading/sequenced_task_runner_handle.h"
|
#include "base/threading/sequenced_task_runner_handle.h"
|
||||||
#include "components/cast_streaming/browser/config_conversions.h"
|
#include "components/cast_streaming/public/config_conversions.h"
|
||||||
#include "third_party/openscreen/src/cast/streaming/capture_recommendations.h"
|
#include "third_party/openscreen/src/cast/streaming/capture_recommendations.h"
|
||||||
|
|
||||||
namespace cast_streaming {
|
namespace cast_streaming {
|
||||||
@ -88,14 +88,12 @@ bool CastStreamingTestSender::Start(
|
|||||||
|
|
||||||
std::vector<openscreen::cast::AudioCaptureConfig> audio_configs;
|
std::vector<openscreen::cast::AudioCaptureConfig> audio_configs;
|
||||||
if (audio_config) {
|
if (audio_config) {
|
||||||
audio_configs.push_back(
|
audio_configs.push_back(ToAudioCaptureConfig(audio_config.value()));
|
||||||
AudioDecoderConfigToAudioCaptureConfig(audio_config.value()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<openscreen::cast::VideoCaptureConfig> video_configs;
|
std::vector<openscreen::cast::VideoCaptureConfig> video_configs;
|
||||||
if (video_config) {
|
if (video_config) {
|
||||||
video_configs.push_back(
|
video_configs.push_back(ToVideoCaptureConfig(video_config.value()));
|
||||||
VideoDecoderConfigToVideoCaptureConfig(video_config.value()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
openscreen::Error error = sender_session_->Negotiate(
|
openscreen::Error error = sender_session_->Negotiate(
|
||||||
@ -191,14 +189,12 @@ void CastStreamingTestSender::OnNegotiated(
|
|||||||
|
|
||||||
if (senders.audio_sender) {
|
if (senders.audio_sender) {
|
||||||
audio_sender_ = senders.audio_sender;
|
audio_sender_ = senders.audio_sender;
|
||||||
audio_decoder_config_ =
|
audio_decoder_config_ = ToAudioDecoderConfig(senders.audio_config);
|
||||||
AudioCaptureConfigToAudioDecoderConfig(senders.audio_config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (senders.video_sender) {
|
if (senders.video_sender) {
|
||||||
video_sender_ = senders.video_sender;
|
video_sender_ = senders.video_sender;
|
||||||
video_decoder_config_ =
|
video_decoder_config_ = ToVideoDecoderConfig(senders.video_config);
|
||||||
VideoCaptureConfigToVideoDecoderConfig(senders.video_config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is_active_ = true;
|
is_active_ = true;
|
||||||
|
@ -5,18 +5,33 @@
|
|||||||
import("//testing/test.gni")
|
import("//testing/test.gni")
|
||||||
|
|
||||||
source_set("public") {
|
source_set("public") {
|
||||||
deps = [ "//url" ]
|
deps = [
|
||||||
|
"//base",
|
||||||
|
"//media",
|
||||||
|
"//ui/gfx/geometry",
|
||||||
|
"//url",
|
||||||
|
]
|
||||||
|
public_deps = [
|
||||||
|
"//third_party/openscreen/src/cast/streaming:receiver",
|
||||||
|
"//third_party/openscreen/src/cast/streaming:streaming_configs",
|
||||||
|
]
|
||||||
sources = [
|
sources = [
|
||||||
"cast_streaming_url.cc",
|
"cast_streaming_url.cc",
|
||||||
"cast_streaming_url.h",
|
"cast_streaming_url.h",
|
||||||
|
"config_conversions.cc",
|
||||||
|
"config_conversions.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
# NOTE: This source set is intentionally empty. It is used to force the building
|
|
||||||
# of the code defined in this directory, as it is production code which must
|
|
||||||
# be validated as part of the CQ.
|
|
||||||
source_set("unit_tests") {
|
source_set("unit_tests") {
|
||||||
testonly = true
|
testonly = true
|
||||||
deps = [ ":public" ]
|
deps = [
|
||||||
sources = []
|
":public",
|
||||||
|
"//base/test:test_support",
|
||||||
|
"//media:test_support",
|
||||||
|
"//media/mojo:test_support",
|
||||||
|
"//testing/gmock",
|
||||||
|
"//testing/gtest",
|
||||||
|
]
|
||||||
|
sources = [ "config_conversions_unittest.cc" ]
|
||||||
}
|
}
|
||||||
|
6
components/cast_streaming/public/DEPS
Normal file
6
components/cast_streaming/public/DEPS
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
include_rules = [
|
||||||
|
"+media/base",
|
||||||
|
"+third_party/openscreen/src/cast",
|
||||||
|
"+ui/gfx/geometry",
|
||||||
|
"+url",
|
||||||
|
]
|
166
components/cast_streaming/public/config_conversions.cc
Normal file
166
components/cast_streaming/public/config_conversions.cc
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "components/cast_streaming/public/config_conversions.h"
|
||||||
|
|
||||||
|
#include "base/check.h"
|
||||||
|
#include "base/notreached.h"
|
||||||
|
#include "media/base/media_util.h"
|
||||||
|
#include "ui/gfx/geometry/rect.h"
|
||||||
|
#include "ui/gfx/geometry/size.h"
|
||||||
|
|
||||||
|
namespace cast_streaming {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
media::VideoCodecProfile ToVideoDecoderConfigCodecProfile(
|
||||||
|
openscreen::cast::VideoCodec codec) {
|
||||||
|
switch (codec) {
|
||||||
|
// TODO(b/186875732): Determine the values for Hevc and Vp9 experimentally.
|
||||||
|
case openscreen::cast::VideoCodec::kH264:
|
||||||
|
return media::VideoCodecProfile::H264PROFILE_BASELINE;
|
||||||
|
case openscreen::cast::VideoCodec::kHevc:
|
||||||
|
return media::VideoCodecProfile::HEVCPROFILE_MAIN;
|
||||||
|
case openscreen::cast::VideoCodec::kVp8:
|
||||||
|
return media::VideoCodecProfile::VP8PROFILE_MIN;
|
||||||
|
case openscreen::cast::VideoCodec::kVp9:
|
||||||
|
return media::VideoCodecProfile::VP9PROFILE_PROFILE0;
|
||||||
|
case openscreen::cast::VideoCodec::kNotSpecified:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NOTREACHED();
|
||||||
|
return media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
media::AudioCodec ToAudioDecoderConfigCodec(
|
||||||
|
openscreen::cast::AudioCodec codec) {
|
||||||
|
switch (codec) {
|
||||||
|
case openscreen::cast::AudioCodec::kAac:
|
||||||
|
return media::AudioCodec::kCodecAAC;
|
||||||
|
case openscreen::cast::AudioCodec::kOpus:
|
||||||
|
return media::AudioCodec::kCodecOpus;
|
||||||
|
case openscreen::cast::AudioCodec::kNotSpecified:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NOTREACHED();
|
||||||
|
return media::AudioCodec::kUnknownAudioCodec;
|
||||||
|
}
|
||||||
|
|
||||||
|
media::VideoCodec ToVideoDecoderConfigCodec(
|
||||||
|
openscreen::cast::VideoCodec codec) {
|
||||||
|
switch (codec) {
|
||||||
|
case openscreen::cast::VideoCodec::kH264:
|
||||||
|
return media::VideoCodec::kCodecH264;
|
||||||
|
case openscreen::cast::VideoCodec::kVp8:
|
||||||
|
return media::VideoCodec::kCodecVP8;
|
||||||
|
case openscreen::cast::VideoCodec::kHevc:
|
||||||
|
return media::VideoCodec::kCodecHEVC;
|
||||||
|
case openscreen::cast::VideoCodec::kVp9:
|
||||||
|
return media::VideoCodec::kCodecVP9;
|
||||||
|
case openscreen::cast::VideoCodec::kNotSpecified:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NOTREACHED();
|
||||||
|
return media::VideoCodec::kUnknownVideoCodec;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
openscreen::cast::AudioCodec ToAudioCaptureConfigCodec(
|
||||||
|
media::AudioCodec codec) {
|
||||||
|
switch (codec) {
|
||||||
|
case media::AudioCodec::kCodecAAC:
|
||||||
|
return openscreen::cast::AudioCodec::kAac;
|
||||||
|
case media::AudioCodec::kCodecOpus:
|
||||||
|
return openscreen::cast::AudioCodec::kOpus;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NOTREACHED();
|
||||||
|
return openscreen::cast::AudioCodec::kNotSpecified;
|
||||||
|
}
|
||||||
|
|
||||||
|
openscreen::cast::VideoCodec ToVideoCaptureConfigCodec(
|
||||||
|
media::VideoCodec codec) {
|
||||||
|
switch (codec) {
|
||||||
|
case media::VideoCodec::kCodecH264:
|
||||||
|
return openscreen::cast::VideoCodec::kH264;
|
||||||
|
case media::VideoCodec::kCodecVP8:
|
||||||
|
return openscreen::cast::VideoCodec::kVp8;
|
||||||
|
case media::VideoCodec::kCodecHEVC:
|
||||||
|
return openscreen::cast::VideoCodec::kHevc;
|
||||||
|
case media::VideoCodec::kCodecVP9:
|
||||||
|
return openscreen::cast::VideoCodec::kVp9;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NOTREACHED();
|
||||||
|
return openscreen::cast::VideoCodec::kNotSpecified;
|
||||||
|
}
|
||||||
|
|
||||||
|
openscreen::cast::AudioCaptureConfig ToAudioCaptureConfig(
|
||||||
|
const media::AudioDecoderConfig& audio_config) {
|
||||||
|
DCHECK(!audio_config.is_encrypted());
|
||||||
|
|
||||||
|
openscreen::cast::AudioCaptureConfig audio_capture_config;
|
||||||
|
audio_capture_config.codec = ToAudioCaptureConfigCodec(audio_config.codec());
|
||||||
|
audio_capture_config.channels =
|
||||||
|
media::ChannelLayoutToChannelCount(audio_config.channel_layout());
|
||||||
|
audio_capture_config.sample_rate = audio_config.samples_per_second();
|
||||||
|
audio_capture_config.bit_rate = 0; // Selected by the sender.
|
||||||
|
|
||||||
|
return audio_capture_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
openscreen::cast::VideoCaptureConfig ToVideoCaptureConfig(
|
||||||
|
const media::VideoDecoderConfig& video_config) {
|
||||||
|
DCHECK(!video_config.is_encrypted());
|
||||||
|
|
||||||
|
openscreen::cast::VideoCaptureConfig video_capture_config;
|
||||||
|
video_capture_config.codec = ToVideoCaptureConfigCodec(video_config.codec());
|
||||||
|
video_capture_config.resolutions.push_back(
|
||||||
|
{video_config.visible_rect().width(),
|
||||||
|
video_config.visible_rect().height()});
|
||||||
|
video_capture_config.max_bit_rate = 0; // Selected by the sender.
|
||||||
|
return video_capture_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
media::AudioDecoderConfig ToAudioDecoderConfig(
|
||||||
|
const openscreen::cast::AudioCaptureConfig& audio_capture_config) {
|
||||||
|
media::AudioCodec media_audio_codec =
|
||||||
|
ToAudioDecoderConfigCodec(audio_capture_config.codec);
|
||||||
|
|
||||||
|
return media::AudioDecoderConfig(
|
||||||
|
media_audio_codec, media::SampleFormat::kSampleFormatF32,
|
||||||
|
media::GuessChannelLayout(audio_capture_config.channels),
|
||||||
|
audio_capture_config.sample_rate /* samples_per_second */,
|
||||||
|
media::EmptyExtraData(), media::EncryptionScheme::kUnencrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
media::VideoDecoderConfig ToVideoDecoderConfig(
|
||||||
|
const openscreen::cast::VideoCaptureConfig& video_capture_config) {
|
||||||
|
// Gather data for the video decoder config.
|
||||||
|
DCHECK(video_capture_config.resolutions.size());
|
||||||
|
uint32_t video_width = video_capture_config.resolutions[0].width;
|
||||||
|
uint32_t video_height = video_capture_config.resolutions[0].height;
|
||||||
|
gfx::Size video_size(video_width, video_height);
|
||||||
|
gfx::Rect video_rect(video_width, video_height);
|
||||||
|
|
||||||
|
media::VideoCodec media_video_codec =
|
||||||
|
ToVideoDecoderConfigCodec(video_capture_config.codec);
|
||||||
|
media::VideoCodecProfile video_codec_profile =
|
||||||
|
ToVideoDecoderConfigCodecProfile(video_capture_config.codec);
|
||||||
|
|
||||||
|
return media::VideoDecoderConfig(
|
||||||
|
media_video_codec, video_codec_profile,
|
||||||
|
media::VideoDecoderConfig::AlphaMode::kIsOpaque, media::VideoColorSpace(),
|
||||||
|
media::VideoTransformation(), video_size, video_rect, video_size,
|
||||||
|
media::EmptyExtraData(), media::EncryptionScheme::kUnencrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cast_streaming
|
50
components/cast_streaming/public/config_conversions.h
Normal file
50
components/cast_streaming/public/config_conversions.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// 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 COMPONENTS_CAST_STREAMING_PUBLIC_CONFIG_CONVERSIONS_H_
|
||||||
|
#define COMPONENTS_CAST_STREAMING_PUBLIC_CONFIG_CONVERSIONS_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "media/base/audio_decoder_config.h"
|
||||||
|
#include "media/base/video_decoder_config.h"
|
||||||
|
#include "third_party/openscreen/src/cast/streaming/capture_configs.h"
|
||||||
|
|
||||||
|
namespace cast_streaming {
|
||||||
|
|
||||||
|
// Utility functions to convert between media and Open Screen types.
|
||||||
|
|
||||||
|
openscreen::cast::AudioCaptureConfig ToAudioCaptureConfig(
|
||||||
|
const media::AudioDecoderConfig& audio_config);
|
||||||
|
|
||||||
|
openscreen::cast::VideoCaptureConfig ToVideoCaptureConfig(
|
||||||
|
const media::VideoDecoderConfig& video_config);
|
||||||
|
|
||||||
|
media::AudioDecoderConfig ToAudioDecoderConfig(
|
||||||
|
const openscreen::cast::AudioCaptureConfig& audio_capture_config);
|
||||||
|
|
||||||
|
media::VideoDecoderConfig ToVideoDecoderConfig(
|
||||||
|
const openscreen::cast::VideoCaptureConfig& video_capture_config);
|
||||||
|
|
||||||
|
openscreen::cast::AudioCodec ToAudioCaptureConfigCodec(media::AudioCodec codec);
|
||||||
|
|
||||||
|
openscreen::cast::VideoCodec ToVideoCaptureConfigCodec(media::VideoCodec codec);
|
||||||
|
|
||||||
|
template <typename... TCodecs>
|
||||||
|
std::vector<openscreen::cast::AudioCodec> ToAudioCaptureConfigCodecs(
|
||||||
|
TCodecs... codecs) {
|
||||||
|
return std::vector<openscreen::cast::AudioCodec>{
|
||||||
|
ToAudioCaptureConfigCodec(codecs)...};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... TCodecs>
|
||||||
|
std::vector<openscreen::cast::VideoCodec> ToVideoCaptureConfigCodecs(
|
||||||
|
TCodecs... codecs) {
|
||||||
|
return std::vector<openscreen::cast::VideoCodec>{
|
||||||
|
ToVideoCaptureConfigCodec(codecs)...};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cast_streaming
|
||||||
|
|
||||||
|
#endif // COMPONENTS_CAST_STREAMING_PUBLIC_CONFIG_CONVERSIONS_H_
|
241
components/cast_streaming/public/config_conversions_unittest.cc
Normal file
241
components/cast_streaming/public/config_conversions_unittest.cc
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "components/cast_streaming/public/config_conversions.h"
|
||||||
|
|
||||||
|
#include "media/base/media_util.h"
|
||||||
|
#include "testing/gmock/include/gmock/gmock.h"
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "third_party/openscreen/src/cast/streaming/capture_configs.h"
|
||||||
|
#include "ui/gfx/geometry/rect.h"
|
||||||
|
#include "ui/gfx/geometry/size.h"
|
||||||
|
|
||||||
|
namespace cast_streaming {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void ValidateAudioConfig(const media::AudioDecoderConfig& config,
|
||||||
|
const media::AudioDecoderConfig& expected) {
|
||||||
|
EXPECT_EQ(config.codec(), expected.codec());
|
||||||
|
EXPECT_EQ(config.sample_format(), media::SampleFormat::kSampleFormatF32);
|
||||||
|
EXPECT_EQ(config.channel_layout(), expected.channel_layout());
|
||||||
|
EXPECT_EQ(config.samples_per_second(), expected.samples_per_second());
|
||||||
|
EXPECT_EQ(config.extra_data().size(), size_t{0});
|
||||||
|
EXPECT_FALSE(config.is_encrypted());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateAudioConfig(const openscreen::cast::AudioCaptureConfig& config,
|
||||||
|
const openscreen::cast::AudioCaptureConfig& expected) {
|
||||||
|
EXPECT_EQ(config.codec, expected.codec);
|
||||||
|
EXPECT_EQ(config.channels, expected.channels);
|
||||||
|
EXPECT_EQ(config.bit_rate, expected.bit_rate);
|
||||||
|
EXPECT_EQ(config.sample_rate, expected.sample_rate);
|
||||||
|
EXPECT_EQ(config.target_playout_delay, expected.target_playout_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateVideoConfig(const media::VideoDecoderConfig& config,
|
||||||
|
const media::VideoDecoderConfig& expected) {
|
||||||
|
EXPECT_EQ(config.codec(), expected.codec());
|
||||||
|
EXPECT_EQ(config.profile(), expected.profile());
|
||||||
|
EXPECT_EQ(config.alpha_mode(),
|
||||||
|
media::VideoDecoderConfig::AlphaMode::kIsOpaque);
|
||||||
|
EXPECT_EQ(config.extra_data().size(), size_t{0});
|
||||||
|
EXPECT_FALSE(config.is_encrypted());
|
||||||
|
|
||||||
|
EXPECT_EQ(config.coded_size().width(), expected.coded_size().width());
|
||||||
|
EXPECT_EQ(config.coded_size().height(), expected.coded_size().height());
|
||||||
|
|
||||||
|
EXPECT_EQ(config.visible_rect().width(), expected.visible_rect().width());
|
||||||
|
EXPECT_EQ(config.visible_rect().height(), expected.visible_rect().height());
|
||||||
|
|
||||||
|
EXPECT_EQ(config.natural_size().width(), expected.natural_size().width());
|
||||||
|
EXPECT_EQ(config.natural_size().height(), expected.natural_size().height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateVideoConfig(const openscreen::cast::VideoCaptureConfig& config,
|
||||||
|
const openscreen::cast::VideoCaptureConfig& expected) {
|
||||||
|
EXPECT_EQ(config.codec, expected.codec);
|
||||||
|
EXPECT_EQ(config.max_frame_rate, expected.max_frame_rate);
|
||||||
|
EXPECT_EQ(config.max_bit_rate, expected.max_bit_rate);
|
||||||
|
EXPECT_EQ(config.target_playout_delay, expected.target_playout_delay);
|
||||||
|
ASSERT_EQ(config.resolutions.size(), expected.resolutions.size());
|
||||||
|
for (const auto& resolution : config.resolutions) {
|
||||||
|
EXPECT_TRUE(std::find(expected.resolutions.begin(),
|
||||||
|
expected.resolutions.end(),
|
||||||
|
resolution) != expected.resolutions.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openscreen::cast::AudioCaptureConfig CreateAudioCaptureConfig() {
|
||||||
|
openscreen::cast::AudioCaptureConfig config;
|
||||||
|
config.codec = openscreen::cast::AudioCodec::kAac;
|
||||||
|
config.channels = 2;
|
||||||
|
config.sample_rate = 42;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
media::AudioDecoderConfig CreateAudioDecoderConfig(
|
||||||
|
media::AudioCodec codec,
|
||||||
|
media::ChannelLayout channel_layout,
|
||||||
|
int samples_per_second) {
|
||||||
|
return media::AudioDecoderConfig(codec, media::SampleFormat::kSampleFormatF32,
|
||||||
|
channel_layout, samples_per_second,
|
||||||
|
media::EmptyExtraData(),
|
||||||
|
media::EncryptionScheme::kUnencrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
openscreen::cast::VideoCaptureConfig CreateVideoCaptureConfig() {
|
||||||
|
openscreen::cast::VideoCaptureConfig config;
|
||||||
|
config.codec = openscreen::cast::VideoCodec::kH264;
|
||||||
|
config.resolutions.push_back({1080, 720});
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
media::VideoDecoderConfig CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec codec,
|
||||||
|
media::VideoCodecProfile codec_profile,
|
||||||
|
int width,
|
||||||
|
int height) {
|
||||||
|
gfx::Size video_size(width, height);
|
||||||
|
gfx::Rect video_rect(width, height);
|
||||||
|
return media::VideoDecoderConfig(
|
||||||
|
codec, codec_profile, media::VideoDecoderConfig::AlphaMode::kIsOpaque,
|
||||||
|
media::VideoColorSpace(), media::VideoTransformation(), video_size,
|
||||||
|
video_rect, video_size, media::EmptyExtraData(),
|
||||||
|
media::EncryptionScheme::kUnencrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(ConfigConversionsTest, AudioConfigCodecConversion) {
|
||||||
|
auto capture_config = CreateAudioCaptureConfig();
|
||||||
|
auto decoder_config =
|
||||||
|
CreateAudioDecoderConfig(media::AudioCodec::kCodecAAC,
|
||||||
|
media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 42);
|
||||||
|
ValidateAudioConfig(ToAudioDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateAudioConfig(ToAudioCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.codec = openscreen::cast::AudioCodec::kOpus;
|
||||||
|
decoder_config =
|
||||||
|
CreateAudioDecoderConfig(media::AudioCodec::kCodecOpus,
|
||||||
|
media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 42);
|
||||||
|
ValidateAudioConfig(ToAudioDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateAudioConfig(ToAudioCaptureConfig(decoder_config), capture_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConfigConversionsTest, AudioConfigChannelsConversion) {
|
||||||
|
auto capture_config = CreateAudioCaptureConfig();
|
||||||
|
auto decoder_config =
|
||||||
|
CreateAudioDecoderConfig(media::AudioCodec::kCodecAAC,
|
||||||
|
media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 42);
|
||||||
|
ValidateAudioConfig(ToAudioDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateAudioConfig(ToAudioCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.channels = 1;
|
||||||
|
decoder_config =
|
||||||
|
CreateAudioDecoderConfig(media::AudioCodec::kCodecAAC,
|
||||||
|
media::ChannelLayout::CHANNEL_LAYOUT_MONO, 42);
|
||||||
|
ValidateAudioConfig(ToAudioDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateAudioConfig(ToAudioCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
// Other configurations are not expected in practice.
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConfigConversionsTest, AudioConfigSampleRateConversion) {
|
||||||
|
auto capture_config = CreateAudioCaptureConfig();
|
||||||
|
auto decoder_config =
|
||||||
|
CreateAudioDecoderConfig(media::AudioCodec::kCodecAAC,
|
||||||
|
media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 42);
|
||||||
|
ValidateAudioConfig(ToAudioDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateAudioConfig(ToAudioCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.sample_rate = 1234;
|
||||||
|
decoder_config = CreateAudioDecoderConfig(
|
||||||
|
media::AudioCodec::kCodecAAC, media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
|
||||||
|
1234);
|
||||||
|
ValidateAudioConfig(ToAudioDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateAudioConfig(ToAudioCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.sample_rate = -1;
|
||||||
|
decoder_config =
|
||||||
|
CreateAudioDecoderConfig(media::AudioCodec::kCodecAAC,
|
||||||
|
media::ChannelLayout::CHANNEL_LAYOUT_STEREO, -1);
|
||||||
|
ValidateAudioConfig(ToAudioDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateAudioConfig(ToAudioCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.sample_rate = 0;
|
||||||
|
decoder_config =
|
||||||
|
CreateAudioDecoderConfig(media::AudioCodec::kCodecAAC,
|
||||||
|
media::ChannelLayout::CHANNEL_LAYOUT_STEREO, 0);
|
||||||
|
ValidateAudioConfig(ToAudioDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateAudioConfig(ToAudioCaptureConfig(decoder_config), capture_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConfigConversionsTest, VideoConfigCodecConversion) {
|
||||||
|
const int width = 1080;
|
||||||
|
const int height = 720;
|
||||||
|
auto capture_config = CreateVideoCaptureConfig();
|
||||||
|
auto decoder_config = CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec::kCodecH264,
|
||||||
|
media::VideoCodecProfile::H264PROFILE_BASELINE, width, height);
|
||||||
|
ValidateVideoConfig(ToVideoDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateVideoConfig(ToVideoCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.codec = openscreen::cast::VideoCodec::kVp8;
|
||||||
|
decoder_config = CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec::kCodecVP8, media::VideoCodecProfile::VP8PROFILE_MIN,
|
||||||
|
width, height);
|
||||||
|
ValidateVideoConfig(ToVideoDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateVideoConfig(ToVideoCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.codec = openscreen::cast::VideoCodec::kHevc;
|
||||||
|
decoder_config = CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec::kCodecHEVC, media::VideoCodecProfile::HEVCPROFILE_MAIN,
|
||||||
|
width, height);
|
||||||
|
ValidateVideoConfig(ToVideoDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateVideoConfig(ToVideoCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.codec = openscreen::cast::VideoCodec::kVp9;
|
||||||
|
decoder_config = CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec::kCodecVP9,
|
||||||
|
media::VideoCodecProfile::VP9PROFILE_PROFILE0, width, height);
|
||||||
|
ValidateVideoConfig(ToVideoDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateVideoConfig(ToVideoCaptureConfig(decoder_config), capture_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConfigConversionsTest, VideoConfigResolutionConversion) {
|
||||||
|
auto capture_config = CreateVideoCaptureConfig();
|
||||||
|
auto decoder_config = CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec::kCodecH264,
|
||||||
|
media::VideoCodecProfile::H264PROFILE_BASELINE, 1080, 720);
|
||||||
|
ValidateVideoConfig(ToVideoDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateVideoConfig(ToVideoCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
ASSERT_EQ(capture_config.resolutions.size(), size_t{1});
|
||||||
|
|
||||||
|
capture_config.resolutions[0].width = 42;
|
||||||
|
capture_config.resolutions[0].height = 16;
|
||||||
|
decoder_config = CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec::kCodecH264,
|
||||||
|
media::VideoCodecProfile::H264PROFILE_BASELINE, 42, 16);
|
||||||
|
ValidateVideoConfig(ToVideoDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateVideoConfig(ToVideoCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.resolutions[0].width = 1;
|
||||||
|
capture_config.resolutions[0].height = 2;
|
||||||
|
decoder_config = CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec::kCodecH264,
|
||||||
|
media::VideoCodecProfile::H264PROFILE_BASELINE, 1, 2);
|
||||||
|
ValidateVideoConfig(ToVideoDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateVideoConfig(ToVideoCaptureConfig(decoder_config), capture_config);
|
||||||
|
|
||||||
|
capture_config.resolutions[0].width = 0;
|
||||||
|
capture_config.resolutions[0].height = 0;
|
||||||
|
decoder_config = CreateVideoDecoderConfig(
|
||||||
|
media::VideoCodec::kCodecH264,
|
||||||
|
media::VideoCodecProfile::H264PROFILE_BASELINE, 0, 0);
|
||||||
|
ValidateVideoConfig(ToVideoDecoderConfig(capture_config), decoder_config);
|
||||||
|
ValidateVideoConfig(ToVideoCaptureConfig(decoder_config), capture_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cast_streaming
|
@ -104,6 +104,7 @@ component("web_engine_core") {
|
|||||||
"//base/util/memory_pressure",
|
"//base/util/memory_pressure",
|
||||||
"//components/cast/message_port:message_port_fuchsia",
|
"//components/cast/message_port:message_port_fuchsia",
|
||||||
"//components/cast_streaming/browser",
|
"//components/cast_streaming/browser",
|
||||||
|
"//components/cast_streaming/public",
|
||||||
"//components/cast_streaming/public/mojom",
|
"//components/cast_streaming/public/mojom",
|
||||||
"//components/cast_streaming/renderer",
|
"//components/cast_streaming/renderer",
|
||||||
"//components/cdm/renderer",
|
"//components/cdm/renderer",
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "components/cast/message_port/message_port_fuchsia.h"
|
#include "components/cast/message_port/message_port_fuchsia.h"
|
||||||
|
#include "components/cast_streaming/public/config_conversions.h"
|
||||||
|
#include "media/base/audio_decoder_config.h"
|
||||||
|
#include "media/base/video_decoder_config.h"
|
||||||
|
|
||||||
ReceiverSessionClient::ReceiverSessionClient(
|
ReceiverSessionClient::ReceiverSessionClient(
|
||||||
fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request)
|
fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request)
|
||||||
@ -20,12 +23,26 @@ void ReceiverSessionClient::SetCastStreamingReceiver(
|
|||||||
cast_streaming_receiver) {
|
cast_streaming_receiver) {
|
||||||
DCHECK(message_port_request_);
|
DCHECK(message_port_request_);
|
||||||
|
|
||||||
receiver_session_ = cast_streaming::ReceiverSession::Create(base::BindOnce(
|
// TODO: Add streaming session Constraints based on system capabilities
|
||||||
[](fidl::InterfaceRequest<fuchsia::web::MessagePort> port)
|
// (see crbug.com/1013412) and DisplayDescription (see crbug.com/1087520).
|
||||||
-> std::unique_ptr<cast_api_bindings::MessagePort> {
|
// TODO(crbug.com/1218498): Only populate codecs corresponding to those called
|
||||||
return cast_api_bindings::MessagePortFuchsia::Create(std::move(port));
|
// out by build flags.
|
||||||
},
|
auto stream_config =
|
||||||
std::move(message_port_request_)));
|
std::make_unique<cast_streaming::ReceiverSession::AVConstraints>(
|
||||||
|
cast_streaming::ToVideoCaptureConfigCodecs(
|
||||||
|
media::VideoCodec::kCodecH264, media::VideoCodec::kCodecVP8),
|
||||||
|
cast_streaming::ToAudioCaptureConfigCodecs(
|
||||||
|
media::AudioCodec::kCodecAAC, media::AudioCodec::kCodecOpus));
|
||||||
|
|
||||||
|
receiver_session_ = cast_streaming::ReceiverSession::Create(
|
||||||
|
std::move(stream_config),
|
||||||
|
base::BindOnce(
|
||||||
|
[](fidl::InterfaceRequest<fuchsia::web::MessagePort> port)
|
||||||
|
-> std::unique_ptr<cast_api_bindings::MessagePort> {
|
||||||
|
return cast_api_bindings::MessagePortFuchsia::Create(
|
||||||
|
std::move(port));
|
||||||
|
},
|
||||||
|
std::move(message_port_request_)));
|
||||||
receiver_session_->SetCastStreamingReceiver(
|
receiver_session_->SetCastStreamingReceiver(
|
||||||
std::move(cast_streaming_receiver));
|
std::move(cast_streaming_receiver));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user