From 892153fa00f4aebc632792cc4accb46faa680eee Mon Sep 17 00:00:00 2001 From: Michael Hallock Date: Fri, 19 Mar 2021 01:38:13 -0400 Subject: [PATCH 1/6] Possible solution to #3647, adds option to ignore devicePixelRatio in calculation for stream level choice calculations --- src/config.ts | 2 ++ src/controller/cap-level-controller.ts | 8 +++++-- src/hls.ts | 30 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index f164750e766..0e1ed0bf6a4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -45,6 +45,7 @@ export type BufferControllerConfig = { export type CapLevelControllerConfig = { capLevelToPlayerSize: boolean; + playerSizeIgnoreDevicePixelRatio: boolean; }; export type DRMSystemOptions = { @@ -192,6 +193,7 @@ export const hlsDefaultConfig: HlsConfig = { debug: false, // used by logger capLevelOnFPSDrop: false, // used by fps-controller capLevelToPlayerSize: false, // used by cap-level-controller + playerSizeIgnoreDevicePixelRatio: false, // used by cap-level-controller initialLiveManifestSize: 1, // used by stream-controller maxBufferLength: 30, // used by stream-controller backBufferLength: Infinity, // used by buffer-controller diff --git a/src/controller/cap-level-controller.ts b/src/controller/cap-level-controller.ts index 9c616ba051f..0555a689337 100644 --- a/src/controller/cap-level-controller.ts +++ b/src/controller/cap-level-controller.ts @@ -215,11 +215,15 @@ class CapLevelController implements ComponentAPI { } get mediaWidth(): number { - return this.getDimensions().width * CapLevelController.contentScaleFactor; + return this.hls.config.playerSizeIgnoreDevicePixelRatio + ? this.getDimensions().width + : this.getDimensions().width * CapLevelController.contentScaleFactor; } get mediaHeight(): number { - return this.getDimensions().height * CapLevelController.contentScaleFactor; + return this.hls.config.playerSizeIgnoreDevicePixelRatio + ? this.getDimensions().height + : this.getDimensions().height * CapLevelController.contentScaleFactor; } static get contentScaleFactor(): number { diff --git a/src/hls.ts b/src/hls.ts index bcf54c25760..152188a0a62 100644 --- a/src/hls.ts +++ b/src/hls.ts @@ -545,6 +545,36 @@ export default class Hls implements HlsEventEmitter { } } + /** + * Get the current setting for playerSizeIgnoreDevicePixelRatio + * + * @type {boolean} + */ + get playerSizeIgnoreDevicePixelRatio(): boolean { + return this.config.playerSizeIgnoreDevicePixelRatio; + } + + /** + * set dynamically set playerSizeIgnoreDevicePixelRatio against (`CapLevelController`) + * + * @type {boolean} + */ + set playerSizeIgnoreDevicePixelRatio(shouldStartCapping: boolean) { + const newPlayerSizeIgnoreDevicePixelRatio = !!shouldStartCapping; + + if (newPlayerSizeIgnoreDevicePixelRatio !== this.config.playerSizeIgnoreDevicePixelRatio) { + if (newPlayerSizeIgnoreDevicePixelRatio) { + this.capLevelController.startCapping(); // If capping occurs, nextLevelSwitch will happen based on size. + } else { + this.capLevelController.stopCapping(); + this.autoLevelCapping = -1; + this.streamController.nextLevelSwitch(); // Now we're uncapped, get the next level asap. + } + + this.config.playerSizeIgnoreDevicePixelRatio = newPlayerSizeIgnoreDevicePixelRatio; + } + } + /** * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`) * @type {number} From 5348b497a02a2a35b2dc3d65d158aac58d46109a Mon Sep 17 00:00:00 2001 From: Michael Hallock Date: Wed, 24 Mar 2021 21:27:33 -0400 Subject: [PATCH 2/6] More generic solution for devicePixelRatio override --- demo/chart/timeline-chart.ts | 2 +- src/config.ts | 4 +-- src/controller/cap-level-controller.ts | 18 ++----------- src/hls.ts | 37 +++++++++----------------- 4 files changed, 18 insertions(+), 43 deletions(-) diff --git a/demo/chart/timeline-chart.ts b/demo/chart/timeline-chart.ts index d954f258639..00de797fdc1 100644 --- a/demo/chart/timeline-chart.ts +++ b/demo/chart/timeline-chart.ts @@ -642,7 +642,7 @@ export class TimelineChart { drawLineX(ctx, x: number, chartArea) { if (!this.imageDataBuffer) { - const devicePixelRatio = self.devicePixelRatio || 1; + const devicePixelRatio = self.hls.devicePixelRatio || 1; this.imageDataBuffer = ctx.getImageData( 0, 0, diff --git a/src/config.ts b/src/config.ts index 0e1ed0bf6a4..c0b5ad9f990 100644 --- a/src/config.ts +++ b/src/config.ts @@ -45,7 +45,6 @@ export type BufferControllerConfig = { export type CapLevelControllerConfig = { capLevelToPlayerSize: boolean; - playerSizeIgnoreDevicePixelRatio: boolean; }; export type DRMSystemOptions = { @@ -150,6 +149,7 @@ export type HlsConfig = { enableWorker: boolean; enableSoftwareAES: boolean; minAutoBitrate: number; + ignoreDevicePixelRatio: boolean; loader: { new (confg: HlsConfig): Loader }; xhrSetup?: (xhr: XMLHttpRequest, url: string) => void; @@ -193,7 +193,7 @@ export const hlsDefaultConfig: HlsConfig = { debug: false, // used by logger capLevelOnFPSDrop: false, // used by fps-controller capLevelToPlayerSize: false, // used by cap-level-controller - playerSizeIgnoreDevicePixelRatio: false, // used by cap-level-controller + ignoreDevicePixelRatio: false, // used by devicePixelRatio initialLiveManifestSize: 1, // used by stream-controller maxBufferLength: 30, // used by stream-controller backBufferLength: Infinity, // used by buffer-controller diff --git a/src/controller/cap-level-controller.ts b/src/controller/cap-level-controller.ts index 0555a689337..401bd5da82c 100644 --- a/src/controller/cap-level-controller.ts +++ b/src/controller/cap-level-controller.ts @@ -215,25 +215,11 @@ class CapLevelController implements ComponentAPI { } get mediaWidth(): number { - return this.hls.config.playerSizeIgnoreDevicePixelRatio - ? this.getDimensions().width - : this.getDimensions().width * CapLevelController.contentScaleFactor; + return this.getDimensions().width * this.hls.devicePixelRatio; } get mediaHeight(): number { - return this.hls.config.playerSizeIgnoreDevicePixelRatio - ? this.getDimensions().height - : this.getDimensions().height * CapLevelController.contentScaleFactor; - } - - static get contentScaleFactor(): number { - let pixelRatio = 1; - try { - pixelRatio = self.devicePixelRatio; - } catch (e) { - /* no-op */ - } - return pixelRatio; + return this.getDimensions().height * this.hls.devicePixelRatio; } static isLevelAllowed( diff --git a/src/hls.ts b/src/hls.ts index 152188a0a62..da4eeda810b 100644 --- a/src/hls.ts +++ b/src/hls.ts @@ -546,33 +546,22 @@ export default class Hls implements HlsEventEmitter { } /** - * Get the current setting for playerSizeIgnoreDevicePixelRatio - * - * @type {boolean} - */ - get playerSizeIgnoreDevicePixelRatio(): boolean { - return this.config.playerSizeIgnoreDevicePixelRatio; - } - - /** - * set dynamically set playerSizeIgnoreDevicePixelRatio against (`CapLevelController`) - * - * @type {boolean} + * Get the current devicePixelRatio + * @type {number} */ - set playerSizeIgnoreDevicePixelRatio(shouldStartCapping: boolean) { - const newPlayerSizeIgnoreDevicePixelRatio = !!shouldStartCapping; - - if (newPlayerSizeIgnoreDevicePixelRatio !== this.config.playerSizeIgnoreDevicePixelRatio) { - if (newPlayerSizeIgnoreDevicePixelRatio) { - this.capLevelController.startCapping(); // If capping occurs, nextLevelSwitch will happen based on size. - } else { - this.capLevelController.stopCapping(); - this.autoLevelCapping = -1; - this.streamController.nextLevelSwitch(); // Now we're uncapped, get the next level asap. - } + get devicePixelRatio(): number { + if (this.config.ignoreDevicePixelRatio) { + return 1; + } - this.config.playerSizeIgnoreDevicePixelRatio = newPlayerSizeIgnoreDevicePixelRatio; + let pixelRatio = 1; + try { + pixelRatio = self.devicePixelRatio; + } catch (e) { + /* no-op */ } + + return pixelRatio; } /** From f0c739a88f0eebad1078f97fd9e3c224f92c2ae7 Mon Sep 17 00:00:00 2001 From: Michael Hallock Date: Sun, 28 Mar 2021 16:21:05 -0400 Subject: [PATCH 3/6] Fies tests --- api-extractor/report/hls.js.api.md | 22 ++++++++++--------- src/hls.ts | 2 +- tests/unit/controller/cap-level-controller.js | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/api-extractor/report/hls.js.api.md b/api-extractor/report/hls.js.api.md index 28a5bd92ebe..11dc93e8637 100644 --- a/api-extractor/report/hls.js.api.md +++ b/api-extractor/report/hls.js.api.md @@ -839,6 +839,7 @@ class Hls implements HlsEventEmitter { static set DefaultConfig(defaultConfig: HlsConfig); destroy(): void; detachMedia(): void; + get devicePixelRatio(): number; // (undocumented) emit(event: E, name: E, eventObject: Parameters[1]): boolean; // (undocumented) @@ -935,6 +936,7 @@ export type HlsConfig = { enableWorker: boolean; enableSoftwareAES: boolean; minAutoBitrate: number; + ignoreDevicePixelRatio: boolean; loader: { new (confg: HlsConfig): Loader; }; @@ -2106,16 +2108,16 @@ export interface UserdataSample { // Warnings were encountered during analysis: // -// src/config.ts:156:3 - (ae-forgotten-export) The symbol "AudioStreamController" needs to be exported by the entry point hls.d.ts -// src/config.ts:157:3 - (ae-forgotten-export) The symbol "AudioTrackController" needs to be exported by the entry point hls.d.ts -// src/config.ts:159:3 - (ae-forgotten-export) The symbol "SubtitleStreamController" needs to be exported by the entry point hls.d.ts -// src/config.ts:160:3 - (ae-forgotten-export) The symbol "SubtitleTrackController" needs to be exported by the entry point hls.d.ts -// src/config.ts:161:3 - (ae-forgotten-export) The symbol "TimelineController" needs to be exported by the entry point hls.d.ts -// src/config.ts:163:3 - (ae-forgotten-export) The symbol "EMEController" needs to be exported by the entry point hls.d.ts -// src/config.ts:165:3 - (ae-forgotten-export) The symbol "AbrController" needs to be exported by the entry point hls.d.ts -// src/config.ts:166:3 - (ae-forgotten-export) The symbol "BufferController" needs to be exported by the entry point hls.d.ts -// src/config.ts:167:3 - (ae-forgotten-export) The symbol "CapLevelController" needs to be exported by the entry point hls.d.ts -// src/config.ts:168:3 - (ae-forgotten-export) The symbol "FPSController" needs to be exported by the entry point hls.d.ts +// src/config.ts:157:3 - (ae-forgotten-export) The symbol "AudioStreamController" needs to be exported by the entry point hls.d.ts +// src/config.ts:158:3 - (ae-forgotten-export) The symbol "AudioTrackController" needs to be exported by the entry point hls.d.ts +// src/config.ts:160:3 - (ae-forgotten-export) The symbol "SubtitleStreamController" needs to be exported by the entry point hls.d.ts +// src/config.ts:161:3 - (ae-forgotten-export) The symbol "SubtitleTrackController" needs to be exported by the entry point hls.d.ts +// src/config.ts:162:3 - (ae-forgotten-export) The symbol "TimelineController" needs to be exported by the entry point hls.d.ts +// src/config.ts:164:3 - (ae-forgotten-export) The symbol "EMEController" needs to be exported by the entry point hls.d.ts +// src/config.ts:166:3 - (ae-forgotten-export) The symbol "AbrController" needs to be exported by the entry point hls.d.ts +// src/config.ts:167:3 - (ae-forgotten-export) The symbol "BufferController" needs to be exported by the entry point hls.d.ts +// src/config.ts:168:3 - (ae-forgotten-export) The symbol "CapLevelController" needs to be exported by the entry point hls.d.ts +// src/config.ts:169:3 - (ae-forgotten-export) The symbol "FPSController" needs to be exported by the entry point hls.d.ts // (No @packageDocumentation comment for this package) diff --git a/src/hls.ts b/src/hls.ts index da4eeda810b..07cd2aa5860 100644 --- a/src/hls.ts +++ b/src/hls.ts @@ -554,7 +554,7 @@ export default class Hls implements HlsEventEmitter { return 1; } - let pixelRatio = 1; + let pixelRatio = 1; try { pixelRatio = self.devicePixelRatio; } catch (e) { diff --git a/tests/unit/controller/cap-level-controller.js b/tests/unit/controller/cap-level-controller.js index 6bc22f4acfc..14bc64a6666 100644 --- a/tests/unit/controller/cap-level-controller.js +++ b/tests/unit/controller/cap-level-controller.js @@ -113,7 +113,7 @@ describe('CapLevelController', function () { it('gets width and height attributes when the media element is not in the DOM', function () { media.setAttribute('width', 320); media.setAttribute('height', 240); - const pixelRatio = CapLevelController.contentScaleFactor; + const pixelRatio = hls.devicePixelRatio; const bounds = capLevelController.getDimensions(); expect(bounds.width).to.equal(320); expect(bounds.height).to.equal(240); @@ -125,7 +125,7 @@ describe('CapLevelController', function () { media.style.width = '1280px'; media.style.height = '720px'; document.querySelector('#test-fixture').appendChild(media); - const pixelRatio = CapLevelController.contentScaleFactor; + const pixelRatio = hls.devicePixelRatio; const bounds = capLevelController.getDimensions(); expect(bounds.width).to.equal(1280); expect(bounds.height).to.equal(720); From f09c645d6f988dfa2e9118f823dc91f197e4237d Mon Sep 17 00:00:00 2001 From: Michael Hallock Date: Sun, 28 Mar 2021 20:40:28 -0400 Subject: [PATCH 4/6] Adds API.md docs --- docs/API.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/API.md b/docs/API.md index 316dbf0306b..b2737cc0342 100644 --- a/docs/API.md +++ b/docs/API.md @@ -19,6 +19,7 @@ - [`Hls.DefaultConfig get/set`](#hlsdefaultconfig-getset) - [`capLevelToPlayerSize`](#capleveltoplayersize) - [`capLevelOnFPSDrop`](#caplevelonfpsdrop) + - ['ignoreDevicePixelRatio'](#ignoreDevicePixelRatio) - [`debug`](#debug) - [`autoStartLoad`](#autostartload) - [`startPosition`](#startposition) @@ -417,6 +418,13 @@ This configuration will be applied by default to all instances. then the quality level is dropped and capped at this lower level. - when set to false, levels will not be limited. All available levels could be used in auto-quality mode taking only bandwidth into consideration. +### `ignoreDevicePixelRatio` + +(default: `false`) + +- when set to true, calculations related to player size will ignore browser `devicePixelRatio`. +- when set to false, calculations related to player size will respect browser `devicePixelRatio`. + ### `debug` (default: `false`) From 00a1d9632cdd81ef61e52bcf36b04f2e40492d7c Mon Sep 17 00:00:00 2001 From: Michael Hallock Date: Fri, 16 Apr 2021 20:04:50 -0400 Subject: [PATCH 5/6] Makes requested changes for PR --- api-extractor/report/hls.js.api.md | 1 - demo/chart/timeline-chart.ts | 2 +- src/config.ts | 2 +- src/controller/cap-level-controller.ts | 17 +++++++++++++++-- src/hls.ts | 19 ------------------- tests/unit/controller/cap-level-controller.js | 4 ++-- 6 files changed, 19 insertions(+), 26 deletions(-) diff --git a/api-extractor/report/hls.js.api.md b/api-extractor/report/hls.js.api.md index ea334ddb34b..b17a2cbe7cd 100644 --- a/api-extractor/report/hls.js.api.md +++ b/api-extractor/report/hls.js.api.md @@ -845,7 +845,6 @@ class Hls implements HlsEventEmitter { static set DefaultConfig(defaultConfig: HlsConfig); destroy(): void; detachMedia(): void; - get devicePixelRatio(): number; get drift(): number | null; // (undocumented) emit(event: E, name: E, eventObject: Parameters[1]): boolean; diff --git a/demo/chart/timeline-chart.ts b/demo/chart/timeline-chart.ts index df35ab2ed91..d3286cf4795 100644 --- a/demo/chart/timeline-chart.ts +++ b/demo/chart/timeline-chart.ts @@ -654,7 +654,7 @@ export class TimelineChart { drawLineX(ctx, x: number, chartArea) { if (!this.imageDataBuffer) { - const devicePixelRatio = self.hls.devicePixelRatio || 1; + const devicePixelRatio = self.devicePixelRatio || 1; this.imageDataBuffer = ctx.getImageData( 0, 0, diff --git a/src/config.ts b/src/config.ts index c0b5ad9f990..63eda3e58fb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -193,7 +193,7 @@ export const hlsDefaultConfig: HlsConfig = { debug: false, // used by logger capLevelOnFPSDrop: false, // used by fps-controller capLevelToPlayerSize: false, // used by cap-level-controller - ignoreDevicePixelRatio: false, // used by devicePixelRatio + ignoreDevicePixelRatio: false, // used by cap-level-controller initialLiveManifestSize: 1, // used by stream-controller maxBufferLength: 30, // used by stream-controller backBufferLength: Infinity, // used by buffer-controller diff --git a/src/controller/cap-level-controller.ts b/src/controller/cap-level-controller.ts index 401bd5da82c..653237e3062 100644 --- a/src/controller/cap-level-controller.ts +++ b/src/controller/cap-level-controller.ts @@ -215,11 +215,24 @@ class CapLevelController implements ComponentAPI { } get mediaWidth(): number { - return this.getDimensions().width * this.hls.devicePixelRatio; + return this.getDimensions().width * this.contentScaleFactor; } get mediaHeight(): number { - return this.getDimensions().height * this.hls.devicePixelRatio; + return this.getDimensions().height * this.contentScaleFactor; + } + + get contentScaleFactor(): number { + let pixelRatio = 1; + if (!this.hls.config.ignoreDevicePixelRatio) { + try { + pixelRatio = self.devicePixelRatio; + } catch (e) { + /* no-op */ + } + } + + return pixelRatio; } static isLevelAllowed( diff --git a/src/hls.ts b/src/hls.ts index 6e8a09babf2..0fcb79a5454 100644 --- a/src/hls.ts +++ b/src/hls.ts @@ -556,25 +556,6 @@ export default class Hls implements HlsEventEmitter { } } - /** - * Get the current devicePixelRatio - * @type {number} - */ - get devicePixelRatio(): number { - if (this.config.ignoreDevicePixelRatio) { - return 1; - } - - let pixelRatio = 1; - try { - pixelRatio = self.devicePixelRatio; - } catch (e) { - /* no-op */ - } - - return pixelRatio; - } - /** * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`) * @type {number} diff --git a/tests/unit/controller/cap-level-controller.js b/tests/unit/controller/cap-level-controller.js index 14bc64a6666..5347bc5b072 100644 --- a/tests/unit/controller/cap-level-controller.js +++ b/tests/unit/controller/cap-level-controller.js @@ -113,7 +113,7 @@ describe('CapLevelController', function () { it('gets width and height attributes when the media element is not in the DOM', function () { media.setAttribute('width', 320); media.setAttribute('height', 240); - const pixelRatio = hls.devicePixelRatio; + const pixelRatio = capLevelController.contentScaleFactor; const bounds = capLevelController.getDimensions(); expect(bounds.width).to.equal(320); expect(bounds.height).to.equal(240); @@ -125,7 +125,7 @@ describe('CapLevelController', function () { media.style.width = '1280px'; media.style.height = '720px'; document.querySelector('#test-fixture').appendChild(media); - const pixelRatio = hls.devicePixelRatio; + const pixelRatio = capLevelController.contentScaleFactor; const bounds = capLevelController.getDimensions(); expect(bounds.width).to.equal(1280); expect(bounds.height).to.equal(720); From 154995993b62cdeae221ecb075480e90c3105176 Mon Sep 17 00:00:00 2001 From: Michael Hallock Date: Fri, 4 Feb 2022 19:59:42 -0500 Subject: [PATCH 6/6] Regenerated the api md file for the build hopefully --- api-extractor/report/hls.js.api.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/api-extractor/report/hls.js.api.md b/api-extractor/report/hls.js.api.md index 84bb2a039e4..196fc044df6 100644 --- a/api-extractor/report/hls.js.api.md +++ b/api-extractor/report/hls.js.api.md @@ -2151,16 +2151,18 @@ export interface UserdataSample { // Warnings were encountered during analysis: // -// src/config.ts:157:3 - (ae-forgotten-export) The symbol "AudioStreamController" needs to be exported by the entry point hls.d.ts -// src/config.ts:158:3 - (ae-forgotten-export) The symbol "AudioTrackController" needs to be exported by the entry point hls.d.ts -// src/config.ts:160:3 - (ae-forgotten-export) The symbol "SubtitleStreamController" needs to be exported by the entry point hls.d.ts -// src/config.ts:161:3 - (ae-forgotten-export) The symbol "SubtitleTrackController" needs to be exported by the entry point hls.d.ts -// src/config.ts:162:3 - (ae-forgotten-export) The symbol "TimelineController" needs to be exported by the entry point hls.d.ts -// src/config.ts:164:3 - (ae-forgotten-export) The symbol "EMEController" needs to be exported by the entry point hls.d.ts -// src/config.ts:166:3 - (ae-forgotten-export) The symbol "AbrController" needs to be exported by the entry point hls.d.ts -// src/config.ts:167:3 - (ae-forgotten-export) The symbol "BufferController" needs to be exported by the entry point hls.d.ts -// src/config.ts:168:3 - (ae-forgotten-export) The symbol "CapLevelController" needs to be exported by the entry point hls.d.ts -// src/config.ts:169:3 - (ae-forgotten-export) The symbol "FPSController" needs to be exported by the entry point hls.d.ts +// src/config.ts:163:3 - (ae-forgotten-export) The symbol "ILogger" needs to be exported by the entry point hls.d.ts +// src/config.ts:173:3 - (ae-forgotten-export) The symbol "AudioStreamController" needs to be exported by the entry point hls.d.ts +// src/config.ts:174:3 - (ae-forgotten-export) The symbol "AudioTrackController" needs to be exported by the entry point hls.d.ts +// src/config.ts:176:3 - (ae-forgotten-export) The symbol "SubtitleStreamController" needs to be exported by the entry point hls.d.ts +// src/config.ts:177:3 - (ae-forgotten-export) The symbol "SubtitleTrackController" needs to be exported by the entry point hls.d.ts +// src/config.ts:178:3 - (ae-forgotten-export) The symbol "TimelineController" needs to be exported by the entry point hls.d.ts +// src/config.ts:180:3 - (ae-forgotten-export) The symbol "EMEController" needs to be exported by the entry point hls.d.ts +// src/config.ts:183:3 - (ae-forgotten-export) The symbol "CMCDController" needs to be exported by the entry point hls.d.ts +// src/config.ts:185:3 - (ae-forgotten-export) The symbol "AbrController" needs to be exported by the entry point hls.d.ts +// src/config.ts:186:3 - (ae-forgotten-export) The symbol "BufferController" needs to be exported by the entry point hls.d.ts +// src/config.ts:187:3 - (ae-forgotten-export) The symbol "CapLevelController" needs to be exported by the entry point hls.d.ts +// src/config.ts:188:3 - (ae-forgotten-export) The symbol "FPSController" needs to be exported by the entry point hls.d.ts // (No @packageDocumentation comment for this package)