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

Commit 685dfdf

Browse files
committed
Merge branch 'release/1.14.0'
2 parents f1b61eb + f8cc8cd commit 685dfdf

23 files changed

+305
-262
lines changed

.travis.yml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ branches:
1313
- /(release).*/
1414
stages:
1515
- build
16+
- deploy
1617
- name: test
1718
# Run test stage only if cron job
1819
if: type = cron
@@ -25,11 +26,7 @@ env:
2526
- BROWSER=edge
2627
# - BROWSER=firefox
2728
before_install:
28-
- openssl aes-256-cbc -K $encrypted_f186f3e7458a_key -iv $encrypted_f186f3e7458a_iv -in travis_deploy.enc -out travis_deploy -d
2929
- npm install -g gulp
30-
- chmod 600 travis_deploy
31-
- eval `ssh-agent -s`
32-
- ssh-add travis_deploy
3330
install:
3431
- npm install
3532
jobs:
@@ -40,12 +37,19 @@ jobs:
4037
- npm run build
4138
# Build/generate the jsdoc
4239
- npm run doc
43-
# Package and deploy version on project's pages
44-
- npm run deploy
40+
- |
41+
if [ "$TRAVIS_BRANCH" == "master" ] || [ "$TRAVIS_BRANCH" == "development" ]; then
42+
# Package and deploy version on project's pages
43+
openssl aes-256-cbc -K $encrypted_f186f3e7458a_key -iv $encrypted_f186f3e7458a_iv -in travis_deploy.enc -out travis_deploy -d
44+
chmod 600 travis_deploy
45+
eval `ssh-agent -s`
46+
ssh-add travis_deploy
47+
npm run deploy
48+
fi
4549
deploy:
4650
api_key:
4751
secure: fLr/s6xT5T2mh2UaPUtt3UlkdmvRkqzOlolJss3c6OICeFegFmx/ieuf8iACnB5u3fZ1pgY9/wIXq9f6uKUpTsDQd/B0uALpe/Nzv/OFGkC1S8qk66Z9VC4/LNkDSEOryAKDDPwMgcZgxyPe5u20NrVUKahMB0B4vhYKwGle5LQ=
4852
on:
4953
branch: master
5054
tags: true
51-
skip_cleanup: true
55+
skip_cleanup: true

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ In the case of protected content, here is an example illustrating setting of the
117117
laURL: "<licenser_url>",
118118
withCredentials: "<license_request_withCredentials_value (true or false)>",
119119
cdmData: "<CDM_specific_data>", // Supported by PlayReady key system (using MS-prefixed EME API) only
120-
pssh: "<pssh (as Base64 string)>" // Considered for Widevine key system only
121120
serverCertificate: "<license_server_certificate (as Base64 string)>"
122121
audioRobustness: "<audio_robustness_level>" // Considered for Widevine key system only
123122
videoRobustness: "<video_robustness_level>" // Considered for Widevine key system only

