Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space

[**.ts]
indent_size = 4

[*.json]
indent_size = 2
22 changes: 22 additions & 0 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Node CI

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [25.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install, build, and test
run: |
npm ci
npm test
env:
CI: true
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 2.0.1
Fixes for `findMaxHdcpVersion()`.

# 2.0.0
- Added `findMaxHdcpVersion()` function to quickly find maximum supported HDCP version.
- Replaced `HDCP_MIN_VERSION_WITH_UHD` with `HDCP_MIN_VERSION_WITH_4K`.
Expand Down
64 changes: 41 additions & 23 deletions dist/index.common.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

// https://wicg.github.io/hdcp-detection/
// https://w3c.github.io/encrypted-media/#dom-mediakeys-getstatusforpolicy
const hdcpVersions = [
'1.0',
'1.1',
Expand All @@ -12,34 +12,37 @@ const hdcpVersions = [
'2.2', // 4K
'2.3', // 8K
];
const defaultConfig = [{
videoCapabilities: [{
contentType: 'video/mp4; codecs="avc1.42E01E"',
}],
}];
const HDCP_MIN_VERSION_WITH_4K = '2.2';
const HDCP_MIN_VERSION_WITH_8K = '2.3';
function isUsableStatus(status) {
return status === 'usable';
}
function getMaxHdcpVersion(versions) {
for (let i = versions.length - 1; i >= 0; i--) {
const item = versions[i];
if (item.status === 'usable') {
if (isUsableStatus(item.status)) {
return item.version;
}
}
return '';
}
function is4KHdcpSupported(versions) {
const maxVersion = getMaxHdcpVersion(versions);
function is4KHdcpSupported(version) {
const maxVersion = Array.isArray(version) ? getMaxHdcpVersion(version) : version;
return maxVersion ?
parseFloat(maxVersion) >= parseFloat(HDCP_MIN_VERSION_WITH_4K) :
false;
}
function is8KHdcpSupported(versions) {
const maxVersion = getMaxHdcpVersion(versions);
function is8KHdcpSupported(version) {
const maxVersion = Array.isArray(version) ? getMaxHdcpVersion(version) : version;
return maxVersion ?
parseFloat(maxVersion) >= parseFloat(HDCP_MIN_VERSION_WITH_8K) :
false;
}
const defaultConfig = [{
videoCapabilities: [{
contentType: 'video/mp4; codecs="avc1.42E01E"',
}],
}];
function checkHdcpVersion(keySystem, version) {
if (typeof window.navigator.requestMediaKeySystemAccess !== 'function') {
const error = new Error('navigator.requestMediaKeySystemAccess is not supported');
Expand Down Expand Up @@ -96,27 +99,41 @@ async function findMaxHdcpVersion(keySystem) {
}
let left = 0;
let right = hdcpVersions.length - 1;
let maxSupportedVersion = '';
const maxVersion = hdcpVersions[right];
const maxStatus = await mediaKeys.getStatusForPolicy({ minHdcpVersion: maxVersion });
if (maxStatus === 'usable') {
return maxVersion;
let version = hdcpVersions[right];
let status = await mediaKeys.getStatusForPolicy({ minHdcpVersion: version });
const attempts = [{
version,
status,
}];
if (isUsableStatus(status)) {
return {
version,
status,
attempts,
};
}
while (left <= right) {
const middle = Math.floor((left + right) / 2);
const middleVersion = hdcpVersions[middle];
const midStatus = await mediaKeys.getStatusForPolicy({ minHdcpVersion: middleVersion });
if (midStatus === 'usable') {
// Если текущая версия поддерживается, сохраняем её и ищем более высокую
maxSupportedVersion = middleVersion;
version = hdcpVersions[middle];
status = await mediaKeys.getStatusForPolicy({ minHdcpVersion: version });
attempts.push({
version,
status,
});
if (isUsableStatus(status)) {
left = middle + 1;
}
else {
// Если текущая версия не поддерживается, ищем более низкую
right = middle - 1;
}
}
return maxSupportedVersion;
attempts.sort((a, b) => parseFloat(a.version) - parseFloat(b.version));
const maxVersion = getMaxHdcpVersion(attempts);
return {
version: maxVersion,
status: maxVersion ? 'usable' : attempts[0].status,
attempts,
};
}

exports.HDCP_MIN_VERSION_WITH_4K = HDCP_MIN_VERSION_WITH_4K;
Expand All @@ -128,3 +145,4 @@ exports.getMaxHdcpVersion = getMaxHdcpVersion;
exports.hdcpVersions = hdcpVersions;
exports.is4KHdcpSupported = is4KHdcpSupported;
exports.is8KHdcpSupported = is8KHdcpSupported;
exports.isUsableStatus = isUsableStatus;
17 changes: 11 additions & 6 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
export interface CheckHdcpVersion {
version: string;
status: MediaKeyStatus;
}
export declare const hdcpVersions: string[];
export declare const HDCP_MIN_VERSION_WITH_4K = "2.2";
export declare const HDCP_MIN_VERSION_WITH_8K = "2.3";
export declare function isUsableStatus(status: MediaKeyStatus): status is "usable";
export declare function getMaxHdcpVersion(versions: CheckHdcpVersion[]): string;
export declare function is4KHdcpSupported(versions: CheckHdcpVersion[]): boolean;
export declare function is8KHdcpSupported(versions: CheckHdcpVersion[]): boolean;
export declare function is4KHdcpSupported(version: string | CheckHdcpVersion[]): boolean;
export declare function is8KHdcpSupported(version: string | CheckHdcpVersion[]): boolean;
export declare function checkHdcpVersion(keySystem: string, version: string): Promise<MediaKeyStatus>;
export interface CheckHdcpVersion {
export declare function checkAllHdcpVersions(keySystem: string): Promise<CheckHdcpVersion[]>;
export declare function findMaxHdcpVersion(keySystem: string): Promise<{
version: string;
status: MediaKeyStatus;
}
export declare function checkAllHdcpVersions(keySystem: string): Promise<CheckHdcpVersion[]>;
export declare function findMaxHdcpVersion(keySystem: string): Promise<string>;
attempts: CheckHdcpVersion[];
}>;
66 changes: 43 additions & 23 deletions dist/index.esm.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// https://w3c.github.io/encrypted-media/#dom-mediakeys-getstatusforpolicy
const hdcpVersions = [
'1.0',
'1.1',
Expand All @@ -6,37 +7,40 @@ const hdcpVersions = [
'1.4',
'2.0',
'2.1',
'2.2',
'2.3',
'2.2', // 4K
'2.3', // 8K
];
const defaultConfig = [{
videoCapabilities: [{
contentType: 'video/mp4; codecs="avc1.42E01E"',
}],
}];
const HDCP_MIN_VERSION_WITH_4K = '2.2';
const HDCP_MIN_VERSION_WITH_8K = '2.3';
function isUsableStatus(status) {
return status === 'usable';
}
function getMaxHdcpVersion(versions) {
for (let i = versions.length - 1; i >= 0; i--) {
const item = versions[i];
if (item.status === 'usable') {
if (isUsableStatus(item.status)) {
return item.version;
}
}
return '';
}
function is4KHdcpSupported(versions) {
const maxVersion = getMaxHdcpVersion(versions);
function is4KHdcpSupported(version) {
const maxVersion = Array.isArray(version) ? getMaxHdcpVersion(version) : version;
return maxVersion ?
parseFloat(maxVersion) >= parseFloat(HDCP_MIN_VERSION_WITH_4K) :
false;
}
function is8KHdcpSupported(versions) {
const maxVersion = getMaxHdcpVersion(versions);
function is8KHdcpSupported(version) {
const maxVersion = Array.isArray(version) ? getMaxHdcpVersion(version) : version;
return maxVersion ?
parseFloat(maxVersion) >= parseFloat(HDCP_MIN_VERSION_WITH_8K) :
false;
}
const defaultConfig = [{
videoCapabilities: [{
contentType: 'video/mp4; codecs="avc1.42E01E"',
}],
}];
function checkHdcpVersion(keySystem, version) {
if (typeof window.navigator.requestMediaKeySystemAccess !== 'function') {
const error = new Error('navigator.requestMediaKeySystemAccess is not supported');
Expand Down Expand Up @@ -93,25 +97,41 @@ async function findMaxHdcpVersion(keySystem) {
}
let left = 0;
let right = hdcpVersions.length - 1;
let maxSupportedVersion = '';
const maxVersion = hdcpVersions[right];
const maxStatus = await mediaKeys.getStatusForPolicy({ minHdcpVersion: maxVersion });
if (maxStatus === 'usable') {
return maxVersion;
let version = hdcpVersions[right];
let status = await mediaKeys.getStatusForPolicy({ minHdcpVersion: version });
const attempts = [{
version,
status,
}];
if (isUsableStatus(status)) {
return {
version,
status,
attempts,
};
}
while (left <= right) {
const middle = Math.floor((left + right) / 2);
const middleVersion = hdcpVersions[middle];
const midStatus = await mediaKeys.getStatusForPolicy({ minHdcpVersion: middleVersion });
if (midStatus === 'usable') {
maxSupportedVersion = middleVersion;
version = hdcpVersions[middle];
status = await mediaKeys.getStatusForPolicy({ minHdcpVersion: version });
attempts.push({
version,
status,
});
if (isUsableStatus(status)) {
left = middle + 1;
}
else {
right = middle - 1;
}
}
return maxSupportedVersion;
attempts.sort((a, b) => parseFloat(a.version) - parseFloat(b.version));
const maxVersion = getMaxHdcpVersion(attempts);
return {
version: maxVersion,
status: maxVersion ? 'usable' : attempts[0].status,
attempts,
};
}

export { HDCP_MIN_VERSION_WITH_4K, HDCP_MIN_VERSION_WITH_8K, checkAllHdcpVersions, checkHdcpVersion, findMaxHdcpVersion, getMaxHdcpVersion, hdcpVersions, is4KHdcpSupported, is8KHdcpSupported };
export { HDCP_MIN_VERSION_WITH_4K, HDCP_MIN_VERSION_WITH_8K, checkAllHdcpVersions, checkHdcpVersion, findMaxHdcpVersion, getMaxHdcpVersion, hdcpVersions, is4KHdcpSupported, is8KHdcpSupported, isUsableStatus };
4 changes: 4 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default {
preset: 'ts-jest',
testEnvironment: 'jsdom',
};
Loading