Browse Source

feat: add an option to ignore player size in selection logic (#238)

pull/248/head
Matt Ward 7 years ago
committed by Joe Forbes
parent
commit
7ae42b1893
  1. 9
      README.md
  2. 2
      src/config.js
  3. 22
      src/playlist-selectors.js
  4. 11
      src/videojs-http-streaming.js
  5. 5
      test/configuration.test.js
  6. 34
      test/playlist-selectors.test.js

9
README.md

@ -333,6 +333,15 @@ When `enableLowInitialPlaylist` is set to true, it will be used to select
the lowest bitrate playlist initially. This helps to decrease playback start time.
This setting is `false` by default.
##### limitRenditionByPlayerDimensions
* Type: `boolean`
* can be used as an initialization option
When `limitRenditionByPlayerDimensions` is set to true, rendition
selection logic will take into account the player size and rendition
resolutions when making a decision.
This setting is `true` by default.
### Runtime Properties
Runtime properties are attached to the tech object when HLS is in
use. You can get a reference to the HLS source handler like this:

2
src/config.js

@ -2,6 +2,8 @@ export default {
GOAL_BUFFER_LENGTH: 30,
MAX_GOAL_BUFFER_LENGTH: 60,
GOAL_BUFFER_LENGTH_RATE: 1,
// 0.5 MB/s
INITIAL_BANDWIDTH: 4194304,
// A fudge factor to apply to advertised playlist bitrates to account for
// temporary flucations in client bandwidth
BANDWIDTH_VARIANCE: 1.2,

22
src/playlist-selectors.js

@ -124,6 +124,8 @@ export const comparePlaylistResolution = function(left, right) {
* Current width of the player element
* @param {Number} playerHeight
* Current height of the player element
* @param {Boolean} limitRenditionByPlayerDimensions
* True if the player width and height should be used during the selection, false otherwise
* @return {Playlist} the highest bitrate playlist less than the
* currently detected bandwidth, accounting for some amount of
* bandwidth variance
@ -131,7 +133,8 @@ export const comparePlaylistResolution = function(left, right) {
export const simpleSelector = function(master,
playerBandwidth,
playerWidth,
playerHeight) {
playerHeight,
limitRenditionByPlayerDimensions) {
// convert the playlists to an intermediary representation to make comparisons easier
let sortedPlaylistReps = master.playlists.map((playlist) => {
let width;
@ -190,6 +193,17 @@ export const simpleSelector = function(master,
(rep) => rep.bandwidth === highestRemainingBandwidthRep.bandwidth
)[0];
// if we're not going to limit renditions by player size, make an early decision.
if (limitRenditionByPlayerDimensions === false) {
let chosenRep = (
bandwidthBestRep ||
enabledPlaylistReps[0] ||
sortedPlaylistReps[0]
);
return chosenRep ? chosenRep.playlist : null;
}
// filter out playlists without resolution information
let haveResolution = bandwidthPlaylistReps.filter((rep) => rep.width && rep.height);
@ -261,7 +275,8 @@ export const lastBandwidthSelector = function() {
return simpleSelector(this.playlists.master,
this.systemBandwidth,
parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10),
parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10));
parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10),
this.limitRenditionByPlayerDimensions);
};
/**
@ -294,7 +309,8 @@ export const movingAverageBandwidthSelector = function(decay) {
return simpleSelector(this.playlists.master,
average,
parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10),
parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10));
parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10),
this.limitRenditionByPlayerDimensions);
};
};

11
src/videojs-http-streaming.js

@ -44,9 +44,6 @@ const Hls = {
xhr: xhrFactory()
};
// 0.5 MB/s
const INITIAL_BANDWIDTH = 4194304;
// Define getter/setters for config properites
[
'GOAL_BUFFER_LENGTH',
@ -335,6 +332,7 @@ class HlsHandler extends Component {
setOptions_() {
// defaults
this.options_.withCredentials = this.options_.withCredentials || false;
this.options_.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions === false ? false : true;
if (typeof this.options_.blacklistDuration !== 'number') {
this.options_.blacklistDuration = 5 * 60;
@ -343,23 +341,24 @@ class HlsHandler extends Component {
// start playlist selection at a reasonable bandwidth for
// broadband internet (0.5 MB/s) or mobile (0.0625 MB/s)
if (typeof this.options_.bandwidth !== 'number') {
this.options_.bandwidth = INITIAL_BANDWIDTH;
this.options_.bandwidth = Config.INITIAL_BANDWIDTH;
}
// If the bandwidth number is unchanged from the initial setting
// then this takes precedence over the enableLowInitialPlaylist option
this.options_.enableLowInitialPlaylist =
this.options_.enableLowInitialPlaylist &&
this.options_.bandwidth === INITIAL_BANDWIDTH;
this.options_.bandwidth === Config.INITIAL_BANDWIDTH;
// grab options passed to player.src
['withCredentials', 'bandwidth'].forEach((option) => {
['withCredentials', 'limitRenditionByPlayerDimensions', 'bandwidth'].forEach((option) => {
if (typeof this.source_[option] !== 'undefined') {
this.options_[option] = this.source_[option];
}
});
this.bandwidth = this.options_.bandwidth;
this.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions;
}
/**
* called when player.src gets called, handle a new source

5
test/configuration.test.js

@ -23,6 +23,11 @@ const options = [{
default: false,
test: true,
alt: false
}, {
name: 'limitRenditionByPlayerDimensions',
default: true,
test: false,
alt: false
}, {
name: 'bandwidth',
default: 4194304,

34
test/playlist-selectors.test.js

@ -163,7 +163,39 @@ test('simpleSelector switches up even without resolution information', function(
{ attributes: { BANDWIDTH: 1000 } }
];
const selectedPlaylist = simpleSelector(master, 2000, 1, 1);
const selectedPlaylist = simpleSelector(master, 2000, 1, 1, false);
assert.equal(selectedPlaylist, master.playlists[1], 'selected the correct playlist');
});
// A set of playlists that were defined using non-traditional encoding.
// The resolutions were selected using a per-title encoding technique
// that ensures the resolution maximizes quality at a given bitrate.
const trickyPlaylists = [
{ attributes: { BANDWIDTH: 2362080, RESOLUTION: { width: 1280, height: 720 } } },
{ attributes: { BANDWIDTH: 1390830, RESOLUTION: { width: 1280, height: 720 } } },
{ attributes: { BANDWIDTH: 866114, RESOLUTION: { width: 1024, height: 576 } } },
{ attributes: { BANDWIDTH: 573028, RESOLUTION: { width: 768, height: 432 } } },
{ attributes: { BANDWIDTH: 3482070, RESOLUTION: { width: 1920, height: 1080 } } },
{ attributes: { BANDWIDTH: 6151620, RESOLUTION: { width: 1920, height: 1080 } } }
];
test('simpleSelector limits using resolution information when it exists', function(assert) {
let master = this.hls.playlists.master;
master.playlists = trickyPlaylists;
const selectedPlaylist = simpleSelector(master, Config.INITIAL_BANDWIDTH, 444, 790, true);
assert.equal(selectedPlaylist, master.playlists[3], 'selected the playlist with the lowest bandwidth higher than player resolution');
});
test('simpleSelector can not limit based on resolution information', function(assert) {
let master = this.hls.playlists.master;
master.playlists = trickyPlaylists;
const selectedPlaylist = simpleSelector(master, Config.INITIAL_BANDWIDTH, 444, 790, false);
assert.equal(selectedPlaylist, master.playlists[4], 'selected a playlist based solely on bandwidth');
});
Loading…
Cancel
Save