mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-14 15:56:38 +03:00
970d7756ea
The goal is to simplify and abstract feature logic detection. Currently lots of places depend on various calls to `shaka.util.Platform` and mainteinance of this is hard & not easy to read. By introducing device API ideally rest of the player logic would look into device features instead of directly checking platform. Additionally we can more easily cache needed values, so we won't have to parse user agent several times anymore. --------- Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
183 lines
4.4 KiB
JavaScript
183 lines
4.4 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.provide('shaka.device.Xbox');
|
|
|
|
goog.require('shaka.device.AbstractDevice');
|
|
goog.require('shaka.device.DeviceFactory');
|
|
goog.require('shaka.device.IDevice');
|
|
goog.require('shaka.log');
|
|
|
|
|
|
/**
|
|
* @final
|
|
*/
|
|
shaka.device.Xbox = class extends shaka.device.AbstractDevice {
|
|
constructor() {
|
|
super();
|
|
|
|
/** @private {boolean} */
|
|
this.isLegacyEdge_ = navigator.userAgent.includes('Edge/');
|
|
|
|
// Looking for something like "Edg/106.0.0.0".
|
|
const match = navigator.userAgent.match(/Edge?\/(\d+)/);
|
|
|
|
/** @private {?number} */
|
|
this.version_ = match ? parseInt(match[1], /* base= */ 10) : null;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
getVersion() {
|
|
return this.version_;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
getDeviceName() {
|
|
return 'Xbox';
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
getDeviceType() {
|
|
return shaka.device.IDevice.DeviceType.CONSOLE;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
getBrowserEngine() {
|
|
return this.isLegacyEdge_ ? shaka.device.IDevice.BrowserEngine.EDGE :
|
|
shaka.device.IDevice.BrowserEngine.CHROMIUM;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
requiresEncryptionInfoInAllInitSegments(keySystem) {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
insertEncryptionDataBeforeClear() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
shouldOverrideDolbyVisionCodecs() {
|
|
return this.isLegacyEdge_;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
detectMaxHardwareResolution() {
|
|
const maxResolution = {width: 1920, height: 1080};
|
|
const winRT = shaka.device.Xbox.getWinRT_();
|
|
|
|
if (winRT) {
|
|
try {
|
|
const protectionCapabilities =
|
|
new winRT.Media.Protection.ProtectionCapabilities();
|
|
const protectionResult =
|
|
winRT.Media.Protection.ProtectionCapabilityResult;
|
|
// isTypeSupported may return "maybe", which means the operation
|
|
// is not completed. This means we need to retry
|
|
// https://learn.microsoft.com/en-us/uwp/api/windows.media.protection.protectioncapabilityresult?view=winrt-22621
|
|
let result = null;
|
|
const type =
|
|
'video/mp4;codecs="hvc1,mp4a";features="decode-res-x=3840,' +
|
|
'decode-res-y=2160,decode-bitrate=20000,decode-fps=30,' +
|
|
'decode-bpc=10,display-res-x=3840,display-res-y=2160,' +
|
|
'display-bpc=8"';
|
|
const keySystem = 'com.microsoft.playready.recommendation';
|
|
do {
|
|
result = protectionCapabilities.isTypeSupported(type, keySystem);
|
|
} while (result === protectionResult.maybe);
|
|
if (result === protectionResult.probably) {
|
|
maxResolution.width = 3840;
|
|
maxResolution.height = 2160;
|
|
}
|
|
} catch (e) {
|
|
shaka.log.alwaysWarn('Xbox: Error detecting screen size, default ' +
|
|
'screen size 1920x1080.');
|
|
}
|
|
}
|
|
|
|
return Promise.resolve(maxResolution);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
adjustConfig(config) {
|
|
super.adjustConfig(config);
|
|
|
|
// The Xbox One browser does not detect DRM key changes signalled by a
|
|
// change in the PSSH in media segments. We need to parse PSSH from media
|
|
// segments to detect key changes.
|
|
config.drm.parseInbandPsshEnabled = this.isLegacyEdge_;
|
|
// The Xbox only supports the Playready DRM, so it should
|
|
// prefer that key system by default to improve startup performance.
|
|
config.drm.preferredKeySystems.push('com.microsoft.playready');
|
|
if (this.isLegacyEdge_) {
|
|
config.streaming.gapPadding = 0.01;
|
|
}
|
|
return config;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
supportsOfflineStorage() {
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return {?WinRT}
|
|
* @private
|
|
*/
|
|
static getWinRT_() {
|
|
let winRT = null;
|
|
try {
|
|
// Try to access to WinRT for WebView, if it's not defined,
|
|
// try to access to WinRT for WebView2, if it's not defined either,
|
|
// let it throw.
|
|
if (typeof Windows !== 'undefined') {
|
|
winRT = Windows;
|
|
} else {
|
|
winRT = chrome.webview.hostObjects.sync.Windows;
|
|
}
|
|
} catch (e) {}
|
|
return winRT;
|
|
}
|
|
|
|
/**
|
|
* Check if the current platform is an Xbox One.
|
|
*
|
|
* @return {boolean}
|
|
* @private
|
|
*/
|
|
static isXbox_() {
|
|
return navigator.userAgent.includes('Xbox One') ||
|
|
shaka.device.Xbox.getWinRT_() !== null;
|
|
}
|
|
};
|
|
|
|
if (shaka.device.Xbox.isXbox_()) {
|
|
shaka.device.DeviceFactory.registerDeviceFactory(
|
|
() => new shaka.device.Xbox());
|
|
}
|