Skip to content
This repository was archived by the owner on Oct 20, 2022. It is now read-only.

Commit 6258466

Browse files
committed
Merge branch 'release/1.13.0'
2 parents 5fd4695 + bd4d4dd commit 6258466

File tree

195 files changed

+914
-241292
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+914
-241292
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ node_modules
1313
npm-debug.log
1414

1515
#################
16-
## Grunt
16+
## Gulp
1717
#################
1818

19-
.grunt
19+
doc/jsdoc
2020
_SpecRunner.html
2121
reports
2222

.travis.yml

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,51 @@
11
language: node_js
2-
branches:
3-
only:
4-
- master
5-
- development
6-
- /(release).*/
7-
env:
8-
global:
9-
- ENCRYPTION_LABEL: 98a7d362e1e4
10-
matrix:
11-
- BUILD=true TEST=false
12-
- BUILD=false TEST=true BROWSER=chrome
13-
- BUILD=false TEST=true BROWSER=ie
14-
- BUILD=false TEST=true BROWSER=edge
15-
- BUILD=false TEST=true BROWSER=firefox
162
node_js:
17-
- stable
3+
- stable
184
addons:
19-
browserstack:
20-
username: "bertrandberthelo1"
21-
access_key:
22-
secure: "kB8iXiydT+xheyHox2zwq/1k75uUmF+F2b9k76Nhbb001Mh5608kzhH9xXFM+BUyM1pm3LImF+vYcSfKMYlDn/KBB7s9p8TJfwC/obbmtWJucSjtRiVo9aOOa7Ox2M+ACb0rsLpvzFRiHtYo0HZNFVkIfvqZN389Imm6UCOXsyo="
5+
browserstack:
6+
username: "bertrandberthelo1"
7+
access_key:
8+
secure: "kB8iXiydT+xheyHox2zwq/1k75uUmF+F2b9k76Nhbb001Mh5608kzhH9xXFM+BUyM1pm3LImF+vYcSfKMYlDn/KBB7s9p8TJfwC/obbmtWJucSjtRiVo9aOOa7Ox2M+ACb0rsLpvzFRiHtYo0HZNFVkIfvqZN389Imm6UCOXsyo="
9+
branches:
10+
only:
11+
- master
12+
- development
13+
- /(release).*/
14+
stages:
15+
- build
16+
- name: test
17+
# Run test stage only if cron job
18+
if: type = cron
19+
env:
20+
global:
21+
- ENCRYPTION_LABEL: 98a7d362e1e4
22+
matrix:
23+
- BROWSER=chrome
24+
- BROWSER=ie
25+
- BROWSER=edge
26+
# - BROWSER=firefox
2327
before_install:
24-
- openssl aes-256-cbc -K $encrypted_98a7d362e1e4_key -iv $encrypted_98a7d362e1e4_iv -in travis_deploy.enc -out travis_deploy -d
25-
- npm install -g gulp
26-
- chmod 600 travis_deploy
27-
- eval `ssh-agent -s`
28-
- ssh-add travis_deploy
28+
- openssl aes-256-cbc -K $encrypted_f186f3e7458a_key -iv $encrypted_f186f3e7458a_iv -in travis_deploy.enc -out travis_deploy -d
29+
- npm install -g gulp
30+
- chmod 600 travis_deploy
31+
- eval `ssh-agent -s`
32+
- ssh-add travis_deploy
2933
install:
30-
- npm install
31-
script:
32-
- if [[ "$BUILD" = "true" ]]; then npm run build ; fi
33-
- if [[ "$BUILD" = "true" ]]; then npm run deploy ; fi
34-
- if [[ "$BUILD" = "true" ]]; then npm run dist ; fi
35-
- if [[ "$TEST" = "true" && "$TRAVIS_BRANCH" != "master" && "$TRAVIS_BRANCH" != "development" ]]; then npm test ; fi
34+
- npm install
35+
jobs:
36+
include:
37+
- stage: build
38+
script:
39+
# Build the source files
40+
- npm run build
41+
# Build/generate the jsdoc
42+
- npm run doc
43+
# Package and deploy version on project's pages
44+
- npm run deploy
45+
deploy:
46+
api_key:
47+
secure: fLr/s6xT5T2mh2UaPUtt3UlkdmvRkqzOlolJss3c6OICeFegFmx/ieuf8iACnB5u3fZ1pgY9/wIXq9f6uKUpTsDQd/B0uALpe/Nzv/OFGkC1S8qk66Z9VC4/LNkDSEOryAKDDPwMgcZgxyPe5u20NrVUKahMB0B4vhYKwGle5LQ=
48+
on:
49+
branch: master
50+
tags: true
51+
skip_cleanup: true

