shaka-player 4.5.0 → 4.6.0
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/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/AUTHORS +2 -0
- package/CHANGELOG.md +98 -0
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTORS +2 -0
- package/README.md +38 -32
- package/demo/common/asset.js +11 -17
- package/demo/common/assets.js +117 -11
- package/demo/config.js +28 -1
- package/demo/custom.js +52 -38
- package/demo/main.js +11 -3
- package/demo/search.js +7 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +133 -124
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +133 -124
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +20 -18
- package/dist/locales.js +35 -31
- package/dist/receiver.compiled.debug.js +58 -50
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +58 -50
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +440 -390
- package/dist/shaka-player.compiled.debug.d.ts +440 -390
- package/dist/shaka-player.compiled.debug.externs.js +162 -77
- package/dist/shaka-player.compiled.debug.js +786 -736
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +162 -77
- package/dist/shaka-player.compiled.js +1154 -1121
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +491 -437
- package/dist/shaka-player.ui.debug.d.ts +491 -437
- package/dist/shaka-player.ui.debug.externs.js +167 -77
- package/dist/shaka-player.ui.debug.js +877 -811
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +167 -77
- package/dist/shaka-player.ui.js +1362 -1318
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ad_monetization.md +54 -0
- package/docs/tutorials/basic-usage.md +2 -1
- package/docs/tutorials/errors.md +2 -1
- package/docs/tutorials/offline.md +10 -8
- package/docs/tutorials/plugins.md +5 -0
- package/docs/tutorials/ui-customization.md +13 -0
- package/docs/tutorials/ui.md +2 -1
- package/docs/tutorials/upgrade.md +3 -0
- package/externs/managedmediasource.js +24 -0
- package/externs/shaka/abr_manager.js +6 -2
- package/externs/shaka/cea.js +7 -0
- package/externs/shaka/codecs.js +5 -3
- package/externs/shaka/manifest.js +21 -5
- package/externs/shaka/manifest_parser.js +17 -0
- package/externs/shaka/net.js +2 -2
- package/externs/shaka/offline.js +9 -2
- package/externs/shaka/player.js +53 -7
- package/externs/shaka/text.js +3 -1
- package/externs/shaka/transmuxer.js +1 -1
- package/lib/abr/simple_abr_manager.js +25 -8
- package/lib/ads/media_tailor_ad_manager.js +14 -3
- package/lib/cast/cast_receiver.js +1 -1
- package/lib/cea/cea_decoder.js +28 -0
- package/lib/cea/dummy_caption_decoder.js +5 -0
- package/lib/dash/dash_parser.js +249 -83
- package/lib/dash/mpd_utils.js +52 -31
- package/lib/dash/segment_base.js +4 -5
- package/lib/dash/segment_list.js +5 -4
- package/lib/dash/segment_template.js +83 -26
- package/lib/hls/hls_classes.js +28 -43
- package/lib/hls/hls_parser.js +761 -649
- package/lib/hls/hls_utils.js +64 -5
- package/lib/hls/manifest_text_parser.js +7 -11
- package/lib/media/adaptation_set.js +20 -13
- package/lib/media/adaptation_set_criteria.js +70 -18
- package/lib/media/closed_caption_parser.js +13 -0
- package/lib/media/content_workarounds.js +6 -0
- package/lib/media/drm_engine.js +8 -13
- package/lib/media/manifest_parser.js +8 -113
- package/lib/media/media_source_capabilities.js +10 -3
- package/lib/media/media_source_engine.js +75 -21
- package/lib/media/play_rate_controller.js +8 -38
- package/lib/media/presentation_timeline.js +7 -1
- package/lib/media/quality_observer.js +1 -1
- package/lib/media/segment_index.js +5 -5
- package/lib/media/segment_prefetch.js +92 -24
- package/lib/media/segment_reference.js +67 -1
- package/lib/media/segment_utils.js +343 -0
- package/lib/media/stall_detector.js +0 -3
- package/lib/media/streaming_engine.js +41 -21
- package/lib/mss/mss_parser.js +18 -2
- package/lib/net/networking_engine.js +66 -12
- package/lib/net/networking_utils.js +95 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
- package/lib/offline/manifest_converter.js +2 -0
- package/lib/offline/offline_manifest_parser.js +10 -0
- package/lib/offline/storage.js +11 -7
- package/lib/player.js +993 -1502
- package/lib/polyfill/mediasource.js +22 -1
- package/lib/text/mp4_ttml_parser.js +2 -2
- package/lib/text/srt_text_parser.js +2 -2
- package/lib/text/stub_text_displayer.js +51 -0
- package/lib/text/text_engine.js +3 -2
- package/lib/text/ttml_text_parser.js +28 -5
- package/lib/text/ui_text_displayer.js +4 -0
- package/lib/text/vtt_text_parser.js +7 -2
- package/lib/transmuxer/aac_transmuxer.js +1 -1
- package/lib/transmuxer/ac3_transmuxer.js +1 -1
- package/lib/transmuxer/ec3_transmuxer.js +1 -1
- package/lib/transmuxer/h264.js +5 -4
- package/lib/transmuxer/h265.js +5 -4
- package/lib/transmuxer/mp3_transmuxer.js +1 -1
- package/lib/transmuxer/mpeg_ts_transmuxer.js +1 -1
- package/lib/transmuxer/mss_transmuxer.js +1 -1
- package/lib/transmuxer/ts_transmuxer.js +33 -13
- package/lib/util/buffer_utils.js +26 -4
- package/lib/util/content_steering_manager.js +358 -0
- package/lib/util/error.js +2 -6
- package/lib/util/fairplay_utils.js +1 -1
- package/lib/util/fake_event.js +5 -1
- package/lib/util/id3_utils.js +50 -1
- package/lib/util/manifest_parser_utils.js +12 -8
- package/lib/util/mp4_generator.js +2 -4
- package/lib/util/mutex.js +59 -0
- package/lib/util/object_utils.js +1 -1
- package/lib/util/periods.js +154 -179
- package/lib/util/platform.js +4 -3
- package/lib/util/player_configuration.js +35 -6
- package/lib/util/stream_utils.js +105 -98
- package/lib/util/ts_parser.js +124 -73
- package/lib/util/uint8array_utils.js +5 -1
- package/lib/util/xml_utils.js +5 -0
- package/maintained-branches.md +2 -2
- package/package.json +1 -1
- package/roadmap.md +15 -5
- package/shaka-player.uncompiled.js +0 -1
- package/test/abr/simple_abr_manager_unit.js +33 -33
- package/test/ads/ad_manager_unit.js +3 -2
- package/test/cast/cast_receiver_integration.js +3 -4
- package/test/cast/cast_utils_unit.js +2 -0
- package/test/cea/cea_decoder_unit.js +7 -0
- package/test/codec_switching/codec_switching_integration.js +2 -1
- package/test/dash/dash_parser_integration.js +2 -1
- package/test/dash/dash_parser_live_unit.js +0 -19
- package/test/dash/dash_parser_manifest_unit.js +494 -2
- package/test/dash/mpd_utils_unit.js +61 -30
- package/test/hls/hls_live_unit.js +12 -3
- package/test/hls/hls_parser_unit.js +377 -27
- package/test/hls/manifest_text_parser_unit.js +32 -99
- package/test/media/adaptation_set_criteria_unit.js +172 -21
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/content_workarounds_unit.js +1 -1
- package/test/media/drm_engine_unit.js +3 -3
- package/test/media/media_source_engine_unit.js +1 -1
- package/test/media/play_rate_controller_unit.js +0 -48
- package/test/media/segment_index_unit.js +2 -1
- package/test/mss/mss_player_integration.js +3 -2
- package/test/net/networking_engine_unit.js +3 -3
- package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
- package/test/offline/manifest_convert_unit.js +9 -0
- package/test/offline/offline_integration.js +2 -1
- package/test/offline/storage_integration.js +21 -9
- package/test/player_external.js +4 -2
- package/test/player_integration.js +15 -4
- package/test/player_load_graph_integration.js +47 -151
- package/test/player_src_equals_external.js +1 -0
- package/test/player_src_equals_integration.js +71 -4
- package/test/player_unit.js +80 -27
- package/test/test/util/fake_media_source_engine.js +5 -0
- package/test/test/util/fake_networking_engine.js +9 -1
- package/test/test/util/fake_segment_prefetch.js +3 -0
- package/test/test/util/manifest_generator.js +4 -0
- package/test/test/util/manifest_parser_util.js +14 -2
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/simple_fakes.js +2 -2
- package/test/test/util/streaming_engine_util.js +3 -0
- package/test/test/util/test_scheme.js +6 -0
- package/test/test/util/ui_utils.js +4 -3
- package/test/text/mp4_ttml_parser_unit.js +4 -4
- package/test/text/srt_text_parser_unit.js +1 -1
- package/test/text/text_displayer_layout_unit.js +1 -1
- package/test/text/text_engine_unit.js +6 -0
- package/test/text/ttml_text_parser_unit.js +33 -2
- package/test/transmuxer/transmuxer_engine_integration.js +9 -0
- package/test/transmuxer/transmuxer_integration.js +33 -3
- package/test/ui/ad_ui_unit.js +2 -2
- package/test/ui/ui_customization_unit.js +17 -16
- package/test/ui/ui_integration.js +30 -20
- package/test/ui/ui_unit.js +25 -19
- package/test/util/buffer_utils_unit.js +1 -1
- package/test/util/content_steering_manager_unit.js +427 -0
- package/test/util/id3_utils_unit.js +52 -0
- package/test/util/stream_utils_unit.js +17 -113
- package/test/util/ts_parser_unit.js +3 -3
- package/third_party/closure-uri/uri.js +13 -1
- package/ui/audio_language_selection.js +9 -2
- package/ui/externs/ui.js +17 -2
- package/ui/language_utils.js +43 -8
- package/ui/less/range_elements.less +33 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/es-419.json +1 -0
- package/ui/locales/es.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +10 -0
- package/ui/remote_button.js +3 -1
- package/ui/resolution_selection.js +47 -10
- package/ui/seek_bar.js +296 -3
- package/ui/text_selection.js +2 -1
- package/ui/ui.js +6 -2
- package/lib/routing/node.js +0 -23
- package/lib/routing/payload.js +0 -47
- package/lib/routing/walker.js +0 -587
- package/test/routing/walker_unit.js +0 -505
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.util.ContentSteeringManager');
|
|
8
|
+
|
|
9
|
+
goog.require('goog.Uri');
|
|
10
|
+
goog.require('shaka.media.ManifestParser');
|
|
11
|
+
goog.require('shaka.net.NetworkingEngine');
|
|
12
|
+
goog.require('shaka.util.Error');
|
|
13
|
+
goog.require('shaka.util.IDestroyable');
|
|
14
|
+
goog.require('shaka.util.ManifestParserUtils');
|
|
15
|
+
goog.require('shaka.util.OperationManager');
|
|
16
|
+
goog.require('shaka.util.StringUtils');
|
|
17
|
+
goog.require('shaka.util.Timer');
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a Content Steering manager.
|
|
22
|
+
*
|
|
23
|
+
* @implements {shaka.util.IDestroyable}
|
|
24
|
+
*/
|
|
25
|
+
shaka.util.ContentSteeringManager = class {
|
|
26
|
+
/**
|
|
27
|
+
* @param {shaka.extern.ManifestParser.PlayerInterface} playerInterface
|
|
28
|
+
*/
|
|
29
|
+
constructor(playerInterface) {
|
|
30
|
+
/** @private {?shaka.extern.ManifestConfiguration} */
|
|
31
|
+
this.config_ = null;
|
|
32
|
+
|
|
33
|
+
/** @private {?shaka.extern.ManifestParser.PlayerInterface} */
|
|
34
|
+
this.playerInterface_ = playerInterface;
|
|
35
|
+
|
|
36
|
+
/** @private {!shaka.util.OperationManager} */
|
|
37
|
+
this.operationManager_ = new shaka.util.OperationManager();
|
|
38
|
+
|
|
39
|
+
/** @private {!Array.<string>} */
|
|
40
|
+
this.baseUris_ = [];
|
|
41
|
+
|
|
42
|
+
/** @private {?string} */
|
|
43
|
+
this.defaultPathwayId_ = null;
|
|
44
|
+
|
|
45
|
+
/** @private {!Array.<string>} */
|
|
46
|
+
this.pathwayPriority_ = [];
|
|
47
|
+
|
|
48
|
+
/** @private {?string} */
|
|
49
|
+
this.lastPathwayUsed_ = null;
|
|
50
|
+
|
|
51
|
+
/** @private {!Array.<shaka.util.ContentSteeringManager.PathawayClone>} */
|
|
52
|
+
this.pathwayClones_ = [];
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Default to 5 minutes. Value in seconds.
|
|
56
|
+
*
|
|
57
|
+
* @private {number}
|
|
58
|
+
*/
|
|
59
|
+
this.lastTTL_ = 300;
|
|
60
|
+
|
|
61
|
+
/** @private {!Map.<(string|number), !Map.<string, string>>} */
|
|
62
|
+
this.locations_ = new Map();
|
|
63
|
+
|
|
64
|
+
/** @private {!Map.<string, number>} */
|
|
65
|
+
this.bannedLocations_ = new Map();
|
|
66
|
+
|
|
67
|
+
/** @private {?shaka.util.Timer} */
|
|
68
|
+
this.updateTimer_ = null;
|
|
69
|
+
|
|
70
|
+
/** @private {string} */
|
|
71
|
+
this.manifestType_ = shaka.media.ManifestParser.UNKNOWN;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {shaka.extern.ManifestConfiguration} config
|
|
76
|
+
*/
|
|
77
|
+
configure(config) {
|
|
78
|
+
this.config_ = config;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
/** @override */
|
|
83
|
+
destroy() {
|
|
84
|
+
this.config_ = null;
|
|
85
|
+
this.playerInterface_ = null;
|
|
86
|
+
this.baseUris_ = [];
|
|
87
|
+
this.defaultPathwayId_ = null;
|
|
88
|
+
this.pathwayPriority_ = [];
|
|
89
|
+
this.pathwayClones_ = [];
|
|
90
|
+
this.locations_.clear();
|
|
91
|
+
|
|
92
|
+
if (this.updateTimer_ != null) {
|
|
93
|
+
this.updateTimer_.stop();
|
|
94
|
+
this.updateTimer_ = null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return this.operationManager_.destroy();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {string} manifestType
|
|
102
|
+
*/
|
|
103
|
+
setManifestType(manifestType) {
|
|
104
|
+
this.manifestType_ = manifestType;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {!Array.<string>} baseUris
|
|
109
|
+
*/
|
|
110
|
+
setBaseUris(baseUris) {
|
|
111
|
+
this.baseUris_ = baseUris;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @param {?string} defaultPathwayId
|
|
116
|
+
*/
|
|
117
|
+
setDefaultPathwayId(defaultPathwayId) {
|
|
118
|
+
this.defaultPathwayId_ = defaultPathwayId;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Request the Content Steering info.
|
|
123
|
+
*
|
|
124
|
+
* @param {string} uri
|
|
125
|
+
* @return {!Promise}
|
|
126
|
+
*/
|
|
127
|
+
async requestInfo(uri) {
|
|
128
|
+
const uris = shaka.util.ManifestParserUtils.resolveUris(
|
|
129
|
+
this.baseUris_, [this.addQueryParams_(uri)]);
|
|
130
|
+
const type = shaka.net.NetworkingEngine.RequestType.CONTENT_STEERING;
|
|
131
|
+
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
132
|
+
uris, this.config_.retryParameters);
|
|
133
|
+
|
|
134
|
+
const op = this.playerInterface_.networkingEngine.request(type, request);
|
|
135
|
+
this.operationManager_.manage(op);
|
|
136
|
+
try {
|
|
137
|
+
const response = await op.promise;
|
|
138
|
+
const str = shaka.util.StringUtils.fromUTF8(response.data);
|
|
139
|
+
const steeringManifest =
|
|
140
|
+
/** @type {shaka.util.ContentSteeringManager.SteeringManifest} */
|
|
141
|
+
(JSON.parse(str));
|
|
142
|
+
if (steeringManifest.VERSION == 1) {
|
|
143
|
+
this.processManifest_(steeringManifest, response.uri);
|
|
144
|
+
}
|
|
145
|
+
} catch (e) {
|
|
146
|
+
if (e && e.code == shaka.util.Error.Code.OPERATION_ABORTED) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (this.updateTimer_ != null) {
|
|
150
|
+
this.updateTimer_.stop();
|
|
151
|
+
this.updateTimer_ = null;
|
|
152
|
+
}
|
|
153
|
+
this.updateTimer_ = new shaka.util.Timer(() => {
|
|
154
|
+
this.requestInfo(uri);
|
|
155
|
+
});
|
|
156
|
+
this.updateTimer_.tickAfter(this.lastTTL_);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** @private */
|
|
161
|
+
addQueryParams_(uri) {
|
|
162
|
+
if (!this.pathwayPriority_.length) {
|
|
163
|
+
return uri;
|
|
164
|
+
}
|
|
165
|
+
const finalUri = new goog.Uri(uri);
|
|
166
|
+
const currentPathwayID = this.lastPathwayUsed_ || this.pathwayPriority_[0];
|
|
167
|
+
const currentBandwidth =
|
|
168
|
+
Math.round(this.playerInterface_.getBandwidthEstimate());
|
|
169
|
+
const queryData = finalUri.getQueryData();
|
|
170
|
+
if (this.manifestType_ == shaka.media.ManifestParser.DASH) {
|
|
171
|
+
queryData.add('_DASH_pathway', currentPathwayID);
|
|
172
|
+
queryData.add('_DASH_throughput', String(currentBandwidth));
|
|
173
|
+
} else if (this.manifestType_ == shaka.media.ManifestParser.HLS) {
|
|
174
|
+
queryData.add('_HLS_pathway', currentPathwayID);
|
|
175
|
+
queryData.add('_HLS_throughput', String(currentBandwidth));
|
|
176
|
+
}
|
|
177
|
+
if (queryData.getCount()) {
|
|
178
|
+
finalUri.setQueryData(queryData);
|
|
179
|
+
}
|
|
180
|
+
return finalUri.toString();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @param {shaka.util.ContentSteeringManager.SteeringManifest} manifest
|
|
185
|
+
* @param {string} finalManifestUri
|
|
186
|
+
* @private
|
|
187
|
+
*/
|
|
188
|
+
processManifest_(manifest, finalManifestUri) {
|
|
189
|
+
if (this.updateTimer_ != null) {
|
|
190
|
+
this.updateTimer_.stop();
|
|
191
|
+
this.updateTimer_ = null;
|
|
192
|
+
}
|
|
193
|
+
const uri = manifest['RELOAD-URI'] || finalManifestUri;
|
|
194
|
+
this.updateTimer_ = new shaka.util.Timer(() => {
|
|
195
|
+
this.requestInfo(uri);
|
|
196
|
+
});
|
|
197
|
+
const newTTL = manifest['TTL'];
|
|
198
|
+
if (newTTL) {
|
|
199
|
+
this.lastTTL_ = newTTL;
|
|
200
|
+
}
|
|
201
|
+
this.updateTimer_.tickAfter(this.lastTTL_);
|
|
202
|
+
this.pathwayPriority_ = manifest['PATHWAY-PRIORITY'] || [];
|
|
203
|
+
this.pathwayClones_ = manifest['PATHWAY-CLONES'] || [];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Clear the previous locations added.
|
|
208
|
+
*/
|
|
209
|
+
clearPreviousLocations() {
|
|
210
|
+
this.locations_.clear();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @param {string|number} streamId
|
|
215
|
+
* @param {string} pathwayId
|
|
216
|
+
* @param {string} uri
|
|
217
|
+
*/
|
|
218
|
+
addLocation(streamId, pathwayId, uri) {
|
|
219
|
+
let streamLocations = this.locations_.get(streamId);
|
|
220
|
+
if (!streamLocations) {
|
|
221
|
+
streamLocations = new Map();
|
|
222
|
+
}
|
|
223
|
+
streamLocations.set(pathwayId, uri);
|
|
224
|
+
this.locations_.set(streamId, streamLocations);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @param {string} uri
|
|
229
|
+
*/
|
|
230
|
+
banLocation(uri) {
|
|
231
|
+
const bannedUntil = Date.now() + 60000;
|
|
232
|
+
this.bannedLocations_.set(uri, bannedUntil);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get the base locations ordered according the priority.
|
|
237
|
+
*
|
|
238
|
+
* @param {string|number} streamId
|
|
239
|
+
* @return {!Array.<string>}
|
|
240
|
+
*/
|
|
241
|
+
getLocations(streamId) {
|
|
242
|
+
const streamLocations = this.locations_.get(streamId) || new Map();
|
|
243
|
+
/** @type {!Array.<!{pathwayId: string, location: string}>} */
|
|
244
|
+
let locationsPathwayIdMap = [];
|
|
245
|
+
for (const pathwayId of this.pathwayPriority_) {
|
|
246
|
+
const location = streamLocations.get(pathwayId);
|
|
247
|
+
if (location) {
|
|
248
|
+
locationsPathwayIdMap.push({pathwayId, location});
|
|
249
|
+
} else {
|
|
250
|
+
const clone = this.pathwayClones_.find((c) => c.ID == pathwayId);
|
|
251
|
+
if (clone) {
|
|
252
|
+
const cloneLocation = streamLocations.get(clone['BASE-ID']);
|
|
253
|
+
if (cloneLocation) {
|
|
254
|
+
if (clone['URI-REPLACEMENT'].HOST) {
|
|
255
|
+
const uri = new goog.Uri(cloneLocation);
|
|
256
|
+
uri.setDomain(clone['URI-REPLACEMENT'].HOST);
|
|
257
|
+
locationsPathwayIdMap.push({
|
|
258
|
+
pathwayId: pathwayId,
|
|
259
|
+
location: uri.toString(),
|
|
260
|
+
});
|
|
261
|
+
} else {
|
|
262
|
+
locationsPathwayIdMap.push({
|
|
263
|
+
pathwayId: pathwayId,
|
|
264
|
+
location: cloneLocation,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const now = Date.now();
|
|
273
|
+
for (const uri of this.bannedLocations_.keys()) {
|
|
274
|
+
const bannedUntil = this.bannedLocations_.get(uri);
|
|
275
|
+
if (now > bannedUntil) {
|
|
276
|
+
this.bannedLocations_.delete(uri);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
locationsPathwayIdMap = locationsPathwayIdMap.filter((l) => {
|
|
280
|
+
for (const uri of this.bannedLocations_.keys()) {
|
|
281
|
+
if (uri.includes(new goog.Uri(l.location).getDomain())) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return true;
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
if (locationsPathwayIdMap.length) {
|
|
289
|
+
this.lastPathwayUsed_ = locationsPathwayIdMap[0].pathwayId;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const locations = locationsPathwayIdMap.map((l) => l.location);
|
|
293
|
+
|
|
294
|
+
if (!locations.length && this.defaultPathwayId_) {
|
|
295
|
+
for (const pathwayId of this.defaultPathwayId_.split(',')) {
|
|
296
|
+
const location = streamLocations.get(pathwayId);
|
|
297
|
+
if (location) {
|
|
298
|
+
this.lastPathwayUsed_ = this.defaultPathwayId_;
|
|
299
|
+
locations.push(location);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (!locations.length) {
|
|
304
|
+
for (const location of streamLocations.values()) {
|
|
305
|
+
locations.push(location);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return shaka.util.ManifestParserUtils.resolveUris(
|
|
309
|
+
this.baseUris_, locations);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* @typedef {{
|
|
316
|
+
* VERSION: number,
|
|
317
|
+
* TTL: number,
|
|
318
|
+
* RELOAD-URI: string,
|
|
319
|
+
* PATHWAY-PRIORITY: !Array.<string>,
|
|
320
|
+
* PATHWAY-CLONES: !Array.<shaka.util.ContentSteeringManager.PathawayClone>
|
|
321
|
+
* }}
|
|
322
|
+
*
|
|
323
|
+
* @description
|
|
324
|
+
* Contains information about the Steering Manifest
|
|
325
|
+
*
|
|
326
|
+
* @property {string} VERSION
|
|
327
|
+
* @property {number} TTL
|
|
328
|
+
* @property {string RELOAD-URI
|
|
329
|
+
* @property {!Array.<string>} PATHWAY-PRIORITY
|
|
330
|
+
* @property {!Array.<
|
|
331
|
+
* shaka.util.ContentSteeringManager.PathawayClone>} PATHWAY-CLONES
|
|
332
|
+
*/
|
|
333
|
+
shaka.util.ContentSteeringManager.SteeringManifest;
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* @typedef {{
|
|
338
|
+
* BASE-ID: string,
|
|
339
|
+
* ID: string,
|
|
340
|
+
* URI-REPLACEMENT: !Array.<shaka.util.ContentSteeringManager.UriReplacement>
|
|
341
|
+
* }}
|
|
342
|
+
*
|
|
343
|
+
* @property {string} BASE-ID
|
|
344
|
+
* @property {string} ID
|
|
345
|
+
* @property {!Array.<
|
|
346
|
+
* shaka.util.ContentSteeringManager.UriReplacement>} URI-REPLACEMENT
|
|
347
|
+
*/
|
|
348
|
+
shaka.util.ContentSteeringManager.PathawayClone;
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* @typedef {{
|
|
353
|
+
* HOST: string
|
|
354
|
+
* }}
|
|
355
|
+
*
|
|
356
|
+
* @property {string} HOST
|
|
357
|
+
*/
|
|
358
|
+
shaka.util.ContentSteeringManager.UriReplacement;
|
package/lib/util/error.js
CHANGED
|
@@ -330,7 +330,7 @@ shaka.util.Error.Code = {
|
|
|
330
330
|
|
|
331
331
|
/**
|
|
332
332
|
* Unable to guess mime type of the text.
|
|
333
|
-
* <br> error.data[0] is the text file's
|
|
333
|
+
* <br> error.data[0] is the text file's uri.
|
|
334
334
|
*/
|
|
335
335
|
'TEXT_COULD_NOT_GUESS_MIME_TYPE': 2011,
|
|
336
336
|
|
|
@@ -360,11 +360,7 @@ shaka.util.Error.Code = {
|
|
|
360
360
|
*/
|
|
361
361
|
'CHAPTERS_TRACK_FAILED': 2015,
|
|
362
362
|
|
|
363
|
-
|
|
364
|
-
* External thumbnails tracks cannot be added in src= because native platform
|
|
365
|
-
* doesn't support it.
|
|
366
|
-
*/
|
|
367
|
-
'CANNOT_ADD_EXTERNAL_THUMBNAILS_TO_SRC_EQUALS': 2016,
|
|
363
|
+
// RETIRED: 'CANNOT_ADD_EXTERNAL_THUMBNAILS_TO_SRC_EQUALS': 2016,
|
|
368
364
|
|
|
369
365
|
/**
|
|
370
366
|
* Only external urls of WebVTT type are supported.
|
|
@@ -205,7 +205,7 @@ shaka.util.FairPlayUtils = class {
|
|
|
205
205
|
const stringToArray = (string) => {
|
|
206
206
|
// 2 bytes for each char
|
|
207
207
|
const buffer = new ArrayBuffer(string.length * 2);
|
|
208
|
-
const array =
|
|
208
|
+
const array = shaka.util.BufferUtils.toUint16(buffer);
|
|
209
209
|
for (let i = 0, strLen = string.length; i < strLen; i++) {
|
|
210
210
|
array[i] = string.charCodeAt(i);
|
|
211
211
|
}
|
package/lib/util/fake_event.js
CHANGED
|
@@ -156,6 +156,7 @@ shaka.util.FakeEvent.EventName = {
|
|
|
156
156
|
AbrStatusChanged: 'abrstatuschanged',
|
|
157
157
|
Adaptation: 'adaptation',
|
|
158
158
|
Buffering: 'buffering',
|
|
159
|
+
Complete: 'complete',
|
|
159
160
|
DownloadFailed: 'downloadfailed',
|
|
160
161
|
DownloadHeadersReceived: 'downloadheadersreceived',
|
|
161
162
|
DrmSessionUpdate: 'drmsessionupdate',
|
|
@@ -163,6 +164,7 @@ shaka.util.FakeEvent.EventName = {
|
|
|
163
164
|
Prft: 'prft',
|
|
164
165
|
Error: 'error',
|
|
165
166
|
ExpirationUpdated: 'expirationupdated',
|
|
167
|
+
FirstQuartile: 'firstquartile',
|
|
166
168
|
GapJumped: 'gapjumped',
|
|
167
169
|
KeyStatusChanged: 'keystatuschanged',
|
|
168
170
|
Loaded: 'loaded',
|
|
@@ -171,16 +173,18 @@ shaka.util.FakeEvent.EventName = {
|
|
|
171
173
|
ManifestUpdated: 'manifestupdated',
|
|
172
174
|
MediaQualityChanged: 'mediaqualitychanged',
|
|
173
175
|
Metadata: 'metadata',
|
|
176
|
+
Midpoint: 'midpoint',
|
|
174
177
|
OnStateChange: 'onstatechange',
|
|
175
|
-
OnStateIdle: 'onstateidle',
|
|
176
178
|
RateChange: 'ratechange',
|
|
177
179
|
SegmentAppended: 'segmentappended',
|
|
178
180
|
SessionDataEvent: 'sessiondata',
|
|
179
181
|
StallDetected: 'stalldetected',
|
|
182
|
+
Started: 'started',
|
|
180
183
|
StateChanged: 'statechanged',
|
|
181
184
|
Streaming: 'streaming',
|
|
182
185
|
TextChanged: 'textchanged',
|
|
183
186
|
TextTrackVisibility: 'texttrackvisibility',
|
|
187
|
+
ThirdQuartile: 'thirdquartile',
|
|
184
188
|
TimelineRegionAdded: 'timelineregionadded',
|
|
185
189
|
TimelineRegionEnter: 'timelineregionenter',
|
|
186
190
|
TimelineRegionExit: 'timelineregionexit',
|
package/lib/util/id3_utils.js
CHANGED
|
@@ -140,9 +140,58 @@ shaka.util.Id3Utils = class {
|
|
|
140
140
|
key: frame.type,
|
|
141
141
|
description: '',
|
|
142
142
|
data: '',
|
|
143
|
+
mimeType: null,
|
|
144
|
+
pictureType: null,
|
|
143
145
|
};
|
|
144
146
|
|
|
145
|
-
if (frame.type === '
|
|
147
|
+
if (frame.type === 'APIC') {
|
|
148
|
+
/*
|
|
149
|
+
* Format:
|
|
150
|
+
* [0] = {Text Encoding}
|
|
151
|
+
* [1 - X] = {MIME Type}\0
|
|
152
|
+
* [X+1] = {Picture Type}
|
|
153
|
+
* [X+2 - Y] = {Description}\0
|
|
154
|
+
* [Y - ?] = {Picture Data or Picture URL}
|
|
155
|
+
*/
|
|
156
|
+
if (frame.size < 2) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
if (frame.data[0] !== shaka.util.Id3Utils.UTF8_encoding) {
|
|
160
|
+
shaka.log.warning('Ignore frame with unrecognized character ' +
|
|
161
|
+
'encoding');
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const mimeTypeEndIndex = frame.data.subarray(1).indexOf(0);
|
|
166
|
+
if (mimeTypeEndIndex === -1) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const mimeType = StringUtils.fromUTF8(
|
|
170
|
+
BufferUtils.toUint8(frame.data, 1, mimeTypeEndIndex));
|
|
171
|
+
const pictureType = frame.data[2 + mimeTypeEndIndex];
|
|
172
|
+
const descriptionEndIndex = frame.data.subarray(3 + mimeTypeEndIndex)
|
|
173
|
+
.indexOf(0);
|
|
174
|
+
if (descriptionEndIndex === -1) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
const description = StringUtils.fromUTF8(
|
|
178
|
+
BufferUtils.toUint8(frame.data, 3 + mimeTypeEndIndex,
|
|
179
|
+
descriptionEndIndex));
|
|
180
|
+
let data;
|
|
181
|
+
if (mimeType === '-->') {
|
|
182
|
+
data = StringUtils.fromUTF8(
|
|
183
|
+
BufferUtils.toUint8(
|
|
184
|
+
frame.data, 4 + mimeTypeEndIndex + descriptionEndIndex));
|
|
185
|
+
} else {
|
|
186
|
+
data = BufferUtils.toArrayBuffer(
|
|
187
|
+
frame.data.subarray(4 + mimeTypeEndIndex + descriptionEndIndex));
|
|
188
|
+
}
|
|
189
|
+
metadataFrame.mimeType = mimeType;
|
|
190
|
+
metadataFrame.pictureType = pictureType;
|
|
191
|
+
metadataFrame.description = description;
|
|
192
|
+
metadataFrame.data = data;
|
|
193
|
+
return metadataFrame;
|
|
194
|
+
} else if (frame.type === 'TXXX') {
|
|
146
195
|
/*
|
|
147
196
|
* Format:
|
|
148
197
|
* [0] = {Text Encoding}
|
|
@@ -8,7 +8,6 @@ goog.provide('shaka.util.ManifestParserUtils');
|
|
|
8
8
|
|
|
9
9
|
goog.require('goog.Uri');
|
|
10
10
|
goog.require('shaka.util.Error');
|
|
11
|
-
goog.require('shaka.util.Functional');
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
/**
|
|
@@ -27,7 +26,6 @@ shaka.util.ManifestParserUtils = class {
|
|
|
27
26
|
* @return {!Array.<string>}
|
|
28
27
|
*/
|
|
29
28
|
static resolveUris(baseUris, relativeUris) {
|
|
30
|
-
const Functional = shaka.util.Functional;
|
|
31
29
|
if (relativeUris.length == 0) {
|
|
32
30
|
return baseUris;
|
|
33
31
|
}
|
|
@@ -39,12 +37,18 @@ shaka.util.ManifestParserUtils = class {
|
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
const relativeAsGoog = relativeUris.map((uri) => new goog.Uri(uri));
|
|
42
|
-
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
|
|
41
|
+
// For each base URI, this code resolves it with every relative URI.
|
|
42
|
+
// The result is a single array containing all the resolved URIs.
|
|
43
|
+
const resolvedUris = [];
|
|
44
|
+
for (const baseStr of baseUris) {
|
|
45
|
+
const base = new goog.Uri(baseStr);
|
|
46
|
+
for (const relative of relativeAsGoog) {
|
|
47
|
+
resolvedUris.push(base.resolve(relative).toString());
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return resolvedUris;
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
|
|
@@ -1037,10 +1037,8 @@ shaka.util.Mp4Generator = class {
|
|
|
1037
1037
|
mdat_(streamInfo) {
|
|
1038
1038
|
const Mp4Generator = shaka.util.Mp4Generator;
|
|
1039
1039
|
const samples = streamInfo.data ? streamInfo.data.samples : [];
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
bytes = shaka.util.Uint8ArrayUtils.concat(bytes, sample.data);
|
|
1043
|
-
}
|
|
1040
|
+
const allData = samples.map((sample) => sample.data);
|
|
1041
|
+
const bytes = shaka.util.Uint8ArrayUtils.concat(...allData);
|
|
1044
1042
|
return Mp4Generator.box('mdat', bytes);
|
|
1045
1043
|
}
|
|
1046
1044
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.util.Mutex');
|
|
8
|
+
|
|
9
|
+
goog.require('shaka.log');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @summary A simple mutex.
|
|
14
|
+
*/
|
|
15
|
+
shaka.util.Mutex = class {
|
|
16
|
+
/** Constructs the mutex. */
|
|
17
|
+
constructor() {
|
|
18
|
+
/** @private {?string} */
|
|
19
|
+
this.acquiredIdentifier = null;
|
|
20
|
+
|
|
21
|
+
/** @private {!Array.<function()>} */
|
|
22
|
+
this.unlockQueue = [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Acquires the mutex, as soon as possible.
|
|
27
|
+
* @param {string} identifier
|
|
28
|
+
* @return {!Promise}
|
|
29
|
+
*/
|
|
30
|
+
async acquire(identifier) {
|
|
31
|
+
shaka.log.v2(identifier + ' has requested mutex');
|
|
32
|
+
if (this.acquiredIdentifier) {
|
|
33
|
+
await new Promise((resolve) => this.unlockQueue.push(resolve));
|
|
34
|
+
}
|
|
35
|
+
this.acquiredIdentifier = identifier;
|
|
36
|
+
shaka.log.v2(identifier + ' has acquired mutex');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Releases your hold on the mutex.
|
|
41
|
+
*/
|
|
42
|
+
release() {
|
|
43
|
+
shaka.log.v2(this.acquiredIdentifier + ' has released mutex');
|
|
44
|
+
if (this.unlockQueue.length > 0) {
|
|
45
|
+
this.unlockQueue.shift()();
|
|
46
|
+
} else {
|
|
47
|
+
this.acquiredIdentifier = null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Completely releases the mutex. Meant for use by the tests.
|
|
53
|
+
*/
|
|
54
|
+
releaseAll() {
|
|
55
|
+
while (this.acquiredIdentifier) {
|
|
56
|
+
this.release();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
package/lib/util/object_utils.js
CHANGED
|
@@ -19,7 +19,7 @@ shaka.util.ObjectUtils = class {
|
|
|
19
19
|
* @return {T}
|
|
20
20
|
*/
|
|
21
21
|
static cloneObject(arg) {
|
|
22
|
-
const seenObjects = new
|
|
22
|
+
const seenObjects = new WeakSet();
|
|
23
23
|
// This recursively clones the value |val|, using the captured variable
|
|
24
24
|
// |seenObjects| to track the objects we have already cloned.
|
|
25
25
|
/** @suppress {strictMissingProperties} */
|