diff --git a/starboard/shared/starboard/speech_recognizer/xb1_get_type.cc b/starboard/shared/starboard/speech_recognizer/xb1_get_type.cc new file mode 100644 index 000000000000..c3e4b2644e54 --- /dev/null +++ b/starboard/shared/starboard/speech_recognizer/xb1_get_type.cc @@ -0,0 +1,52 @@ +// Copyright 2023 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "starboard/shared/uwp/xb1_get_type.h" + +#include + +#include "starboard/system.h" + +namespace starboard { +namespace shared { +namespace uwp { +XboxType GetXboxType() { + // The value kXboxUndefined means that the model name needs to be clarified at + // the first time and cached for further calls. + static XboxType xbox_type = kXboxUndefined; + constexpr size_t kNameLength = 1024; + char name[kNameLength] = {}; + + if (xbox_type == kXboxUndefined) { + // Provide a base functionality even for unknown models. + xbox_type = kXboxOneBase; + + // Detect from system properties which model runs the application. + if (SbSystemGetProperty(kSbSystemPropertyModelName, name, kNameLength)) { + const std::string friendly_name(name); + if (friendly_name == "XboxOne S") { + xbox_type = kXboxOneS; + } else if (friendly_name == "XboxOne X") { + xbox_type = kXboxOneX; + } else if (friendly_name == "XboxScarlett Series S") { + xbox_type = kXboxSeriesS; + } else if (friendly_name == "XboxScarlett Series X") { + xbox_type = kXboxSeriesX; + } + } + } + return xbox_type; +} +} // namespace uwp +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/starboard/speech_recognizer/xb1_get_type.h b/starboard/shared/starboard/speech_recognizer/xb1_get_type.h new file mode 100644 index 000000000000..f943fc1f4b36 --- /dev/null +++ b/starboard/shared/starboard/speech_recognizer/xb1_get_type.h @@ -0,0 +1,36 @@ +// Copyright 2023 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_SHARED_UWP_XB1_GET_TYPE_H_ +#define STARBOARD_SHARED_UWP_XB1_GET_TYPE_H_ + +namespace starboard { +namespace shared { +namespace uwp { + +enum XboxType { + kXboxUndefined, + kXboxOneBase, + kXboxOneS, + kXboxOneX, + kXboxSeriesS, + kXboxSeriesX, +}; + +XboxType GetXboxType(); +} // namespace uwp +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_UWP_XB1_GET_TYPE_H_ diff --git a/starboard/shared/uwp/media_is_video_supported.cc b/starboard/shared/uwp/media_is_video_supported.cc new file mode 100644 index 000000000000..5316a985e24c --- /dev/null +++ b/starboard/shared/uwp/media_is_video_supported.cc @@ -0,0 +1,283 @@ +// Copyright 2018 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/shared/starboard/media/media_support_internal.h" + +#include "starboard/shared/starboard/media/video_capabilities.h" +#include "starboard/shared/uwp/application_uwp.h" +#include "starboard/shared/uwp/extended_resources_manager.h" +#include "starboard/shared/uwp/xb1_get_type.h" +#include "starboard/shared/win32/video_decoder.h" +#include "starboard/window.h" + +using ::starboard::shared::starboard::media::MimeType; + +namespace { +using ::starboard::shared::uwp::ApplicationUwp; +using ::starboard::shared::uwp::ExtendedResourcesManager; + +class XboxVideoCapabilities { + public: + XboxVideoCapabilities() { + bool limit_to_2k = false; + SbWindowSize window_size = ApplicationUwp::Get()->GetVisibleAreaSize(); + if (window_size.width <= 1920 || window_size.height <= 1080) { + limit_to_2k = true; + } + +#ifdef ENABLE_H264_4K_SUPPORT + // Documentation claims the following resolution constraints for H264 + // decoder: + // (https://docs.microsoft.com/en-us/windows/win32/medfound/h-264-video-decoder) + // - minimum Resolution 48*48 pixels + // - maximum Resolution 4096*2304 pixels + // For Windows 8 and higher the maximum guaranteed resolution for DXVA + // acceleration is 1920*1088 pixels. + // At higher resolutions, decoding is done with DXVA, if it is supported by + // the underlying hardware, otherwise, decoding is done with software. + // Therefore platforms must explicitly opt-in to support 4k H264. + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecH264, 4096, 2304, 60); +#else // ENABLE_H264_4K_SUPPORT + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecH264, 1920, 1088, 60); +#endif // ENABLE_H264_4K_SUPPORT + + switch (starboard::shared::uwp::GetXboxType()) { + case starboard::shared::uwp::kXboxOneBase: + // Horizontal video resolutions + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 2560, 1440, + 30); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 1920, 1080, + 60); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 2560, 1440, + 30); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 1920, 1080, + 60); + // Vertical video resolutions + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 1440, 2560, + 30); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 1080, 1920, + 60); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 1440, 2560, + 30); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 1080, 1920, + 60); + break; + case starboard::shared::uwp::kXboxOneS: + if (!limit_to_2k) { + // Horizontal video resolution + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 3840, + 2160, 30); + // Vertical video resolution + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 2160, + 3840, 30); + } + // Horizontal video resolutions + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 2560, 1440, + 60); + gpu_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecVp9, 2560, 1440, + 60); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 2560, 1440, + 30); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 1920, 1080, + 60); + gpu_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 2560, 1440, + 30); + gpu_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 1920, 1080, + 60); + // Vertical video resolutions + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 1440, 2560, + 60); + gpu_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecVp9, 1440, 2560, + 60); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 1440, 2560, + 30); + gpu_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 1080, 1920, + 60); + gpu_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 1440, 2560, + 30); + gpu_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 1080, 1920, + 60); + break; + case starboard::shared::uwp::kXboxOneX: + // Horizontal video resolutions + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 3840, 2160, + 30); + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 2560, 1440, + 60); + // Until we can resolve b/170881040, we should cap Xbox One X to 2K for + // HDR 60 FPS. + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecVp9, 3840, 2160, + 30); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecVp9, 2560, 1440, + 60); + // Vertical video resolutions + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 2160, 3840, + 30); + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 1440, 2560, + 60); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecVp9, 2160, 3840, + 30); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecVp9, 1440, 2560, + 60); + break; + case starboard::shared::uwp::kXboxSeriesS: + // Horizontal video resolutions + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 3840, 2160, + 60); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecVp9, 3840, 2160, + 60); + // Vertical video resolutions + // Microsoft Vp9 MFT component is limited by 3840x2160 resolution + // so vertical video resolutions is the same as horizontal + + // Horizontal video resolutions + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 3840, 2160, + 30); + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 3840, 2160, + 60); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 3840, 2160, + 30); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 1920, 1080, + 60); + // Vertical video resolutions + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 2160, 3840, + 30); + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 2160, 3840, + 60); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 2160, 3840, + 30); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 1080, 1920, + 60); + break; + case starboard::shared::uwp::kXboxSeriesX: + // Horizontal video resolutions + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecVp9, 3840, 2160, + 60); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecVp9, 3840, 2160, + 60); + // Vertical video resolutions vor vp9 is the same as horizontal + + // Horizontal video resolutions + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 3840, 2160, + 30); + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 2560, 1440, + 60); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 2560, 1440, + 30); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 1920, 1080, + 60); + // Vertical video resolutions + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 2160, 3840, + 30); + hw_decoder_capabilities_.AddSdrRule(kSbMediaVideoCodecAv1, 1440, 2560, + 60); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 1440, 2560, + 30); + hw_decoder_capabilities_.AddHdrRule(kSbMediaVideoCodecAv1, 1080, 1920, + 60); + break; + default: + // If you appeared here you likely added new XBox model name but not + // specified corresponded case here to add rule for SDR and HDR + // supported resolution/framerate. + SB_NOTREACHED(); + } + } + + bool IsSupported(SbMediaVideoCodec codec, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int width, + int height, + int fps) const { + bool is_supported = hw_decoder_capabilities_.IsSupported( + codec, transfer_id, width, height, fps); + + if (ExtendedResourcesManager::GetInstance()->IsGpuDecoderReady() && + !is_supported) { + is_supported = gpu_decoder_capabilities_.IsSupported(codec, transfer_id, + width, height, fps); + } + + if (starboard::shared::starboard::media::IsSDRVideo( + bit_depth, primary_id, transfer_id, matrix_id)) { + return is_supported; + } + +#if SB_API_VERSION < 14 + // AV1 decoder only supports YUVI420 compact texture format. The new format + // is only supported after + // 14. + if (codec == kSbMediaVideoCodecAv1) { + return false; + } +#endif // SB_API_VERSION >= 14 + + is_supported &= ApplicationUwp::Get()->IsHdrSupported(); + is_supported &= bit_depth == 10; + is_supported &= primary_id == kSbMediaPrimaryIdBt2020; + is_supported &= transfer_id == kSbMediaTransferIdSmpteSt2084; + // According to https://support.google.com/youtube/answer/7126552 + // upload requirements the color matrix should be Rec.2020 + // non-constant luminance. + is_supported &= matrix_id == kSbMediaMatrixIdBt2020NonconstantLuminance; + return is_supported; + } + + private: + // We use gpu accelerated software decoder on kXboxOneBase and kXboxOneS. The + // software decoder initialization takes some time at app launch, and will be + // only available after initialization. So, we use |gpu_decoder_capabilities_| + // and ExtendedResourcesManager::IsGpuDecoderReady() to determine the device + // capabilities with software decoder. |hw_decoder_capabilities_| is + // determined by the device type and would not change at all. + starboard::shared::starboard::media::VideoCapabilities + hw_decoder_capabilities_; + starboard::shared::starboard::media::VideoCapabilities + gpu_decoder_capabilities_; +}; + +} // namespace + +bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, + const MimeType* mime_type, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required) { + if (bitrate > kSbMediaMaxVideoBitrateInBitsPerSecond) { + return false; + } + + // To avoid massive dropping frames, only support video's fps + // that is at most 20% higher than the refresh rate of display + // in HDR mode. + if (1.2 * ApplicationUwp::Get()->GetRefreshRate() < fps) { + return false; + } + + static const XboxVideoCapabilities xbox_video_capabilities; + return xbox_video_capabilities.IsSupported(video_codec, bit_depth, primary_id, + transfer_id, matrix_id, + frame_width, frame_height, fps); +}