From 86e993f15520990250918af29c42757a8d777582 Mon Sep 17 00:00:00 2001 From: Joe Martin Date: Mon, 3 Jun 2024 11:46:37 -0400 Subject: [PATCH] feat: Add key name prefix; other fixes --- package-lock.json | 286 +++--------------- package.json | 2 +- .../specifications/media/media-info.md | 226 +++++++++++--- src/openrpc/device.json | 2 +- src/schemas/media.json | 17 +- 5 files changed, 231 insertions(+), 302 deletions(-) diff --git a/package-lock.json b/package-lock.json index d79ffae5b..c158f5b77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "devDependencies": { "@commitlint/cli": "^17.0.3", "@commitlint/config-conventional": "^17.0.3", - "@firebolt-js/openrpc": "rdkcentral/firebolt-openrpc#feature/x-subscriber-type", + "@firebolt-js/openrpc": "file:/Users/jmarti350/src/firebolt-openrpc", "@firebolt-js/schemas": "2.0.0", "@saithodev/semantic-release-backmerge": "^3.2.0", "@semantic-release/changelog": "^6.0.1", @@ -36,6 +36,37 @@ "typescript": "^4.6.4" } }, + "../firebolt-openrpc": { + "version": "3.0.0-next.3", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "ajv": "^8.3.0", + "ajv-formats": "^2.1.0", + "array.prototype.groupby": "^1.1.0", + "crocks": "^0.12.4", + "deepmerge": "^4.2.2", + "fs-extra": "^10.1.0", + "highland": "^2.13.5", + "mkdirp": "^0.5.6", + "node-fetch": "^3.2.10", + "nopt": "^5.0.0", + "util": "^0.12.4" + }, + "bin": { + "firebolt-openrpc": "src/cli.mjs" + }, + "devDependencies": { + "@commitlint/cli": "^17.1.2", + "@commitlint/config-conventional": "^17.1.0", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/git": "^10.0.1", + "@semantic-release/npm": "^9.0.1", + "husky": "^8.0.1", + "jest": "^27.3.1", + "semantic-release": "^19.0.5" + } + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -1070,94 +1101,8 @@ "link": true }, "node_modules/@firebolt-js/openrpc": { - "version": "3.0.0-next.3", - "resolved": "git+ssh://git@github.com/rdkcentral/firebolt-openrpc.git#daa0d06f64026ac1cf8416810854421756fbc377", - "dev": true, - "dependencies": { - "ajv": "^8.3.0", - "ajv-formats": "^2.1.0", - "array.prototype.groupby": "^1.1.0", - "crocks": "^0.12.4", - "deepmerge": "^4.2.2", - "fs-extra": "^10.1.0", - "highland": "^2.13.5", - "mkdirp": "^0.5.6", - "node-fetch": "^3.2.10", - "nopt": "^5.0.0", - "util": "^0.12.4" - }, - "bin": { - "firebolt-openrpc": "src/cli.mjs" - } - }, - "node_modules/@firebolt-js/openrpc/node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/@firebolt-js/openrpc/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@firebolt-js/openrpc/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@firebolt-js/openrpc/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/@firebolt-js/openrpc/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/@firebolt-js/openrpc/node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } + "resolved": "../firebolt-openrpc", + "link": true }, "node_modules/@firebolt-js/schemas": { "version": "2.0.0", @@ -2730,20 +2675,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.groupby": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array.prototype.groupby/-/array.prototype.groupby-1.1.0.tgz", - "integrity": "sha512-p+QtvmnNEBqajQWLG3kPls8cLPBfJgvayzc/qplsX8Vchtevtq+TR2gyav5xs5h+mdUjfgOvYoCdTsVxu3b5sA==", - "deprecated": "This proposal has been altered; please use https://npmjs.com/object.groupby instead!", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.1" - } - }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", @@ -3369,12 +3300,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "node_modules/crocks": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/crocks/-/crocks-0.12.4.tgz", - "integrity": "sha512-paln6xJUrR9e/OWMFsyTi4dLyr+q99C5f7PQbGgSDHtwsfW0sCNZvnpHzvniI2dAE0uoBgeIP1Ukmme8Z0HxxA==", - "dev": true - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -3431,15 +3356,6 @@ "node": ">=8" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", @@ -4809,29 +4725,6 @@ "bser": "2.1.1" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "node_modules/figures": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", @@ -4946,18 +4839,6 @@ "node": ">= 6" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -5415,15 +5296,6 @@ "node": ">= 0.4" } }, - "node_modules/highland": { - "version": "2.13.5", - "resolved": "https://registry.npmjs.org/highland/-/highland-2.13.5.tgz", - "integrity": "sha512-dn2flPapIIAa4BtkB2ahjshg8iSJtrJtdhEb9/oiOrS5HMQTR/GuhFpqJ+11YBdtnl3AwWKvbZd1Uxr8uAmA7A==", - "dev": true, - "dependencies": { - "util-deprecate": "^1.0.2" - } - }, "node_modules/hook-std": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", @@ -5682,22 +5554,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -5812,21 +5668,6 @@ "node": ">=6" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7457,25 +7298,6 @@ "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", "dev": true }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -7485,24 +7307,6 @@ "lodash": "^4.17.21" } }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -16575,19 +16379,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -16667,15 +16458,6 @@ "makeerror": "1.0.12" } }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", diff --git a/package.json b/package.json index e80822d17..7729aa446 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "devDependencies": { "@commitlint/cli": "^17.0.3", "@commitlint/config-conventional": "^17.0.3", - "@firebolt-js/openrpc": "rdkcentral/firebolt-openrpc#feature/x-subscriber-type", + "@firebolt-js/openrpc": "rdkcentral/firebolt-openrpc#feature/key-name-prefix", "@firebolt-js/schemas": "2.0.0", "@saithodev/semantic-release-backmerge": "^3.2.0", "@semantic-release/changelog": "^6.0.1", diff --git a/requirements/specifications/media/media-info.md b/requirements/specifications/media/media-info.md index 25a749f53..a4cc50a3e 100644 --- a/requirements/specifications/media/media-info.md +++ b/requirements/specifications/media/media-info.md @@ -72,6 +72,7 @@ I want to show an audio/videophile overlay with detailed information: - [3.5. Video Modes](#35-video-modes) - [3.6. Media HDR Profiles](#36-media-hdr-profiles) - [3.7. Color Depth](#37-color-depth) + - [3.8 Colorimetry](#38-colorimetry) - [4. Device Media Support](#4-device-media-support) - [4.1. Video Format Supported](#41-video-format-supported) - [4.2. Audio Format Supported](#42-audio-format-supported) @@ -106,23 +107,27 @@ I want to show an audio/videophile overlay with detailed information: The Firebolt `Media` module **MUST** have an `AudioContainer` enumeration of the following media container content types: -- `audio/mp4` -- `audio/mpeg` -- `audio/ogg` -- `audio/webm` +| Name | Description | +| ------------ | ------------------------------------------------------------------------------------------------------------------------------ | +| `audio/mp4` | [MP4 Audio](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#mpeg-4_mp4) | +| `audio/mpeg` | [Moving Picture Experts Group (MPEG1/MPEG2)](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#mpegmpeg-2) | +| `audio/ogg` | [OGG](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#ogg) | +| `audio/webm` | [Web Media](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#webm) | The Firebolt `Media` module **MUST** have a `VideoContainer` enumeration of the following media container content types: -- `video/mp2t` -- `video/mp4` -- `video/mpeg` -- `video/webm` +| Name | Description | +| ------------ | ------------------------------------------------------------------------------------------------------------------------------ | +| `video/mp2t` | [MPEG transport stream](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) | +| `video/mp4` | [MP4 Audio](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/) | +| `video/mpeg` | [Moving Picture Experts Group (MPEG1/MPEG2)](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#mpegmpeg-2) | +| `video/webm` | [Web Media](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#webm) | ### 3.2. Media Codecs The Firebolt `Media` module **MUST** have an `AudioCodec` enumeration: -| Name | Value | +| Name | Description | | -------- | ---------------------------------------------- | | `aac` | Advanced Audio Coding | | `ac3` | Dolby Digital / Dolby Audio Codec 3 | @@ -131,13 +136,14 @@ The Firebolt `Media` module **MUST** have an `AudioCodec` enumeration: | `eac3` | Dolby Digital Plus / Dolby Enhanced AC-3 / DD+ | | `mpeg3` | MPEG-1 Part 3 & MPEG-2 Part 3 | | `opus` | IETF Opus | -| `truehd` | Dolby TrueHD | +| `truehd` | Dolby TrueHD / MLP | | `vorbis` | Xiph.org Vorbis | The Firebolt `Media` module **MUST** have a `VideoCodec` enumeration: | Name | Description | | ------- | ------------------------------------ | +| `av1` | AOMedia Video 1 | | `avc` | Advanced Video Coding (H.264) | | `hevc` | High Efficiency Video Coding (H.265) | | `mpeg1` | MPEG-1 Part 2 Visual | @@ -152,7 +158,7 @@ For the purposes of the Firebolt API, a `Resolution` shall be defined by two val For example, the resolution for a display may be defined as `[1920, 1080]`. -Any methods relating to a resolution (such as the supported resolution of a display or the output resolution of a device) **MUST** return an array of two values: the width and height. +Any methods relating to a resolution (such as the supported resolution of a display or the output resolution of a device) **MUST** return two values: the width and height. ### 3.4. Resolution User-Friendly Name @@ -168,7 +174,7 @@ The Firebolt `Media` module **MUST** have a `ResolutionName` enumeration: ### 3.5. Video Modes -For the purposes of the Firebolt API, a `VideoMode` shall be defined as the shorthand resolution and frame rate of video content. +For the purposes of the Firebolt API, a `VideoMode` shall be defined as the shorthand vertical resolution and frame rate of video content. The Firebolt `Media` module **MUST** have a `VideoMode` enumeration: @@ -179,17 +185,20 @@ The Firebolt `Media` module **MUST** have a `VideoMode` enumeration: - `576p60` - `720p50` - `720p60` -- `1080i25` - `1080i50` - `1080i60` - `1080p24` +- `1080p25` - `1080p30` - `1080p50` - `1080p60` +- `2160p24` +- `2160p25` - `2160p30` - `2160p50` - `2160p60` - `4320p60` +- `unknown` Any methods relating to the video mode (such as a device's video output mode) **MUST** return `Media.VideoMode` values. @@ -213,6 +222,22 @@ The Firebolt `Media` module **MUST** have an `ColorDepth` enumeration: - `10` - `12` +### 3.8 Colorimetry + +The Firebolt `Media` module **MUST** have an `Colorimetry` enumeration: + +- `BT2020cYCC` +- `BT2020RGB` +- `BT2020YCC` +- `DCI-P3` +- `ICtCp` +- `opRGB` (Adobe RGB 1998) +- `opYCC601` +- `sYCC601` +- `xvYCC601` +- `xvYCC709` +- `unknown` + ## 4. Device Media Support Apps need to know what types of media support the device is capable of. @@ -226,16 +251,18 @@ These values do not change without a settings change or a firmware update. The `Device` module **MUST** have a `videoFormatSupported` API that returns `true` or `false` depending on whether the format specified is supported by the current device and its AV chain. This API **MUST** return `boolean`. ```javascript -const hdr10plusWithH265 = videoFormatSupported(Media.VideoCodec.HEVC, { +const hdr10plusWithH265 = Device.videoFormatSupported(Media.VideoCodec.HEVC, { profile: "main10", hdr: Media.HDRProfile.HDR10_PLUS }) +//> true -const hdr10plusWithVP9 = videoFormatSupported(Media.VideoCodec.VP9, { +const hdr10plusWithVP9 = Device.videoFormatSupported(Media.VideoCodec.VP9, { profile: "p2", hdr: Media.HDRProfile.HDR10_PLUS, resolution: [3840, 2160] }) +//> true ``` The `videoFormatSupported` API **MUST** have a required `codec` parameter with the type `Media.VideoCodec`. @@ -248,7 +275,7 @@ The `videoFormatSupported` API **MUST** have an optional `info` parameter which | `hdr` | `Media.HDRProfile` | The HDR profile that support is being checked for | | `level` | `string` | The codec level:
**hevc**: `4.1`, `4.2`, `5.0`, `5.1`
**vp9**:`3.0`, `3.1`, `4.0`, `4.1`, `5.0`, `5.1` | | `profile` | `string` | The codec profile:
**hevc**: `main`, `high`, `main10`
**vp9**: `p0`, `p2` | -| `resolution` | `array` | The resolution in width and height (e.g. `[1920, 1080]`) of the media content being requested | +| `resolution` | `Media.Dimensions` | The resolution in width and height (e.g. `[1920, 1080]`) of the media content being requested | > **NOTE**: A device supporting a particular HDR profile and resolution does not mean that the current display also supports that profile and resolution. See `Display.hdrProfiles()` for more info on detecting display HDR support. @@ -261,13 +288,21 @@ Use of the `videoFormatSupported` API requires access to the `use` role of the ` The `Device` module **MUST** have an `audioFormatSupported` API that returns `true` or `false` depending on whether the format specified is supported by the current device configuration and its AV chain. This API **MUST** return a `boolean`. ```javascript -const atmosWithAC4 = audioFormatSupported(Media.AudioCodec.AC4, { +const atmosWithAC4 = Device.audioFormatSupported(Media.AudioCodec.AC4, { + atmos: true +}) +//> true + +const atmosWithTrueHD = Device.audioFormatSupported(Media.AudioCodec.TRUEHD, { atmos: true }) +//> true -const atmosWithEAC3 = audioFormatSupported(Media.AudioCodec.EAC3, { +const noAtmosOverMono = Device.audioFormatSupported(Media.AudioCodec.TRUEHD, { atmos: true + mode: 'mono' }) +//> false (mono output not supported with dolby atmos) ``` The `audioFormatSupported` API **MUST** have a required `codec` parameter with the type `Media.AudioCodec`. @@ -302,36 +337,66 @@ The `Display` module **MUST** have an `hdrProfiles` method that returns the disp If no display is present, an empty array is returned. +```javascript +Display.hdrProfiles() +//> ["dolbyVision", "hdr10", "hdr10plus", "hlg", "sdr"] +``` + ### 5.2. Supported Color Depth The `Display` module **MUST** have a `colorDepth` method that returns a `Media.ColorDepth` value. If no display is present, a value of zero is returned. +```javascript +Display.colorDepth() +//> 10 +``` + ### 5.3. Display Size The `Display` module **MUST** have a `size` method that returns the width and height of the display, in centimeters. If no display is present, a value of zero is returned for both the width and height. +```javascript +Display.size() +//> [157, 91] +``` + ### 5.4. Display Resolution The `Display` module **MUST** have a `resolution` method that returns the width and height of the display's native resolution. If no display is present, both returned values **MUST** be zero. +```javascript +Display.resolution() +//> [1920, 1080] +``` + ### 5.5. Display Resolution Name The `Display` module **MUST** have a `resolutionName` method that returns a user-friendly name of the display's resolution as defined by `Media.ResolutionName`. If no display is present, a value of `unknown` is returned. +```javascript +Display.resolutionName() +//> "uhd" +``` + ### 5.6. Refresh Rate -The `Display` module **MUST** have a `refreshRate` method that returns an number value for the refresh rate that the display supports (in Hz). +The `Display` module **MUST** have a `refreshRate` method that returns an number value for the optimal refresh rate that the display supports (in Hz). If no display is present, a value of zero is returned. +```javascript +Display.refreshRate() +//> 120 +``` + ## 6. Device Properties Apps need to know various aspects of the device, including its media playing capabilities. @@ -348,28 +413,53 @@ This method **MUST** return a value from the `Media.VideoMode` enum. If no display is present, a value of `unknown` is returned. +```javascript +Device.videoMode() +//> 1080p60 +``` + ### 6.2. Supported Video Modes The `Device` module **MUST** have a `videoModes` method that returns an array of valid video modes that the device and display together support. This method **MUST** return an array with one or more values from the `Media.VideoMode` enum. +```javascript +Device.supportedVideoModes() +//> ["720p50", "720p60", "1080p50", "1080p60"] +``` + ### 6.3. Video Resolution The `Device` module **MUST** have a `videoResolution` method that returns the width and height of the current video output resolution. If no display is present, both returned values **MUST** be zero. +```javascript +Device.videoResolution() +//> [1920, 1080] +``` + ### 6.4. Current HDR Profile The `Device` module **MUST** have a `hdrProfile` method that returns the HDR profile currently used by the device for video output. This method **MUST** return a value from the `Media.HDRProfile` enum. +```javascript +Device.hdrProfile() +//> "hdr10plus" +``` + ### 6.5. Supported HDR Profiles The `Device` module **MUST** have an `hdrProfiles` method that returns the HDR profiles that the device supports, regardless of any connected display. +```javascript +Device.hdrProfile() +//> ["hdr10", "hdr10plus", "hlg", "sdr"] +``` + ### 6.6. Supported HDCP Version The `Device` module **MUST** have a `hdcpVersion` method that returns the latest HDCP version supported by the device. @@ -380,14 +470,24 @@ This method **MUST** return a value such as: - `2.2` - `unknown` +```javascript +Device.hdcpVersion() +//> "2.2" +``` + ### 6.7. Source Frame Rate Used The `Device` module **MUST** have a boolean `sourceFrameRateUsed` API. -This API **MUST** return `true` if the HDMI output frame rate is set to follow video source frame rate. +This API **MUST** return `true` if the HDMI output frame rate is set to follow the video source's frame rate. Otherwise, this API **MUST** return `false`. +```javascript +Device.sourceFrameRateUsed() +//> true +``` + ## 7. Audio Output Properties Apps need to know various aspects of the current (or built in) audio output system on a device. @@ -418,14 +518,14 @@ Apps need a way to query the media info for media currently being played by the ```javascript import { MediaInfo } from '@firebolt-js/sdk' -MediaInfo.videoFormat(1) // return the video codec in the current app's media pipeline 1 -MediaInfo.videoFormat(2) // return the video codec in the current app's media pipeline 2 +MediaInfo.videoFormat(1) // return the video format in the current app's media pipeline 1 +MediaInfo.videoFormat(2) // return the video format in the current app's media pipeline 2 ``` **TODO**: where do we map video tags to ids? need a spec for this? same spec, new spec? JL: i linked to the Media Pipeline spec and merged it into this branch... we should review. -The `pipeline` parameter is required for the JSON-RPC request, however, the Firebolt SDK **SHOULD** provide a default value of `1` if it is not provided by the calling app. +The `pipeline` parameter is required for the JSON-RPC request, however, the Firebolt SDK **SHOULD** provide a default value of `1` if not provided by the calling app. For example, the following would query the video format for the app's pipeline `1` in JavaScript (which supports default values for parameters). @@ -455,6 +555,26 @@ have a corresponding `onVideoFormatChanged` notification. Use of the `videoFormat` APIs require access to the `use` role of the `xrn:firebolt:capability:media-info:video-format` capability. +```javascript +MediaInfo.videoFormat(1) +/* +{ + "codec": "hevc", + "codecLevel": "4.2", + "codecProfile": "main", + "container": "video/mp4", + "frameRate": 30, + "hdr": [ + "hdr10" + ], + "resolution": [ + 1920, + 1080 + ] +} +*/ +``` + #### 7.1.2. Audio Format The `MediaInfo` module **MUST** have a `audioFormat` API that returns an `object` with the @@ -475,6 +595,19 @@ The `audioFormat` API **MUST** be a Firebolt `property:readonly` API, and have a Use of the `audioFormat` APIs require access to the `use` role of the `xrn:firebolt:capability:media-info:audio-format` capability. +```javascript +MediaInfo.audioFormat(1) +/* +{ + "bitRate": 128, + "channels": 2, + "codec": "aac", + "container": "audio/mp4", + "sampleRate": 48 +} +*/ +``` + ### 7.2. Global MediaInfo First party apps need a way to query which media formats are currently being output to the [media pipeline](./media-pipeline.md), without caring about which pipeline. @@ -488,13 +621,26 @@ Additionally, the `MediaInfo` module **MUST** have an `onActiveVideoFormatsChang Example: -```typescript -const ishevc:boolean = await MediaInfo.activeVideoFormats().find(f => f.codec === Media.VideoCodec.HEVC) - -MediaInfo.activeVideoFormats((active) => { - const hevc = active.find(f => f.codec === Media.VideoCodec.HEVC) - console.log('HEVC codec is now ' + (hevc ? 'active' : 'inactive') + '.') -}) +```javascript +MediaInfo.activeVideoFormats().find(f => f.codec === Media.VideoCodec.HEVC) +/* +[ + { + "codec": "hevc", + "codecLevel": "4.2", + "codecProfile": "main", + "container": "video/mp4", + "frameRate": 30, + "hdr": [ + "hdr10" + ], + "resolution": [ + 1920, + 1080 + ] + } +] +*/ ``` Access to these APIs is gated by `manage` access to the `xrn:firebolt:capability:media-info:video-format` capability. @@ -508,13 +654,19 @@ Additionally, the `MediaInfo` module **MUST** have an `onActiveAudioFormatsChang Example: -```typescript -const isaac:boolean = await MediaInfo.activeAudioFormats().find(f => f.codec === Media.AudioCodec.AAC) - -MediaInfo.activeAudioFormats((active) => { - const aac = active.find(f => f.codec === Media.AudioCodec.AAC) - console.log('AAC codec is now ' + (aac ? 'active' : 'inactive') + '.') -}) +```javascript +MediaInfo.activeAudioFormats().find(f => f.codec === Media.AudioCodec.AAC) +/* +[ + { + "bitRate": 128, + "channels": 2, + "codec": "aac", + "container": "audio/mp4", + "sampleRate": 48 + } +] +*/ ``` Access to these APIs is gated by `manage` access to the `xrn:firebolt:capability:media-info:audio-format` capability. diff --git a/src/openrpc/device.json b/src/openrpc/device.json index 2015a3ff8..06ec22a45 100644 --- a/src/openrpc/device.json +++ b/src/openrpc/device.json @@ -939,7 +939,6 @@ "value": [ "720p50", "720p60", - "1080i25", "1080i50", "1080i60", "1080p24", @@ -1170,6 +1169,7 @@ "HDCPVersion": { "description": "The HDCP version", "type": "string", + "enumKeyPrefix": "hdcp", "enum": [ "1.4", "2.2", diff --git a/src/schemas/media.json b/src/schemas/media.json index c2370570a..7ccaef35d 100644 --- a/src/schemas/media.json +++ b/src/schemas/media.json @@ -21,6 +21,7 @@ "AudioCodecLevel": { "description": "Audio codec level", "type": "string", + "enumKeyPrefix": "level", "enum": [ "3.0", "3.1", @@ -67,16 +68,6 @@ "unknown" ] }, - "ColorDepth": { - "description": "Color depth in number of bits", - "type": "integer", - "enum": [ - 0, - 8, - 10, - 12 - ] - }, "Dimensions": { "type": "array", "description": "The dimensions specified as width and height.", @@ -119,6 +110,7 @@ "type": "string", "description": "video codec", "enum": [ + "av1", "avc", "hevc", "mpeg1", @@ -141,6 +133,7 @@ "VideoMode": { "description": "Video output mode; the shorthand resolution and frame rate", "type": "string", + "enumKeyPrefix": "mode", "enum": [ "480i", "480p", @@ -149,13 +142,15 @@ "576p60", "720p50", "720p60", - "1080i25", "1080i50", "1080i60", "1080p24", + "1080p25", "1080p30", "1080p50", "1080p60", + "2160p24", + "2160p25", "2160p30", "2160p50", "2160p60",