Skip to content

Commit

Permalink
feat(HLS): Add support to HOLD-BACK in EXT-X-SERVER-CONTROL (shaka-pr…
Browse files Browse the repository at this point in the history
  • Loading branch information
avelad committed Jun 12, 2023
1 parent 090554b commit bb2c06a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
15 changes: 12 additions & 3 deletions lib/hls/hls_parser.js
Expand Up @@ -185,6 +185,9 @@ shaka.hls.HlsParser = class {
*/
this.partialTargetDuration_ = 0;

/** @private {number} */
this.presentationDelay_ = 0;

/** @private {number} */
this.lowLatencyPresentationDelay_ = 0;

Expand Down Expand Up @@ -2621,6 +2624,9 @@ shaka.hls.HlsParser = class {
const targetDuration = Number(targetDurationTag.value);
const partialTargetDurationTag =
shaka.hls.Utils.getFirstTagWithName(playlist.tags, 'EXT-X-PART-INF');
// Get the server-recommended min distance from the live edge.
const serverControlTag = shaka.hls.Utils.getFirstTagWithName(
playlist.tags, 'EXT-X-SERVER-CONTROL');
// According to the HLS spec, updates should not happen more often than
// once in targetDuration. It also requires us to only update the active
// variant. We might implement that later, but for now every variant
Expand All @@ -2634,9 +2640,6 @@ shaka.hls.HlsParser = class {
partialTargetDurationTag.getRequiredAttrValue('PART-TARGET'));
this.lastTargetDuration_ = Math.min(
this.partialTargetDuration_, this.lastTargetDuration_);
// Get the server-recommended min distance from the live edge.
const serverControlTag = shaka.hls.Utils.getFirstTagWithName(
playlist.tags, 'EXT-X-SERVER-CONTROL');
// Use 'PART-HOLD-BACK' as the presentation delay for low latency mode.
this.lowLatencyPresentationDelay_ = serverControlTag ? Number(
serverControlTag.getRequiredAttrValue('PART-HOLD-BACK')) : 0;
Expand All @@ -2656,6 +2659,10 @@ shaka.hls.HlsParser = class {
}
this.lastTargetDuration_ = Math.min(
lastTargetDuration, this.lastTargetDuration_);
// Use 'HOLD-BACK' as the presentation delay for default if defined.
const holdBack = serverControlTag ?
serverControlTag.getAttribute('HOLD-BACK') : null;
this.presentationDelay_ = holdBack ? Number(holdBack.value) : 0;
}
// 2. Update the longest target duration if need be to use as a
// presentation delay later.
Expand Down Expand Up @@ -2687,6 +2694,8 @@ shaka.hls.HlsParser = class {
presentationDelay = this.config_.defaultPresentationDelay;
} else if (this.lowLatencyPresentationDelay_) {
presentationDelay = this.lowLatencyPresentationDelay_;
} else if (this.presentationDelay_) {
presentationDelay = this.presentationDelay_;
} else {
const numberOfSegments = this.config_.hls.liveSegmentsDelay;
presentationDelay = this.maxTargetDuration_ * numberOfSegments;
Expand Down
18 changes: 18 additions & 0 deletions test/hls/hls_live_unit.js
Expand Up @@ -544,6 +544,24 @@ describe('HlsParser live', () => {
expect(manifest.presentationTimeline.getDelay()).toBe(15);
});

it('sets presentation delay if defined', async () => {
const media = [
'#EXTM3U\n',
'#EXT-X-SERVER-CONTROL:HOLD-BACK=2\n',
'#EXT-X-TARGETDURATION:5\n',
'#EXT-X-PART-INF:PART-TARGET=0.5\n',
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
'#EXT-X-MEDIA-SEQUENCE:0\n',
'#EXTINF:2,\n',
'main.mp4\n',
].join('');

const manifest = await testInitialManifest(master, media);
// Presentation delay should be the value of 'HOLD-BACK' if not
// configured.
expect(manifest.presentationTimeline.getDelay()).toBe(2);
});

it('sets presentation delay for low latency mode', async () => {
const mediaWithLowLatency = [
'#EXTM3U\n',
Expand Down

0 comments on commit bb2c06a

Please sign in to comment.