shaka-player 4.0.4 → 4.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -34
- package/CONTRIBUTORS +1 -0
- package/demo/common/message_ids.js +1 -0
- package/demo/config.js +3 -1
- package/demo/locales/en.json +1 -0
- package/demo/locales/source.json +4 -0
- package/dist/demo.compiled.debug.js +4 -4
- package/dist/demo.compiled.debug.map +2 -2
- package/dist/demo.compiled.js +4 -4
- package/dist/demo.compiled.map +2 -2
- package/dist/deps.js +2 -2
- package/dist/locales.js +30 -30
- package/dist/receiver.compiled.debug.js +2 -2
- package/dist/receiver.compiled.debug.map +2 -2
- package/dist/receiver.compiled.js +2 -2
- package/dist/receiver.compiled.map +2 -2
- package/dist/shaka-player.compiled.d.ts +14 -8
- package/dist/shaka-player.compiled.debug.d.ts +14 -8
- package/dist/shaka-player.compiled.debug.externs.js +10 -2
- package/dist/shaka-player.compiled.debug.js +168 -160
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +10 -2
- package/dist/shaka-player.compiled.js +767 -764
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +15 -9
- package/dist/shaka-player.ui.debug.d.ts +15 -9
- package/dist/shaka-player.ui.debug.externs.js +10 -2
- package/dist/shaka-player.ui.debug.js +201 -189
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +10 -2
- package/dist/shaka-player.ui.js +934 -931
- package/dist/shaka-player.ui.map +3 -3
- package/docs/design/chromecast.md +3 -1
- package/docs/tutorials/drm-config.md +16 -0
- package/docs/tutorials/ui.md +26 -0
- package/externs/chromecast.js +9 -2
- package/externs/shaka/manifest.js +7 -0
- package/externs/shaka/player.js +21 -2
- package/externs/shaka/text.js +7 -0
- package/lib/cast/cast_proxy.js +19 -8
- package/lib/cast/cast_receiver.js +3 -3
- package/lib/cast/cast_sender.js +12 -2
- package/lib/hls/hls_parser.js +12 -1
- package/lib/media/drm_engine.js +17 -8
- package/lib/media/gap_jumping_controller.js +23 -1
- package/lib/media/playhead.js +47 -4
- package/lib/media/stall_detector.js +19 -2
- package/lib/media/streaming_engine.js +8 -1
- package/lib/offline/manifest_converter.js +1 -0
- package/lib/player.js +175 -69
- package/lib/text/cue.js +6 -0
- package/lib/text/ui_text_displayer.js +1 -0
- package/lib/text/vtt_text_parser.js +4 -0
- package/lib/util/error.js +6 -0
- package/lib/util/fake_event.js +39 -0
- package/lib/util/player_configuration.js +2 -0
- package/lib/util/stats.js +28 -1
- package/lib/util/stream_utils.js +7 -0
- package/package.json +1 -1
- package/test/cast/cast_proxy_unit.js +3 -1
- package/test/cast/cast_sender_unit.js +21 -6
- package/test/demo/demo_unit.js +2 -1
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/playhead_unit.js +114 -25
- package/test/media/stall_detector_unit.js +20 -2
- package/test/media/streaming_engine_integration.js +2 -1
- package/test/media/streaming_engine_unit.js +1 -0
- package/test/player_integration.js +3 -0
- package/test/player_unit.js +142 -1
- package/test/test/util/manifest_generator.js +2 -0
- package/test/test/util/simple_fakes.js +14 -0
- package/test/test/util/streaming_engine_util.js +1 -0
- package/test/text/vtt_text_parser_unit.js +4 -0
- package/test/ui/ui_unit.js +18 -5
- package/test/util/stream_utils_unit.js +108 -0
- package/ui/controls.js +12 -8
- package/ui/externs/ui.js +10 -1
- package/ui/statistics_button.js +10 -0
- package/ui/ui.js +12 -1
package/lib/util/fake_event.js
CHANGED
|
@@ -144,3 +144,42 @@ shaka.util.FakeEvent = class {
|
|
|
144
144
|
*/
|
|
145
145
|
stopPropagation() {}
|
|
146
146
|
};
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* An internal enum that contains the string values of all of the player events.
|
|
151
|
+
* This exists primarily to act as an implicit list of events, for tests.
|
|
152
|
+
*
|
|
153
|
+
* @enum {string}
|
|
154
|
+
*/
|
|
155
|
+
shaka.util.FakeEvent.EventName = {
|
|
156
|
+
AbrStatusChanged: 'abrstatuschanged',
|
|
157
|
+
Adaptation: 'adaptation',
|
|
158
|
+
Buffering: 'buffering',
|
|
159
|
+
DownloadFailed: 'downloadfailed',
|
|
160
|
+
DownloadHeadersReceived: 'downloadheadersreceived',
|
|
161
|
+
DrmSessionUpdate: 'drmsessionupdate',
|
|
162
|
+
Emsg: 'emsg',
|
|
163
|
+
Error: 'error',
|
|
164
|
+
ExpirationUpdated: 'expirationupdated',
|
|
165
|
+
GapJumped: 'gapjumped',
|
|
166
|
+
Loaded: 'loaded',
|
|
167
|
+
Loading: 'loading',
|
|
168
|
+
ManifestParsed: 'manifestparsed',
|
|
169
|
+
MediaQualityChanged: 'mediaqualitychanged',
|
|
170
|
+
Metadata: 'metadata',
|
|
171
|
+
OnStateChange: 'onstatechange',
|
|
172
|
+
OnStateIdle: 'onstateidle',
|
|
173
|
+
RateChange: 'ratechange',
|
|
174
|
+
SessionDataEvent: 'sessiondata',
|
|
175
|
+
StallDetected: 'stalldetected',
|
|
176
|
+
Streaming: 'streaming',
|
|
177
|
+
TextChanged: 'textchanged',
|
|
178
|
+
TextTrackVisibility: 'texttrackvisibility',
|
|
179
|
+
TimelineRegionAdded: 'timelineregionadded',
|
|
180
|
+
TimelineRegionEnter: 'timelineregionenter',
|
|
181
|
+
TimelineRegionExit: 'timelineregionexit',
|
|
182
|
+
TracksChanged: 'trackschanged',
|
|
183
|
+
Unloading: 'unloading',
|
|
184
|
+
VariantChanged: 'variantchanged',
|
|
185
|
+
};
|
|
@@ -74,6 +74,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
74
74
|
logLicenseExchange: false,
|
|
75
75
|
updateExpirationTime: 1,
|
|
76
76
|
preferredKeySystems: [],
|
|
77
|
+
keySystemsMapping: {},
|
|
77
78
|
};
|
|
78
79
|
|
|
79
80
|
const manifest = {
|
|
@@ -169,6 +170,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
169
170
|
updateIntervalSeconds: 1,
|
|
170
171
|
dispatchAllEmsgBoxes: false,
|
|
171
172
|
observeQualityChanges: false,
|
|
173
|
+
maxDisabledTime: 30,
|
|
172
174
|
};
|
|
173
175
|
|
|
174
176
|
// Some browsers will stop earlier than others before a gap (e.g., Edge
|
package/lib/util/stats.js
CHANGED
|
@@ -31,6 +31,11 @@ shaka.util.Stats = class {
|
|
|
31
31
|
/** @private {number} */
|
|
32
32
|
this.totalCorruptedFrames_ = NaN;
|
|
33
33
|
|
|
34
|
+
/** @private {number} */
|
|
35
|
+
this.totalStallsDetected_ = NaN;
|
|
36
|
+
/** @private {number} */
|
|
37
|
+
this.totalGapsJumped_ = NaN;
|
|
38
|
+
|
|
34
39
|
/** @private {number} */
|
|
35
40
|
this.completionPercent_ = NaN;
|
|
36
41
|
|
|
@@ -76,7 +81,6 @@ shaka.util.Stats = class {
|
|
|
76
81
|
this.totalDecodedFrames_ = decoded;
|
|
77
82
|
}
|
|
78
83
|
|
|
79
|
-
|
|
80
84
|
/**
|
|
81
85
|
* Update corrupted frames. This will replace the previous values.
|
|
82
86
|
*
|
|
@@ -86,6 +90,25 @@ shaka.util.Stats = class {
|
|
|
86
90
|
this.totalCorruptedFrames_ = corrupted;
|
|
87
91
|
}
|
|
88
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Update number of stalls detected. This will replace the previous value.
|
|
95
|
+
*
|
|
96
|
+
* @param {number} stallsDetected
|
|
97
|
+
*/
|
|
98
|
+
setStallsDetected(stallsDetected) {
|
|
99
|
+
this.totalStallsDetected_ = stallsDetected;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Update number of playback gaps jumped over. This will replace the previous
|
|
104
|
+
* value.
|
|
105
|
+
*
|
|
106
|
+
* @param {number} gapsJumped
|
|
107
|
+
*/
|
|
108
|
+
setGapsJumped(gapsJumped) {
|
|
109
|
+
this.totalGapsJumped_ = gapsJumped;
|
|
110
|
+
}
|
|
111
|
+
|
|
89
112
|
/**
|
|
90
113
|
* Set the width and height of the video we are currently playing.
|
|
91
114
|
*
|
|
@@ -208,6 +231,8 @@ shaka.util.Stats = class {
|
|
|
208
231
|
decodedFrames: this.totalDecodedFrames_,
|
|
209
232
|
droppedFrames: this.totalDroppedFrames_,
|
|
210
233
|
corruptedFrames: this.totalCorruptedFrames_,
|
|
234
|
+
stallsDetected: this.totalStallsDetected_,
|
|
235
|
+
gapsJumped: this.totalGapsJumped_,
|
|
211
236
|
estimatedBandwidth: this.bandwidthEstimate_,
|
|
212
237
|
completionPercent: this.completionPercent_,
|
|
213
238
|
loadLatency: this.loadLatencySeconds_,
|
|
@@ -238,6 +263,8 @@ shaka.util.Stats = class {
|
|
|
238
263
|
decodedFrames: NaN,
|
|
239
264
|
droppedFrames: NaN,
|
|
240
265
|
corruptedFrames: NaN,
|
|
266
|
+
stallsDetected: NaN,
|
|
267
|
+
gapsJumped: NaN,
|
|
241
268
|
estimatedBandwidth: NaN,
|
|
242
269
|
completionPercent: NaN,
|
|
243
270
|
loadLatency: NaN,
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -329,6 +329,13 @@ shaka.util.StreamUtils = class {
|
|
|
329
329
|
|
|
330
330
|
const video = variant.video;
|
|
331
331
|
|
|
332
|
+
if (variant.disabledUntilTime != 0) {
|
|
333
|
+
if (variant.disabledUntilTime > Date.now() / 1000) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
variant.disabledUntilTime = 0;
|
|
337
|
+
}
|
|
338
|
+
|
|
332
339
|
// |video.width| and |video.height| can be undefined, which breaks
|
|
333
340
|
// the math, so make sure they are there first.
|
|
334
341
|
if (video && video.width && video.height) {
|
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ describe('CastProxy', () => {
|
|
|
11
11
|
|
|
12
12
|
const originalCastSender = shaka.cast.CastSender;
|
|
13
13
|
const fakeAppId = 'fake app ID';
|
|
14
|
+
const fakeAndroidReceiverCompatible = false;
|
|
14
15
|
|
|
15
16
|
let mockPlayer;
|
|
16
17
|
let mockSender;
|
|
@@ -31,7 +32,8 @@ describe('CastProxy', () => {
|
|
|
31
32
|
mockPlayer = createMockPlayer();
|
|
32
33
|
mockSender = null;
|
|
33
34
|
|
|
34
|
-
proxy = new CastProxy(mockVideo, mockPlayer, fakeAppId
|
|
35
|
+
proxy = new CastProxy(mockVideo, mockPlayer, fakeAppId,
|
|
36
|
+
fakeAndroidReceiverCompatible);
|
|
35
37
|
});
|
|
36
38
|
|
|
37
39
|
afterEach(async () => {
|
|
@@ -13,6 +13,7 @@ describe('CastSender', () => {
|
|
|
13
13
|
const originalStatusDelay = shaka.cast.CastSender.STATUS_DELAY;
|
|
14
14
|
|
|
15
15
|
const fakeAppId = 'asdf';
|
|
16
|
+
const fakeAndroidReceiverCompatible = false;
|
|
16
17
|
const fakeInitState = {
|
|
17
18
|
manifest: null,
|
|
18
19
|
player: null,
|
|
@@ -52,7 +53,8 @@ describe('CastSender', () => {
|
|
|
52
53
|
sender = new CastSender(
|
|
53
54
|
fakeAppId, Util.spyFunc(onStatusChanged),
|
|
54
55
|
Util.spyFunc(onFirstCastStateUpdate), Util.spyFunc(onRemoteEvent),
|
|
55
|
-
Util.spyFunc(onResumeLocal), Util.spyFunc(onInitStateRequired)
|
|
56
|
+
Util.spyFunc(onResumeLocal), Util.spyFunc(onInitStateRequired),
|
|
57
|
+
fakeAndroidReceiverCompatible);
|
|
56
58
|
});
|
|
57
59
|
|
|
58
60
|
afterEach(async () => {
|
|
@@ -87,7 +89,12 @@ describe('CastSender', () => {
|
|
|
87
89
|
expect(sender.apiReady()).toBe(true);
|
|
88
90
|
expect(sender.hasReceivers()).toBe(false);
|
|
89
91
|
expect(onStatusChanged).toHaveBeenCalled();
|
|
90
|
-
expect(mockCastApi.SessionRequest).toHaveBeenCalledWith(
|
|
92
|
+
expect(mockCastApi.SessionRequest).toHaveBeenCalledWith(
|
|
93
|
+
fakeAppId,
|
|
94
|
+
/* capabilities= */ [],
|
|
95
|
+
/* timeout= */ null,
|
|
96
|
+
fakeAndroidReceiverCompatible,
|
|
97
|
+
/* credentialsData= */ null);
|
|
91
98
|
expect(mockCastApi.initialize).toHaveBeenCalled();
|
|
92
99
|
});
|
|
93
100
|
|
|
@@ -97,7 +104,12 @@ describe('CastSender', () => {
|
|
|
97
104
|
expect(sender.apiReady()).toBe(true);
|
|
98
105
|
expect(sender.hasReceivers()).toBe(false);
|
|
99
106
|
expect(onStatusChanged).toHaveBeenCalled();
|
|
100
|
-
expect(mockCastApi.SessionRequest).toHaveBeenCalledWith(
|
|
107
|
+
expect(mockCastApi.SessionRequest).toHaveBeenCalledWith(
|
|
108
|
+
fakeAppId,
|
|
109
|
+
/* capabilities= */ [],
|
|
110
|
+
/* timeout= */ null,
|
|
111
|
+
fakeAndroidReceiverCompatible,
|
|
112
|
+
/* credentialsData= */ null);
|
|
101
113
|
expect(mockCastApi.initialize).toHaveBeenCalled();
|
|
102
114
|
});
|
|
103
115
|
});
|
|
@@ -122,7 +134,8 @@ describe('CastSender', () => {
|
|
|
122
134
|
sender = new CastSender(
|
|
123
135
|
fakeAppId, Util.spyFunc(onStatusChanged),
|
|
124
136
|
Util.spyFunc(onFirstCastStateUpdate), Util.spyFunc(onRemoteEvent),
|
|
125
|
-
Util.spyFunc(onResumeLocal), Util.spyFunc(onInitStateRequired)
|
|
137
|
+
Util.spyFunc(onResumeLocal), Util.spyFunc(onInitStateRequired),
|
|
138
|
+
/* androidReceiverCompatible= */ false);
|
|
126
139
|
sender.init();
|
|
127
140
|
// You get an initial call to onStatusChanged when it initializes.
|
|
128
141
|
expect(onStatusChanged).toHaveBeenCalledTimes(3);
|
|
@@ -256,7 +269,8 @@ describe('CastSender', () => {
|
|
|
256
269
|
sender = new CastSender(
|
|
257
270
|
fakeAppId, Util.spyFunc(onStatusChanged),
|
|
258
271
|
Util.spyFunc(onFirstCastStateUpdate), Util.spyFunc(onRemoteEvent),
|
|
259
|
-
Util.spyFunc(onResumeLocal), Util.spyFunc(onInitStateRequired)
|
|
272
|
+
Util.spyFunc(onResumeLocal), Util.spyFunc(onInitStateRequired),
|
|
273
|
+
/* androidReceiverCompatible= */ false);
|
|
260
274
|
sender.init();
|
|
261
275
|
|
|
262
276
|
// The sender should automatically rejoin the session, without needing
|
|
@@ -288,7 +302,8 @@ describe('CastSender', () => {
|
|
|
288
302
|
sender = new CastSender(
|
|
289
303
|
fakeAppId, Util.spyFunc(onStatusChanged),
|
|
290
304
|
Util.spyFunc(onFirstCastStateUpdate), Util.spyFunc(onRemoteEvent),
|
|
291
|
-
Util.spyFunc(onResumeLocal), Util.spyFunc(onInitStateRequired)
|
|
305
|
+
Util.spyFunc(onResumeLocal), Util.spyFunc(onInitStateRequired),
|
|
306
|
+
/* androidReceiverCompatible= */ false);
|
|
292
307
|
sender.init();
|
|
293
308
|
|
|
294
309
|
expect(sender.isCasting()).toBe(false);
|
package/test/demo/demo_unit.js
CHANGED
|
@@ -94,7 +94,8 @@ describe('Demo', () => {
|
|
|
94
94
|
.add('playRangeStart')
|
|
95
95
|
.add('playRangeEnd')
|
|
96
96
|
.add('manifest.dash.keySystemsByURI')
|
|
97
|
-
.add('manifest.hls.mediaPlaylistFullMimeType')
|
|
97
|
+
.add('manifest.hls.mediaPlaylistFullMimeType')
|
|
98
|
+
.add('drm.keySystemsMapping');
|
|
98
99
|
|
|
99
100
|
/**
|
|
100
101
|
* @param {!Object} section
|