RELEASES NOTES.txt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1+
### Release Notes v1.14.0 (2018/02/08)
2+
* [MSS] Add automatic Widevine pssh generation [#216]
3+
* [MSS] Detect PlayReady messages encoding [#207]
4+
* Avoid seeking to stream duration [#219]
5+
* Bugs fixing:
6+
* - Do not remove past buffers for generic WebKit [#205]
7+
* - Fix ArrayBuffer.isView method implementation [#206]
8+
* - Fix initData type passing to CDM for ProtectionModel_01b [#208]
9+
* - Perform null check on playBackQuality [#211]
10+
* - [MSS] Fix for live stream with only one entry in tfrf box [#215]
11+
112
### Release Notes v1.13.1 (2017/12/01)
213
* Bugs fixing:
314
* - Fix regression on segment download error management
415

516
### Release Notes v1.13.0 (2017/11/09)
6-
* [MSS] Enhanced support for live start-over streams, processed as 'static' streams) [#196]
17+
* [MSS] Enhanced support for live start-over streams, processed as 'static' streams [#196]
718
* [MSS] Add support for chunk 'r' (repeat) attribute [#198]
819
* Bugs fixing:
920
* - Bug fix on metrics persistence [#192]

app/js/hls/HlsStream.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ Hls.dependencies.HlsStream = function() {
236236
getCertificate = function () {
237237
var protData = getKsProtectionData('com.apple.fps.1_0');
238238
if (!protData || !protData.serverCertificate) {
239-
return [];
239+
return new Uint8Array(0);
240240
}
241241
return BASE64.decodeArray(protData.serverCertificate);
242242
},

app/js/mss/MssFragmentController.js

Lines changed: 69 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -18,72 +18,76 @@ Mss.dependencies.MssFragmentController = function() {
1818

1919
var processTfrf = function(request, tfrf, tfdt, adaptation) {
2020
var manifest = this.manifestModel.getValue(),
21-
segmentsUpdated = false,
2221
segments = adaptation.SegmentTemplate.SegmentTimeline.S_asArray,
2322
timescale = adaptation.SegmentTemplate.timescale,
2423
entries = tfrf.entry,
24+
entry,
2525
segment = null,
2626
segmentTime,
2727
t = 0,
28-
i = 0,
2928
availabilityStartTime = null,
3029
type = adaptation.type,
3130
range;
3231

33-
// Process tfrf only for live streams
32+
// Process tfrf only for live or start-over streams
3433
if (!this.manifestExt.getIsDynamic(manifest) && !this.manifestExt.getIsStartOver(manifest)) {
3534
return;
3635
}
3736

38-
// Go through tfrf entries
37+
if (entries.length === 0) {
38+
return;
39+
}
40+
41+
// Consider only first tfrf entry (to avoid pre-condition failure on fragment info requests)
42+
entry = entries[0];
43+
3944
// !! For tfrf fragment_absolute_time and fragment_duration are returned as goog.math.Long values (see mp4lib)
40-
while (i < entries.length) {
41-
// Check if time is not greater than Number.MAX_SAFE_INTEGER (2^53-1), see MssParser
42-
// => fragment_absolute_timeManifest = original timestamp value as a string (for constructing the fragment request url, see DashHandler)
43-
// => fragment_absolute_time = number value of timestamp (maybe rounded value, but only for 0.1 microsecond)
44-
if (entries[i].fragment_absolute_time.greaterThan(goog.math.Long.fromNumber(Number.MAX_SAFE_INTEGER))) {
45-
entries[i].fragment_absolute_timeManifest = entries[i].fragment_absolute_time.toString();
46-
}
4745

48-
// Convert goog.math.Long to Number values
49-
entries[i].fragment_absolute_time = entries[i].fragment_absolute_time.toNumber();
50-
entries[i].fragment_duration = entries[i].fragment_duration.toNumber();
51-
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-
}
46+
// Check if time is not greater than Number.MAX_SAFE_INTEGER (2^53-1), see MssParser
47+
// => fragment_absolute_timeManifest = original timestamp value as a string (for constructing the fragment request url, see DashHandler)
48+
// => fragment_absolute_time = number value of timestamp (maybe rounded value, but only for 0.1 microsecond)
49+
if (entry.fragment_absolute_time.greaterThan(goog.math.Long.fromNumber(Number.MAX_SAFE_INTEGER))) {
50+
entry.fragment_absolute_timeManifest = entry.fragment_absolute_time.toString();
51+
}
6152

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));
67-
segment = {};
68-
segment.t = entries[i].fragment_absolute_time;
69-
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
75-
if (entries[i].fragment_absolute_timeManifest) {
76-
segment.tManifest = entries[i].fragment_absolute_timeManifest;
77-
} else if (segments[0].tManifest) {
78-
segment.tManifest = entries[i].fragment_absolute_time;
79-
}
80-
segments.push(segment);
81-
segmentsUpdated = true;
82-
}
53+
// Convert goog.math.Long to Number values
54+
entry.fragment_absolute_time = entry.fragment_absolute_time.toNumber();
55+
entry.fragment_duration = entry.fragment_duration.toNumber();
56+
57+
// In case of start-over streams, check if we have reached end of original manifest duration (set in timeShiftBufferDepth)
58+
// => then do not update anymore timeline
59+
if (this.manifestExt.getIsStartOver(manifest)) {
60+
// Get first segment time
61+
segmentTime = segments[0].tManifest ? parseFloat(segments[0].tManifest) : segments[0].t;
62+
if (entry.fragment_absolute_time > (segmentTime + (manifest.timeShiftBufferDepth * timescale))) {
63+
return;
64+
}
65+
}
66+
67+
// Get last segment time
68+
segmentTime = segments[segments.length - 1].tManifest ? parseFloat(segments[segments.length - 1].tManifest) : segments[segments.length - 1].t;
8369

84-
i += 1;
70+
// Check if we have to append new segment to timeline
71+
if (entry.fragment_absolute_time <= segmentTime) {
72+
return;
8573
}
8674

75+
this.debug.log("[MssFragmentController][" + type + "] Add new segment - t = " + (entry.fragment_absolute_time / timescale));
76+
segment = {};
77+
segment.t = entry.fragment_absolute_time;
78+
segment.d = entry.fragment_duration;
79+
// If timestamps starts at 0 relative to 1st segment (dynamic to static) then update segment time
80+
if (segments[0].tManifest) {
81+
segment.t -= parseFloat(segments[0].tManifest) - segments[0].t;
82+
}
83+
// Set tManifest either in case of timestamps greater then 2^53 or in case of dynamic to static streams
84+
if (entry.fragment_absolute_timeManifest) {
85+
segment.tManifest = entry.fragment_absolute_timeManifest;
86+
} else if (segments[0].tManifest) {
87+
segment.tManifest = entry.fragment_absolute_time;
88+
}
89+
segments.push(segment);
90+
8791
// In case of static start-over streams, update content duration
8892
if (this.manifestExt.getIsStartOver(manifest)) {
8993
if (type === 'video') {
@@ -95,48 +99,21 @@ Mss.dependencies.MssFragmentController = function() {
9599
}
96100
return;
97101
}
98-
99-
// Update segment timeline in case the timestamps from tfrf differ from timestamps in Manifest.
100-
// In that case we consider tfrf timing
101-
// var j = 0,
102-
// segmentId = -1,
103-
// for (j = segments.length - 1; j >= 0; j -= 1) {
104-
// if (segments[j].t === tfdt.baseMediaDecodeTime) {
105-
// segmentId = j;
106-
// break;
107-
// }
108-
// }
109-
// if (segmentId >= 0) {
110-
// for (i = 0; i < entries.length; i += 1) {
111-
// if (segmentId + i < segments.length) {
112-
// t = segments[segmentId + i].t;
113-
// if ((t + segments[segmentId + i].d) !== entries[i].fragment_absolute_time) {
114-
// segments[segmentId + i].t = entries[i].fragment_absolute_time;
115-
// segments[segmentId + i].d = entries[i].fragment_duration;
116-
// this.debug.log("[MssFragmentController] Correct tfrf time = " + entries[i].fragment_absolute_time + " and duration = " + entries[i].fragment_duration);
117-
// segmentsUpdated = true;
118-
// }
119-
// }
120-
// }
121-
// }
122-
123-
// Update segment timeline according to DVR window
124-
if (manifest.timeShiftBufferDepth && manifest.timeShiftBufferDepth > 0) {
125-
if (segmentsUpdated) {
126-
// Get timestamp of the last segment
127-
segment = segments[segments.length - 1];
128-
t = segment.t;
129-
130-
// Determine the segments' availability start time
131-
availabilityStartTime = t - (manifest.timeShiftBufferDepth * timescale);
132-
133-
// Remove segments prior to availability start time
102+
// In case of live streams, update segment timeline according to DVR window
103+
else if (manifest.timeShiftBufferDepth && manifest.timeShiftBufferDepth > 0) {
104+
// Get timestamp of the last segment
105+
segment = segments[segments.length - 1];
106+
t = segment.t;
107+
108+
// Determine the segments' availability start time
109+
availabilityStartTime = t - (manifest.timeShiftBufferDepth * timescale);
110+
111+
// Remove segments prior to availability start time
112+
segment = segments[0];
113+
while (segment.t < availabilityStartTime) {
114+
this.debug.log("[MssFragmentController][" + type + "] Remove segment - t = " + (segment.t / timescale));
115+
segments.splice(0, 1);
134116
segment = segments[0];
135-
while (segment.t < availabilityStartTime) {
136-
this.debug.log("[MssFragmentController][" + type + "] Remove segment - t = " + (segment.t / timescale));
137-
segments.splice(0, 1);
138-
segment = segments[0];
139-
}
140117
}
141118

142119
// Update DVR window range => set range's end to end time of current segment
@@ -159,8 +136,7 @@ Mss.dependencies.MssFragmentController = function() {
159136
traf = null,
160137
tfdt = null,
161138
tfrf = null,
162-
pos,
163-
i = 0;
139+
pos;
164140

165141
// Create new fragment
166142
fragment = mp4lib.deserialize(bytes);
@@ -188,9 +164,7 @@ Mss.dependencies.MssFragmentController = function() {
188164
}
189165
};
190166
} else {
191-
for (i = 0; i < tfrf.length; i += 1) {
192-
processTfrf.call(this, request, tfrf[i], tfdt, adaptation);
193-
}
167+
processTfrf.call(this, request, tfrf[0], tfdt, adaptation);
194168
}
195169
},
196170

@@ -354,8 +328,8 @@ Mss.dependencies.MssFragmentController = function() {
354328
traf.boxes.splice(pos + 1, 0, tfdt);
355329
}
356330

357-
// Process tfrf box
358331
if (manifest.type === 'dynamic') {
332+
// Process tfrf box
359333
tfrf = traf.getBoxesByType("tfrf");
360334
if (tfrf === null || tfrf.length === 0) {
361335
throw {
@@ -366,10 +340,8 @@ Mss.dependencies.MssFragmentController = function() {
366340
}
367341
};
368342
} else {
369-
for (i = 0; i < tfrf.length; i += 1) {
370-
processTfrf.call(this, request, tfrf[i], tfdt, adaptation);
371-
traf.removeBoxByType("tfrf");
372-
}
343+
processTfrf.call(this, request, tfrf[0], tfdt, adaptation);
344+
traf.removeBoxByType("tfrf");
373345
}
374346
}
375347

app/js/mss/MssFragmentInfoController.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,16 @@ Mss.dependencies.MssFragmentInfoController = function() {
5252
return Q.when(null);
5353
},
5454

55-
start = function() {
55+
start = function(delay) {
5656
if (!_ready || _started) {
5757
return;
5858
}
5959

6060
this.debug.info("[MssFragmentInfoController][" + _type + "] START");
6161
_started = true;
62-
_startTime = new Date().getTime();
62+
_startTime = new Date().getTime() + delay * 1000;
6363

64-
loadNextFragmentInfo.call(this);
64+
delayLoadNextFragmentInfo.call(this, delay);
6565
},
6666

6767
stop = function() {
@@ -86,8 +86,7 @@ Mss.dependencies.MssFragmentInfoController = function() {
8686

8787
var adaptation = _bufferController.getData(),
8888
segments = adaptation.SegmentTemplate.SegmentTimeline.S_asArray,
89-
// tak before last segment to avoid precondition failed (412) errors
90-
segment = segments[segments.length - 2],
89+
segment = segments[segments.length - 1],
9190
representation = adaptation.Representation_asArray[0],
9291
request;
9392

0 commit comments

Comments
 (0)