Skip to content

Commit 4c97562

Browse files
feat(ll-hls): only request delta updates when server supports it
We should only request playlist delta updates when the lowLatencyMode is enabled, and when the server supports the feature. We can check if the playlist has a "CAN-SKIP-UNTIL" tag to know if the server supports that. Issue shaka-project#1525 Change-Id: I304a008aeb3a9e019f27304ba836d31538c94fbf
1 parent 7e50866 commit 4c97562

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

lib/hls/hls_parser.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ shaka.hls.HlsParser = class {
302302
const PresentationType = shaka.hls.HlsParser.PresentationType_;
303303
const manifestUri = streamInfo.absoluteMediaPlaylistUri;
304304
const uriObj = new goog.Uri(manifestUri);
305-
if (this.lowLatencyMode_) {
305+
if (this.lowLatencyMode_ && streamInfo.canSkipSegments) {
306306
// Enable delta updates. This will replace older segments with
307307
// 'EXT-X-SKIP' tag in the media playlist.
308308
uriObj.setQueryData(new goog.Uri.QueryData('_HLS_skip=YES'));
@@ -1383,6 +1383,11 @@ shaka.hls.HlsParser = class {
13831383
}
13841384
}
13851385

1386+
const serverControlTag = shaka.hls.Utils.getFirstTagWithName(
1387+
playlist.tags, 'EXT-X-SERVER-CONTROL');
1388+
const canSkipSegments = serverControlTag ?
1389+
serverControlTag.getAttribute('CAN-SKIP-UNTIL') != null : false;
1390+
13861391
/** @type {shaka.extern.Stream} */
13871392
const stream = {
13881393
id: this.globalId_++,
@@ -1425,6 +1430,7 @@ shaka.hls.HlsParser = class {
14251430
maxTimestamp: lastEndTime,
14261431
mediaSequenceToStartTime,
14271432
discontinuityToMediaSequence,
1433+
canSkipSegments,
14281434
};
14291435
}
14301436

@@ -2658,7 +2664,8 @@ shaka.hls.HlsParser = class {
26582664
* minTimestamp: number,
26592665
* maxTimestamp: number,
26602666
* mediaSequenceToStartTime: !Map.<number, number>,
2661-
* discontinuityToMediaSequence: !Map.<number, number>
2667+
* discontinuityToMediaSequence: !Map.<number, number>,
2668+
* canSkipSegments: boolean
26622669
* }}
26632670
*
26642671
* @description
@@ -2683,6 +2690,9 @@ shaka.hls.HlsParser = class {
26832690
* @property {!Map.<number, number>} discontinuityToMediaSequence
26842691
* A map of discontinuity sequence numbers to the media sequence number of the
26852692
* segment starting with that discontinuity sequence number.
2693+
* @property {boolean} canSkipSegments
2694+
* True if the server supports delta playlist updates, and we can send a
2695+
* request for a playlist that can skip older media segments.
26862696
*/
26872697
shaka.hls.HlsParser.StreamInfo;
26882698

test/hls/hls_live_unit.js

+51-1
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,56 @@ describe('HlsParser live', () => {
907907
partialEndByte); // partial segment request
908908
});
909909

910+
it('request playlist delta updates to skip segments', async () => {
911+
const mediaWithDeltaUpdates = [
912+
'#EXTM3U\n',
913+
'#EXT-X-PLAYLIST-TYPE:LIVE\n',
914+
'#EXT-X-TARGETDURATION:5\n',
915+
'#EXT-X-MEDIA-SEQUENCE:0\n',
916+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
917+
'#EXT-X-SERVER-CONTROL:CAN-SKIP-UNTIL=60.0\n',
918+
'#EXTINF:2,\n',
919+
'main.mp4\n',
920+
'#EXTINF:2,\n',
921+
'main2.mp4\n',
922+
].join('');
923+
924+
const mediaWithSkippedSegments = [
925+
'#EXTM3U\n',
926+
'#EXT-X-TARGETDURATION:5\n',
927+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
928+
'#EXT-X-MEDIA-SEQUENCE:0\n',
929+
'#EXT-X-SERVER-CONTROL:CAN-SKIP-UNTIL=60.0\n',
930+
'#EXT-X-SKIP:SKIPPED-SEGMENTS=1\n',
931+
'#EXTINF:2,\n',
932+
'main2.mp4\n',
933+
'#EXTINF:2,\n',
934+
'main3.mp4\n',
935+
].join('');
936+
937+
fakeNetEngine
938+
.setResponseText('test:/master', master)
939+
.setResponseText('test:/video', mediaWithDeltaUpdates)
940+
.setResponseText('test:/video?_HLS_skip=YES',
941+
mediaWithSkippedSegments)
942+
.setResponseValue('test:/init.mp4', initSegmentData)
943+
.setResponseValue('test:/main.mp4', segmentData)
944+
.setResponseValue('test:/main2.mp4', segmentData)
945+
.setResponseValue('test:/main3.mp4', segmentData);
946+
947+
playerInterface.isLowLatencyMode = () => true;
948+
await parser.start('test:/master', playerInterface);
949+
// Replace the entries with the updated values.
950+
951+
fakeNetEngine.request.calls.reset();
952+
await delayForUpdatePeriod();
953+
954+
fakeNetEngine.expectRequest(
955+
'test:/video?_HLS_skip=YES',
956+
shaka.net.NetworkingEngine.RequestType.MANIFEST);
957+
});
958+
959+
910960
it('skips older segments', async () => {
911961
const mediaWithSkippedSegments = [
912962
'#EXTM3U\n',
@@ -935,7 +985,7 @@ describe('HlsParser live', () => {
935985
it('skips older segments with discontinuity', async () => {
936986
const mediaWithDiscontinuity2 = [
937987
'#EXTM3U\n',
938-
'#EXT-X-PLAYLIST-TYPE:EVENT\n',
988+
'#EXT-X-PLAYLIST-TYPE:LIVE\n',
939989
'#EXT-X-TARGETDURATION:5\n',
940990
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
941991
'#EXT-X-DISCONTINUITY-SEQUENCE:30\n',

0 commit comments

Comments
 (0)