RELEASES NOTES.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
### Release Notes v1.13.0 (2017/11/09)
2+
* [MSS] Enhanced support for live start-over streams, processed as 'static' streams) [#196]
3+
* [MSS] Add support for chunk 'r' (repeat) attribute [#198]
4+
* Bugs fixing:
5+
* - Bug fix on metrics persistence [#192]
6+
* - Bug fix on audio track switch [#193]
7+
* - Bug fix for video freeze after pause/resume [#195]
8+
* - [HLS] Bug fix in playlist parsing (segments list update) [#199]
9+
110
### Release Notes v1.12.0 (2017/10/02)
211
* [MSS] Add support for start-over streams
312
* Add keyboard shorcut to display version number (in debug console)

app/js/dash/DashHandler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ Dash.dependencies.DashHandler = function() {
359359
}
360360
}
361361

362-
if (!isAvailableSegmentNumberCalculated) {
362+
if (true/*!isAvailableSegmentNumberCalculated*/) {
363363
var availabilityStartTime,
364364
availabilityEndTime,
365365
f = fragments[0];

app/js/dash/DashManifestExtensions.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ Dash.dependencies.DashManifestExtensions = function() {
2121
Dash.dependencies.DashManifestExtensions.prototype = {
2222
constructor: Dash.dependencies.DashManifestExtensions,
2323

24+
isInteger: Number.isInteger || function (value) {
25+
return typeof value === 'number' &&
26+
isFinite(value) &&
27+
Math.floor(value) === value;
28+
},
29+
2430
getIsType: function(adaptation, type, mimeTypes) {
2531
"use strict";
2632
var i, j,
@@ -400,6 +406,17 @@ Dash.dependencies.DashManifestExtensions.prototype = {
400406
return isOnDemand;
401407
},
402408

409+
getIsStartOver: function(manifest) {
410+
"use strict";
411+
var isStartOver = false;
412+
413+
if (manifest && manifest.hasOwnProperty("startOver")) {
414+
isStartOver = (manifest.startOver === true);
415+
}
416+
417+
return isStartOver;
418+
},
419+
403420
getDuration: function(manifest) {
404421
var mpdDuration;
405422

@@ -416,7 +433,7 @@ Dash.dependencies.DashManifestExtensions.prototype = {
416433

417434
getBandwidth: function(representation) {
418435
"use strict";
419-
return representation.bandwidth;
436+
return representation && representation.bandwidth ? representation.bandwidth : NaN;
420437
},
421438

422439
getRefreshDelay: function(manifest) {
@@ -442,7 +459,8 @@ Dash.dependencies.DashManifestExtensions.prototype = {
442459

443460
getRepresentationFor: function(index, data) {
444461
"use strict";
445-
return data.Representation_asArray[index];
462+
return data && data.Representation_asArray && data.Representation_asArray.length > 0 &&
463+
this.isInteger(index) && index < data.Representation_asArray.length ? data.Representation_asArray[index] : null;
446464
},
447465

448466
getRepresentationsForAdaptation: function(manifest, adaptation) {

app/js/hls/HlsParser.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,18 +246,27 @@ Hls.dependencies.HlsParser = function() {
246246
removeSegments(segments, segmentList.startNumber);
247247

248248
// Correct segments timeline according to previous segment list (in case of variant stream switching)
249-
if (adaptation.segments) {
249+
if (adaptation.segments && adaptation.segments.length > 0) {
250250
// Align segment list according to sequence number
251251
removeSegments(segments, adaptation.segments[0].sequenceNumber);
252-
removeSegments(adaptation.segments, segments[0].sequenceNumber);
253-
if (segments[0].time !== adaptation.segments[0].time) {
254-
segments[0].time = adaptation.segments[0].time;
255-
for (i = 1; i < segments.length; i++) {
256-
segments[i].time = segments[i - 1].time + segments[i - 1].duration;
252+
if (segments.length > 0) {
253+
removeSegments(adaptation.segments, segments[0].sequenceNumber);
254+
if (adaptation.segments.length > 0) {
255+
if (segments[0].time !== adaptation.segments[0].time) {
256+
segments[0].time = adaptation.segments[0].time;
257+
for (i = 1; i < segments.length; i++) {
258+
segments[i].time = segments[i - 1].time + segments[i - 1].duration;
259+
}
260+
}
257261
}
258262
}
259263
}
260264

265+
// segment list from manifest may be empty (or shifted/desynchronized from previous playlists)
266+
if (segments.length === 0) {
267+
return true;
268+
}
269+
261270
adaptation.segments = segments;
262271

263272
var range = {
@@ -338,7 +347,7 @@ Hls.dependencies.HlsParser = function() {
338347
for (j = 0; j < adaptation.Representation_asArray.length; j++) {
339348
if (adaptation.Representation_asArray[j].SegmentList) {
340349
var segments = adaptation.Representation_asArray[j].SegmentList.SegmentURL_asArray;
341-
if (segments[0].sequenceNumber < maxSequenceNumber) {
350+
if (segments.length > 0 && segments[0].sequenceNumber < maxSequenceNumber) {
342351
removeSegments(segments, maxSequenceNumber);
343352
if (segments.length > 0) {
344353
segments[0].time = 0;
@@ -557,7 +566,7 @@ Hls.dependencies.HlsParser = function() {
557566

558567
// Alternative renditions of the same content (alternative audio tracks or subtitles) #EXT-X-MEDIA
559568
medias = getMedias(manifest);
560-
for (i =0; i < medias.length; i++) {
569+
for (i = 0; i < medias.length; i++) {
561570
media = medias[i];
562571
adaptationSet = {
563572
name: 'AdaptationSet',

app/js/mss/MssFragmentController.js

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,19 @@ Mss.dependencies.MssFragmentController = function() {
1919
var processTfrf = function(request, tfrf, tfdt, adaptation) {
2020
var manifest = this.manifestModel.getValue(),
2121
segmentsUpdated = false,
22-
// Get adaptation's segment timeline (always a SegmentTimeline in Smooth Streaming use case)
23-
segments = adaptation.SegmentTemplate.SegmentTimeline.S,
22+
segments = adaptation.SegmentTemplate.SegmentTimeline.S_asArray,
23+
timescale = adaptation.SegmentTemplate.timescale,
2424
entries = tfrf.entry,
2525
segment = null,
26+
segmentTime,
2627
t = 0,
2728
i = 0,
28-
// j = 0,
29-
// segmentId = -1,
3029
availabilityStartTime = null,
30+
type = adaptation.type,
3131
range;
3232

3333
// Process tfrf only for live streams
34-
if (manifest.type !== 'dynamic') {
34+
if (!this.manifestExt.getIsDynamic(manifest) && !this.manifestExt.getIsStartOver(manifest)) {
3535
return;
3636
}
3737

@@ -49,13 +49,33 @@ Mss.dependencies.MssFragmentController = function() {
4949
entries[i].fragment_absolute_time = entries[i].fragment_absolute_time.toNumber();
5050
entries[i].fragment_duration = entries[i].fragment_duration.toNumber();
5151

52-
if (entries[i].fragment_absolute_time > segments[segments.length - 1].t) {
53-
this.debug.log("[MssFragmentController] Add new segment - t = " + (entries[i].fragment_absolute_time / 10000000.0));
52+
// In case of start-over streams, check if we have reached end of original manifest duration (set in timeShiftBufferDepth)
53+
// => then do not update anymore timeline
54+
if (this.manifestExt.getIsStartOver(manifest)) {
55+
// Get first segment time
56+
segmentTime = segments[0].tManifest ? parseFloat(segments[0].tManifest) : segments[0].t;
57+
if (entries[i].fragment_absolute_time > (segmentTime + (manifest.timeShiftBufferDepth * timescale))) {
58+
break;
59+
}
60+
}
61+
62+
// Get last segment time
63+
segmentTime = segments[segments.length - 1].tManifest ? parseFloat(segments[segments.length - 1].tManifest) : segments[segments.length - 1].t;
64+
// Check if we have to append new segment to timeline
65+
if (entries[i].fragment_absolute_time > segmentTime) {
66+
this.debug.log("[MssFragmentController][" + type + "] Add new segment - t = " + (entries[i].fragment_absolute_time / timescale));
5467
segment = {};
5568
segment.t = entries[i].fragment_absolute_time;
5669
segment.d = entries[i].fragment_duration;
70+
// If timestamps starts at 0 relative to 1st segment (dynamic to static) then update segment time
71+
if (segments[0].tManifest) {
72+
segment.t -= parseFloat(segments[0].tManifest) - segments[0].t;
73+
}
74+
// Set tManifest either in case of timestamps greater then 2^53 or in case of dynamic to static streams
5775
if (entries[i].fragment_absolute_timeManifest) {
5876
segment.tManifest = entries[i].fragment_absolute_timeManifest;
77+
} else if (segments[0].tManifest) {
78+
segment.tManifest = entries[i].fragment_absolute_time;
5979
}
6080
segments.push(segment);
6181
segmentsUpdated = true;
@@ -64,8 +84,22 @@ Mss.dependencies.MssFragmentController = function() {
6484
i += 1;
6585
}
6686

87+
// In case of static start-over streams, update content duration
88+
if (this.manifestExt.getIsStartOver(manifest)) {
89+
if (type === 'video') {
90+
segment = segments[segments.length - 1];
91+
var end = (segment.t + segment.d) / timescale;
92+
if (end > this.videoModel.getDuration()) {
93+
this.system.notify("sourceDurationChanged", end);
94+
}
95+
}
96+
return;
97+
}
98+
6799
// Update segment timeline in case the timestamps from tfrf differ from timestamps in Manifest.
68100
// In that case we consider tfrf timing
101+
// var j = 0,
102+
// segmentId = -1,
69103
// for (j = segments.length - 1; j >= 0; j -= 1) {
70104
// if (segments[j].t === tfdt.baseMediaDecodeTime) {
71105
// segmentId = j;
@@ -88,18 +122,18 @@ Mss.dependencies.MssFragmentController = function() {
88122

89123
// Update segment timeline according to DVR window
90124
if (manifest.timeShiftBufferDepth && manifest.timeShiftBufferDepth > 0) {
91-
if (segmentsUpdated && manifest.startOver !== true) {
125+
if (segmentsUpdated) {
92126
// Get timestamp of the last segment
93127
segment = segments[segments.length - 1];
94128
t = segment.t;
95129

96130
// Determine the segments' availability start time
97-
availabilityStartTime = t - (manifest.timeShiftBufferDepth * 10000000);
131+
availabilityStartTime = t - (manifest.timeShiftBufferDepth * timescale);
98132

99133
// Remove segments prior to availability start time
100134
segment = segments[0];
101135
while (segment.t < availabilityStartTime) {
102-
this.debug.log("[MssFragmentController] Remove segment - t = " + (segment.t / 10000000.0));
136+
this.debug.log("[MssFragmentController][" + type + "] Remove segment - t = " + (segment.t / timescale));
103137
segments.splice(0, 1);
104138
segment = segments[0];
105139
}
@@ -116,7 +150,7 @@ Mss.dependencies.MssFragmentController = function() {
116150
}
117151
}
118152

119-
return segmentsUpdated;
153+
return;
120154
},
121155

122156
updateSegmentsList = function(bytes, request, adaptation) {
@@ -413,6 +447,8 @@ Mss.dependencies.MssFragmentController = function() {
413447
rslt.manifestModel = undefined;
414448
rslt.manifestExt = undefined;
415449
rslt.metricsModel = undefined;
450+
rslt.videoModel = undefined;
451+
rslt.mediaSourceExt = undefined;
416452

417453
rslt.process = function(bytes, request, representation) {
418454
var deferred = Q.defer(),

0 commit comments

Comments
 (0)