Skip to content

Commit

Permalink
feat(HLS): Add support to blocking playlist reload by adding the CAN-…
Browse files Browse the repository at this point in the history
…BLOCK-RELOAD=YES (#5279)
  • Loading branch information
avelad authored Jun 12, 2023
1 parent 9dddc09 commit 090554b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 34 deletions.
32 changes: 22 additions & 10 deletions lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,16 +349,18 @@ shaka.hls.HlsParser = class {
// 'EXT-X-SKIP' tag in the media playlist.
queryData.add('_HLS_skip', 'YES');
}
if (streamInfo.nextMediaSequence >= 0) {
// Indicates that the server must hold the request until a Playlist
// contains a Media Segment with Media Sequence
queryData.add('_HLS_msn', String(streamInfo.nextMediaSequence));
}
if (streamInfo.nextPart >= 0) {
// Indicates, in combination with _HLS_msn, that the server must hold
// the request until a Playlist contains Partial Segment N of Media
// Sequence Number M or later.
queryData.add('_HLS_part', String(streamInfo.nextPart));
if (streamInfo.canBlockReload) {
if (streamInfo.nextMediaSequence >= 0) {
// Indicates that the server must hold the request until a Playlist
// contains a Media Segment with Media Sequence
queryData.add('_HLS_msn', String(streamInfo.nextMediaSequence));
}
if (streamInfo.nextPart >= 0) {
// Indicates, in combination with _HLS_msn, that the server must hold
// the request until a Playlist contains Partial Segment N of Media
// Sequence Number M or later.
queryData.add('_HLS_part', String(streamInfo.nextPart));
}
}
if (queryData.getCount()) {
uriObj.setQueryData(queryData);
Expand Down Expand Up @@ -1960,6 +1962,7 @@ shaka.hls.HlsParser = class {
maxTimestamp: 0,
mediaSequenceToStartTime: new Map(),
canSkipSegments: false,
canBlockReload: false,
hasEndList: false,
firstSequenceNumber: -1,
nextMediaSequence: -1,
Expand Down Expand Up @@ -2007,6 +2010,7 @@ shaka.hls.HlsParser = class {
streamInfo.minTimestamp = realStreamInfo.minTimestamp;
streamInfo.maxTimestamp = realStreamInfo.maxTimestamp;
streamInfo.canSkipSegments = realStreamInfo.canSkipSegments;
streamInfo.canBlockReload = realStreamInfo.canBlockReload;
streamInfo.hasEndList = realStreamInfo.hasEndList;
streamInfo.mediaSequenceToStartTime =
realStreamInfo.mediaSequenceToStartTime;
Expand Down Expand Up @@ -2297,6 +2301,8 @@ shaka.hls.HlsParser = class {
playlist.tags, 'EXT-X-SERVER-CONTROL');
const canSkipSegments = serverControlTag ?
serverControlTag.getAttribute('CAN-SKIP-UNTIL') != null : false;
const canBlockReload = serverControlTag ?
serverControlTag.getAttribute('CAN-BLOCK-RELOAD') != null : false;

const mediaSequenceNumber = shaka.hls.Utils.getFirstTagWithNameAsNumber(
playlist.tags, 'EXT-X-MEDIA-SEQUENCE', 0);
Expand All @@ -2320,6 +2326,7 @@ shaka.hls.HlsParser = class {
minTimestamp: firstStartTime,
maxTimestamp: lastEndTime,
canSkipSegments,
canBlockReload,
hasEndList: false,
firstSequenceNumber: -1,
nextMediaSequence,
Expand Down Expand Up @@ -3695,6 +3702,7 @@ shaka.hls.HlsParser = class {
* maxTimestamp: number,
* mediaSequenceToStartTime: !Map.<number, number>,
* canSkipSegments: boolean,
* canBlockReload: boolean,
* hasEndList: boolean,
* firstSequenceNumber: number,
* nextMediaSequence: number,
Expand Down Expand Up @@ -3727,6 +3735,10 @@ shaka.hls.HlsParser = class {
* @property {boolean} canSkipSegments
* True if the server supports delta playlist updates, and we can send a
* request for a playlist that can skip older media segments.
* @property {boolean} canBlockReload
* True if the server supports blocking playlist reload, and we can send a
* request for a playlist that can block reload until some segments are
* present.
* @property {boolean} hasEndList
* True if the stream has an EXT-X-ENDLIST tag.
* @property {number} firstSequenceNumber
Expand Down
34 changes: 10 additions & 24 deletions test/hls/hls_live_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,28 +163,14 @@ describe('HlsParser live', () => {
* @param {shaka.extern.Manifest} manifest
* @param {string} updatedMedia
* @param {Array=} updatedReferences
* @param {?number=} sequenceNumber
*/
async function testUpdate(manifest, updatedMedia, updatedReferences=null,
sequenceNumber=null) {
async function testUpdate(manifest, updatedMedia, updatedReferences=null) {
// Replace the entries with the updated values.
if (sequenceNumber == null) {
fakeNetEngine
.setResponseText('test:/video', updatedMedia)
.setResponseText('test:/redirected/video', updatedMedia)
.setResponseText('test:/video2', updatedMedia)
.setResponseText('test:/audio', updatedMedia);
} else {
fakeNetEngine
.setResponseText('test:/video?_HLS_msn=' + sequenceNumber,
updatedMedia)
.setResponseText('test:/redirected/video?_HLS_msn=' + sequenceNumber,
updatedMedia)
.setResponseText('test:/video2?_HLS_msn=' + sequenceNumber,
updatedMedia)
.setResponseText('test:/audio?_HLS_msn=' + sequenceNumber,
updatedMedia);
}
fakeNetEngine
.setResponseText('test:/video', updatedMedia)
.setResponseText('test:/redirected/video', updatedMedia)
.setResponseText('test:/video2', updatedMedia)
.setResponseText('test:/audio', updatedMedia);

await delayForUpdatePeriod();

Expand Down Expand Up @@ -916,7 +902,7 @@ describe('HlsParser live', () => {
'#EXT-X-TARGETDURATION:5\n',
'#EXT-X-MEDIA-SEQUENCE:0\n',
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
'#EXT-X-SERVER-CONTROL:CAN-SKIP-UNTIL=60.0\n',
'#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-UNTIL=60.0,\n',
'#EXTINF:2,\n',
'main.mp4\n',
'#EXTINF:2,\n',
Expand All @@ -928,7 +914,7 @@ describe('HlsParser live', () => {
'#EXT-X-TARGETDURATION:5\n',
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
'#EXT-X-MEDIA-SEQUENCE:1\n',
'#EXT-X-SERVER-CONTROL:CAN-SKIP-UNTIL=60.0\n',
'#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-UNTIL=60.0,\n',
'#EXT-X-SKIP:SKIPPED-SEGMENTS=1\n',
'#EXTINF:2,\n',
'main2.mp4\n',
Expand Down Expand Up @@ -981,7 +967,7 @@ describe('HlsParser live', () => {
// and ref1 should be in the SegmentReferences list.
// ref3 should be appended to the SegmentReferences list.
await testUpdate(
manifest, mediaWithSkippedSegments, [ref1, ref2, ref3], 2);
manifest, mediaWithSkippedSegments, [ref1, ref2, ref3]);
});

it('skips older segments with discontinuity', async () => {
Expand Down Expand Up @@ -1046,7 +1032,7 @@ describe('HlsParser live', () => {
// and ref1,ref2 should be in the SegmentReferences list.
// ref3,ref4 should be appended to the SegmentReferences list.
await testUpdate(
manifest, mediaWithSkippedSegments2, [ref1, ref2, ref3, ref4], 3);
manifest, mediaWithSkippedSegments2, [ref1, ref2, ref3, ref4]);
});

it('updates encryption keys', async () => {
Expand Down

0 comments on commit 090554b

Please sign in to comment.