shaka-player 3.3.12 → 3.3.14
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 +33 -0
- package/CONTRIBUTORS +1 -0
- package/dist/deps.js +3 -3
- package/dist/locales.js +31 -31
- package/dist/shaka-player.compiled.d.ts +1 -1
- package/dist/shaka-player.compiled.debug.d.ts +1 -1
- package/dist/shaka-player.compiled.debug.externs.js +2 -1
- package/dist/shaka-player.compiled.debug.js +135 -126
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +2 -1
- package/dist/shaka-player.compiled.js +744 -739
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +1 -1
- package/dist/shaka-player.ui.debug.d.ts +1 -1
- package/dist/shaka-player.ui.debug.externs.js +2 -1
- package/dist/shaka-player.ui.debug.js +228 -219
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +2 -1
- package/dist/shaka-player.ui.js +849 -845
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/welcome.md +2 -2
- package/externs/shaka/player.js +2 -1
- package/lib/cast/cast_proxy.js +2 -1
- package/lib/cast/cast_receiver.js +19 -5
- package/lib/cast/cast_sender.js +2 -1
- package/lib/cast/cast_utils.js +16 -6
- package/lib/cea/cea708_window.js +2 -2
- package/lib/dash/segment_template.js +1 -1
- package/lib/hls/hls_parser.js +17 -3
- package/lib/media/content_workarounds.js +12 -0
- package/lib/media/playhead.js +23 -1
- package/lib/media/streaming_engine.js +3 -12
- package/lib/player.js +24 -11
- package/lib/polyfill/media_capabilities.js +59 -9
- package/lib/text/ttml_text_parser.js +32 -7
- package/lib/text/ui_text_displayer.js +22 -5
- package/lib/util/manifest_parser_utils.js +4 -0
- package/lib/util/platform.js +21 -2
- package/lib/util/stream_utils.js +30 -10
- package/package.json +1 -1
- package/test/cast/cast_receiver_integration.js +97 -16
- package/test/cast/cast_receiver_unit.js +17 -12
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/dash/dash_parser_manifest_unit.js +1 -0
- package/test/hls/hls_parser_unit.js +1 -0
- package/test/media/playhead_unit.js +41 -0
- package/test/media/streaming_engine_integration.js +13 -0
- package/test/media/streaming_engine_unit.js +23 -8
- package/test/player_unit.js +87 -0
- package/test/polyfill/media_capabilities_unit.js +261 -0
- package/test/test/util/simple_fakes.js +3 -0
- package/test/text/mp4_ttml_parser_unit.js +4 -4
- package/test/text/ttml_text_parser_unit.js +119 -86
- package/test/text/ui_text_displayer_unit.js +76 -0
- package/test/ui/text_displayer_layout_unit.js +14 -0
- package/test/util/stream_utils_unit.js +18 -0
- package/test/util/xml_utils_unit.js +6 -1
- package/ui/controls.js +5 -2
- package/ui/settings_menu.js +11 -2
|
@@ -857,7 +857,7 @@ describe('StreamingEngine', () => {
|
|
|
857
857
|
|
|
858
858
|
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
|
|
859
859
|
config.bufferingGoal = 60;
|
|
860
|
-
config.failureCallback = () => streamingEngine.retry();
|
|
860
|
+
config.failureCallback = () => streamingEngine.retry(0.1);
|
|
861
861
|
createStreamingEngine(config);
|
|
862
862
|
|
|
863
863
|
// Make requests for different types take different amounts of time.
|
|
@@ -1716,8 +1716,23 @@ describe('StreamingEngine', () => {
|
|
|
1716
1716
|
beforeEach(() => {
|
|
1717
1717
|
setupLive();
|
|
1718
1718
|
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData, 0);
|
|
1719
|
-
|
|
1719
|
+
|
|
1720
|
+
// Retry on failure for live streams.
|
|
1721
|
+
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
|
|
1722
|
+
config.failureCallback = () => streamingEngine.retry(0.1);
|
|
1723
|
+
|
|
1724
|
+
createStreamingEngine(config);
|
|
1720
1725
|
presentationTimeInSeconds = 100;
|
|
1726
|
+
|
|
1727
|
+
// Ignore 404 errors in live stream tests.
|
|
1728
|
+
onError.and.callFake((error) => {
|
|
1729
|
+
if (error.code == shaka.util.Error.Code.BAD_HTTP_STATUS &&
|
|
1730
|
+
error.data[1] == 404) {
|
|
1731
|
+
// 404 error
|
|
1732
|
+
} else {
|
|
1733
|
+
fail(error);
|
|
1734
|
+
}
|
|
1735
|
+
});
|
|
1721
1736
|
});
|
|
1722
1737
|
|
|
1723
1738
|
it('outside segment availability window', async () => {
|
|
@@ -1753,9 +1768,9 @@ describe('StreamingEngine', () => {
|
|
|
1753
1768
|
if (startTime >= 100) {
|
|
1754
1769
|
// Ignore a possible call for the first Period.
|
|
1755
1770
|
expect(Util.invokeSpy(timeline.getSegmentAvailabilityStart))
|
|
1756
|
-
.
|
|
1771
|
+
.not.toBeLessThan(100);
|
|
1757
1772
|
expect(Util.invokeSpy(timeline.getSegmentAvailabilityEnd))
|
|
1758
|
-
.
|
|
1773
|
+
.not.toBeLessThan(120);
|
|
1759
1774
|
playing = true;
|
|
1760
1775
|
mediaSourceEngine.appendBuffer.and.callFake(
|
|
1761
1776
|
originalAppendBuffer);
|
|
@@ -1980,7 +1995,7 @@ describe('StreamingEngine', () => {
|
|
|
1980
1995
|
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
|
|
1981
1996
|
|
|
1982
1997
|
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
|
|
1983
|
-
config.failureCallback = () => streamingEngine.retry();
|
|
1998
|
+
config.failureCallback = () => streamingEngine.retry(0.1);
|
|
1984
1999
|
createStreamingEngine(config);
|
|
1985
2000
|
|
|
1986
2001
|
presentationTimeInSeconds = 100;
|
|
@@ -2141,7 +2156,7 @@ describe('StreamingEngine', () => {
|
|
|
2141
2156
|
netEngine.request.calls.reset();
|
|
2142
2157
|
|
|
2143
2158
|
// Retry streaming.
|
|
2144
|
-
expect(streamingEngine.retry()).toBe(true);
|
|
2159
|
+
expect(streamingEngine.retry(0.1)).toBe(true);
|
|
2145
2160
|
});
|
|
2146
2161
|
|
|
2147
2162
|
// Here we go!
|
|
@@ -2171,7 +2186,7 @@ describe('StreamingEngine', () => {
|
|
|
2171
2186
|
|
|
2172
2187
|
// Retry streaming, which should fail and return false.
|
|
2173
2188
|
netEngine.request.calls.reset();
|
|
2174
|
-
expect(streamingEngine.retry()).toBe(false);
|
|
2189
|
+
expect(streamingEngine.retry(0.1)).toBe(false);
|
|
2175
2190
|
});
|
|
2176
2191
|
|
|
2177
2192
|
// Here we go!
|
|
@@ -2223,7 +2238,7 @@ describe('StreamingEngine', () => {
|
|
|
2223
2238
|
|
|
2224
2239
|
// Retry streaming, which should fail and return false.
|
|
2225
2240
|
netEngine.request.calls.reset();
|
|
2226
|
-
expect(streamingEngine.retry()).toBe(false);
|
|
2241
|
+
expect(streamingEngine.retry(0.1)).toBe(false);
|
|
2227
2242
|
}
|
|
2228
2243
|
});
|
|
2229
2244
|
|
package/test/player_unit.js
CHANGED
|
@@ -3735,6 +3735,93 @@ describe('Player', () => {
|
|
|
3735
3735
|
});
|
|
3736
3736
|
});
|
|
3737
3737
|
|
|
3738
|
+
describe('config streaming.failureCallback default', () => {
|
|
3739
|
+
/** @type {jasmine.Spy} */
|
|
3740
|
+
let retryStreaming;
|
|
3741
|
+
/** @type {jasmine.Spy} */
|
|
3742
|
+
let isLive;
|
|
3743
|
+
|
|
3744
|
+
/**
|
|
3745
|
+
* @suppress {accessControls}
|
|
3746
|
+
* @param {!shaka.util.Error} error
|
|
3747
|
+
*/
|
|
3748
|
+
function defaultStreamingFailureCallback(error) {
|
|
3749
|
+
player.defaultStreamingFailureCallback_(error);
|
|
3750
|
+
}
|
|
3751
|
+
|
|
3752
|
+
beforeEach(() => {
|
|
3753
|
+
retryStreaming = jasmine.createSpy('retryStreaming');
|
|
3754
|
+
isLive = jasmine.createSpy('isLive');
|
|
3755
|
+
|
|
3756
|
+
player.retryStreaming = Util.spyFunc(retryStreaming);
|
|
3757
|
+
player.isLive = Util.spyFunc(isLive);
|
|
3758
|
+
});
|
|
3759
|
+
|
|
3760
|
+
it('ignores VOD failures', () => {
|
|
3761
|
+
isLive.and.returnValue(false);
|
|
3762
|
+
|
|
3763
|
+
const error = new shaka.util.Error(
|
|
3764
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3765
|
+
shaka.util.Error.Category.NETWORK,
|
|
3766
|
+
shaka.util.Error.Code.BAD_HTTP_STATUS,
|
|
3767
|
+
/* url= */ '',
|
|
3768
|
+
/* http_status= */ 404);
|
|
3769
|
+
|
|
3770
|
+
defaultStreamingFailureCallback(error);
|
|
3771
|
+
expect(retryStreaming).not.toHaveBeenCalled();
|
|
3772
|
+
});
|
|
3773
|
+
|
|
3774
|
+
it('retries live on HTTP 404', () => {
|
|
3775
|
+
isLive.and.returnValue(true);
|
|
3776
|
+
|
|
3777
|
+
const error = new shaka.util.Error(
|
|
3778
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3779
|
+
shaka.util.Error.Category.NETWORK,
|
|
3780
|
+
shaka.util.Error.Code.BAD_HTTP_STATUS,
|
|
3781
|
+
/* url= */ '',
|
|
3782
|
+
/* http_status= */ 404);
|
|
3783
|
+
|
|
3784
|
+
defaultStreamingFailureCallback(error);
|
|
3785
|
+
expect(retryStreaming).toHaveBeenCalled();
|
|
3786
|
+
});
|
|
3787
|
+
|
|
3788
|
+
it('retries live on generic HTTP error', () => {
|
|
3789
|
+
isLive.and.returnValue(true);
|
|
3790
|
+
|
|
3791
|
+
const error = new shaka.util.Error(
|
|
3792
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3793
|
+
shaka.util.Error.Category.NETWORK,
|
|
3794
|
+
shaka.util.Error.Code.HTTP_ERROR);
|
|
3795
|
+
|
|
3796
|
+
defaultStreamingFailureCallback(error);
|
|
3797
|
+
expect(retryStreaming).toHaveBeenCalled();
|
|
3798
|
+
});
|
|
3799
|
+
|
|
3800
|
+
it('retries live on HTTP timeout', () => {
|
|
3801
|
+
isLive.and.returnValue(true);
|
|
3802
|
+
|
|
3803
|
+
const error = new shaka.util.Error(
|
|
3804
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3805
|
+
shaka.util.Error.Category.NETWORK,
|
|
3806
|
+
shaka.util.Error.Code.TIMEOUT);
|
|
3807
|
+
|
|
3808
|
+
defaultStreamingFailureCallback(error);
|
|
3809
|
+
expect(retryStreaming).toHaveBeenCalled();
|
|
3810
|
+
});
|
|
3811
|
+
|
|
3812
|
+
it('ignores other live failures', () => {
|
|
3813
|
+
isLive.and.returnValue(true);
|
|
3814
|
+
|
|
3815
|
+
const error = new shaka.util.Error(
|
|
3816
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3817
|
+
shaka.util.Error.Category.MEDIA,
|
|
3818
|
+
shaka.util.Error.Code.VIDEO_ERROR);
|
|
3819
|
+
|
|
3820
|
+
defaultStreamingFailureCallback(error);
|
|
3821
|
+
expect(retryStreaming).not.toHaveBeenCalled();
|
|
3822
|
+
});
|
|
3823
|
+
});
|
|
3824
|
+
|
|
3738
3825
|
/**
|
|
3739
3826
|
* Gets the currently active variant track.
|
|
3740
3827
|
* @return {shaka.extern.Track}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
describe('MediaCapabilities', () => {
|
|
8
|
+
const Util = shaka.test.Util;
|
|
9
|
+
const originalCast = window['cast'];
|
|
10
|
+
const originalVendor = navigator.vendor;
|
|
11
|
+
const originalUserAgent = navigator.userAgent;
|
|
12
|
+
const originalRequestMediaKeySystemAccess =
|
|
13
|
+
navigator.requestMediaKeySystemAccess;
|
|
14
|
+
const originalMediaCapabilities = navigator.mediaCapabilities;
|
|
15
|
+
|
|
16
|
+
/** @type {MediaDecodingConfiguration} */
|
|
17
|
+
let mockDecodingConfig;
|
|
18
|
+
/** @type {!jasmine.Spy} */
|
|
19
|
+
let mockCanDisplayType;
|
|
20
|
+
|
|
21
|
+
beforeAll(() => {
|
|
22
|
+
Object.defineProperty(window['navigator'],
|
|
23
|
+
'userAgent', {
|
|
24
|
+
value: 'unknown', configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
});
|
|
27
|
+
Object.defineProperty(window['navigator'],
|
|
28
|
+
'vendor', {
|
|
29
|
+
value: 'unknown', configurable: true,
|
|
30
|
+
writable: true,
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(window['navigator'],
|
|
33
|
+
'requestMediaKeySystemAccess', {
|
|
34
|
+
value: 'unknown', configurable: true,
|
|
35
|
+
writable: true,
|
|
36
|
+
});
|
|
37
|
+
Object.defineProperty(window['navigator'],
|
|
38
|
+
'mediaCapabilities', {
|
|
39
|
+
value: undefined, configurable: true,
|
|
40
|
+
writable: true,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
mockDecodingConfig = {
|
|
46
|
+
audio: {
|
|
47
|
+
bitrate: 100891,
|
|
48
|
+
channels: 2,
|
|
49
|
+
contentType: 'audio/mp4; codecs="mp4a.40.2"',
|
|
50
|
+
samplerate: 48000,
|
|
51
|
+
spatialRendering: false,
|
|
52
|
+
},
|
|
53
|
+
keySystemConfiguration: {
|
|
54
|
+
audio: {robustness: 'SW_SECURE_CRYPTO'},
|
|
55
|
+
distinctiveIdentifier: 'optional',
|
|
56
|
+
initDataType: 'cenc',
|
|
57
|
+
keySystem: 'com.widevine.alpha',
|
|
58
|
+
persistentState: 'optional',
|
|
59
|
+
sessionTypes: ['temporary'],
|
|
60
|
+
video: {robustness: 'SW_SECURE_CRYPTO'},
|
|
61
|
+
},
|
|
62
|
+
type: 'media-source',
|
|
63
|
+
video: {
|
|
64
|
+
bitrate: 349265,
|
|
65
|
+
contentType: 'video/mp4; codecs="avc1.4D4015"',
|
|
66
|
+
framerate: 23.976023976023978,
|
|
67
|
+
height: 288,
|
|
68
|
+
width: 512,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
shaka.polyfill.MediaCapabilities.memoizedMediaKeySystemAccessRequests_ = {};
|
|
72
|
+
|
|
73
|
+
mockCanDisplayType = jasmine.createSpy('canDisplayType');
|
|
74
|
+
mockCanDisplayType.and.returnValue(false);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
afterEach(() => {
|
|
78
|
+
window['cast'] = originalCast;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
afterAll(() => {
|
|
82
|
+
window['cast'] = originalCast;
|
|
83
|
+
Object.defineProperty(window['navigator'],
|
|
84
|
+
'userAgent', {value: originalUserAgent});
|
|
85
|
+
Object.defineProperty(window['navigator'],
|
|
86
|
+
'vendor', {value: originalVendor});
|
|
87
|
+
Object.defineProperty(window['navigator'],
|
|
88
|
+
'requestMediaKeySystemAccess',
|
|
89
|
+
{value: originalRequestMediaKeySystemAccess});
|
|
90
|
+
Object.defineProperty(window['navigator'],
|
|
91
|
+
'mediaCapabilities', {value: originalMediaCapabilities});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('install', () => {
|
|
95
|
+
it('should define decoding info method', () => {
|
|
96
|
+
shaka.polyfill.MediaCapabilities.install();
|
|
97
|
+
|
|
98
|
+
expect(navigator.mediaCapabilities.decodingInfo).toBeDefined();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('decodingInfo', () => {
|
|
103
|
+
it('should check codec support when MediaDecodingConfiguration.type ' +
|
|
104
|
+
'is "media-source"', () => {
|
|
105
|
+
const isTypeSupportedSpy =
|
|
106
|
+
spyOn(window['MediaSource'], 'isTypeSupported').and.returnValue(true);
|
|
107
|
+
shaka.polyfill.MediaCapabilities.install();
|
|
108
|
+
navigator.mediaCapabilities.decodingInfo(mockDecodingConfig);
|
|
109
|
+
|
|
110
|
+
expect(isTypeSupportedSpy).toHaveBeenCalledTimes(2);
|
|
111
|
+
expect(isTypeSupportedSpy).toHaveBeenCalledWith(
|
|
112
|
+
mockDecodingConfig.video.contentType,
|
|
113
|
+
);
|
|
114
|
+
expect(isTypeSupportedSpy).toHaveBeenCalledWith(
|
|
115
|
+
mockDecodingConfig.audio.contentType,
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should check codec support when MediaDecodingConfiguration.type ' +
|
|
120
|
+
'is "file"', () => {
|
|
121
|
+
const supportsMediaTypeSpy =
|
|
122
|
+
spyOn(shaka['util']['Platform'],
|
|
123
|
+
'supportsMediaType').and.returnValue(true);
|
|
124
|
+
mockDecodingConfig.type = 'file';
|
|
125
|
+
shaka.polyfill.MediaCapabilities.install();
|
|
126
|
+
navigator.mediaCapabilities.decodingInfo(mockDecodingConfig);
|
|
127
|
+
|
|
128
|
+
expect(supportsMediaTypeSpy).toHaveBeenCalledTimes(2);
|
|
129
|
+
expect(supportsMediaTypeSpy).toHaveBeenCalledWith(
|
|
130
|
+
mockDecodingConfig.video.contentType,
|
|
131
|
+
);
|
|
132
|
+
expect(supportsMediaTypeSpy).toHaveBeenCalledWith(
|
|
133
|
+
mockDecodingConfig.audio.contentType,
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should check MediaKeySystem when keySystemConfiguration is present',
|
|
138
|
+
async () => {
|
|
139
|
+
const mockResult = {mockKeySystemAccess: 'mockKeySystemAccess'};
|
|
140
|
+
spyOn(window['MediaSource'], 'isTypeSupported').and.returnValue(true);
|
|
141
|
+
const requestKeySystemAccessSpy =
|
|
142
|
+
spyOn(window['navigator'],
|
|
143
|
+
'requestMediaKeySystemAccess').and.returnValue(mockResult);
|
|
144
|
+
|
|
145
|
+
shaka.polyfill.MediaCapabilities.install();
|
|
146
|
+
const result = await navigator.mediaCapabilities
|
|
147
|
+
.decodingInfo(mockDecodingConfig);
|
|
148
|
+
|
|
149
|
+
expect(requestKeySystemAccessSpy).toHaveBeenCalledWith(
|
|
150
|
+
'com.widevine.alpha',
|
|
151
|
+
[{
|
|
152
|
+
audioCapabilities: [
|
|
153
|
+
{
|
|
154
|
+
robustness: 'SW_SECURE_CRYPTO',
|
|
155
|
+
contentType: 'audio/mp4; codecs="mp4a.40.2"',
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
distinctiveIdentifier: 'optional',
|
|
159
|
+
initDataTypes: ['cenc'],
|
|
160
|
+
persistentState: 'optional',
|
|
161
|
+
sessionTypes: ['temporary'],
|
|
162
|
+
videoCapabilities: [{
|
|
163
|
+
robustness: 'SW_SECURE_CRYPTO',
|
|
164
|
+
contentType: 'video/mp4; codecs="avc1.4D4015"',
|
|
165
|
+
}],
|
|
166
|
+
}],
|
|
167
|
+
);
|
|
168
|
+
expect(result.keySystemAccess).toEqual(mockResult);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('throws when the cast namespace is not available', async () => {
|
|
172
|
+
// Temporarily remove window.cast to trigger error. It's restored after
|
|
173
|
+
// every test.
|
|
174
|
+
delete window['cast'];
|
|
175
|
+
|
|
176
|
+
const isChromecastSpy =
|
|
177
|
+
spyOn(shaka['util']['Platform'],
|
|
178
|
+
'isChromecast').and.returnValue(true);
|
|
179
|
+
const expected = Util.jasmineError(new shaka.util.Error(
|
|
180
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
181
|
+
shaka.util.Error.Category.CAST,
|
|
182
|
+
shaka.util.Error.Code.CAST_API_UNAVAILABLE));
|
|
183
|
+
const isTypeSupportedSpy =
|
|
184
|
+
spyOn(window['MediaSource'], 'isTypeSupported').and.returnValue(true);
|
|
185
|
+
|
|
186
|
+
shaka.polyfill.MediaCapabilities.install();
|
|
187
|
+
await expectAsync(
|
|
188
|
+
navigator.mediaCapabilities.decodingInfo(mockDecodingConfig))
|
|
189
|
+
.toBeRejectedWith(expected);
|
|
190
|
+
|
|
191
|
+
expect(isTypeSupportedSpy).not.toHaveBeenCalled();
|
|
192
|
+
// 1 (during install()) + 1 (for video config check).
|
|
193
|
+
expect(isChromecastSpy).toHaveBeenCalledTimes(2);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('falls back to isTypeSupported() when canDisplayType() missing',
|
|
197
|
+
async () => {
|
|
198
|
+
// We only set the cast namespace, but not the canDisplayType() API.
|
|
199
|
+
window['cast'] = {};
|
|
200
|
+
const isChromecastSpy =
|
|
201
|
+
spyOn(shaka['util']['Platform'],
|
|
202
|
+
'isChromecast').and.returnValue(true);
|
|
203
|
+
const isTypeSupportedSpy =
|
|
204
|
+
spyOn(window['MediaSource'], 'isTypeSupported')
|
|
205
|
+
.and.returnValue(true);
|
|
206
|
+
|
|
207
|
+
shaka.polyfill.MediaCapabilities.install();
|
|
208
|
+
await navigator.mediaCapabilities.decodingInfo(mockDecodingConfig);
|
|
209
|
+
|
|
210
|
+
expect(mockCanDisplayType).not.toHaveBeenCalled();
|
|
211
|
+
// 1 (during install()) + 1 (for video config check).
|
|
212
|
+
expect(isChromecastSpy).toHaveBeenCalledTimes(2);
|
|
213
|
+
// 1 (fallback in canCastDisplayType()) +
|
|
214
|
+
// 1 (mockDecodingConfig.audio).
|
|
215
|
+
expect(isTypeSupportedSpy).toHaveBeenCalledTimes(2);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('should use cast.__platform__.canDisplayType for "supported" field ' +
|
|
219
|
+
'when platform is Cast', async () => {
|
|
220
|
+
// We're using quotes to access window.cast because the compiler
|
|
221
|
+
// knows about lots of Cast-specific APIs we aren't mocking. We
|
|
222
|
+
// don't need this mock strictly type-checked.
|
|
223
|
+
window['cast'] = {
|
|
224
|
+
__platform__: {canDisplayType: mockCanDisplayType},
|
|
225
|
+
};
|
|
226
|
+
const isChromecastSpy =
|
|
227
|
+
spyOn(shaka['util']['Platform'],
|
|
228
|
+
'isChromecast').and.returnValue(true);
|
|
229
|
+
const isTypeSupportedSpy =
|
|
230
|
+
spyOn(window['MediaSource'], 'isTypeSupported').and.returnValue(true);
|
|
231
|
+
|
|
232
|
+
// Tests an HDR stream's extended MIME type is correctly provided.
|
|
233
|
+
mockDecodingConfig.video.transferFunction = 'pq';
|
|
234
|
+
mockDecodingConfig.video.contentType =
|
|
235
|
+
'video/mp4; codecs="hev1.2.4.L153.B0"';
|
|
236
|
+
// Round to a whole number since we can't rely on number => string
|
|
237
|
+
// conversion precision on all devices.
|
|
238
|
+
mockDecodingConfig.video.framerate = 24;
|
|
239
|
+
mockCanDisplayType.and.callFake((type) => {
|
|
240
|
+
expect(type).toBe(
|
|
241
|
+
'video/mp4; ' +
|
|
242
|
+
'codecs="hev1.2.4.L153.B0"; ' +
|
|
243
|
+
'width=512; ' +
|
|
244
|
+
'height=288; ' +
|
|
245
|
+
'framerate=24; ' +
|
|
246
|
+
'eotf=smpte2084');
|
|
247
|
+
return true;
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
shaka.polyfill.MediaCapabilities.install();
|
|
251
|
+
await navigator.mediaCapabilities.decodingInfo(mockDecodingConfig);
|
|
252
|
+
|
|
253
|
+
// 1 (during install()) + 1 (for video config check).
|
|
254
|
+
expect(isChromecastSpy).toHaveBeenCalledTimes(2);
|
|
255
|
+
// 1 (mockDecodingConfig.audio).
|
|
256
|
+
expect(isTypeSupportedSpy).toHaveBeenCalledTimes(1);
|
|
257
|
+
// Called once in canCastDisplayType.
|
|
258
|
+
expect(mockCanDisplayType).toHaveBeenCalledTimes(1);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
});
|
|
@@ -333,6 +333,9 @@ shaka.test.FakePlayhead = class {
|
|
|
333
333
|
/** @private {number} */
|
|
334
334
|
this.startTime_ = 0;
|
|
335
335
|
|
|
336
|
+
/** @type {!jasmine.Spy} */
|
|
337
|
+
this.ready = jasmine.createSpy('ready');
|
|
338
|
+
|
|
336
339
|
/** @type {!jasmine.Spy} */
|
|
337
340
|
this.setStartTime = jasmine.createSpy('setStartTime')
|
|
338
341
|
.and.callFake((value) => {
|
|
@@ -41,7 +41,7 @@ describe('Mp4TtmlParser', () => {
|
|
|
41
41
|
it('handles media segments with multiple mdats', () => {
|
|
42
42
|
const parser = new shaka.text.Mp4TtmlParser();
|
|
43
43
|
parser.parseInit(ttmlInitSegment);
|
|
44
|
-
const time = {periodStart: 0, segmentStart:
|
|
44
|
+
const time = {periodStart: 0, segmentStart: 60, segmentEnd: 0};
|
|
45
45
|
const ret = parser.parseMedia(ttmlSegmentMultipleMDAT, time);
|
|
46
46
|
// Bodies.
|
|
47
47
|
expect(ret.length).toBe(2);
|
|
@@ -54,8 +54,8 @@ describe('Mp4TtmlParser', () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it('accounts for offset', () => {
|
|
57
|
-
const time1 = {periodStart: 0, segmentStart: 0, segmentEnd:
|
|
58
|
-
const time2 = {periodStart: 7, segmentStart: 0, segmentEnd:
|
|
57
|
+
const time1 = {periodStart: 0, segmentStart: 0, segmentEnd: 70};
|
|
58
|
+
const time2 = {periodStart: 7, segmentStart: 0, segmentEnd: 70};
|
|
59
59
|
|
|
60
60
|
const parser = new shaka.text.Mp4TtmlParser();
|
|
61
61
|
parser.parseInit(ttmlInitSegment);
|
|
@@ -159,7 +159,7 @@ describe('Mp4TtmlParser', () => {
|
|
|
159
159
|
];
|
|
160
160
|
const parser = new shaka.text.Mp4TtmlParser();
|
|
161
161
|
parser.parseInit(ttmlInitSegment);
|
|
162
|
-
const time = {periodStart: 0, segmentStart: 0, segmentEnd:
|
|
162
|
+
const time = {periodStart: 0, segmentStart: 0, segmentEnd: 60};
|
|
163
163
|
const result = parser.parseMedia(ttmlSegment, time);
|
|
164
164
|
shaka.test.TtmlUtils.verifyHelper(
|
|
165
165
|
cues, result, {startTime: 23, endTime: 53.5});
|