Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make low latency specific reduction and multiplication factor for ret… #3279

Merged
merged 1 commit into from Jun 8, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 10 additions & 6 deletions src/core/Settings.js
Expand Up @@ -87,7 +87,8 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest';
* IndexSegment: 1000,
* MediaSegment: 1000,
* BitstreamSwitchingSegment: 1000,
* other: 1000
* other: 1000,
* lowLatencyReductionFactor: 10
* },
* retryAttempts: {
* MPD: 3,
Expand All @@ -96,7 +97,8 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest';
* IndexSegment: 3,
* MediaSegment: 3,
* BitstreamSwitchingSegment: 3,
* other: 3
* other: 3,
* lowLatencyMultiplyFactor: 5
* },
* abr: {
* movingAverageMethod: Constants.MOVING_AVERAGE_SLIDING_WINDOW,
Expand Down Expand Up @@ -316,8 +318,8 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest';
* @property {module:Settings~AudioVideoSettings} [cacheLoadThresholds={video: 50, audio: 5}]
* For a given media type, the threshold which defines if the response to a fragment
* request is coming from browser cache or not.
* @property {module:Settings~RequestTypeSettings} [retryIntervals] Time in milliseconds of which to reload a failed file load attempt.
* @property {module:Settings~RequestTypeSettings} [retryAttempts] Total number of retry attempts that will occur on a file load before it fails.
* @property {module:Settings~RequestTypeSettings} [retryIntervals] Time in milliseconds of which to reload a failed file load attempt. For low latency mode these values are divided by lowLatencyReductionFactor.
* @property {module:Settings~RequestTypeSettings} [retryAttempts] Total number of retry attempts that will occur on a file load before it fails. For low latency mode these values are multiplied by lowLatencyMultiplyFactor.
* @property {module:Settings~AbrSettings} abr Adaptive Bitrate algorithm related settings.
* @property {module:Settings~CmcdSettings} cmcd Settings related to Common Media Client Data reporting.
*/
Expand Down Expand Up @@ -406,7 +408,8 @@ function Settings() {
[HTTPRequest.INIT_SEGMENT_TYPE]: 1000,
[HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE]: 1000,
[HTTPRequest.INDEX_SEGMENT_TYPE]: 1000,
[HTTPRequest.OTHER_TYPE]: 1000
[HTTPRequest.OTHER_TYPE]: 1000,
lowLatencyReductionFactor: 10
},
retryAttempts: {
[HTTPRequest.MPD_TYPE]: 3,
Expand All @@ -415,7 +418,8 @@ function Settings() {
[HTTPRequest.INIT_SEGMENT_TYPE]: 3,
[HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE]: 3,
[HTTPRequest.INDEX_SEGMENT_TYPE]: 3,
[HTTPRequest.OTHER_TYPE]: 3
[HTTPRequest.OTHER_TYPE]: 3,
lowLatencyMultiplyFactor: 5
},
abr: {
movingAverageMethod: Constants.MOVING_AVERAGE_SLIDING_WINDOW,
Expand Down
10 changes: 7 additions & 3 deletions src/streaming/models/MediaPlayerModel.js
Expand Up @@ -126,11 +126,15 @@ function MediaPlayerModel() {
}

function getRetryAttemptsForType(type) {
return settings.get().streaming.lowLatencyEnabled ? settings.get().streaming.retryAttempts[type] * LOW_LATENCY_MULTIPLY_FACTOR : settings.get().streaming.retryAttempts[type];
const lowLatencyMultiplyFactor = !isNaN(settings.get().streaming.retryAttempts.lowLatencyMultiplyFactor) ? settings.get().streaming.retryAttempts.lowLatencyMultiplyFactor : LOW_LATENCY_MULTIPLY_FACTOR;

return settings.get().streaming.lowLatencyEnabled ? settings.get().streaming.retryAttempts[type] * lowLatencyMultiplyFactor : settings.get().streaming.retryAttempts[type];
}

function getRetryIntervalsForType(type) {
return settings.get().streaming.lowLatencyEnabled ? settings.get().streaming.retryIntervals[type] / LOW_LATENCY_REDUCTION_FACTOR : settings.get().streaming.retryIntervals[type];
const lowLatencyReductionFactor = !isNaN(settings.get().streaming.retryIntervals.lowLatencyReductionFactor) ? settings.get().streaming.retryIntervals.lowLatencyReductionFactor : LOW_LATENCY_REDUCTION_FACTOR;

return settings.get().streaming.lowLatencyEnabled ? settings.get().streaming.retryIntervals[type] / lowLatencyReductionFactor : settings.get().streaming.retryIntervals[type];
}

function getLiveDelay() {
Expand Down Expand Up @@ -221,4 +225,4 @@ function MediaPlayerModel() {

//TODO see if you can move this and not export and just getter to get default value.
MediaPlayerModel.__dashjs_factory_name = 'MediaPlayerModel';
export default FactoryMaker.getSingletonFactory(MediaPlayerModel);
export default FactoryMaker.getSingletonFactory(MediaPlayerModel);
77 changes: 60 additions & 17 deletions test/unit/streaming.models.MediaPlayerModel.js
Expand Up @@ -12,7 +12,11 @@ const expect = chai.expect;
describe('MediaPlayerModel', function () {
const context = {};
const mediaPlayerModel = MediaPlayerModel(context).getInstance();
const settings = Settings(context).getInstance();
let settings = Settings(context).getInstance();

beforeEach(() => {
settings.reset();
});

it('Method removeUTCTimingSource should throw an exception', function () {
expect(mediaPlayerModel.removeUTCTimingSource.bind(mediaPlayerModel, true, 'string')).to.throw(Constants.BAD_ARGUMENT_ERROR);
Expand Down Expand Up @@ -44,7 +48,7 @@ describe('MediaPlayerModel', function () {
let FragmentLoaderRetryAttempts = mediaPlayerModel.getRetryAttemptsForType(HTTPRequest.MEDIA_SEGMENT_TYPE);
expect(FragmentLoaderRetryAttempts).to.equal(3);

const s = { streaming: { retryAttempts: {}}};
const s = {streaming: {retryAttempts: {}}};
s.streaming.retryAttempts[HTTPRequest.MEDIA_SEGMENT_TYPE] = 50;
settings.update(s);

Expand All @@ -53,46 +57,85 @@ describe('MediaPlayerModel', function () {
});

it('should configure FragmentLoaderRetryInterval', function () {
let FragmentLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MEDIA_SEGMENT_TYPE);
let FragmentLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MEDIA_SEGMENT_TYPE);
expect(FragmentLoaderRetryInterval).to.equal(1000);

const s = { streaming: { retryIntervals: {}}};
const s = {streaming: {retryIntervals: {}}};
s.streaming.retryIntervals[HTTPRequest.MEDIA_SEGMENT_TYPE] = 50;
settings.update(s);

FragmentLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MEDIA_SEGMENT_TYPE);
FragmentLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MEDIA_SEGMENT_TYPE);
expect(FragmentLoaderRetryInterval).to.equal(50);
});

it('should configure ManifestLoaderRetryAttempts', function () {
let ManifestLoaderRetryAttempts = mediaPlayerModel.getRetryAttemptsForType(HTTPRequest.MPD_TYPE);
expect(ManifestLoaderRetryAttempts).to.equal(3);
let manifestLoaderRetryAttempts = mediaPlayerModel.getRetryAttemptsForType(HTTPRequest.MPD_TYPE);
expect(manifestLoaderRetryAttempts).to.equal(3);

const s = { streaming: { retryAttempts: {}}};
const s = {streaming: {retryAttempts: {}}};
s.streaming.retryAttempts[HTTPRequest.MPD_TYPE] = 50;
settings.update(s);

ManifestLoaderRetryAttempts = mediaPlayerModel.getRetryAttemptsForType(HTTPRequest.MPD_TYPE);
expect(ManifestLoaderRetryAttempts).to.equal(50);
manifestLoaderRetryAttempts = mediaPlayerModel.getRetryAttemptsForType(HTTPRequest.MPD_TYPE);
expect(manifestLoaderRetryAttempts).to.equal(50);
});

it('should configure low latency retry attempt multiplication factor', function () {
let manifestLoaderRetryAttempts = mediaPlayerModel.getRetryAttemptsForType(HTTPRequest.MPD_TYPE);
expect(manifestLoaderRetryAttempts).to.equal(3);

const s = {
streaming:
{
lowLatencyEnabled: true,
retryAttempts: {
lowLatencyMultiplyFactor: 10
}
}
};
settings.update(s);

manifestLoaderRetryAttempts = mediaPlayerModel.getRetryAttemptsForType(HTTPRequest.MPD_TYPE);
expect(manifestLoaderRetryAttempts).to.equal(30);
});

it('should configure ManifestLoaderRetryInterval', function () {
let ManifestLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MPD_TYPE);
expect(ManifestLoaderRetryInterval).to.equal(500);
let manifestLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MPD_TYPE);
expect(manifestLoaderRetryInterval).to.equal(500);

const s = { streaming: { retryIntervals: {}}};
const s = {streaming: {retryIntervals: {}}};
s.streaming.retryIntervals[HTTPRequest.MPD_TYPE] = 50;
settings.update(s);

ManifestLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MPD_TYPE);
expect(ManifestLoaderRetryInterval).to.equal(50);
manifestLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MPD_TYPE);
expect(manifestLoaderRetryInterval).to.equal(50);
});

it('should configure low latency retry interval reduction factor', function () {
let manifestLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MPD_TYPE);
expect(manifestLoaderRetryInterval).to.equal(500);

const s = {
streaming:
{
lowLatencyEnabled: true,
retryIntervals: {
lowLatencyReductionFactor: 5
}
}
};
settings.update(s);

manifestLoaderRetryInterval = mediaPlayerModel.getRetryIntervalsForType(HTTPRequest.MPD_TYPE);
expect(manifestLoaderRetryInterval).to.equal(100);
});

it('should configure StableBufferTime', function () {
const s = { streaming: { stableBufferTime: 50 } };
const s = {streaming: {stableBufferTime: 50}};
settings.update(s);

let StableBufferTime = mediaPlayerModel.getStableBufferTime();
expect(StableBufferTime).to.equal(50);
});
});

});