shaka-player 4.0.2 → 4.1.1
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/AUTHORS +1 -0
- package/CHANGELOG.md +36 -16
- package/CONTRIBUTORS +2 -0
- package/build/test.py +1 -1
- package/demo/common/assets.js +1 -1
- 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/demo/main.js +3 -3
- package/dist/demo.compiled.debug.js +7 -7
- package/dist/demo.compiled.debug.map +2 -2
- package/dist/demo.compiled.js +7 -7
- 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 +3 -3
- package/dist/receiver.compiled.debug.map +2 -2
- package/dist/receiver.compiled.js +3 -3
- 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 +13 -4
- package/dist/shaka-player.compiled.debug.js +296 -282
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +13 -4
- package/dist/shaka-player.compiled.js +781 -773
- package/dist/shaka-player.compiled.map +4 -4
- 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 +13 -4
- package/dist/shaka-player.ui.debug.js +345 -326
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +13 -4
- package/dist/shaka-player.ui.js +955 -949
- package/dist/shaka-player.ui.map +4 -4
- 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 +25 -4
- 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 +189 -69
- 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/segment_index.js +26 -1
- package/lib/media/segment_reference.js +10 -3
- package/lib/media/stall_detector.js +19 -2
- package/lib/media/streaming_engine.js +9 -2
- 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 +8 -0
- package/package.json +2 -2
- 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/hls/hls_parser_unit.js +102 -8
- 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
|
@@ -21,12 +21,15 @@ let TimeRange;
|
|
|
21
21
|
* start: number,
|
|
22
22
|
* waitingAt: number,
|
|
23
23
|
* expectedEndTime: number,
|
|
24
|
+
* expectEvent: boolean,
|
|
24
25
|
* }}
|
|
25
26
|
*
|
|
26
27
|
* @description
|
|
27
28
|
* Parameters for a test where we start playing inside a buffered range and play
|
|
28
29
|
* until the end of the buffer. Then, if we expect it, Playhead should jump
|
|
29
|
-
* to the expected time.
|
|
30
|
+
* to the expected time. We should get a 'stalldetected' event when the Playhead
|
|
31
|
+
* detects a stall through the StallDetector, and a 'gapjumped' event when the
|
|
32
|
+
* Playhead jumps over a gap in the buffered range(s).
|
|
30
33
|
*
|
|
31
34
|
* @property {!Array.<TimeRange>} buffered
|
|
32
35
|
* The buffered ranges for the test.
|
|
@@ -36,6 +39,9 @@ let TimeRange;
|
|
|
36
39
|
* The time to pause at and fire a 'waiting' event.
|
|
37
40
|
* @property {number} expectedEndTime
|
|
38
41
|
* The expected time at the end of the test.
|
|
42
|
+
* @property {boolean} expectEvent
|
|
43
|
+
* If true, expect either the 'stalldetected' or 'gapjumped' event to be
|
|
44
|
+
* fired.
|
|
39
45
|
*/
|
|
40
46
|
let PlayingTestInfo;
|
|
41
47
|
|
|
@@ -47,6 +53,7 @@ let PlayingTestInfo;
|
|
|
47
53
|
* start: number,
|
|
48
54
|
* seekTo: number,
|
|
49
55
|
* expectedEndTime: number,
|
|
56
|
+
* expectEvent: boolean,
|
|
50
57
|
* }}
|
|
51
58
|
*
|
|
52
59
|
* @description
|
|
@@ -65,6 +72,9 @@ let PlayingTestInfo;
|
|
|
65
72
|
* The time to seek to.
|
|
66
73
|
* @property {number} expectedEndTime
|
|
67
74
|
* The expected time at the end of the test.
|
|
75
|
+
* @property {boolean} expectEvent
|
|
76
|
+
* If true, expect either the 'stalldetected' or 'gapjumped' event to be
|
|
77
|
+
* fired.
|
|
68
78
|
*/
|
|
69
79
|
let SeekTestInfo;
|
|
70
80
|
|
|
@@ -87,6 +97,10 @@ describe('Playhead', () => {
|
|
|
87
97
|
/** @type {!jasmine.Spy} */
|
|
88
98
|
let onSeek;
|
|
89
99
|
|
|
100
|
+
// Callback to us from Playhead when an event should be sent to the app.
|
|
101
|
+
/** @type {!jasmine.Spy} */
|
|
102
|
+
let onEvent;
|
|
103
|
+
|
|
90
104
|
beforeAll(() => {
|
|
91
105
|
jasmine.clock().install();
|
|
92
106
|
});
|
|
@@ -100,6 +114,7 @@ describe('Playhead', () => {
|
|
|
100
114
|
timeline = new shaka.test.FakePresentationTimeline();
|
|
101
115
|
|
|
102
116
|
onSeek = jasmine.createSpy('onSeek');
|
|
117
|
+
onEvent = jasmine.createSpy('onEvent');
|
|
103
118
|
|
|
104
119
|
timeline.isLive.and.returnValue(false);
|
|
105
120
|
timeline.getSeekRangeStart.and.returnValue(5);
|
|
@@ -143,7 +158,8 @@ describe('Playhead', () => {
|
|
|
143
158
|
manifest,
|
|
144
159
|
config,
|
|
145
160
|
/* startTime= */ 5,
|
|
146
|
-
Util.spyFunc(onSeek)
|
|
161
|
+
Util.spyFunc(onSeek),
|
|
162
|
+
Util.spyFunc(onEvent));
|
|
147
163
|
|
|
148
164
|
expect(video.currentTime).toBe(5);
|
|
149
165
|
expect(playhead.getTime()).toBe(5);
|
|
@@ -163,7 +179,8 @@ describe('Playhead', () => {
|
|
|
163
179
|
manifest,
|
|
164
180
|
config,
|
|
165
181
|
/* startTime= */ 5,
|
|
166
|
-
Util.spyFunc(onSeek)
|
|
182
|
+
Util.spyFunc(onSeek),
|
|
183
|
+
Util.spyFunc(onEvent));
|
|
167
184
|
|
|
168
185
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
169
186
|
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
@@ -203,7 +220,8 @@ describe('Playhead', () => {
|
|
|
203
220
|
manifest,
|
|
204
221
|
config,
|
|
205
222
|
/* startTime= */ 5,
|
|
206
|
-
Util.spyFunc(onSeek)
|
|
223
|
+
Util.spyFunc(onSeek),
|
|
224
|
+
Util.spyFunc(onEvent));
|
|
207
225
|
|
|
208
226
|
video.on['seeking']();
|
|
209
227
|
expect(playhead.getTime()).toBe(5);
|
|
@@ -221,7 +239,12 @@ describe('Playhead', () => {
|
|
|
221
239
|
timeline.getSeekRangeEnd.and.returnValue(60);
|
|
222
240
|
|
|
223
241
|
playhead = new shaka.media.MediaSourcePlayhead(
|
|
224
|
-
video,
|
|
242
|
+
video,
|
|
243
|
+
manifest,
|
|
244
|
+
config,
|
|
245
|
+
/* startTime= */ 0,
|
|
246
|
+
Util.spyFunc(onSeek),
|
|
247
|
+
Util.spyFunc(onEvent));
|
|
225
248
|
|
|
226
249
|
expect(playhead.getTime()).toBe(0);
|
|
227
250
|
});
|
|
@@ -234,7 +257,12 @@ describe('Playhead', () => {
|
|
|
234
257
|
timeline.getDuration.and.returnValue(60);
|
|
235
258
|
|
|
236
259
|
playhead = new shaka.media.MediaSourcePlayhead(
|
|
237
|
-
video,
|
|
260
|
+
video,
|
|
261
|
+
manifest,
|
|
262
|
+
config,
|
|
263
|
+
/* startTime= */ 60,
|
|
264
|
+
Util.spyFunc(onSeek),
|
|
265
|
+
Util.spyFunc(onEvent));
|
|
238
266
|
|
|
239
267
|
expect(playhead.getTime()).toBe(59); // duration - durationBackoff
|
|
240
268
|
expect(video.currentTime).toBe(59); // duration - durationBackoff
|
|
@@ -248,7 +276,12 @@ describe('Playhead', () => {
|
|
|
248
276
|
timeline.getSeekRangeEnd.and.returnValue(60);
|
|
249
277
|
|
|
250
278
|
playhead = new shaka.media.MediaSourcePlayhead(
|
|
251
|
-
video,
|
|
279
|
+
video,
|
|
280
|
+
manifest,
|
|
281
|
+
config,
|
|
282
|
+
/* startTime= */ -15,
|
|
283
|
+
Util.spyFunc(onSeek),
|
|
284
|
+
Util.spyFunc(onEvent));
|
|
252
285
|
|
|
253
286
|
expect(playhead.getTime()).toBe(45);
|
|
254
287
|
});
|
|
@@ -262,7 +295,12 @@ describe('Playhead', () => {
|
|
|
262
295
|
// If the live stream's playback offset time is not available, start
|
|
263
296
|
// playing from the seek range start time.
|
|
264
297
|
playhead = new shaka.media.MediaSourcePlayhead(
|
|
265
|
-
video,
|
|
298
|
+
video,
|
|
299
|
+
manifest,
|
|
300
|
+
config,
|
|
301
|
+
/* startTime= */ -40,
|
|
302
|
+
Util.spyFunc(onSeek),
|
|
303
|
+
Util.spyFunc(onEvent));
|
|
266
304
|
|
|
267
305
|
expect(playhead.getTime()).toBe(30);
|
|
268
306
|
});
|
|
@@ -273,7 +311,8 @@ describe('Playhead', () => {
|
|
|
273
311
|
manifest,
|
|
274
312
|
config,
|
|
275
313
|
/* startTime= */ 5,
|
|
276
|
-
Util.spyFunc(onSeek)
|
|
314
|
+
Util.spyFunc(onSeek),
|
|
315
|
+
Util.spyFunc(onEvent));
|
|
277
316
|
|
|
278
317
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
279
318
|
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
@@ -305,7 +344,8 @@ describe('Playhead', () => {
|
|
|
305
344
|
manifest,
|
|
306
345
|
config,
|
|
307
346
|
/* startTime= */ null,
|
|
308
|
-
Util.spyFunc(onSeek)
|
|
347
|
+
Util.spyFunc(onSeek),
|
|
348
|
+
Util.spyFunc(onEvent));
|
|
309
349
|
|
|
310
350
|
expect(video.addEventListener).toHaveBeenCalledWith(
|
|
311
351
|
'loadedmetadata', jasmine.any(Function), jasmine.anything());
|
|
@@ -337,7 +377,8 @@ describe('Playhead', () => {
|
|
|
337
377
|
manifest,
|
|
338
378
|
config,
|
|
339
379
|
/* startTime= */ 5,
|
|
340
|
-
Util.spyFunc(onSeek)
|
|
380
|
+
Util.spyFunc(onSeek),
|
|
381
|
+
Util.spyFunc(onEvent));
|
|
341
382
|
|
|
342
383
|
// This has to periodically increment the mock date to allow the onSeeking_
|
|
343
384
|
// handler to seek, if appropriate.
|
|
@@ -496,7 +537,8 @@ describe('Playhead', () => {
|
|
|
496
537
|
manifest,
|
|
497
538
|
config,
|
|
498
539
|
/* startTime= */ 5,
|
|
499
|
-
Util.spyFunc(onSeek)
|
|
540
|
+
Util.spyFunc(onSeek),
|
|
541
|
+
Util.spyFunc(onEvent));
|
|
500
542
|
|
|
501
543
|
setMockDate(0);
|
|
502
544
|
video.on['seeking']();
|
|
@@ -544,7 +586,8 @@ describe('Playhead', () => {
|
|
|
544
586
|
manifest,
|
|
545
587
|
config,
|
|
546
588
|
/* startTime= */ 5,
|
|
547
|
-
Util.spyFunc(onSeek)
|
|
589
|
+
Util.spyFunc(onSeek),
|
|
590
|
+
Util.spyFunc(onEvent));
|
|
548
591
|
|
|
549
592
|
// First, seek to start time.
|
|
550
593
|
video.currentTime = 0;
|
|
@@ -604,7 +647,8 @@ describe('Playhead', () => {
|
|
|
604
647
|
manifest,
|
|
605
648
|
config,
|
|
606
649
|
/* startTime= */ 5,
|
|
607
|
-
Util.spyFunc(onSeek)
|
|
650
|
+
Util.spyFunc(onSeek),
|
|
651
|
+
Util.spyFunc(onEvent));
|
|
608
652
|
expect(currentTime).toBe(1000);
|
|
609
653
|
seekCount = 0;
|
|
610
654
|
|
|
@@ -649,7 +693,8 @@ describe('Playhead', () => {
|
|
|
649
693
|
manifest,
|
|
650
694
|
config,
|
|
651
695
|
/* startTime= */ 5,
|
|
652
|
-
Util.spyFunc(onSeek)
|
|
696
|
+
Util.spyFunc(onSeek),
|
|
697
|
+
Util.spyFunc(onEvent));
|
|
653
698
|
|
|
654
699
|
video.on['seeking']();
|
|
655
700
|
expect(video.currentTime).toBe(5);
|
|
@@ -680,7 +725,8 @@ describe('Playhead', () => {
|
|
|
680
725
|
manifest,
|
|
681
726
|
config,
|
|
682
727
|
/* startTime= */ 5,
|
|
683
|
-
Util.spyFunc(onSeek)
|
|
728
|
+
Util.spyFunc(onSeek),
|
|
729
|
+
Util.spyFunc(onEvent));
|
|
684
730
|
|
|
685
731
|
video.on['seeking']();
|
|
686
732
|
expect(video.currentTime).toBe(5);
|
|
@@ -714,7 +760,8 @@ describe('Playhead', () => {
|
|
|
714
760
|
manifest,
|
|
715
761
|
config,
|
|
716
762
|
/* startTime= */ 30,
|
|
717
|
-
Util.spyFunc(onSeek)
|
|
763
|
+
Util.spyFunc(onSeek),
|
|
764
|
+
Util.spyFunc(onEvent));
|
|
718
765
|
|
|
719
766
|
video.currentTime = 0;
|
|
720
767
|
video.seeking = true;
|
|
@@ -759,7 +806,8 @@ describe('Playhead', () => {
|
|
|
759
806
|
manifest,
|
|
760
807
|
config,
|
|
761
808
|
/* startTime= */ 30,
|
|
762
|
-
Util.spyFunc(onSeek)
|
|
809
|
+
Util.spyFunc(onSeek),
|
|
810
|
+
Util.spyFunc(onEvent));
|
|
763
811
|
|
|
764
812
|
/**
|
|
765
813
|
* Prevent retries on the initial start time seek. This will ensure that
|
|
@@ -798,6 +846,7 @@ describe('Playhead', () => {
|
|
|
798
846
|
buffered: [{start: 0, end: 10}],
|
|
799
847
|
start: 3,
|
|
800
848
|
waitingAt: 10,
|
|
849
|
+
expectEvent: false,
|
|
801
850
|
expectedEndTime: 10,
|
|
802
851
|
});
|
|
803
852
|
|
|
@@ -805,6 +854,7 @@ describe('Playhead', () => {
|
|
|
805
854
|
buffered: [{start: 0, end: 10}, {start: 20, end: 30}],
|
|
806
855
|
start: 24,
|
|
807
856
|
waitingAt: 30,
|
|
857
|
+
expectEvent: false,
|
|
808
858
|
expectedEndTime: 30,
|
|
809
859
|
});
|
|
810
860
|
|
|
@@ -812,6 +862,7 @@ describe('Playhead', () => {
|
|
|
812
862
|
buffered: [{start: 0, end: 10}, {start: 11, end: 20}],
|
|
813
863
|
start: 5,
|
|
814
864
|
waitingAt: 10,
|
|
865
|
+
expectEvent: true,
|
|
815
866
|
expectedEndTime: 11,
|
|
816
867
|
});
|
|
817
868
|
|
|
@@ -820,6 +871,7 @@ describe('Playhead', () => {
|
|
|
820
871
|
[{start: 0, end: 10}, {start: 11, end: 20}, {start: 21, end: 30}],
|
|
821
872
|
start: 5,
|
|
822
873
|
waitingAt: 10,
|
|
874
|
+
expectEvent: true,
|
|
823
875
|
expectedEndTime: 11,
|
|
824
876
|
});
|
|
825
877
|
|
|
@@ -828,6 +880,7 @@ describe('Playhead', () => {
|
|
|
828
880
|
[{start: 0, end: 10}, {start: 11, end: 20}, {start: 21, end: 30}],
|
|
829
881
|
start: 15,
|
|
830
882
|
waitingAt: 20,
|
|
883
|
+
expectEvent: true,
|
|
831
884
|
expectedEndTime: 21,
|
|
832
885
|
});
|
|
833
886
|
}); // with small gaps
|
|
@@ -837,6 +890,7 @@ describe('Playhead', () => {
|
|
|
837
890
|
buffered: [{start: 0, end: 10}, {start: 30, end: 40}],
|
|
838
891
|
start: 5,
|
|
839
892
|
waitingAt: 10,
|
|
893
|
+
expectEvent: true,
|
|
840
894
|
expectedEndTime: 30,
|
|
841
895
|
});
|
|
842
896
|
|
|
@@ -845,6 +899,7 @@ describe('Playhead', () => {
|
|
|
845
899
|
[{start: 0, end: 10}, {start: 30, end: 40}, {start: 50, end: 60}],
|
|
846
900
|
start: 5,
|
|
847
901
|
waitingAt: 10,
|
|
902
|
+
expectEvent: true,
|
|
848
903
|
expectedEndTime: 30,
|
|
849
904
|
});
|
|
850
905
|
|
|
@@ -853,6 +908,7 @@ describe('Playhead', () => {
|
|
|
853
908
|
[{start: 0, end: 10}, {start: 20, end: 30}, {start: 50, end: 60}],
|
|
854
909
|
start: 24,
|
|
855
910
|
waitingAt: 30,
|
|
911
|
+
expectEvent: true,
|
|
856
912
|
expectedEndTime: 50,
|
|
857
913
|
});
|
|
858
914
|
}); // with large gaps
|
|
@@ -867,12 +923,15 @@ describe('Playhead', () => {
|
|
|
867
923
|
video.currentTime = data.start;
|
|
868
924
|
video.readyState = HTMLMediaElement.HAVE_ENOUGH_DATA;
|
|
869
925
|
|
|
926
|
+
onEvent.and.callFake((event) => {});
|
|
927
|
+
|
|
870
928
|
playhead = new shaka.media.MediaSourcePlayhead(
|
|
871
929
|
video,
|
|
872
930
|
manifest,
|
|
873
931
|
config,
|
|
874
932
|
/* startTime= */ data.start,
|
|
875
|
-
Util.spyFunc(onSeek)
|
|
933
|
+
Util.spyFunc(onSeek),
|
|
934
|
+
Util.spyFunc(onEvent));
|
|
876
935
|
|
|
877
936
|
jasmine.clock().tick(500);
|
|
878
937
|
for (let time = data.start; time < data.waitingAt; time++) {
|
|
@@ -893,11 +952,14 @@ describe('Playhead', () => {
|
|
|
893
952
|
expect(video.currentTime).toBe(time + 0.4);
|
|
894
953
|
}
|
|
895
954
|
|
|
955
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
956
|
+
|
|
896
957
|
video.currentTime = data.waitingAt;
|
|
897
958
|
video.readyState = HTMLMediaElement.HAVE_CURRENT_DATA;
|
|
898
959
|
video.on['waiting']();
|
|
899
960
|
jasmine.clock().tick(500);
|
|
900
961
|
|
|
962
|
+
expect(onEvent).toHaveBeenCalledTimes(data.expectEvent ? 1 : 0);
|
|
901
963
|
expect(video.currentTime).toBe(data.expectedEndTime);
|
|
902
964
|
});
|
|
903
965
|
}
|
|
@@ -909,6 +971,7 @@ describe('Playhead', () => {
|
|
|
909
971
|
buffered: [{start: 0, end: 10}],
|
|
910
972
|
start: 4,
|
|
911
973
|
seekTo: 14,
|
|
974
|
+
expectEvent: false,
|
|
912
975
|
expectedEndTime: 14,
|
|
913
976
|
});
|
|
914
977
|
|
|
@@ -916,6 +979,7 @@ describe('Playhead', () => {
|
|
|
916
979
|
buffered: [{start: 0, end: 10}, {start: 11, end: 20}],
|
|
917
980
|
start: 3,
|
|
918
981
|
seekTo: 10.4,
|
|
982
|
+
expectEvent: true,
|
|
919
983
|
expectedEndTime: 11,
|
|
920
984
|
});
|
|
921
985
|
|
|
@@ -924,6 +988,7 @@ describe('Playhead', () => {
|
|
|
924
988
|
[{start: 0, end: 10}, {start: 11, end: 20}, {start: 21, end: 30}],
|
|
925
989
|
start: 3,
|
|
926
990
|
seekTo: 10.4,
|
|
991
|
+
expectEvent: true,
|
|
927
992
|
expectedEndTime: 11,
|
|
928
993
|
});
|
|
929
994
|
|
|
@@ -932,6 +997,7 @@ describe('Playhead', () => {
|
|
|
932
997
|
[{start: 0, end: 10}, {start: 11, end: 20}, {start: 21, end: 30}],
|
|
933
998
|
start: 3,
|
|
934
999
|
seekTo: 20.5,
|
|
1000
|
+
expectEvent: true,
|
|
935
1001
|
expectedEndTime: 21,
|
|
936
1002
|
});
|
|
937
1003
|
|
|
@@ -939,6 +1005,7 @@ describe('Playhead', () => {
|
|
|
939
1005
|
buffered: [{start: 0, end: 10}, {start: 30, end: 40}],
|
|
940
1006
|
start: 3,
|
|
941
1007
|
seekTo: 29.2,
|
|
1008
|
+
expectEvent: true,
|
|
942
1009
|
expectedEndTime: 30,
|
|
943
1010
|
});
|
|
944
1011
|
}); // with small gaps
|
|
@@ -948,6 +1015,7 @@ describe('Playhead', () => {
|
|
|
948
1015
|
buffered: [{start: 0, end: 10}, {start: 30, end: 40}],
|
|
949
1016
|
start: 5,
|
|
950
1017
|
seekTo: 12,
|
|
1018
|
+
expectEvent: true,
|
|
951
1019
|
expectedEndTime: 30,
|
|
952
1020
|
});
|
|
953
1021
|
}); // with large gaps
|
|
@@ -961,6 +1029,7 @@ describe('Playhead', () => {
|
|
|
961
1029
|
newBuffered: [{start: 20, end: 30}, {start: 31, end: 40}],
|
|
962
1030
|
start: 3,
|
|
963
1031
|
seekTo: 22,
|
|
1032
|
+
expectEvent: false,
|
|
964
1033
|
expectedEndTime: 22,
|
|
965
1034
|
});
|
|
966
1035
|
|
|
@@ -971,6 +1040,7 @@ describe('Playhead', () => {
|
|
|
971
1040
|
newBuffered: [{start: 0.2, end: 10}],
|
|
972
1041
|
start: 4,
|
|
973
1042
|
seekTo: 0,
|
|
1043
|
+
expectEvent: true,
|
|
974
1044
|
expectedEndTime: 0.2,
|
|
975
1045
|
});
|
|
976
1046
|
|
|
@@ -980,6 +1050,7 @@ describe('Playhead', () => {
|
|
|
980
1050
|
newBuffered: [{start: 20, end: 30}, {start: 31, end: 40}],
|
|
981
1051
|
start: 3,
|
|
982
1052
|
seekTo: 30.2,
|
|
1053
|
+
expectEvent: true,
|
|
983
1054
|
expectedEndTime: 31,
|
|
984
1055
|
});
|
|
985
1056
|
|
|
@@ -989,6 +1060,7 @@ describe('Playhead', () => {
|
|
|
989
1060
|
newBuffered: [{start: 20, end: 30}, {start: 31, end: 40}],
|
|
990
1061
|
start: 3,
|
|
991
1062
|
seekTo: 30,
|
|
1063
|
+
expectEvent: true,
|
|
992
1064
|
expectedEndTime: 31,
|
|
993
1065
|
});
|
|
994
1066
|
|
|
@@ -998,6 +1070,7 @@ describe('Playhead', () => {
|
|
|
998
1070
|
newBuffered: [{start: 20, end: 30}],
|
|
999
1071
|
start: 3,
|
|
1000
1072
|
seekTo: 34,
|
|
1073
|
+
expectEvent: false,
|
|
1001
1074
|
expectedEndTime: 34,
|
|
1002
1075
|
});
|
|
1003
1076
|
|
|
@@ -1007,6 +1080,7 @@ describe('Playhead', () => {
|
|
|
1007
1080
|
newBuffered: [{start: 0, end: 10}],
|
|
1008
1081
|
start: 24,
|
|
1009
1082
|
seekTo: 4,
|
|
1083
|
+
expectEvent: false,
|
|
1010
1084
|
expectedEndTime: 4,
|
|
1011
1085
|
});
|
|
1012
1086
|
|
|
@@ -1017,6 +1091,7 @@ describe('Playhead', () => {
|
|
|
1017
1091
|
// should still be waiting.
|
|
1018
1092
|
start: 24,
|
|
1019
1093
|
seekTo: 4,
|
|
1094
|
+
expectEvent: false,
|
|
1020
1095
|
expectedEndTime: 4,
|
|
1021
1096
|
});
|
|
1022
1097
|
|
|
@@ -1026,6 +1101,7 @@ describe('Playhead', () => {
|
|
|
1026
1101
|
newBuffered: [{start: 2, end: 10}],
|
|
1027
1102
|
start: 24,
|
|
1028
1103
|
seekTo: 1.6,
|
|
1104
|
+
expectEvent: true,
|
|
1029
1105
|
expectedEndTime: 2,
|
|
1030
1106
|
});
|
|
1031
1107
|
}); // with small gaps
|
|
@@ -1036,6 +1112,7 @@ describe('Playhead', () => {
|
|
|
1036
1112
|
newBuffered: [{start: 20, end: 30}],
|
|
1037
1113
|
start: 25,
|
|
1038
1114
|
seekTo: 0,
|
|
1115
|
+
expectEvent: true,
|
|
1039
1116
|
expectedEndTime: 20,
|
|
1040
1117
|
});
|
|
1041
1118
|
|
|
@@ -1045,6 +1122,7 @@ describe('Playhead', () => {
|
|
|
1045
1122
|
newBuffered: [{start: 20, end: 30}, {start: 40, end: 50}],
|
|
1046
1123
|
start: 3,
|
|
1047
1124
|
seekTo: 32,
|
|
1125
|
+
expectEvent: true,
|
|
1048
1126
|
expectedEndTime: 40,
|
|
1049
1127
|
});
|
|
1050
1128
|
}); // with large gaps
|
|
@@ -1061,9 +1139,11 @@ describe('Playhead', () => {
|
|
|
1061
1139
|
manifest,
|
|
1062
1140
|
config,
|
|
1063
1141
|
/* startTime= */ 12,
|
|
1064
|
-
Util.spyFunc(onSeek)
|
|
1142
|
+
Util.spyFunc(onSeek),
|
|
1143
|
+
Util.spyFunc(onEvent));
|
|
1065
1144
|
|
|
1066
1145
|
jasmine.clock().tick(500);
|
|
1146
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
1067
1147
|
|
|
1068
1148
|
// Append a segment before seeking.
|
|
1069
1149
|
playhead.notifyOfBufferingChange();
|
|
@@ -1107,7 +1187,8 @@ describe('Playhead', () => {
|
|
|
1107
1187
|
manifest,
|
|
1108
1188
|
config,
|
|
1109
1189
|
/* startTime= */ 0,
|
|
1110
|
-
Util.spyFunc(onSeek)
|
|
1190
|
+
Util.spyFunc(onSeek),
|
|
1191
|
+
Util.spyFunc(onEvent));
|
|
1111
1192
|
|
|
1112
1193
|
playhead.notifyOfBufferingChange();
|
|
1113
1194
|
jasmine.clock().tick(500);
|
|
@@ -1128,7 +1209,8 @@ describe('Playhead', () => {
|
|
|
1128
1209
|
manifest,
|
|
1129
1210
|
config,
|
|
1130
1211
|
/* startTime= */ 5,
|
|
1131
|
-
Util.spyFunc(onSeek)
|
|
1212
|
+
Util.spyFunc(onSeek),
|
|
1213
|
+
Util.spyFunc(onEvent));
|
|
1132
1214
|
|
|
1133
1215
|
playhead.notifyOfBufferingChange();
|
|
1134
1216
|
jasmine.clock().tick(500);
|
|
@@ -1151,7 +1233,8 @@ describe('Playhead', () => {
|
|
|
1151
1233
|
manifest,
|
|
1152
1234
|
config,
|
|
1153
1235
|
/* startTime= */ 0,
|
|
1154
|
-
Util.spyFunc(onSeek)
|
|
1236
|
+
Util.spyFunc(onSeek),
|
|
1237
|
+
Util.spyFunc(onEvent));
|
|
1155
1238
|
|
|
1156
1239
|
playhead.notifyOfBufferingChange();
|
|
1157
1240
|
jasmine.clock().tick(500);
|
|
@@ -1174,7 +1257,8 @@ describe('Playhead', () => {
|
|
|
1174
1257
|
manifest,
|
|
1175
1258
|
config,
|
|
1176
1259
|
/* startTime= */ 0,
|
|
1177
|
-
Util.spyFunc(onSeek)
|
|
1260
|
+
Util.spyFunc(onSeek),
|
|
1261
|
+
Util.spyFunc(onEvent));
|
|
1178
1262
|
|
|
1179
1263
|
playhead.notifyOfBufferingChange();
|
|
1180
1264
|
jasmine.clock().tick(500);
|
|
@@ -1193,14 +1277,18 @@ describe('Playhead', () => {
|
|
|
1193
1277
|
video.currentTime = data.start;
|
|
1194
1278
|
video.readyState = HTMLMediaElement.HAVE_ENOUGH_DATA;
|
|
1195
1279
|
|
|
1280
|
+
onEvent.and.callFake((event) => {});
|
|
1281
|
+
|
|
1196
1282
|
playhead = new shaka.media.MediaSourcePlayhead(
|
|
1197
1283
|
video,
|
|
1198
1284
|
manifest,
|
|
1199
1285
|
config,
|
|
1200
1286
|
/* startTime= */ data.start,
|
|
1201
|
-
Util.spyFunc(onSeek)
|
|
1287
|
+
Util.spyFunc(onSeek),
|
|
1288
|
+
Util.spyFunc(onEvent));
|
|
1202
1289
|
|
|
1203
1290
|
jasmine.clock().tick(500);
|
|
1291
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
1204
1292
|
|
|
1205
1293
|
// Seek to the given position and update ready state.
|
|
1206
1294
|
video.currentTime = data.seekTo;
|
|
@@ -1232,6 +1320,7 @@ describe('Playhead', () => {
|
|
|
1232
1320
|
jasmine.clock().tick(250);
|
|
1233
1321
|
}
|
|
1234
1322
|
|
|
1323
|
+
expect(onEvent).toHaveBeenCalledTimes(data.expectEvent ? 1 : 0);
|
|
1235
1324
|
expect(video.currentTime).toBe(data.expectedEndTime);
|
|
1236
1325
|
});
|
|
1237
1326
|
}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
describe('StallDetector', () => {
|
|
8
|
+
const Util = shaka.test.Util;
|
|
9
|
+
|
|
8
10
|
/**
|
|
9
11
|
* @implements {shaka.media.StallDetector.Implementation}
|
|
10
12
|
* @final
|
|
@@ -38,16 +40,21 @@ describe('StallDetector', () => {
|
|
|
38
40
|
/** @type {!jasmine.Spy} */
|
|
39
41
|
let onStall;
|
|
40
42
|
|
|
43
|
+
/** @type {!jasmine.Spy} */
|
|
44
|
+
let onEvent;
|
|
45
|
+
|
|
41
46
|
beforeEach(() => {
|
|
42
47
|
onStall = jasmine.createSpy('onStall');
|
|
48
|
+
onEvent = jasmine.createSpy('onEvent');
|
|
43
49
|
|
|
44
50
|
implementation = new TestImplementation();
|
|
45
51
|
|
|
46
52
|
detector = new shaka.media.StallDetector(
|
|
47
53
|
implementation,
|
|
48
|
-
/* stallThresholdSeconds= */ 1
|
|
54
|
+
/* stallThresholdSeconds= */ 1,
|
|
55
|
+
Util.spyFunc(onEvent));
|
|
49
56
|
|
|
50
|
-
detector.onStall(
|
|
57
|
+
detector.onStall(Util.spyFunc(onStall));
|
|
51
58
|
});
|
|
52
59
|
|
|
53
60
|
it('does not call onStall when values changes', () => {
|
|
@@ -63,6 +70,7 @@ describe('StallDetector', () => {
|
|
|
63
70
|
|
|
64
71
|
detector.poll();
|
|
65
72
|
|
|
73
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
66
74
|
expect(onStall).not.toHaveBeenCalled();
|
|
67
75
|
});
|
|
68
76
|
|
|
@@ -74,6 +82,7 @@ describe('StallDetector', () => {
|
|
|
74
82
|
implementation.wallSeconds = time;
|
|
75
83
|
|
|
76
84
|
detector.poll();
|
|
85
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
77
86
|
expect(onStall).not.toHaveBeenCalled();
|
|
78
87
|
}
|
|
79
88
|
|
|
@@ -81,6 +90,7 @@ describe('StallDetector', () => {
|
|
|
81
90
|
implementation.wallSeconds = 1;
|
|
82
91
|
|
|
83
92
|
detector.poll();
|
|
93
|
+
expect(onEvent).toHaveBeenCalled();
|
|
84
94
|
expect(onStall).toHaveBeenCalledOnceMoreWith([
|
|
85
95
|
/* stalledWith= */ 5,
|
|
86
96
|
/* stallDurationSeconds= */ 1,
|
|
@@ -96,6 +106,7 @@ describe('StallDetector', () => {
|
|
|
96
106
|
implementation.wallSeconds = 10;
|
|
97
107
|
detector.poll();
|
|
98
108
|
|
|
109
|
+
expect(onEvent).toHaveBeenCalled();
|
|
99
110
|
expect(onStall).toHaveBeenCalledOnceMoreWith([
|
|
100
111
|
/* stalledWith= */ 5,
|
|
101
112
|
/* stallDurationms= */ 10,
|
|
@@ -117,6 +128,7 @@ describe('StallDetector', () => {
|
|
|
117
128
|
|
|
118
129
|
detector.poll();
|
|
119
130
|
|
|
131
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
120
132
|
expect(onStall).not.toHaveBeenCalled();
|
|
121
133
|
});
|
|
122
134
|
|
|
@@ -135,6 +147,7 @@ describe('StallDetector', () => {
|
|
|
135
147
|
implementation.wallSeconds = 10;
|
|
136
148
|
detector.poll();
|
|
137
149
|
|
|
150
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
138
151
|
expect(onStall).not.toHaveBeenCalled();
|
|
139
152
|
});
|
|
140
153
|
|
|
@@ -143,16 +156,20 @@ describe('StallDetector', () => {
|
|
|
143
156
|
implementation.presentationSeconds = 0;
|
|
144
157
|
implementation.wallSeconds = 0;
|
|
145
158
|
detector.poll();
|
|
159
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
146
160
|
expect(onStall).not.toHaveBeenCalled();
|
|
147
161
|
|
|
148
162
|
implementation.wallSeconds = 10;
|
|
149
163
|
detector.poll();
|
|
164
|
+
expect(onEvent).toHaveBeenCalled();
|
|
150
165
|
expect(onStall).toHaveBeenCalled();
|
|
166
|
+
onEvent.calls.reset();
|
|
151
167
|
onStall.calls.reset();
|
|
152
168
|
|
|
153
169
|
// This is the same stall, should not be called again.
|
|
154
170
|
implementation.wallSeconds = 20;
|
|
155
171
|
detector.poll();
|
|
172
|
+
expect(onEvent).not.toHaveBeenCalled();
|
|
156
173
|
expect(onStall).not.toHaveBeenCalled();
|
|
157
174
|
|
|
158
175
|
// Now that we changed time, we should get another call.
|
|
@@ -161,6 +178,7 @@ describe('StallDetector', () => {
|
|
|
161
178
|
detector.poll();
|
|
162
179
|
implementation.wallSeconds = 40;
|
|
163
180
|
detector.poll();
|
|
181
|
+
expect(onEvent).toHaveBeenCalled();
|
|
164
182
|
expect(onStall).toHaveBeenCalled();
|
|
165
183
|
});
|
|
166
184
|
});
|
|
@@ -126,6 +126,9 @@ describe('Player', () => {
|
|
|
126
126
|
corruptedFrames: jasmine.any(Number),
|
|
127
127
|
estimatedBandwidth: jasmine.any(Number),
|
|
128
128
|
|
|
129
|
+
gapsJumped: jasmine.any(Number),
|
|
130
|
+
stallsDetected: jasmine.any(Number),
|
|
131
|
+
|
|
129
132
|
completionPercent: jasmine.any(Number),
|
|
130
133
|
loadLatency: jasmine.any(Number),
|
|
131
134
|
manifestTimeSeconds: jasmine.any(Number),
|