Browse Source

feat: Custom Pixel Ratio (#1497)

pull/1498/head
Walter Seymour 1 year ago
committed by GitHub
parent
commit
0e9d9d8f4c
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      README.md
  2. 12
      src/playlist-selectors.js
  3. 8
      src/videojs-http-streaming.js
  4. 9
      test/configuration.test.js
  5. 115
      test/playlist-selectors.test.js

13
README.md

@ -48,6 +48,7 @@ Video.js Compatibility: 7.x, 8.x
- [enableLowInitialPlaylist](#enablelowinitialplaylist)
- [limitRenditionByPlayerDimensions](#limitrenditionbyplayerdimensions)
- [useDevicePixelRatio](#usedevicepixelratio)
- [customPixelRatio](#custompixelratio)
- [allowSeeksWithinUnsafeLiveWindow](#allowseekswithinunsafelivewindow)
- [customTagParsers](#customtagparsers)
- [customTagMappers](#customtagmappers)
@ -404,6 +405,18 @@ This setting is `true` by default.
If true, this will take the device pixel ratio into account when doing rendition switching. This means that if you have a player with the width of `540px` in a high density display with a device pixel ratio of 2, a rendition of `1080p` will be allowed.
This setting is `false` by default.
##### customPixelRatio
* Type: `number`
* can be used as an initialization option.
If set, this will take the initial player dimensions and multiply it by a custom ratio when the player automatically selects renditions. This means that if you have a player where the dimension is `540p`, with a custom pixel ratio of `2`, a rendition of `1080p` or a lower rendition closest to this value will be chosen. Additionally, if you have a player where the dimension is `540p`, with a custom pixel ratio of `0.5`, a rendition of `270p` or a lower rendition closest to this value will be chosen. When the custom pixel ratio is 0, the lowest available rendition will be selected.
It is worth noting that if the player dimension multiplied by the custom pixel ratio is greater than any available rendition resolution, a rendition will be selected based on bandwidth, and the player dimension will be disregarded.
`limitRenditionByPlayerDimensions` must be `true` in order for this feature to be enabled. This is the default value.
If `useDevicePixelRatio` is set to `true`, the custom pixel ratio will be prioritized and overwrite any previous pixel ratio.
##### allowSeeksWithinUnsafeLiveWindow
* Type: `boolean`
* can be used as a source option

12
src/playlist-selectors.js

@ -364,7 +364,11 @@ export const TEST_ONLY_SIMPLE_SELECTOR = (newSimpleSelector) => {
* bandwidth variance
*/
export const lastBandwidthSelector = function() {
const pixelRatio = this.useDevicePixelRatio ? window.devicePixelRatio || 1 : 1;
let pixelRatio = this.useDevicePixelRatio ? window.devicePixelRatio || 1 : 1;
if (!isNaN(this.customPixelRatio)) {
pixelRatio = this.customPixelRatio;
}
return simpleSelector(
this.playlists.main,
@ -399,7 +403,11 @@ export const movingAverageBandwidthSelector = function(decay) {
}
return function() {
const pixelRatio = this.useDevicePixelRatio ? window.devicePixelRatio || 1 : 1;
let pixelRatio = this.useDevicePixelRatio ? window.devicePixelRatio || 1 : 1;
if (!isNaN(this.customPixelRatio)) {
pixelRatio = this.customPixelRatio;
}
if (average < 0) {
average = this.systemBandwidth;

8
src/videojs-http-streaming.js

@ -738,6 +738,7 @@ class VhsHandler extends Component {
[
'withCredentials',
'useDevicePixelRatio',
'customPixelRatio',
'limitRenditionByPlayerDimensions',
'bandwidth',
'customTagParsers',
@ -761,6 +762,13 @@ class VhsHandler extends Component {
this.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions;
this.useDevicePixelRatio = this.options_.useDevicePixelRatio;
const customPixelRatio = this.options_.customPixelRatio;
// Ensure the custom pixel ratio is a number greater than or equal to 0
if (typeof customPixelRatio === 'number' && customPixelRatio >= 0) {
this.customPixelRatio = customPixelRatio;
}
}
// alias for public method to set options
setOptions(options = {}) {

9
test/configuration.test.js

@ -31,7 +31,14 @@ const options = [{
default: false,
test: true,
alt: false
}, {
},
{
name: 'customPixelRatio',
default: undefined,
test: 1,
alt: 0.5
},
{
name: 'bandwidth',
default: 4194304,
test: 5,

115
test/playlist-selectors.test.js

@ -1,11 +1,13 @@
import { module, test } from 'qunit';
import document from 'global/document';
import window from 'global/window';
import {
TEST_ONLY_SIMPLE_SELECTOR,
simpleSelector,
movingAverageBandwidthSelector,
minRebufferMaxBandwidthSelector,
lowestBitrateCompatibleVariantSelector
lowestBitrateCompatibleVariantSelector,
lastBandwidthSelector
} from '../src/playlist-selectors';
import Config from '../src/config';
@ -325,5 +327,116 @@ test('simpleSelector leastPixelDiffSelector selects least pixel diff resolution.
assert.equal(pixelDiff, main.playlists[5], '1280w x 720h pixel diff higher bandwidth');
assert.equal(nonPixelDiff, main.playlists[5], '1280w x 720h resolution plus higher bandwidth');
});
test('lastBandwidthSelector uses customPixelRatio to pick rendition', function(assert) {
let playlist;
const bandwidth = 20;
const oldGetComputedStyle = window.getComputedStyle;
// Mock a 540p player.
window.getComputedStyle = function() {
return {
width: 960,
height: 540
};
};
// Ensure system bandwith is greater than the rendition bandwidths.
this.vhs.systemBandwidth = bandwidth + 10;
// This is true by default.
this.vhs.limitRenditionByPlayerDimensions = true;
this.vhs.playlists.main.playlists = [
{ attributes: { BANDWIDTH: bandwidth, RESOLUTION: { width: 480, height: 270 } } },
{ attributes: { BANDWIDTH: bandwidth, RESOLUTION: { width: 960, height: 540 } } },
{ attributes: { BANDWIDTH: bandwidth, RESOLUTION: { width: 1440, height: 810 } } },
{ attributes: { BANDWIDTH: bandwidth, RESOLUTION: { width: 1920, height: 1080 } } }
];
// Picks the lowest possible rendition
this.vhs.customPixelRatio = 0;
playlist = lastBandwidthSelector.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 270, 'selected the lowest rendition');
this.vhs.customPixelRatio = 0.5;
playlist = lastBandwidthSelector.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 270, 'selected the rendition with 270p');
this.vhs.customPixelRatio = 1;
playlist = lastBandwidthSelector.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 540, 'selected the rendition with 540p');
this.vhs.customPixelRatio = 1.5;
playlist = lastBandwidthSelector.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 810, 'selected the rendition with 810p');
this.vhs.customPixelRatio = 2;
playlist = lastBandwidthSelector.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 1080, 'selected the rendition with 1080p');
// Since the customPixelRatio sets the player dimension higher than any available rendition,
// This value is entirely based on bandwidth.
this.vhs.customPixelRatio = 4;
playlist = lastBandwidthSelector.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 270, 'selected the rendition based on bandwidth');
window.getComputedStyle = oldGetComputedStyle;
});
test('movingAverageBandwidthSelector uses customPixelRatio to pick rendition', function(assert) {
let playlist;
const bandwidth = 20;
const selectionFunction = movingAverageBandwidthSelector(1);
const oldGetComputedStyle = window.getComputedStyle;
// Mock a 540p player.
window.getComputedStyle = function() {
return {
width: 960,
height: 540
};
};
// Ensure system bandwith is greater than the rendition bandwidths.
this.vhs.systemBandwidth = bandwidth + 10;
// This is true by default.
this.vhs.limitRenditionByPlayerDimensions = true;
this.vhs.playlists.main.playlists = [
{ attributes: { BANDWIDTH: bandwidth, RESOLUTION: { width: 480, height: 270 } } },
{ attributes: { BANDWIDTH: bandwidth, RESOLUTION: { width: 960, height: 540 } } },
{ attributes: { BANDWIDTH: bandwidth, RESOLUTION: { width: 1440, height: 810 } } },
{ attributes: { BANDWIDTH: bandwidth, RESOLUTION: { width: 1920, height: 1080 } } }
];
// Picks the lowest possible rendition
this.vhs.customPixelRatio = 0;
playlist = selectionFunction.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 270, 'selected the lowest rendition');
this.vhs.customPixelRatio = 0.5;
playlist = selectionFunction.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 270, 'selected the rendition with 270p');
this.vhs.customPixelRatio = 1;
playlist = selectionFunction.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 540, 'selected the rendition with 540p');
this.vhs.customPixelRatio = 1.5;
playlist = selectionFunction.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 810, 'selected the rendition with 810p');
this.vhs.customPixelRatio = 2;
playlist = selectionFunction.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 1080, 'selected the rendition with 1080p');
// Since the customPixelRatio sets the player dimension higher than any available rendition,
// This value is entirely based on bandwidth.
this.vhs.customPixelRatio = 4;
playlist = selectionFunction.call(this.vhs);
assert.equal(playlist.attributes.RESOLUTION.height, 270, 'selected the rendition based on bandwidth');
window.getComputedStyle = oldGetComputedStyle;
});
Loading…
Cancel
Save