Skip to content

Commit

Permalink
Add support for HLS playlists with type EVENT.
Browse files Browse the repository at this point in the history
HLS Live comes in two flavors: LIVE and EVENT.
EVENTs append segments to the end of the playlist, but do not
ever remove segments. LIVE can both append segments to the end
and remove segments from the beginning of the playlist.
This CL lays the ground for supporting both types and introduces
support for EVENTs.

Issue shaka-project#740.

Change-Id: I2042660daf9d1e7209cb1b40f50ab8b24571faa4
  • Loading branch information
ismena committed Aug 22, 2017
1 parent 87092e2 commit 051531b
Show file tree
Hide file tree
Showing 9 changed files with 852 additions and 251 deletions.
350 changes: 318 additions & 32 deletions lib/hls/hls_parser.js

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions lib/media/presentation_timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,18 @@ shaka.media.PresentationTimeline.prototype.setSegmentAvailabilityDuration =
};


/**
* Sets the presentation delay.
*
* @param {number} delay
* @export
*/
shaka.media.PresentationTimeline.prototype.setDelay = function(delay) {
goog.asserts.assert(delay >= 0, 'delay must be >= 0');
this.presentationDelay_ = delay;
};


/**
* Gives PresentationTimeline a Stream's segments so it can size and position
* the segment availability window, and account for missing segment
Expand Down
73 changes: 39 additions & 34 deletions test/dash/dash_parser_live_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@
*/

