blob: b46802b624eecac4428a4907b737eb4d9a0eb46f [file] [log] [blame]
// Copyright 2017 Google Inc. 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 <sstream>
#include "starboard/common/scoped_ptr.h"
#include "starboard/configuration.h"
#include "starboard/media.h"
#include "starboard/once.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/shared/win32/media_common.h"
#include "starboard/shared/win32/media_foundation_utils.h"
#include "starboard/shared/win32/media_transform.h"
#include "starboard/shared/win32/video_transform.h"
#include "starboard/shared/win32/wchar_utils.h"
#include "starboard/system.h"
#include "starboard/window.h"
// #define ENABLE_VP9_DECODER
using Microsoft::WRL::ComPtr;
using starboard::scoped_ptr;
using starboard::ScopedLock;
using starboard::shared::win32::CheckResult;
using starboard::shared::win32::kVideoFormat_YV12;
using starboard::shared::win32::MediaTransform;
using starboard::shared::win32::TryCreateVP9Transform;
namespace {
class VideoSupported {
public:
static VideoSupported* GetSingleton();
bool IsVideoSupported(SbMediaVideoCodec video_codec,
int frame_width,
int frame_height,
int64_t bitrate,
int fps) {
// Is resolution out of range?
if (frame_width > max_width_ || frame_height > max_height_) {
return false;
}
// Is bitrate in range?
if (bitrate > SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND) {
return false;
}
if (fps > 60) {
return false;
}
if (video_codec == kSbMediaVideoCodecH264) {
return true;
}
if (video_codec == kSbMediaVideoCodecVp9) {
return IsVp9Supported(frame_width, frame_height);
}
return false;
}
private:
bool AllowVp9Decoder() {
#ifdef ENABLE_VP9_DECODER
return platform_supports_vp9_;
#else
return false;
#endif
}
static bool DetectVp9Supported(int width, int height) {
scoped_ptr<MediaTransform> vp9_decoder =
TryCreateVP9Transform(kVideoFormat_YV12, width, height);
return !!vp9_decoder.get();
}
static bool DetectPlatformIsXbox() {
using starboard::shared::win32::platformStringToString;
using Windows::Security::ExchangeActiveSyncProvisioning::
EasClientDeviceInformation;
EasClientDeviceInformation^ device_info =
ref new EasClientDeviceInformation();
const std::string product_name =
platformStringToString(device_info->SystemProductName);
return product_name.find("Xbox One") != std::string::npos;
}
bool IsVp9Supported(int width, int height) {
if (!AllowVp9Decoder()) {
return false;
}
// When width/height is zero then this is a special value to mean
// IsVP9 available at all? Therefore detect the general case by
// testing the specific case of 1024 x 768.
if ((width == 0) && (height == 0)) {
return DetectVp9Supported(1024, 768);
}
Key key = {width, height};
ScopedLock lock(mutex_);
auto it = vpn_size_cache_.find(key);
if (it != vpn_size_cache_.end()) {
return it->second;
} else {
const bool vp9_valid = DetectVp9Supported(width, height);
vpn_size_cache_[key] = vp9_valid;
return vp9_valid;
}
}
VideoSupported() {
platform_supports_vp9_ = DetectPlatformIsXbox();
SbWindowOptions sb_window_options;
SbWindowSetDefaultOptions(&sb_window_options);
max_width_ = sb_window_options.size.width;
max_height_ = sb_window_options.size.height;
}
struct Key {
int width = 0;
int height = 0;
bool operator<(const Key& other) const {
if (width != other.width) {
return width < other.width;
}
return height < other.height;
}
};
starboard::Mutex mutex_;
using Vp9SizeCache = std::map<Key, bool>;
Vp9SizeCache vpn_size_cache_;
bool platform_supports_vp9_ = false;
int max_width_ = 0;
int max_height_ = 0;
};
SB_ONCE_INITIALIZE_FUNCTION(VideoSupported, VideoSupported::GetSingleton);
} // namespace.
SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
int frame_width,
int frame_height,
int64_t bitrate,
int fps) {
bool supported = VideoSupported::GetSingleton()->IsVideoSupported(
video_codec, frame_width, frame_height, bitrate, fps);
return supported;
}