shaka-player 4.8.3 → 4.8.4
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/CONTRIBUTORS +1 -0
- package/dist/deps.js +2 -2
- package/dist/locales.js +34 -34
- package/dist/shaka-player.compiled.debug.js +279 -275
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +744 -742
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.debug.js +295 -291
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +740 -737
- package/dist/shaka-player.ui.map +3 -3
- package/lib/cea/cea_decoder.js +3 -0
- package/lib/media/closed_caption_parser.js +7 -1
- package/lib/media/media_source_engine.js +5 -8
- package/lib/media/segment_utils.js +1 -1
- package/lib/player.js +17 -1
- package/lib/polyfill/media_capabilities.js +150 -133
- package/lib/transmuxer/ts_transmuxer.js +2 -24
- package/lib/util/platform.js +44 -11
- package/package.json +6 -1
package/lib/cea/cea_decoder.js
CHANGED
|
@@ -97,6 +97,7 @@ shaka.cea.CeaDecoder = class {
|
|
|
97
97
|
* @override
|
|
98
98
|
*/
|
|
99
99
|
clear() {
|
|
100
|
+
shaka.log.debug('Clearing CEA decoder');
|
|
100
101
|
this.badFrames_ = 0;
|
|
101
102
|
this.cea608DataArray_ = [];
|
|
102
103
|
this.cea708DataArray_ = [];
|
|
@@ -113,6 +114,7 @@ shaka.cea.CeaDecoder = class {
|
|
|
113
114
|
* Resets the decoder.
|
|
114
115
|
*/
|
|
115
116
|
reset() {
|
|
117
|
+
shaka.log.debug('Resetting CEA decoder');
|
|
116
118
|
this.currentField1Channel_ = 0;
|
|
117
119
|
this.currentField2Channel_ = 0;
|
|
118
120
|
for (const stream of this.cea608ModeToStream_.values()) {
|
|
@@ -128,6 +130,7 @@ shaka.cea.CeaDecoder = class {
|
|
|
128
130
|
*/
|
|
129
131
|
extract(userDataSeiMessage, pts) {
|
|
130
132
|
if (this.waitingForFirstPacket_) {
|
|
133
|
+
shaka.log.debug('Setting first pts value to', pts);
|
|
131
134
|
for (const stream of this.cea608ModeToStream_.values()) {
|
|
132
135
|
stream.firstPts(pts);
|
|
133
136
|
}
|
|
@@ -9,6 +9,7 @@ goog.provide('shaka.media.IClosedCaptionParser');
|
|
|
9
9
|
|
|
10
10
|
goog.require('shaka.cea.DummyCaptionDecoder');
|
|
11
11
|
goog.require('shaka.cea.DummyCeaParser');
|
|
12
|
+
goog.require('shaka.log');
|
|
12
13
|
goog.require('shaka.util.BufferUtils');
|
|
13
14
|
|
|
14
15
|
|
|
@@ -22,7 +23,8 @@ goog.require('shaka.util.BufferUtils');
|
|
|
22
23
|
*/
|
|
23
24
|
shaka.media.IClosedCaptionParser = class {
|
|
24
25
|
/**
|
|
25
|
-
* Initialize the caption parser. This should be called
|
|
26
|
+
* Initialize the caption parser. This should be called whenever new init
|
|
27
|
+
* segment arrives.
|
|
26
28
|
* @param {BufferSource} initSegment
|
|
27
29
|
*/
|
|
28
30
|
init(initSegment) {}
|
|
@@ -88,6 +90,10 @@ shaka.media.ClosedCaptionParser = class {
|
|
|
88
90
|
* @override
|
|
89
91
|
*/
|
|
90
92
|
init(initSegment) {
|
|
93
|
+
shaka.log.debug('Passing new init segment to CEA parser');
|
|
94
|
+
// Reset underlying decoder when new init segment arrives
|
|
95
|
+
// to clear stored pts values.
|
|
96
|
+
this.reset();
|
|
91
97
|
this.ceaParser_.init(initSegment);
|
|
92
98
|
}
|
|
93
99
|
|
|
@@ -347,14 +347,11 @@ shaka.media.MediaSourceEngine = class {
|
|
|
347
347
|
|
|
348
348
|
const support = {};
|
|
349
349
|
for (const type of testMimeTypes) {
|
|
350
|
-
if (shaka.
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
support[type] = shaka.media.Capabilities.isTypeSupported(type) ||
|
|
356
|
-
shaka.transmuxer.TransmuxerEngine.isSupported(type);
|
|
357
|
-
}
|
|
350
|
+
if (shaka.text.TextEngine.isTypeSupported(type)) {
|
|
351
|
+
support[type] = true;
|
|
352
|
+
} else if (shaka.util.Platform.supportsMediaSource()) {
|
|
353
|
+
support[type] = shaka.media.Capabilities.isTypeSupported(type) ||
|
|
354
|
+
shaka.transmuxer.TransmuxerEngine.isSupported(type);
|
|
358
355
|
} else {
|
|
359
356
|
support[type] = shaka.util.Platform.supportsMediaType(type);
|
|
360
357
|
}
|
|
@@ -470,7 +470,7 @@ shaka.media.SegmentUtils = class {
|
|
|
470
470
|
if (!dolbyVision) {
|
|
471
471
|
return codecs;
|
|
472
472
|
}
|
|
473
|
-
const type = `video/mp4; codecs="${dolbyVision}"
|
|
473
|
+
const type = `video/mp4; codecs="${dolbyVision}"`;
|
|
474
474
|
if (shaka.media.Capabilities.isTypeSupported(type)) {
|
|
475
475
|
return [dolbyVision];
|
|
476
476
|
}
|
package/lib/player.js
CHANGED
|
@@ -715,6 +715,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
715
715
|
this.manifestFilterer_ = new shaka.media.ManifestFilterer(
|
|
716
716
|
this.config_, this.maxHwRes_, null);
|
|
717
717
|
|
|
718
|
+
/** @private {!Array.<shaka.media.PreloadManager>} */
|
|
719
|
+
this.createdPreloadManagers_ = [];
|
|
720
|
+
|
|
718
721
|
/** @private {shaka.util.Stats} */
|
|
719
722
|
this.stats_ = null;
|
|
720
723
|
|
|
@@ -881,6 +884,18 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
881
884
|
|
|
882
885
|
await detachPromise;
|
|
883
886
|
|
|
887
|
+
// A PreloadManager can only be used with the Player instance that created
|
|
888
|
+
// it, so all PreloadManagers this Player has created are now useless.
|
|
889
|
+
// Destroy any remaining managers now, to help prevent memory leaks.
|
|
890
|
+
const preloadManagerDestroys = [];
|
|
891
|
+
for (const preloadManager of this.createdPreloadManagers_) {
|
|
892
|
+
if (!preloadManager.isDestroyed()) {
|
|
893
|
+
preloadManagerDestroys.push(preloadManager.destroy());
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
this.createdPreloadManagers_ = [];
|
|
897
|
+
await Promise.all(preloadManagerDestroys);
|
|
898
|
+
|
|
884
899
|
// Tear-down the event managers to ensure handlers stop firing.
|
|
885
900
|
if (this.globalEventManager_) {
|
|
886
901
|
this.globalEventManager_.release();
|
|
@@ -1972,6 +1987,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1972
1987
|
};
|
|
1973
1988
|
preloadManager = new shaka.media.PreloadManager(
|
|
1974
1989
|
assetUri, mimeType, startTimeOfLoad, startTime, playerInterface);
|
|
1990
|
+
this.createdPreloadManagers_.push(preloadManager);
|
|
1975
1991
|
return preloadManager;
|
|
1976
1992
|
}
|
|
1977
1993
|
|
|
@@ -7201,7 +7217,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
7201
7217
|
* @export
|
|
7202
7218
|
*/
|
|
7203
7219
|
// eslint-disable-next-line no-useless-concat
|
|
7204
|
-
shaka.Player.version = 'v4.8.
|
|
7220
|
+
shaka.Player.version = 'v4.8.4' + '-uncompiled'; // x-release-please-version
|
|
7205
7221
|
|
|
7206
7222
|
// Initialize the deprecation system using the version string we just set
|
|
7207
7223
|
// on the player.
|
|
@@ -88,6 +88,7 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
88
88
|
* @private
|
|
89
89
|
*/
|
|
90
90
|
static async decodingInfo_(mediaDecodingConfig) {
|
|
91
|
+
/** @type {!MediaCapabilitiesDecodingInfo} */
|
|
91
92
|
const res = {
|
|
92
93
|
supported: false,
|
|
93
94
|
powerEfficient: true,
|
|
@@ -96,60 +97,26 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
96
97
|
configuration: mediaDecodingConfig,
|
|
97
98
|
};
|
|
98
99
|
|
|
99
|
-
if (!mediaDecodingConfig) {
|
|
100
|
-
return res;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
100
|
const videoConfig = mediaDecodingConfig['video'];
|
|
104
101
|
const audioConfig = mediaDecodingConfig['audio'];
|
|
105
102
|
|
|
106
|
-
const Capabilities = shaka.media.Capabilities;
|
|
107
|
-
|
|
108
103
|
if (mediaDecodingConfig.type == 'media-source') {
|
|
109
104
|
if (!shaka.util.Platform.supportsMediaSource()) {
|
|
110
105
|
return res;
|
|
111
106
|
}
|
|
112
|
-
|
|
113
|
-
// the stream is supported.
|
|
114
|
-
// Cast platforms will additionally check canDisplayType(), which
|
|
115
|
-
// accepts extended MIME type parameters.
|
|
116
|
-
// See: https://github.com/shaka-project/shaka-player/issues/4726
|
|
107
|
+
|
|
117
108
|
if (videoConfig) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
shaka.polyfill.MediaCapabilities.canCastDisplayType_(videoConfig);
|
|
122
|
-
} else if (shaka.util.Platform.isTizen()) {
|
|
123
|
-
let extendedType = videoConfig.contentType;
|
|
124
|
-
if (videoConfig.width && videoConfig.height) {
|
|
125
|
-
extendedType += `; width=${videoConfig.width}`;
|
|
126
|
-
extendedType += `; height=${videoConfig.height}`;
|
|
127
|
-
}
|
|
128
|
-
if (videoConfig.framerate) {
|
|
129
|
-
extendedType += `; framerate=${videoConfig.framerate}`;
|
|
130
|
-
}
|
|
131
|
-
if (videoConfig.bitrate) {
|
|
132
|
-
extendedType += `; bitrate=${videoConfig.bitrate}`;
|
|
133
|
-
}
|
|
134
|
-
isSupported = Capabilities.isTypeSupported(extendedType);
|
|
135
|
-
} else {
|
|
136
|
-
isSupported = Capabilities.isTypeSupported(videoConfig.contentType);
|
|
137
|
-
}
|
|
109
|
+
const isSupported =
|
|
110
|
+
await shaka.polyfill.MediaCapabilities.checkVideoSupport_(
|
|
111
|
+
videoConfig);
|
|
138
112
|
if (!isSupported) {
|
|
139
113
|
return res;
|
|
140
114
|
}
|
|
141
115
|
}
|
|
142
116
|
|
|
143
117
|
if (audioConfig) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
audioConfig.spatialRendering) {
|
|
147
|
-
const extendedType =
|
|
148
|
-
audioConfig.contentType + '; spatialRendering=true';
|
|
149
|
-
isSupported = Capabilities.isTypeSupported(extendedType);
|
|
150
|
-
} else {
|
|
151
|
-
isSupported = Capabilities.isTypeSupported(audioConfig.contentType);
|
|
152
|
-
}
|
|
118
|
+
const isSupported =
|
|
119
|
+
shaka.polyfill.MediaCapabilities.checkAudioSupport_(audioConfig);
|
|
153
120
|
if (!isSupported) {
|
|
154
121
|
return res;
|
|
155
122
|
}
|
|
@@ -178,122 +145,172 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
178
145
|
if (!mediaDecodingConfig.keySystemConfiguration) {
|
|
179
146
|
// The variant is supported if it's unencrypted.
|
|
180
147
|
res.supported = true;
|
|
181
|
-
return
|
|
148
|
+
return res;
|
|
182
149
|
} else {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (mediaCapkeySystemConfig.audio) {
|
|
194
|
-
let capability = {
|
|
195
|
-
robustness: mediaCapkeySystemConfig.audio.robustness || '',
|
|
196
|
-
contentType: mediaDecodingConfig.audio.contentType,
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
// Some Tizen devices seem to misreport AC-3 support, but correctly
|
|
200
|
-
// report EC-3 support. So query EC-3 as a fallback for AC-3.
|
|
201
|
-
// See https://github.com/shaka-project/shaka-player/issues/2989 for
|
|
202
|
-
// details.
|
|
203
|
-
if (shaka.util.Platform.isTizen() &&
|
|
204
|
-
mediaDecodingConfig.audio.contentType.includes('codecs="ac-3"')) {
|
|
205
|
-
capability = {
|
|
206
|
-
robustness: capability.robustness,
|
|
207
|
-
contentType: 'audio/mp4; codecs="ec-3"',
|
|
208
|
-
};
|
|
209
|
-
}
|
|
150
|
+
const mcapKeySystemConfig = mediaDecodingConfig.keySystemConfiguration;
|
|
151
|
+
const keySystemAccess =
|
|
152
|
+
await shaka.polyfill.MediaCapabilities.checkDrmSupport_(
|
|
153
|
+
videoConfig, audioConfig, mcapKeySystemConfig);
|
|
154
|
+
if (keySystemAccess) {
|
|
155
|
+
res.supported = true;
|
|
156
|
+
res.keySystemAccess = keySystemAccess;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
210
159
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
robustness: capability.robustness,
|
|
214
|
-
contentType: capability.contentType,
|
|
215
|
-
encryptionScheme: mediaCapkeySystemConfig.audio.encryptionScheme,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
160
|
+
return res;
|
|
161
|
+
}
|
|
218
162
|
|
|
219
|
-
|
|
163
|
+
/**
|
|
164
|
+
* @param {!VideoConfiguration} videoConfig The 'video' field of the
|
|
165
|
+
* MediaDecodingConfiguration.
|
|
166
|
+
* @return {!Promise<boolean>}
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
169
|
+
static async checkVideoSupport_(videoConfig) {
|
|
170
|
+
// Use 'shaka.media.Capabilities.isTypeSupported' to check if
|
|
171
|
+
// the stream is supported.
|
|
172
|
+
// Cast platforms will additionally check canDisplayType(), which
|
|
173
|
+
// accepts extended MIME type parameters.
|
|
174
|
+
// See: https://github.com/shaka-project/shaka-player/issues/4726
|
|
175
|
+
if (shaka.util.Platform.isChromecast()) {
|
|
176
|
+
const isSupported =
|
|
177
|
+
await shaka.polyfill.MediaCapabilities.canCastDisplayType_(
|
|
178
|
+
videoConfig);
|
|
179
|
+
return isSupported;
|
|
180
|
+
} else if (shaka.util.Platform.isTizen()) {
|
|
181
|
+
let extendedType = videoConfig.contentType;
|
|
182
|
+
if (videoConfig.width && videoConfig.height) {
|
|
183
|
+
extendedType += `; width=${videoConfig.width}`;
|
|
184
|
+
extendedType += `; height=${videoConfig.height}`;
|
|
220
185
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
};
|
|
227
|
-
if (mediaCapkeySystemConfig.video.encryptionScheme) {
|
|
228
|
-
capability = {
|
|
229
|
-
robustness: capability.robustness,
|
|
230
|
-
contentType: capability.contentType,
|
|
231
|
-
encryptionScheme: mediaCapkeySystemConfig.video.encryptionScheme,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
videoCapabilities.push(capability);
|
|
186
|
+
if (videoConfig.framerate) {
|
|
187
|
+
extendedType += `; framerate=${videoConfig.framerate}`;
|
|
188
|
+
}
|
|
189
|
+
if (videoConfig.bitrate) {
|
|
190
|
+
extendedType += `; bitrate=${videoConfig.bitrate}`;
|
|
235
191
|
}
|
|
192
|
+
return shaka.media.Capabilities.isTypeSupported(extendedType);
|
|
193
|
+
}
|
|
194
|
+
return shaka.media.Capabilities.isTypeSupported(videoConfig.contentType);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @param {!AudioConfiguration} audioConfig The 'audio' field of the
|
|
199
|
+
* MediaDecodingConfiguration.
|
|
200
|
+
* @return {boolean}
|
|
201
|
+
* @private
|
|
202
|
+
*/
|
|
203
|
+
static checkAudioSupport_(audioConfig) {
|
|
204
|
+
let extendedType = audioConfig.contentType;
|
|
205
|
+
if (shaka.util.Platform.isChromecast() && audioConfig.spatialRendering) {
|
|
206
|
+
extendedType += '; spatialRendering=true';
|
|
207
|
+
}
|
|
208
|
+
return shaka.media.Capabilities.isTypeSupported(extendedType);
|
|
209
|
+
}
|
|
236
210
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
211
|
+
/**
|
|
212
|
+
* @param {VideoConfiguration} videoConfig The 'video' field of the
|
|
213
|
+
* MediaDecodingConfiguration.
|
|
214
|
+
* @param {AudioConfiguration} audioConfig The 'audio' field of the
|
|
215
|
+
* MediaDecodingConfiguration.
|
|
216
|
+
* @param {!MediaCapabilitiesKeySystemConfiguration} mcapKeySystemConfig The
|
|
217
|
+
* 'keySystemConfiguration' field of the MediaDecodingConfiguration.
|
|
218
|
+
* @return {Promise<MediaKeySystemAccess>}
|
|
219
|
+
* @private
|
|
220
|
+
*/
|
|
221
|
+
static async checkDrmSupport_(videoConfig, audioConfig, mcapKeySystemConfig) {
|
|
222
|
+
const audioCapabilities = [];
|
|
223
|
+
const videoCapabilities = [];
|
|
224
|
+
|
|
225
|
+
if (mcapKeySystemConfig.audio) {
|
|
226
|
+
const capability = {
|
|
227
|
+
robustness: mcapKeySystemConfig.audio.robustness || '',
|
|
228
|
+
contentType: audioConfig.contentType,
|
|
243
229
|
};
|
|
244
230
|
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
231
|
+
// Some Tizen devices seem to misreport AC-3 support, but correctly
|
|
232
|
+
// report EC-3 support. So query EC-3 as a fallback for AC-3.
|
|
233
|
+
// See https://github.com/shaka-project/shaka-player/issues/2989 for
|
|
234
|
+
// details.
|
|
235
|
+
if (shaka.util.Platform.isTizen() &&
|
|
236
|
+
audioConfig.contentType.includes('codecs="ac-3"')) {
|
|
237
|
+
capability.contentType = 'audio/mp4; codecs="ec-3"';
|
|
249
238
|
}
|
|
250
|
-
|
|
251
|
-
|
|
239
|
+
|
|
240
|
+
if (mcapKeySystemConfig.audio.encryptionScheme) {
|
|
241
|
+
capability.encryptionScheme =
|
|
242
|
+
mcapKeySystemConfig.audio.encryptionScheme;
|
|
252
243
|
}
|
|
253
244
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
.memoizedMediaKeySystemAccessRequests_) {
|
|
266
|
-
keySystemAccess = shaka.polyfill.MediaCapabilities
|
|
267
|
-
.memoizedMediaKeySystemAccessRequests_[cacheKey];
|
|
268
|
-
} else {
|
|
269
|
-
keySystemAccess = await navigator.requestMediaKeySystemAccess(
|
|
270
|
-
mediaCapkeySystemConfig.keySystem, [mediaKeySystemConfig]);
|
|
271
|
-
shaka.polyfill.MediaCapabilities
|
|
272
|
-
.memoizedMediaKeySystemAccessRequests_[cacheKey] =
|
|
273
|
-
keySystemAccess;
|
|
274
|
-
}
|
|
275
|
-
} catch (e) {
|
|
276
|
-
shaka.log.info('navigator.requestMediaKeySystemAccess failed.');
|
|
245
|
+
audioCapabilities.push(capability);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (mcapKeySystemConfig.video) {
|
|
249
|
+
const capability = {
|
|
250
|
+
robustness: mcapKeySystemConfig.video.robustness || '',
|
|
251
|
+
contentType: videoConfig.contentType,
|
|
252
|
+
};
|
|
253
|
+
if (mcapKeySystemConfig.video.encryptionScheme) {
|
|
254
|
+
capability.encryptionScheme =
|
|
255
|
+
mcapKeySystemConfig.video.encryptionScheme;
|
|
277
256
|
}
|
|
257
|
+
videoCapabilities.push(capability);
|
|
258
|
+
}
|
|
278
259
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
260
|
+
/** @type {MediaKeySystemConfiguration} */
|
|
261
|
+
const mediaKeySystemConfig = {
|
|
262
|
+
initDataTypes: [mcapKeySystemConfig.initDataType],
|
|
263
|
+
distinctiveIdentifier: mcapKeySystemConfig.distinctiveIdentifier,
|
|
264
|
+
persistentState: mcapKeySystemConfig.persistentState,
|
|
265
|
+
sessionTypes: mcapKeySystemConfig.sessionTypes,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// Only add audio / video capabilities if they have valid data.
|
|
269
|
+
// Otherwise the query will fail.
|
|
270
|
+
if (audioCapabilities.length) {
|
|
271
|
+
mediaKeySystemConfig.audioCapabilities = audioCapabilities;
|
|
272
|
+
}
|
|
273
|
+
if (videoCapabilities.length) {
|
|
274
|
+
mediaKeySystemConfig.videoCapabilities = videoCapabilities;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const cacheKey = shaka.polyfill.MediaCapabilities
|
|
278
|
+
.generateKeySystemCacheKey_(
|
|
279
|
+
videoConfig ? videoConfig.contentType : '',
|
|
280
|
+
audioConfig ? audioConfig.contentType : '',
|
|
281
|
+
mcapKeySystemConfig.keySystem);
|
|
282
|
+
|
|
283
|
+
/** @type {MediaKeySystemAccess} */
|
|
284
|
+
let keySystemAccess = null;
|
|
285
|
+
try {
|
|
286
|
+
if (cacheKey in shaka.polyfill.MediaCapabilities
|
|
287
|
+
.memoizedMediaKeySystemAccessRequests_) {
|
|
288
|
+
keySystemAccess = shaka.polyfill.MediaCapabilities
|
|
289
|
+
.memoizedMediaKeySystemAccessRequests_[cacheKey];
|
|
290
|
+
} else {
|
|
291
|
+
keySystemAccess = await navigator.requestMediaKeySystemAccess(
|
|
292
|
+
mcapKeySystemConfig.keySystem, [mediaKeySystemConfig]);
|
|
293
|
+
shaka.polyfill.MediaCapabilities
|
|
294
|
+
.memoizedMediaKeySystemAccessRequests_[cacheKey] =
|
|
295
|
+
keySystemAccess;
|
|
282
296
|
}
|
|
297
|
+
} catch (e) {
|
|
298
|
+
shaka.log.info('navigator.requestMediaKeySystemAccess failed.');
|
|
283
299
|
}
|
|
284
300
|
|
|
285
|
-
return
|
|
301
|
+
return keySystemAccess;
|
|
286
302
|
}
|
|
287
303
|
|
|
288
304
|
/**
|
|
289
305
|
* Checks if the given media parameters of the video or audio streams are
|
|
290
306
|
* supported by the Cast platform.
|
|
291
307
|
* @param {!VideoConfiguration} videoConfig The 'video' field of the
|
|
292
|
-
*
|
|
293
|
-
* @return {boolean} `true` when the stream can be displayed on a
|
|
308
|
+
* MediaDecodingConfiguration.
|
|
309
|
+
* @return {!Promise<boolean>} `true` when the stream can be displayed on a
|
|
310
|
+
* Cast device.
|
|
294
311
|
* @private
|
|
295
312
|
*/
|
|
296
|
-
static canCastDisplayType_(videoConfig) {
|
|
313
|
+
static async canCastDisplayType_(videoConfig) {
|
|
297
314
|
if (!(window.cast &&
|
|
298
315
|
cast.__platform__ && cast.__platform__.canDisplayType)) {
|
|
299
316
|
shaka.log.warning('Expected cast APIs to be available! Falling back to ' +
|
|
@@ -321,7 +338,7 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
321
338
|
result = shaka.polyfill.MediaCapabilities
|
|
322
339
|
.memoizedCanDisplayTypeRequests_[displayType];
|
|
323
340
|
} else {
|
|
324
|
-
result = cast.__platform__.canDisplayType(displayType);
|
|
341
|
+
result = await cast.__platform__.canDisplayType(displayType);
|
|
325
342
|
shaka.polyfill.MediaCapabilities
|
|
326
343
|
.memoizedCanDisplayTypeRequests_[displayType] = result;
|
|
327
344
|
}
|
|
@@ -22,6 +22,7 @@ goog.require('shaka.util.Id3Utils');
|
|
|
22
22
|
goog.require('shaka.util.ManifestParserUtils');
|
|
23
23
|
goog.require('shaka.util.MimeUtils');
|
|
24
24
|
goog.require('shaka.util.Mp4Generator');
|
|
25
|
+
goog.require('shaka.util.StreamUtils');
|
|
25
26
|
goog.require('shaka.util.TsParser');
|
|
26
27
|
goog.require('shaka.util.Uint8ArrayUtils');
|
|
27
28
|
|
|
@@ -149,7 +150,7 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
149
150
|
// MediaSource.isTypeSupported('audio/mp4; codecs="mp3"') -> true
|
|
150
151
|
const codecs = shaka.util.MimeUtils.getCodecs(mimeType)
|
|
151
152
|
.replace('mp4a.40.34', 'mp3').split(',')
|
|
152
|
-
.map(
|
|
153
|
+
.map(shaka.util.StreamUtils.getCorrectVideoCodecs).join(',');
|
|
153
154
|
if (contentType == ContentType.AUDIO) {
|
|
154
155
|
return `audio/mp4; codecs="${codecs}"`;
|
|
155
156
|
}
|
|
@@ -159,29 +160,6 @@ shaka.transmuxer.TsTransmuxer = class {
|
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
|
|
162
|
-
/**
|
|
163
|
-
* @param {string} codec
|
|
164
|
-
* @return {string}
|
|
165
|
-
* @private
|
|
166
|
-
*/
|
|
167
|
-
getCorrectVideoCodecs_(codec) {
|
|
168
|
-
if (codec.includes('avc1')) {
|
|
169
|
-
// Convert avc1 codec string from RFC-4281 to RFC-6381 for
|
|
170
|
-
// MediaSource.isTypeSupported
|
|
171
|
-
// Example, convert avc1.66.30 to avc1.42001e (0x42 == 66 and 0x1e == 30)
|
|
172
|
-
const avcdata = codec.split('.');
|
|
173
|
-
if (avcdata.length == 3) {
|
|
174
|
-
let result = avcdata.shift() + '.';
|
|
175
|
-
result += parseInt(avcdata.shift(), 10).toString(16);
|
|
176
|
-
result +=
|
|
177
|
-
('000' + parseInt(avcdata.shift(), 10).toString(16)).slice(-4);
|
|
178
|
-
return result;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return codec;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
163
|
/**
|
|
186
164
|
* @override
|
|
187
165
|
* @export
|
package/lib/util/platform.js
CHANGED
|
@@ -197,6 +197,17 @@ shaka.util.Platform = class {
|
|
|
197
197
|
return Platform.isChromecast() && Platform.isAndroid();
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
/**
|
|
201
|
+
* Check if the current platform is a Google Chromecast with Android
|
|
202
|
+
* (i.e. Chromecast with GoogleTV).
|
|
203
|
+
*
|
|
204
|
+
* @return {boolean}
|
|
205
|
+
*/
|
|
206
|
+
static isFuchsiaCastDevice() {
|
|
207
|
+
const Platform = shaka.util.Platform;
|
|
208
|
+
return Platform.isChromecast() && Platform.isFuchsia();
|
|
209
|
+
}
|
|
210
|
+
|
|
200
211
|
/**
|
|
201
212
|
* Returns a major version number for Chrome, or Chromium-based browsers.
|
|
202
213
|
*
|
|
@@ -459,6 +470,15 @@ shaka.util.Platform = class {
|
|
|
459
470
|
return shaka.util.Platform.userAgentContains_('Android');
|
|
460
471
|
}
|
|
461
472
|
|
|
473
|
+
/**
|
|
474
|
+
* Return true if the platform is a Fuchsia, regardless of the browser.
|
|
475
|
+
*
|
|
476
|
+
* @return {boolean}
|
|
477
|
+
*/
|
|
478
|
+
static isFuchsia() {
|
|
479
|
+
return shaka.util.Platform.userAgentContains_('Fuchsia');
|
|
480
|
+
}
|
|
481
|
+
|
|
462
482
|
/**
|
|
463
483
|
* Return true if the platform is controlled by a remote control.
|
|
464
484
|
*
|
|
@@ -611,19 +631,32 @@ shaka.util.Platform = class {
|
|
|
611
631
|
|
|
612
632
|
if (Platform.isChromecast()) {
|
|
613
633
|
// In our tests, the original Chromecast seems to have trouble decoding
|
|
614
|
-
// above 1080p.
|
|
634
|
+
// above 1080p. It would be a waste to select a higher res anyway, given
|
|
615
635
|
// that the device only outputs 1080p to begin with.
|
|
616
636
|
// Chromecast has an extension to query the device/display's resolution.
|
|
617
|
-
|
|
618
|
-
cast.__platform__.canDisplayType
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
637
|
+
const hasCanDisplayType = window.cast && cast.__platform__ &&
|
|
638
|
+
cast.__platform__.canDisplayType;
|
|
639
|
+
|
|
640
|
+
// Some hub devices can only do 720p. Default to that.
|
|
641
|
+
maxResolution.width = 1280;
|
|
642
|
+
maxResolution.height = 720;
|
|
643
|
+
|
|
644
|
+
try {
|
|
645
|
+
if (hasCanDisplayType && await cast.__platform__.canDisplayType(
|
|
646
|
+
'video/mp4; codecs="avc1.640028"; width=3840; height=2160')) {
|
|
647
|
+
// The device and display can both do 4k. Assume a 4k limit.
|
|
648
|
+
maxResolution.width = 3840;
|
|
649
|
+
maxResolution.height = 2160;
|
|
650
|
+
} else if (hasCanDisplayType && await cast.__platform__.canDisplayType(
|
|
651
|
+
'video/mp4; codecs="avc1.640028"; width=1920; height=1080')) {
|
|
652
|
+
// Most Chromecasts can do 1080p.
|
|
653
|
+
maxResolution.width = 1920;
|
|
654
|
+
maxResolution.height = 1080;
|
|
655
|
+
}
|
|
656
|
+
} catch (error) {
|
|
657
|
+
// This shouldn't generally happen. Log the error.
|
|
658
|
+
shaka.log.alwaysError('Failed to check canDisplayType:', error);
|
|
659
|
+
// Now ignore the error and let the 720p default stand.
|
|
627
660
|
}
|
|
628
661
|
} else if (Platform.isTizen()) {
|
|
629
662
|
maxResolution.width = 1920;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shaka-player",
|
|
3
3
|
"description": "DASH/EME video player library",
|
|
4
|
-
"version": "4.8.
|
|
4
|
+
"version": "4.8.4",
|
|
5
5
|
"homepage": "https://github.com/shaka-project/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -63,6 +63,11 @@
|
|
|
63
63
|
"tippy.js": "^4.3.5",
|
|
64
64
|
"which": "^2.0.2"
|
|
65
65
|
},
|
|
66
|
+
"overrides": {
|
|
67
|
+
"karma": {
|
|
68
|
+
"ua-parser-js": "github:joeyparrish/ua-parser-js#preview"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
66
71
|
"shakaCustom": {
|
|
67
72
|
"purposeOfDemoDeps": "These are the files from node_modules that need to be deployed with the demo app.",
|
|
68
73
|
"demoDeps": [
|