describe('DashParser Live', function() {
/** @const */
var Dash = shaka.test.Dash;
/** @const */
var Util = shaka.test.Util;
/** @const */
var ManifestParser = shaka.test.ManifestParser;

/** @const */
var realTimeout = window.setTimeout;
/** @const */
var oldNow = Date.now;
/** @const */
var updateTime = 5;
/** @const */
var originalUri = 'http://example.com/';


/** @type {!shaka.test.FakeNetworkingEngine} */
var fakeNetEngine;
Expand Down Expand Up @@ -152,12 +155,13 @@ describe('DashParser Live', function() {
fakeNetEngine.setResponseMapAsText({'dummy://foo': firstManifest});
parser.start('dummy://foo', playerInterface)
.then(function(manifest) {
Dash.verifySegmentIndex(manifest, firstReferences, 0);
var stream = manifest.periods[0].variants[0].video;
ManifestParser.verifySegmentIndex(stream, firstReferences);
expect(manifest.periods.length).toBe(1);

fakeNetEngine.setResponseMapAsText({'dummy://foo': secondManifest});
delayForUpdatePeriod();
Dash.verifySegmentIndex(manifest, secondReferences, 0);
ManifestParser.verifySegmentIndex(stream, secondReferences);
// In https://github.com/google/shaka-player/issues/963, we
// duplicated periods during the first update. This check covers
// this case.
Expand Down Expand Up @@ -204,15 +208,15 @@ describe('DashParser Live', function() {

expect(stream.findSegmentPosition).toBeTruthy();
expect(stream.findSegmentPosition(0)).toBe(1);
Dash.verifySegmentIndex(manifest, basicRefs, 0);
ManifestParser.verifySegmentIndex(stream, basicRefs);

// 15 seconds for @timeShiftBufferDepth and the first segment
// duration.
Date.now = function() { return 2 * 15 * 1000; };
delayForUpdatePeriod();
// The first reference should have been evicted.
expect(stream.findSegmentPosition(0)).toBe(2);
Dash.verifySegmentIndex(manifest, basicRefs.slice(1), 0);
ManifestParser.verifySegmentIndex(stream, basicRefs.slice(1));
}).catch(fail).then(done);
shaka.polyfill.Promise.flush();
});
Expand Down Expand Up @@ -256,22 +260,24 @@ describe('DashParser Live', function() {
Date.now = function() { return 0; };
parser.start('dummy://foo', playerInterface)
.then(function(manifest) {
Dash.verifySegmentIndex(manifest, basicRefs, 0);
Dash.verifySegmentIndex(manifest, basicRefs, 1);
var stream1 = manifest.periods[0].variants[0].video;
var stream2 = manifest.periods[1].variants[0].video;
ManifestParser.verifySegmentIndex(stream1, basicRefs);
ManifestParser.verifySegmentIndex(stream2, basicRefs);

// 15 seconds for @timeShiftBufferDepth and the first segment
// duration.
Date.now = function() { return 2 * 15 * 1000; };
delayForUpdatePeriod();
// The first reference should have been evicted.
Dash.verifySegmentIndex(manifest, basicRefs.slice(1), 0);
Dash.verifySegmentIndex(manifest, basicRefs, 1);
ManifestParser.verifySegmentIndex(stream1, basicRefs.slice(1));
ManifestParser.verifySegmentIndex(stream2, basicRefs);

// Same as above, but 1 period length later
Date.now = function() { return (2 * 15 + pStart) * 1000; };
delayForUpdatePeriod();
Dash.verifySegmentIndex(manifest, [], 0);
Dash.verifySegmentIndex(manifest, basicRefs.slice(1), 1);
ManifestParser.verifySegmentIndex(stream1, []);
ManifestParser.verifySegmentIndex(stream2, basicRefs.slice(1));
}).catch(fail).then(done);
shaka.polyfill.Promise.flush();
});
Expand Down Expand Up @@ -416,7 +422,6 @@ describe('DashParser Live', function() {
].join('\n');
var manifestText = sprintf(template, {updateTime: updateTime});
var manifestData = shaka.util.StringUtils.toUTF8(manifestText);
var originalUri = 'http://example.com/';
var redirectedUri = 'http://redirected.com/';

// The initial manifest request will be redirected.
Expand Down Expand Up @@ -868,9 +873,9 @@ describe('DashParser Live', function() {
'</SegmentTemplate>'
];
var basicRefs = [
shaka.test.Dash.makeReference('s1.mp4', 1, 0, 10),
shaka.test.Dash.makeReference('s2.mp4', 2, 10, 15),
shaka.test.Dash.makeReference('s3.mp4', 3, 15, 30)
shaka.test.ManifestParser.makeReference('s1.mp4', 1, 0, 10, originalUri),
shaka.test.ManifestParser.makeReference('s2.mp4', 2, 10, 15, originalUri),
shaka.test.ManifestParser.makeReference('s3.mp4', 3, 15, 30, originalUri)
];
var updateLines = [
'<SegmentTemplate startNumber="1" media="s$Number$.mp4">',
Expand All @@ -883,10 +888,10 @@ describe('DashParser Live', function() {
'</SegmentTemplate>'
];
var updateRefs = [
shaka.test.Dash.makeReference('s1.mp4', 1, 0, 10),
shaka.test.Dash.makeReference('s2.mp4', 2, 10, 15),
shaka.test.Dash.makeReference('s3.mp4', 3, 15, 30),
shaka.test.Dash.makeReference('s4.mp4', 4, 30, 40)
shaka.test.ManifestParser.makeReference('s1.mp4', 1, 0, 10, originalUri),
shaka.test.ManifestParser.makeReference('s2.mp4', 2, 10, 15, originalUri),
shaka.test.ManifestParser.makeReference('s3.mp4', 3, 15, 30, originalUri),
shaka.test.ManifestParser.makeReference('s4.mp4', 4, 30, 40, originalUri)
];
var partialUpdateLines = [
'<SegmentTemplate startNumber="3" media="s$Number$.mp4">',
Expand Down Expand Up @@ -915,9 +920,9 @@ describe('DashParser Live', function() {
'</SegmentList>'
];
var basicRefs = [
shaka.test.Dash.makeReference('s1.mp4', 1, 0, 10),
shaka.test.Dash.makeReference('s2.mp4', 2, 10, 15),
shaka.test.Dash.makeReference('s3.mp4', 3, 15, 30)
shaka.test.ManifestParser.makeReference('s1.mp4', 1, 0, 10, originalUri),
shaka.test.ManifestParser.makeReference('s2.mp4', 2, 10, 15, originalUri),
shaka.test.ManifestParser.makeReference('s3.mp4', 3, 15, 30, originalUri)
];
var updateLines = [
'<SegmentList>',
Expand All @@ -934,10 +939,10 @@ describe('DashParser Live', function() {
'</SegmentList>'
];
var updateRefs = [
shaka.test.Dash.makeReference('s1.mp4', 1, 0, 10),
shaka.test.Dash.makeReference('s2.mp4', 2, 10, 15),
shaka.test.Dash.makeReference('s3.mp4', 3, 15, 30),
shaka.test.Dash.makeReference('s4.mp4', 4, 30, 40)
shaka.test.ManifestParser.makeReference('s1.mp4', 1, 0, 10, originalUri),
shaka.test.ManifestParser.makeReference('s2.mp4', 2, 10, 15, originalUri),
shaka.test.ManifestParser.makeReference('s3.mp4', 3, 15, 30, originalUri),
shaka.test.ManifestParser.makeReference('s4.mp4', 4, 30, 40, originalUri)
];
var partialUpdateLines = [
'<SegmentList startNumber="3">',
Expand All @@ -963,9 +968,9 @@ describe('DashParser Live', function() {
'</SegmentList>'
];
var basicRefs = [
shaka.test.Dash.makeReference('s1.mp4', 1, 0, 10),
shaka.test.Dash.makeReference('s2.mp4', 2, 10, 20),
shaka.test.Dash.makeReference('s3.mp4', 3, 20, 30)
shaka.test.ManifestParser.makeReference('s1.mp4', 1, 0, 10, originalUri),
shaka.test.ManifestParser.makeReference('s2.mp4', 2, 10, 20, originalUri),
shaka.test.ManifestParser.makeReference('s3.mp4', 3, 20, 30, originalUri)
];
var updateLines = [
'<SegmentList duration="10">',
Expand All @@ -976,10 +981,10 @@ describe('DashParser Live', function() {
'</SegmentList>'
];
var updateRefs = [
shaka.test.Dash.makeReference('s1.mp4', 1, 0, 10),
shaka.test.Dash.makeReference('s2.mp4', 2, 10, 20),
shaka.test.Dash.makeReference('s3.mp4', 3, 20, 30),
shaka.test.Dash.makeReference('s4.mp4', 4, 30, 40)
shaka.test.ManifestParser.makeReference('s1.mp4', 1, 0, 10, originalUri),
shaka.test.ManifestParser.makeReference('s2.mp4', 2, 10, 20, originalUri),
shaka.test.ManifestParser.makeReference('s3.mp4', 3, 20, 30, originalUri),
shaka.test.ManifestParser.makeReference('s4.mp4', 4, 30, 40, originalUri)
];
var partialUpdateLines = [
'<SegmentList startNumber="3" duration="10">',
Expand Down
67 changes: 36 additions & 31 deletions test/dash/dash_parser_segment_list_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
describe('DashParser SegmentList', function() {
/** @const */
var Dash = shaka.test.Dash;
/** @const */
var ManifestParser = shaka.test.ManifestParser;
/** @const */
var baseUri = 'http://example.com/';

shaka.test.Dash.makeTimelineTests('SegmentList', '', [
'<SegmentURL media="s1.mp4" />',
Expand All @@ -42,8 +46,8 @@ describe('DashParser SegmentList', function() {
'</SegmentList>'
], 65 /* duration */);
var references = [
Dash.makeReference('s1.mp4', 1, 50, 60),
Dash.makeReference('s2.mp4', 2, 60, 65)
ManifestParser.makeReference('s1.mp4', 1, 50, 60, baseUri),
ManifestParser.makeReference('s2.mp4', 2, 60, 65, baseUri)
];
Dash.testSegmentIndex(done, source, references);
});
Expand All @@ -54,7 +58,8 @@ describe('DashParser SegmentList', function() {
' <SegmentURL media="s1.mp4" />',
'</SegmentList>'
], 30 /* duration */);
var references = [Dash.makeReference('s1.mp4', 1, 0, 30)];
var references = [ManifestParser.makeReference('s1.mp4', 1,
0, 30, baseUri)];
Dash.testSegmentIndex(done, source, references);
});

Expand All @@ -69,10 +74,10 @@ describe('DashParser SegmentList', function() {
'</SegmentList>'
]);
var references = [
Dash.makeReference('s1.mp4', 1, 0, 10),
Dash.makeReference('s2.mp4', 2, 10, 20),
Dash.makeReference('s3.mp4', 3, 20, 30),
Dash.makeReference('s4.mp4', 4, 30, 40)
ManifestParser.makeReference('s1.mp4', 1, 0, 10, baseUri),
ManifestParser.makeReference('s2.mp4', 2, 10, 20, baseUri),
ManifestParser.makeReference('s3.mp4', 3, 20, 30, baseUri),
ManifestParser.makeReference('s4.mp4', 4, 30, 40, baseUri)
];
Dash.testSegmentIndex(done, source, references);
});
Expand All @@ -87,10 +92,10 @@ describe('DashParser SegmentList', function() {
'</SegmentList>'
]);
var references = [
Dash.makeReference('s1.mp4', 5, 40, 50),
Dash.makeReference('s2.mp4', 6, 50, 60),
Dash.makeReference('s3.mp4', 7, 60, 70),
Dash.makeReference('s4.mp4', 8, 70, 80)
ManifestParser.makeReference('s1.mp4', 5, 40, 50, baseUri),
ManifestParser.makeReference('s2.mp4', 6, 50, 60, baseUri),
ManifestParser.makeReference('s3.mp4', 7, 60, 70, baseUri),
ManifestParser.makeReference('s4.mp4', 8, 70, 80, baseUri)
];
Dash.testSegmentIndex(done, source, references);
});
Expand All @@ -103,8 +108,8 @@ describe('DashParser SegmentList', function() {
'</SegmentList>'
]);
var references = [
Dash.makeReference('s1.mp4', 1, 0, 10),
Dash.makeReference('s2.mp4', 2, 10, 20)
ManifestParser.makeReference('s1.mp4', 1, 0, 10, baseUri),
ManifestParser.makeReference('s2.mp4', 2, 10, 20, baseUri)
];
Dash.testSegmentIndex(done, source, references);
});
Expand All @@ -119,10 +124,10 @@ describe('DashParser SegmentList', function() {
'</SegmentList>'
]);
var references = [
Dash.makeReference('s1.mp4', 1, 0, 2),
Dash.makeReference('s2.mp4', 2, 2, 4),
Dash.makeReference('s3.mp4', 3, 4, 6),
Dash.makeReference('s4.mp4', 4, 6, 8)
ManifestParser.makeReference('s1.mp4', 1, 0, 2, baseUri),
ManifestParser.makeReference('s2.mp4', 2, 2, 4, baseUri),
ManifestParser.makeReference('s3.mp4', 3, 4, 6, baseUri),
ManifestParser.makeReference('s4.mp4', 4, 6, 8, baseUri)
];
Dash.testSegmentIndex(done, source, references);
});
Expand Down Expand Up @@ -195,10 +200,10 @@ describe('DashParser SegmentList', function() {
'</MPD>'
].join('\n');
var references = [
Dash.makeReference('s1.mp4', 1, 0, 50),
Dash.makeReference('s2.mp4', 2, 50, 100),
Dash.makeReference('s3.mp4', 3, 100, 150),
Dash.makeReference('s4.mp4', 4, 150, 200)
ManifestParser.makeReference('s1.mp4', 1, 0, 50, baseUri),
ManifestParser.makeReference('s2.mp4', 2, 50, 100, baseUri),
ManifestParser.makeReference('s3.mp4', 3, 100, 150, baseUri),
ManifestParser.makeReference('s4.mp4', 4, 150, 200, baseUri)
];
Dash.testSegmentIndex(done, source, references);
});
Expand Down Expand Up @@ -228,9 +233,9 @@ describe('DashParser SegmentList', function() {
'</MPD>'
].join('\n');
var references = [
Dash.makeReference('s1.mp4', 1, 50, 60),
Dash.makeReference('s2.mp4', 2, 60, 65),
Dash.makeReference('s3.mp4', 3, 65, 73)
ManifestParser.makeReference('s1.mp4', 1, 50, 60, baseUri),
ManifestParser.makeReference('s2.mp4', 2, 60, 65, baseUri),
ManifestParser.makeReference('s3.mp4', 3, 65, 73, baseUri)
];
Dash.testSegmentIndex(done, source, references);
});
Expand Down Expand Up @@ -260,9 +265,9 @@ describe('DashParser SegmentList', function() {
'</MPD>'
].join('\n');
var references = [
Dash.makeReference('s1.mp4', 1, 50, 60),
Dash.makeReference('s2.mp4', 2, 60, 65),
Dash.makeReference('s3.mp4', 3, 65, 73)
ManifestParser.makeReference('s1.mp4', 1, 50, 60, baseUri),
ManifestParser.makeReference('s2.mp4', 2, 60, 65, baseUri),
ManifestParser.makeReference('s3.mp4', 3, 65, 73, baseUri)
];
Dash.testSegmentIndex(done, source, references);
});
Expand Down Expand Up @@ -296,10 +301,10 @@ describe('DashParser SegmentList', function() {
'</MPD>'
].join('\n');
var references = [
Dash.makeReference('s1.mp4', 1, 40, 50),
Dash.makeReference('s2.mp4', 2, 50, 55),
Dash.makeReference('s3.mp4', 3, 55, 63),
Dash.makeReference('s4.mp4', 4, 63, 70)
ManifestParser.makeReference('s1.mp4', 1, 40, 50, baseUri),
ManifestParser.makeReference('s2.mp4', 2, 50, 55, baseUri),
ManifestParser.makeReference('s3.mp4', 3, 55, 63, baseUri),
ManifestParser.makeReference('s4.mp4', 4, 63, 70, baseUri)
];

Dash.testSegmentIndex(done, source, references);
Expand Down
Loading

0 comments on commit 051531b

Please sign in to comment.