// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/shared/platform_info_serializer.h"
#include <string_view>
#include "base/check.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "chromecast/bindings/shared/proto_serializer.h"
namespace chromecast {
namespace {
bool IsOutOfRange(int value, int min, int max) {
return min > value || max < value;
}
} // namespace
PlatformInfoSerializer::PlatformInfoSerializer() = default;
PlatformInfoSerializer::PlatformInfoSerializer(PlatformInfoSerializer&& other) =
default;
PlatformInfoSerializer::~PlatformInfoSerializer() = default;
PlatformInfoSerializer& PlatformInfoSerializer::operator=(
PlatformInfoSerializer&& other) = default;
// static
std::optional<PlatformInfoSerializer> PlatformInfoSerializer::Deserialize(
std::string_view base64) {
std::optional<cast::bindings::MediaCapabilitiesMessage> proto =
chromecast::bindings::ProtoSerializer<
cast::bindings::MediaCapabilitiesMessage>::Deserialize(base64);
if (!proto) {
return std::nullopt;
}
PlatformInfoSerializer parser;
parser.platform_info_ = std::move(*proto);
return parser;
}
std::string PlatformInfoSerializer::Serialize() const {
return chromecast::bindings::ProtoSerializer<
cast::bindings::MediaCapabilitiesMessage>::Serialize(platform_info_);
}
void PlatformInfoSerializer::SetMaxWidth(int max_width) {
platform_info_.set_max_width(max_width);
}
void PlatformInfoSerializer::SetMaxHeight(int max_height) {
platform_info_.set_max_height(max_height);
}
void PlatformInfoSerializer::SetMaxFrameRate(int max_frame_rate) {
platform_info_.set_max_frame_rate(max_frame_rate);
}
void PlatformInfoSerializer::SetSupportedCryptoBlockFormat(
const std::string& format) {
platform_info_.set_supported_cryptoblock_format(format);
}
void PlatformInfoSerializer::SetMaxChannels(int max_channels) {
platform_info_.set_max_channels(max_channels);
}
void PlatformInfoSerializer::SetPcmSurroundSoundSupported(bool is_supported) {
platform_info_.set_is_pcm_surround_sound_supported(is_supported);
}
void PlatformInfoSerializer::SetPlatformDolbyVisionEnabled(bool is_enabled) {
platform_info_.set_is_platform_dolby_vision_enabled(is_enabled);
}
void PlatformInfoSerializer::SetDolbyVisionSupported(bool is_supported) {
platform_info_.set_is_dolby_vision_supported(is_supported);
}
void PlatformInfoSerializer::SetDolbyVision4kP60Supported(bool is_supported) {
platform_info_.set_is_dolby_vision4k_p60_supported(is_supported);
}
void PlatformInfoSerializer::SetDolbyVisionSupportedByCurrentHdmiMode(
bool is_supported) {
platform_info_.set_is_dolby_vision_supported_by_current_hdmi_mode(
is_supported);
}
void PlatformInfoSerializer::SetHdmiVideoModeSwitchEnabled(bool is_enabled) {
platform_info_.set_is_hdmi_video_mode_switch_enabled(is_enabled);
}
void PlatformInfoSerializer::SetPlatformHevcEnabled(bool is_enabled) {
platform_info_.set_is_platform_hevc_enabled(is_enabled);
}
void PlatformInfoSerializer::SetHdmiModeHdrCheckEnforced(bool is_enforced) {
platform_info_.set_is_hdmi_mode_hdr_check_enforced(is_enforced);
}
void PlatformInfoSerializer::SetHdrSupportedByCurrentHdmiMode(
bool is_supported) {
platform_info_.set_is_hdr_supported_by_current_hdmi_mode(is_supported);
}
void PlatformInfoSerializer::SetSmpteSt2084Supported(bool is_supported) {
platform_info_.set_is_smpte_st2084_supported(is_supported);
}
void PlatformInfoSerializer::SetHlgSupported(bool is_supported) {
platform_info_.set_is_hlg_supported(is_supported);
}
void PlatformInfoSerializer::SetHdrFeatureEnabled(bool is_enabled) {
platform_info_.set_is_hdr_feature_enabled(is_enabled);
}
void PlatformInfoSerializer::SetSupportedLegacyVp9Levels(
std::vector<int> levels) {
platform_info_.clear_supported_legacy_vp9_levels();
for (int level : levels) {
platform_info_.add_supported_legacy_vp9_levels(level);
}
}
void PlatformInfoSerializer::SetHdcpVersion(int hdcp_version) {
platform_info_.set_hdcp_version(hdcp_version);
}
void PlatformInfoSerializer::SetSpatialRenderingSupportMask(int mask) {
platform_info_.set_spatial_rendering_support_mask(mask);
}
void PlatformInfoSerializer::SetMaxFillRate(int max_fill_rate) {
platform_info_.set_max_fill_rate(max_fill_rate);
}
void PlatformInfoSerializer::SetSupportedAudioCodecs(
std::vector<AudioCodecInfo> codec_infos) {
platform_info_.clear_supported_audio_codecs();
for (const auto& element : codec_infos) {
cast::bindings::AudioCodecInfo info;
DCHECK(cast::bindings::AudioCodecInfo::AudioCodec_IsValid(element.codec));
DCHECK(cast::bindings::AudioCodecInfo::SampleFormat_IsValid(
element.sample_format));
info.set_codec(
cast::bindings::AudioCodecInfo::AudioCodec_IsValid(element.codec)
? static_cast<cast::bindings::AudioCodecInfo::AudioCodec>(
element.codec)
: cast::bindings::AudioCodecInfo::AUDIO_CODEC_UNKNOWN);
info.set_sample_format(
cast::bindings::AudioCodecInfo::SampleFormat_IsValid(
element.sample_format)
? static_cast<cast::bindings::AudioCodecInfo::SampleFormat>(
element.sample_format)
: cast::bindings::AudioCodecInfo::SAMPLE_FORMAT_UNKNOWN);
info.set_max_samples_per_second(element.max_samples_per_second);
info.set_max_audio_channels(element.max_audio_channels);
*platform_info_.add_supported_audio_codecs() = std::move(info);
}
}
void PlatformInfoSerializer::SetSupportedVideoCodecs(
std::vector<VideoCodecInfo> codec_infos) {
for (auto& element : codec_infos) {
cast::bindings::VideoCodecInfo info;
DCHECK(cast::bindings::VideoCodecInfo::VideoCodec_IsValid(element.codec));
DCHECK(
cast::bindings::VideoCodecInfo::VideoProfile_IsValid(element.profile));
info.set_codec(
cast::bindings::VideoCodecInfo::VideoCodec_IsValid(element.codec)
? static_cast<cast::bindings::VideoCodecInfo::VideoCodec>(
element.codec)
: cast::bindings::VideoCodecInfo::VIDEO_CODEC_UNKNOWN);
info.set_profile(
cast::bindings::VideoCodecInfo::VideoProfile_IsValid(element.profile)
? static_cast<cast::bindings::VideoCodecInfo::VideoProfile>(
element.profile)
: cast::bindings::VideoCodecInfo::VIDEO_PROFILE_UNKNOWN);
*platform_info_.add_supported_video_codecs() = std::move(info);
}
}
std::optional<int> PlatformInfoSerializer::MaxWidth() const {
return platform_info_.max_width();
}
std::optional<int> PlatformInfoSerializer::MaxHeight() const {
return platform_info_.max_height();
}
std::optional<int> PlatformInfoSerializer::MaxFrameRate() const {
return platform_info_.max_frame_rate();
}
std::optional<std::string> PlatformInfoSerializer::SupportedCryptoBlockFormat()
const {
return platform_info_.supported_cryptoblock_format();
}
std::optional<int> PlatformInfoSerializer::MaxChannels() const {
return platform_info_.max_channels();
}
std::optional<bool> PlatformInfoSerializer::PcmSurroundSoundSupported() const {
return platform_info_.is_pcm_surround_sound_supported();
}
std::optional<bool> PlatformInfoSerializer::IsPlatformDolbyVisionEnabled()
const {
return platform_info_.is_platform_dolby_vision_enabled();
}
std::optional<bool> PlatformInfoSerializer::IsDolbyVisionSupported() const {
return platform_info_.is_dolby_vision_supported();
}
std::optional<bool> PlatformInfoSerializer::IsDolbyVision4kP60Supported()
const {
return platform_info_.is_dolby_vision4k_p60_supported();
}
std::optional<bool>
PlatformInfoSerializer::IsDolbyVisionSupportedByCurrentHdmiMode() const {
return platform_info_.is_dolby_vision_supported_by_current_hdmi_mode();
}
std::optional<bool> PlatformInfoSerializer::IsHdmiVideoModeSwitchEnabled()
const {
return platform_info_.is_hdmi_video_mode_switch_enabled();
}
std::optional<bool> PlatformInfoSerializer::IsPlatformHevcEnabled() const {
return platform_info_.is_platform_hevc_enabled();
}
std::optional<bool> PlatformInfoSerializer::IsHdmiModeHdrCheckEnforced() const {
return platform_info_.is_hdmi_mode_hdr_check_enforced();
}
std::optional<bool> PlatformInfoSerializer::IsHdrSupportedByCurrentHdmiMode()
const {
return platform_info_.is_hdr_supported_by_current_hdmi_mode();
}
std::optional<bool> PlatformInfoSerializer::IsSmpteSt2084Supported() const {
return platform_info_.is_smpte_st2084_supported();
}
std::optional<bool> PlatformInfoSerializer::IsHlgSupported() const {
return platform_info_.is_hlg_supported();
}
std::optional<bool> PlatformInfoSerializer::IsHdrFeatureEnabled() const {
return platform_info_.is_hdr_feature_enabled();
}
std::optional<std::vector<int>>
PlatformInfoSerializer::SupportedLegacyVp9Levels() const {
std::vector<int> levels;
levels.reserve(platform_info_.supported_legacy_vp9_levels_size());
for (const auto& level : platform_info_.supported_legacy_vp9_levels()) {
levels.push_back(level);
}
return levels;
}
std::optional<int> PlatformInfoSerializer::HdcpVersion() const {
return platform_info_.hdcp_version();
}
std::optional<int> PlatformInfoSerializer::SpatialRenderingSupportMask() const {
return platform_info_.spatial_rendering_support_mask();
}
std::optional<int> PlatformInfoSerializer::MaxFillRate() const {
return platform_info_.max_fill_rate();
}
std::optional<std::vector<PlatformInfoSerializer::AudioCodecInfo>>
PlatformInfoSerializer::SupportedAudioCodecs() const {
std::vector<AudioCodecInfo> infos;
infos.reserve(platform_info_.supported_audio_codecs_size());
for (const auto& info : platform_info_.supported_audio_codecs()) {
if (IsOutOfRange(info.codec(), media::AudioCodec::kAudioCodecMin,
media::AudioCodec::kAudioCodecMax)) {
LOG(WARNING) << "Unrecognized AudioCodec: " << info.codec();
continue;
}
if (IsOutOfRange(info.sample_format(),
media::SampleFormat::kSampleFormatMin,
media::SampleFormat::kSampleFormatMax)) {
LOG(WARNING) << "Unrecognized SampleFormat: " << info.sample_format();
continue;
}
AudioCodecInfo parsed;
parsed.codec = static_cast<media::AudioCodec>(info.codec());
parsed.sample_format =
static_cast<media::SampleFormat>(info.sample_format());
parsed.max_samples_per_second = info.max_samples_per_second();
parsed.max_audio_channels = info.max_audio_channels();
infos.push_back(std::move(parsed));
}
return infos.empty()
? std::nullopt
: std::make_optional<
std::vector<PlatformInfoSerializer::AudioCodecInfo>>(infos);
}
std::optional<std::vector<PlatformInfoSerializer::VideoCodecInfo>>
PlatformInfoSerializer::SupportedVideoCodecs() const {
std::vector<VideoCodecInfo> infos;
infos.reserve(platform_info_.supported_video_codecs_size());
for (const auto& info : platform_info_.supported_video_codecs()) {
if (IsOutOfRange(info.codec(), media::VideoCodec::kVideoCodecMin,
media::VideoCodec::kVideoCodecMax)) {
LOG(WARNING) << "Unrecognized VideoCodec: " << info.codec();
continue;
}
if (IsOutOfRange(info.profile(), media::VideoProfile::kVideoProfileMin,
media::VideoProfile::kVideoProfileMax)) {
LOG(WARNING) << "Unrecognized VideoProfile: " << info.profile();
continue;
}
VideoCodecInfo parsed;
parsed.codec = static_cast<media::VideoCodec>(info.codec());
parsed.profile = static_cast<media::VideoProfile>(info.profile());
infos.push_back(std::move(parsed));
}
return infos.empty()
? std::nullopt
: std::make_optional<
std::vector<PlatformInfoSerializer::VideoCodecInfo>>(infos);
}
bool operator==(const PlatformInfoSerializer::AudioCodecInfo& first,
const PlatformInfoSerializer::AudioCodecInfo& second) {
return first.codec == second.codec &&
first.sample_format == second.sample_format &&
first.max_samples_per_second == second.max_samples_per_second &&
first.max_audio_channels == second.max_audio_channels;
}
bool operator==(const PlatformInfoSerializer::VideoCodecInfo& first,
const PlatformInfoSerializer::VideoCodecInfo& second) {
return first.codec == second.codec && first.profile == second.profile;
}
} // namespace chromecast