shaka-player 4.9.35 → 4.9.36
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/README.md +9 -3
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +5 -5
- package/dist/locales.js +36 -36
- package/dist/shaka-player.compiled.d.ts +1 -0
- package/dist/shaka-player.compiled.debug.d.ts +1 -0
- package/dist/shaka-player.compiled.debug.externs.js +4 -3
- package/dist/shaka-player.compiled.debug.js +436 -421
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +4 -3
- package/dist/shaka-player.compiled.js +1263 -1251
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.dash.d.ts +4099 -0
- package/dist/shaka-player.dash.debug.d.ts +4099 -0
- package/dist/shaka-player.dash.debug.externs.js +4188 -0
- package/dist/shaka-player.dash.debug.js +2161 -0
- package/dist/shaka-player.dash.debug.map +8 -0
- package/dist/shaka-player.dash.externs.js +4188 -0
- package/dist/shaka-player.dash.js +1007 -0
- package/dist/shaka-player.dash.map +8 -0
- package/dist/shaka-player.hls.d.ts +4196 -0
- package/dist/shaka-player.hls.debug.d.ts +4196 -0
- package/dist/shaka-player.hls.debug.externs.js +4403 -0
- package/dist/shaka-player.hls.debug.js +2243 -0
- package/dist/shaka-player.hls.debug.map +8 -0
- package/dist/shaka-player.hls.externs.js +4403 -0
- package/dist/shaka-player.hls.js +1076 -0
- package/dist/shaka-player.hls.map +8 -0
- package/dist/shaka-player.ui.d.ts +1 -0
- package/dist/shaka-player.ui.debug.d.ts +1 -0
- package/dist/shaka-player.ui.debug.externs.js +4 -3
- package/dist/shaka-player.ui.debug.js +460 -445
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +4 -3
- package/dist/shaka-player.ui.js +1462 -1453
- package/dist/shaka-player.ui.map +3 -3
- package/externs/shaka/player.js +8 -4
- package/lib/cast/cast_proxy.js +48 -10
- package/lib/cea/cea708_service.js +9 -16
- package/lib/dash/dash_parser.js +23 -16
- package/lib/dash/segment_template.js +41 -40
- package/lib/hls/hls_parser.js +2 -2
- package/lib/media/content_workarounds.js +110 -72
- package/lib/media/drm_engine.js +72 -11
- package/lib/media/gap_jumping_controller.js +14 -1
- package/lib/media/media_source_engine.js +29 -11
- package/lib/media/region_timeline.js +4 -3
- package/lib/media/streaming_engine.js +37 -11
- package/lib/net/http_plugin_utils.js +1 -1
- package/lib/net/networking_engine.js +8 -0
- package/lib/net/networking_utils.js +1 -0
- package/lib/player.js +109 -37
- package/lib/polyfill/patchedmediakeys_apple.js +21 -0
- package/lib/text/cue.js +6 -2
- package/lib/text/mp4_ttml_parser.js +94 -6
- package/lib/text/ui_text_displayer.js +35 -4
- package/lib/transmuxer/ac3_transmuxer.js +6 -1
- package/lib/util/config_utils.js +13 -3
- package/lib/util/drm_utils.js +8 -0
- package/lib/util/error.js +6 -0
- package/lib/util/mp4_generator.js +19 -4
- package/lib/util/periods.js +4 -2
- package/lib/util/platform.js +60 -12
- package/lib/util/player_configuration.js +6 -1
- package/lib/util/stream_utils.js +18 -0
- package/lib/util/tXml.js +3 -2
- package/package.json +3 -3
- package/ui/controls.js +2 -6
- package/ui/less/thumbnails.less +1 -0
- package/ui/statistics_button.js +3 -1
- package/ui/ui.js +44 -35
package/externs/shaka/player.js
CHANGED
|
@@ -1204,7 +1204,8 @@ shaka.extern.MssManifestConfiguration;
|
|
|
1204
1204
|
* A default <code>presentationDelay</code> value.
|
|
1205
1205
|
* For DASH, it's a default <code>presentationDelay</code> value if
|
|
1206
1206
|
* <code>suggestedPresentationDelay</code> is missing in the MPEG DASH
|
|
1207
|
-
* manifest. The default value is <code>1.5 *
|
|
1207
|
+
* manifest. The default value is the lower of <code>1.5 *
|
|
1208
|
+
* minBufferTime</code> and <code>segmentAvailabilityDuration</code> if not
|
|
1208
1209
|
* configured or set as 0.
|
|
1209
1210
|
* For HLS, the default value is 3 segments duration if not configured or
|
|
1210
1211
|
* set as 0.
|
|
@@ -1483,9 +1484,12 @@ shaka.extern.ManifestConfiguration;
|
|
|
1483
1484
|
* <code>vodDynamicPlaybackRateLowBufferRate</code>.
|
|
1484
1485
|
* Defaults to <code>0.5</code>.
|
|
1485
1486
|
* @property {boolean} infiniteLiveStreamDuration
|
|
1486
|
-
* If <code>true</code>, the media source
|
|
1487
|
-
*
|
|
1488
|
-
*
|
|
1487
|
+
* If <code>true</code>, the media source duration of livestreams will be set
|
|
1488
|
+
* to <code>Infinity</code>. Otherwise, it will be set to a high but
|
|
1489
|
+
* non-infinite number (2^32).
|
|
1490
|
+
* <br>
|
|
1491
|
+
* Defaults to <code>false</code> except on Safari 17 or above whose default
|
|
1492
|
+
* value is <code>true</code>.
|
|
1489
1493
|
* @property {number} preloadNextUrlWindow
|
|
1490
1494
|
* The window of time at the end of the presentation to begin preloading the
|
|
1491
1495
|
* next URL, such as one specified by a urn:mpeg:dash:chaining:2016 element
|
package/lib/cast/cast_proxy.js
CHANGED
|
@@ -81,17 +81,21 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
81
81
|
this.compiledToExternNames_ = new Map();
|
|
82
82
|
|
|
83
83
|
/** @private {shaka.cast.CastSender} */
|
|
84
|
-
this.sender_ =
|
|
85
|
-
receiverAppId,
|
|
86
|
-
() => this.onCastStatusChanged_(),
|
|
87
|
-
() => this.onFirstCastStateUpdate_(),
|
|
88
|
-
(targetName, event) => this.onRemoteEvent_(targetName, event),
|
|
89
|
-
() => this.onResumeLocal_(),
|
|
90
|
-
() => this.getInitState_(),
|
|
91
|
-
androidReceiverCompatible);
|
|
92
|
-
|
|
84
|
+
this.sender_ = null;
|
|
93
85
|
|
|
94
|
-
|
|
86
|
+
if (window.chrome) {
|
|
87
|
+
this.sender_ = new shaka.cast.CastSender(
|
|
88
|
+
receiverAppId,
|
|
89
|
+
() => this.onCastStatusChanged_(),
|
|
90
|
+
() => this.onFirstCastStateUpdate_(),
|
|
91
|
+
(targetName, event) => this.onRemoteEvent_(targetName, event),
|
|
92
|
+
() => this.onResumeLocal_(),
|
|
93
|
+
() => this.getInitState_(),
|
|
94
|
+
androidReceiverCompatible);
|
|
95
|
+
this.init_();
|
|
96
|
+
} else {
|
|
97
|
+
this.initWithoutSender_();
|
|
98
|
+
}
|
|
95
99
|
}
|
|
96
100
|
|
|
97
101
|
/**
|
|
@@ -163,6 +167,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
163
167
|
* @export
|
|
164
168
|
*/
|
|
165
169
|
canCast() {
|
|
170
|
+
if (!this.sender_) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
166
173
|
return this.sender_.apiReady() && this.sender_.hasReceivers();
|
|
167
174
|
}
|
|
168
175
|
|
|
@@ -171,6 +178,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
171
178
|
* @export
|
|
172
179
|
*/
|
|
173
180
|
isCasting() {
|
|
181
|
+
if (!this.sender_) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
174
184
|
return this.sender_.isCasting();
|
|
175
185
|
}
|
|
176
186
|
|
|
@@ -179,6 +189,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
179
189
|
* @export
|
|
180
190
|
*/
|
|
181
191
|
receiverName() {
|
|
192
|
+
if (!this.sender_) {
|
|
193
|
+
return '';
|
|
194
|
+
}
|
|
182
195
|
return this.sender_.receiverName();
|
|
183
196
|
}
|
|
184
197
|
|
|
@@ -188,6 +201,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
188
201
|
* @export
|
|
189
202
|
*/
|
|
190
203
|
async cast() {
|
|
204
|
+
if (!this.sender_) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
191
207
|
// TODO: transfer manually-selected tracks?
|
|
192
208
|
// TODO: transfer side-loaded text tracks?
|
|
193
209
|
|
|
@@ -208,6 +224,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
208
224
|
* @export
|
|
209
225
|
*/
|
|
210
226
|
setAppData(appData) {
|
|
227
|
+
if (!this.sender_) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
211
230
|
this.sender_.setAppData(appData);
|
|
212
231
|
}
|
|
213
232
|
|
|
@@ -216,6 +235,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
216
235
|
* @export
|
|
217
236
|
*/
|
|
218
237
|
suggestDisconnect() {
|
|
238
|
+
if (!this.sender_) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
219
241
|
this.sender_.showDisconnectDialog();
|
|
220
242
|
}
|
|
221
243
|
|
|
@@ -224,6 +246,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
224
246
|
* @export
|
|
225
247
|
*/
|
|
226
248
|
forceDisconnect() {
|
|
249
|
+
if (!this.sender_) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
227
252
|
this.sender_.forceDisconnect();
|
|
228
253
|
}
|
|
229
254
|
|
|
@@ -243,6 +268,10 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
243
268
|
this.receiverAppId_ = newAppId;
|
|
244
269
|
this.androidReceiverCompatible_ = newCastAndroidReceiver;
|
|
245
270
|
|
|
271
|
+
if (!this.sender_) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
246
275
|
// Destroy the old sender
|
|
247
276
|
this.sender_.forceDisconnect();
|
|
248
277
|
await this.sender_.destroy();
|
|
@@ -262,6 +291,15 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
262
291
|
this.sender_.init();
|
|
263
292
|
}
|
|
264
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Initialize the Proxies without Cast sender.
|
|
296
|
+
* @private
|
|
297
|
+
*/
|
|
298
|
+
initWithoutSender_() {
|
|
299
|
+
this.videoProxy_ = /** @type {Object} */(this.localVideo_);
|
|
300
|
+
this.playerProxy_ = /** @type {Object} */(this.localPlayer_);
|
|
301
|
+
}
|
|
302
|
+
|
|
265
303
|
/**
|
|
266
304
|
* Initialize the Proxies and the Cast sender.
|
|
267
305
|
* @private
|
|
@@ -169,24 +169,17 @@ shaka.cea.Cea708Service = class {
|
|
|
169
169
|
const firstByte = dtvccPacket.readByte().value;
|
|
170
170
|
const secondByte = dtvccPacket.readByte().value;
|
|
171
171
|
|
|
172
|
-
const
|
|
173
|
-
return (
|
|
172
|
+
const toHexString = (byteArray) => {
|
|
173
|
+
return byteArray.map((byte) => {
|
|
174
|
+
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
|
175
|
+
}).join('');
|
|
174
176
|
};
|
|
175
177
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
};
|
|
182
|
-
const unicode = toHexString([firstByte, secondByte]);
|
|
183
|
-
// Takes a unicode hex string and creates a single character.
|
|
184
|
-
const char = String.fromCharCode(parseInt(unicode, 16));
|
|
185
|
-
this.currentWindow_.setCharacter(char);
|
|
186
|
-
return null;
|
|
187
|
-
} else {
|
|
188
|
-
dtvccPacket.rewind(2);
|
|
189
|
-
}
|
|
178
|
+
const unicode = toHexString([firstByte, secondByte]);
|
|
179
|
+
// Takes a unicode hex string and creates a single character.
|
|
180
|
+
const char = String.fromCharCode(parseInt(unicode, 16));
|
|
181
|
+
this.currentWindow_.setCharacter(char);
|
|
182
|
+
return null;
|
|
190
183
|
}
|
|
191
184
|
|
|
192
185
|
const window = this.currentWindow_;
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -658,18 +658,28 @@ shaka.dash.DashParser = class {
|
|
|
658
658
|
// feasible choices for the value. Nothing older than
|
|
659
659
|
// timeShiftBufferDepth is still available, and anything less than
|
|
660
660
|
// minBufferTime will cause buffering issues.
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
661
|
+
let delay = 0;
|
|
662
|
+
if (suggestedPresentationDelay != null) {
|
|
663
|
+
// 1. If a suggestedPresentationDelay is provided by the manifest, that
|
|
664
|
+
// will be used preferentially.
|
|
665
|
+
// This is given a minimum bound of segmentAvailabilityDuration.
|
|
666
|
+
// Content providers should provide a suggestedPresentationDelay
|
|
667
|
+
// whenever possible to optimize the live streaming experience.
|
|
668
|
+
delay = Math.min(
|
|
669
|
+
suggestedPresentationDelay,
|
|
670
|
+
segmentAvailabilityDuration || Infinity);
|
|
671
|
+
} else if (this.config_.defaultPresentationDelay > 0) {
|
|
672
|
+
// 2. If the developer provides a value for
|
|
673
|
+
// "manifest.defaultPresentationDelay", that is used as a fallback.
|
|
674
|
+
delay = this.config_.defaultPresentationDelay;
|
|
675
|
+
} else {
|
|
676
|
+
// 3. Otherwise, we default to the lower of segmentAvailabilityDuration
|
|
677
|
+
// and 1.5 * minBufferTime. This is fairly conservative.
|
|
678
|
+
delay = Math.min(
|
|
679
|
+
minBufferTime * 1.5, segmentAvailabilityDuration || Infinity);
|
|
680
|
+
}
|
|
670
681
|
presentationTimeline = new shaka.media.PresentationTimeline(
|
|
671
|
-
presentationStartTime,
|
|
672
|
-
this.config_.dash.autoCorrectDrift);
|
|
682
|
+
presentationStartTime, delay, this.config_.dash.autoCorrectDrift);
|
|
673
683
|
}
|
|
674
684
|
|
|
675
685
|
presentationTimeline.setStatic(mpdType == 'static');
|
|
@@ -2123,12 +2133,8 @@ shaka.dash.DashParser = class {
|
|
|
2123
2133
|
return element.attributes['schemeIdUri'] == expectedUri &&
|
|
2124
2134
|
element.attributes['value'] == expectedValue;
|
|
2125
2135
|
});
|
|
2126
|
-
const codecs = context.representation.codecs;
|
|
2127
|
-
// Detect the presence of Dolby Atmos audio content based on the codec and
|
|
2128
|
-
// bandwidth. Bandwidth above 384 kbps is a good indicator of Atmos content.
|
|
2129
|
-
const isAtmos = codecs.includes('ec-3') && context.bandwidth >= 384000;
|
|
2130
2136
|
let spatialAudio = false;
|
|
2131
|
-
if (hasJoc
|
|
2137
|
+
if (hasJoc) {
|
|
2132
2138
|
spatialAudio = true;
|
|
2133
2139
|
}
|
|
2134
2140
|
|
|
@@ -2162,6 +2168,7 @@ shaka.dash.DashParser = class {
|
|
|
2162
2168
|
|
|
2163
2169
|
let hdr;
|
|
2164
2170
|
const profiles = context.profiles;
|
|
2171
|
+
const codecs = context.representation.codecs;
|
|
2165
2172
|
|
|
2166
2173
|
const hevcHDR = 'http://dashif.org/guidelines/dash-if-uhd#hevc-hdr-pq10';
|
|
2167
2174
|
if (profiles.includes(hevcHDR) && (codecs.includes('hvc1.2.4.L153.B0') ||
|
|
@@ -121,24 +121,6 @@ shaka.dash.SegmentTemplate = class {
|
|
|
121
121
|
|
|
122
122
|
shaka.log.debug(`New manifest ${periodStart} - ${periodEnd}`);
|
|
123
123
|
|
|
124
|
-
/* When to fit segments. All refactors should honor/update this table:
|
|
125
|
-
*
|
|
126
|
-
* | dynamic | infinite | last | should | notes |
|
|
127
|
-
* | | period | period | fit | |
|
|
128
|
-
* | ------- | -------- | ------ | ------ | ------------------------- |
|
|
129
|
-
* | F | F | X | T | typical VOD |
|
|
130
|
-
* | F | T | X | X | impossible: infinite VOD |
|
|
131
|
-
* | T | F | F | T | typical live, old period |
|
|
132
|
-
* | T | F | T | F | typical IPR |
|
|
133
|
-
* | T | T | F | X | impossible: old, infinite |
|
|
134
|
-
* | T | T | T | F | typical live, new period |
|
|
135
|
-
*/
|
|
136
|
-
|
|
137
|
-
// We never fit the final period of dynamic content, which could be
|
|
138
|
-
// infinite live (with no limit to fit to) or IPR (which would expand the
|
|
139
|
-
// most recent segment to the end of the presentation).
|
|
140
|
-
const shouldFit = !(context.dynamic && context.periodInfo.isLastPeriod);
|
|
141
|
-
|
|
142
124
|
if (!segmentIndex) {
|
|
143
125
|
shaka.log.debug(`Creating TSI with end ${periodEnd}`);
|
|
144
126
|
segmentIndex = new TimelineSegmentIndex(
|
|
@@ -149,14 +131,13 @@ shaka.dash.SegmentTemplate = class {
|
|
|
149
131
|
periodStart,
|
|
150
132
|
periodEnd,
|
|
151
133
|
initSegmentReference,
|
|
152
|
-
shouldFit,
|
|
153
134
|
aesKey,
|
|
154
135
|
context.representation.segmentSequenceCadence,
|
|
155
136
|
);
|
|
156
137
|
} else {
|
|
157
138
|
const tsi = /** @type {!TimelineSegmentIndex} */(segmentIndex);
|
|
158
139
|
tsi.appendTemplateInfo(
|
|
159
|
-
info, periodStart, periodEnd,
|
|
140
|
+
info, periodStart, periodEnd, initSegmentReference);
|
|
160
141
|
|
|
161
142
|
const availabilityStart =
|
|
162
143
|
context.presentationTimeline.getSegmentAvailabilityStart();
|
|
@@ -166,7 +147,9 @@ shaka.dash.SegmentTemplate = class {
|
|
|
166
147
|
if (info.timeline &&
|
|
167
148
|
context.adaptationSet.contentType !== 'image' &&
|
|
168
149
|
context.adaptationSet.contentType !== 'text') {
|
|
169
|
-
const
|
|
150
|
+
const tsi = /** @type {!TimelineSegmentIndex} */(segmentIndex);
|
|
151
|
+
// getTimeline is the info.timeline but fitted to the period.
|
|
152
|
+
const timeline = tsi.getTimeline();
|
|
170
153
|
context.presentationTimeline.notifyTimeRange(
|
|
171
154
|
timeline,
|
|
172
155
|
periodStart);
|
|
@@ -184,7 +167,7 @@ shaka.dash.SegmentTemplate = class {
|
|
|
184
167
|
if (segmentIndex instanceof shaka.dash.TimelineSegmentIndex &&
|
|
185
168
|
segmentIndex.isEmpty()) {
|
|
186
169
|
segmentIndex.appendTemplateInfo(info, periodStart,
|
|
187
|
-
periodEnd,
|
|
170
|
+
periodEnd, initSegmentReference);
|
|
188
171
|
}
|
|
189
172
|
return Promise.resolve(segmentIndex);
|
|
190
173
|
},
|
|
@@ -668,38 +651,42 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
668
651
|
* @param {number} periodStart
|
|
669
652
|
* @param {number} periodEnd
|
|
670
653
|
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
671
|
-
* @param {boolean} shouldFit
|
|
672
654
|
* @param {shaka.extern.aesKey|undefined} aesKey
|
|
673
655
|
* @param {number} segmentSequenceCadence
|
|
674
656
|
*/
|
|
675
657
|
constructor(templateInfo, representationId, bandwidth, getBaseUris,
|
|
676
|
-
periodStart, periodEnd, initSegmentReference,
|
|
658
|
+
periodStart, periodEnd, initSegmentReference,
|
|
677
659
|
aesKey, segmentSequenceCadence) {
|
|
678
660
|
super([]);
|
|
679
661
|
|
|
680
662
|
/** @private {?shaka.dash.SegmentTemplate.SegmentTemplateInfo} */
|
|
681
663
|
this.templateInfo_ = templateInfo;
|
|
664
|
+
|
|
682
665
|
/** @private {?string} */
|
|
683
666
|
this.representationId_ = representationId;
|
|
667
|
+
|
|
684
668
|
/** @private {number} */
|
|
685
669
|
this.bandwidth_ = bandwidth;
|
|
686
|
-
|
|
670
|
+
|
|
671
|
+
/** @private {function(): Array<string>} */
|
|
687
672
|
this.getBaseUris_ = getBaseUris;
|
|
673
|
+
|
|
688
674
|
/** @private {number} */
|
|
689
675
|
this.periodStart_ = periodStart;
|
|
676
|
+
|
|
690
677
|
/** @private {number} */
|
|
691
678
|
this.periodEnd_ = periodEnd;
|
|
679
|
+
|
|
692
680
|
/** @private {shaka.media.InitSegmentReference} */
|
|
693
681
|
this.initSegmentReference_ = initSegmentReference;
|
|
682
|
+
|
|
694
683
|
/** @private {shaka.extern.aesKey|undefined} */
|
|
695
684
|
this.aesKey_ = aesKey;
|
|
685
|
+
|
|
696
686
|
/** @private {number} */
|
|
697
687
|
this.segmentSequenceCadence_ = segmentSequenceCadence;
|
|
698
688
|
|
|
699
|
-
|
|
700
|
-
if (shouldFit) {
|
|
701
|
-
this.fitTimeline();
|
|
702
|
-
}
|
|
689
|
+
this.fitTimeline();
|
|
703
690
|
}
|
|
704
691
|
|
|
705
692
|
/**
|
|
@@ -767,11 +754,9 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
767
754
|
* @param {shaka.dash.SegmentTemplate.SegmentTemplateInfo} info
|
|
768
755
|
* @param {number} periodStart
|
|
769
756
|
* @param {number} periodEnd
|
|
770
|
-
* @param {boolean} shouldFit
|
|
771
757
|
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
772
758
|
*/
|
|
773
|
-
appendTemplateInfo(info, periodStart, periodEnd,
|
|
774
|
-
initSegmentReference) {
|
|
759
|
+
appendTemplateInfo(info, periodStart, periodEnd, initSegmentReference) {
|
|
775
760
|
this.updateInitSegmentReference(initSegmentReference);
|
|
776
761
|
if (!this.templateInfo_) {
|
|
777
762
|
this.templateInfo_ = info;
|
|
@@ -805,9 +790,7 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
805
790
|
}
|
|
806
791
|
}
|
|
807
792
|
|
|
808
|
-
|
|
809
|
-
this.fitTimeline();
|
|
810
|
-
}
|
|
793
|
+
this.fitTimeline();
|
|
811
794
|
}
|
|
812
795
|
|
|
813
796
|
/**
|
|
@@ -852,14 +835,19 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
852
835
|
return;
|
|
853
836
|
}
|
|
854
837
|
const timeline = this.templateInfo_.timeline;
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
838
|
+
goog.asserts.assert(timeline, 'Timeline should be non-null!');
|
|
839
|
+
const newTimeline = [];
|
|
840
|
+
for (const range of timeline) {
|
|
841
|
+
if (range.start >= this.periodEnd_) {
|
|
842
|
+
// Starts after end of period.
|
|
843
|
+
} else if (range.end <= 0) {
|
|
844
|
+
// Ends before start of period.
|
|
859
845
|
} else {
|
|
860
|
-
|
|
846
|
+
// Usable.
|
|
847
|
+
newTimeline.push(range);
|
|
861
848
|
}
|
|
862
849
|
}
|
|
850
|
+
this.templateInfo_.timeline = newTimeline;
|
|
863
851
|
|
|
864
852
|
this.evict(this.periodStart_);
|
|
865
853
|
|
|
@@ -869,6 +857,19 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
869
857
|
// find/get() methods whenever possible.
|
|
870
858
|
}
|
|
871
859
|
|
|
860
|
+
/**
|
|
861
|
+
* Get the current timeline
|
|
862
|
+
* @return {!Array<shaka.media.PresentationTimeline.TimeRange>}
|
|
863
|
+
*/
|
|
864
|
+
getTimeline() {
|
|
865
|
+
if (!this.templateInfo_) {
|
|
866
|
+
return [];
|
|
867
|
+
}
|
|
868
|
+
const timeline = this.templateInfo_.timeline;
|
|
869
|
+
goog.asserts.assert(timeline, 'Timeline should be non-null!');
|
|
870
|
+
return timeline;
|
|
871
|
+
}
|
|
872
|
+
|
|
872
873
|
/**
|
|
873
874
|
* @override
|
|
874
875
|
*/
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -4312,7 +4312,7 @@ shaka.hls.HlsParser = class {
|
|
|
4312
4312
|
shaka.util.Error.Code.HLS_MSE_ENCRYPTED_MP2T_NOT_SUPPORTED);
|
|
4313
4313
|
}
|
|
4314
4314
|
|
|
4315
|
-
if (shaka.util.Platform.isMediaKeysPolyfilled()) {
|
|
4315
|
+
if (shaka.util.Platform.isMediaKeysPolyfilled('apple')) {
|
|
4316
4316
|
throw new shaka.util.Error(
|
|
4317
4317
|
shaka.util.Error.Severity.CRITICAL,
|
|
4318
4318
|
shaka.util.Error.Category.MANIFEST,
|
|
@@ -4452,7 +4452,7 @@ shaka.hls.HlsParser = class {
|
|
|
4452
4452
|
shaka.util.Error.Code.HLS_MSE_ENCRYPTED_MP2T_NOT_SUPPORTED);
|
|
4453
4453
|
}
|
|
4454
4454
|
|
|
4455
|
-
if (shaka.util.Platform.isMediaKeysPolyfilled()) {
|
|
4455
|
+
if (shaka.util.Platform.isMediaKeysPolyfilled('apple')) {
|
|
4456
4456
|
throw new shaka.util.Error(
|
|
4457
4457
|
shaka.util.Error.Severity.CRITICAL,
|
|
4458
4458
|
shaka.util.Error.Category.MANIFEST,
|
|
@@ -58,6 +58,20 @@ shaka.media.ContentWorkarounds = class {
|
|
|
58
58
|
/** @type {!Array.<{box: shaka.extern.ParsedBox, newType: number}>} */
|
|
59
59
|
const boxesToModify = [];
|
|
60
60
|
|
|
61
|
+
const pushEncv = (box) => {
|
|
62
|
+
boxesToModify.push({
|
|
63
|
+
box,
|
|
64
|
+
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const pushEnca = (box) => {
|
|
69
|
+
boxesToModify.push({
|
|
70
|
+
box,
|
|
71
|
+
newType: ContentWorkarounds.BOX_TYPE_ENCA_,
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
61
75
|
new shaka.util.Mp4Parser()
|
|
62
76
|
.box('moov', onSimpleAncestorBox)
|
|
63
77
|
.box('trak', onSimpleAncestorBox)
|
|
@@ -71,78 +85,23 @@ shaka.media.ContentWorkarounds = class {
|
|
|
71
85
|
})
|
|
72
86
|
.fullBox('encv', onEncryptionMetadataBox)
|
|
73
87
|
.fullBox('enca', onEncryptionMetadataBox)
|
|
74
|
-
.fullBox('dvav',
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
.fullBox('
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
.fullBox('
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
})
|
|
92
|
-
.fullBox('dvhe', (box) => {
|
|
93
|
-
boxesToModify.push({
|
|
94
|
-
box,
|
|
95
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
96
|
-
});
|
|
97
|
-
})
|
|
98
|
-
.fullBox('hev1', (box) => {
|
|
99
|
-
boxesToModify.push({
|
|
100
|
-
box,
|
|
101
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
102
|
-
});
|
|
103
|
-
})
|
|
104
|
-
.fullBox('hvc1', (box) => {
|
|
105
|
-
boxesToModify.push({
|
|
106
|
-
box,
|
|
107
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
108
|
-
});
|
|
109
|
-
})
|
|
110
|
-
.fullBox('avc1', (box) => {
|
|
111
|
-
boxesToModify.push({
|
|
112
|
-
box,
|
|
113
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
114
|
-
});
|
|
115
|
-
})
|
|
116
|
-
.fullBox('avc3', (box) => {
|
|
117
|
-
boxesToModify.push({
|
|
118
|
-
box,
|
|
119
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCV_,
|
|
120
|
-
});
|
|
121
|
-
})
|
|
122
|
-
.fullBox('ac-3', (box) => {
|
|
123
|
-
boxesToModify.push({
|
|
124
|
-
box,
|
|
125
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCA_,
|
|
126
|
-
});
|
|
127
|
-
})
|
|
128
|
-
.fullBox('ec-3', (box) => {
|
|
129
|
-
boxesToModify.push({
|
|
130
|
-
box,
|
|
131
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCA_,
|
|
132
|
-
});
|
|
133
|
-
})
|
|
134
|
-
.fullBox('ac-4', (box) => {
|
|
135
|
-
boxesToModify.push({
|
|
136
|
-
box,
|
|
137
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCA_,
|
|
138
|
-
});
|
|
139
|
-
})
|
|
140
|
-
.fullBox('mp4a', (box) => {
|
|
141
|
-
boxesToModify.push({
|
|
142
|
-
box,
|
|
143
|
-
newType: ContentWorkarounds.BOX_TYPE_ENCA_,
|
|
144
|
-
});
|
|
145
|
-
}).parse(initSegment);
|
|
88
|
+
.fullBox('dvav', pushEncv)
|
|
89
|
+
.fullBox('dva1', pushEncv)
|
|
90
|
+
.fullBox('dvh1', pushEncv)
|
|
91
|
+
.fullBox('dvhe', pushEncv)
|
|
92
|
+
.fullBox('dvc1', pushEncv)
|
|
93
|
+
.fullBox('dvi1', pushEncv)
|
|
94
|
+
.fullBox('hev1', pushEncv)
|
|
95
|
+
.fullBox('hvc1', pushEncv)
|
|
96
|
+
.fullBox('avc1', pushEncv)
|
|
97
|
+
.fullBox('avc3', pushEncv)
|
|
98
|
+
.fullBox('ac-3', pushEnca)
|
|
99
|
+
.fullBox('ec-3', pushEnca)
|
|
100
|
+
.fullBox('ac-4', pushEnca)
|
|
101
|
+
.fullBox('Opus', pushEnca)
|
|
102
|
+
.fullBox('fLaC', pushEnca)
|
|
103
|
+
.fullBox('mp4a', pushEnca)
|
|
104
|
+
.parse(initSegment);
|
|
146
105
|
|
|
147
106
|
if (isEncrypted) {
|
|
148
107
|
shaka.log.debug('Init segment already indicates encryption.');
|
|
@@ -335,6 +294,53 @@ shaka.media.ContentWorkarounds = class {
|
|
|
335
294
|
boxView.setUint32(ContentWorkarounds.BOX_SIZE_OFFSET_, newBoxSize);
|
|
336
295
|
}
|
|
337
296
|
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Transform the init segment into a new init segment buffer that indicates
|
|
300
|
+
* EC-3 as audio codec instead of AC-3. Even though any EC-3 decoder should
|
|
301
|
+
* be able to decode AC-3 streams, there are platforms that do not accept
|
|
302
|
+
* AC-3 as codec.
|
|
303
|
+
*
|
|
304
|
+
* Should only be called for MP4 init segments, and only on platforms that
|
|
305
|
+
* need this workaround. Returns a new buffer containing the modified init
|
|
306
|
+
* segment.
|
|
307
|
+
*
|
|
308
|
+
* @param {!BufferSource} initSegmentBuffer
|
|
309
|
+
* @return {!Uint8Array}
|
|
310
|
+
*/
|
|
311
|
+
static fakeEC3(initSegmentBuffer) {
|
|
312
|
+
const ContentWorkarounds = shaka.media.ContentWorkarounds;
|
|
313
|
+
const initSegment = shaka.util.BufferUtils.toUint8(initSegmentBuffer);
|
|
314
|
+
const ancestorBoxes = [];
|
|
315
|
+
|
|
316
|
+
const onSimpleAncestorBox = (box) => {
|
|
317
|
+
ancestorBoxes.push({start: box.start, size: box.size});
|
|
318
|
+
shaka.util.Mp4Parser.children(box);
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
new shaka.util.Mp4Parser()
|
|
322
|
+
.box('moov', onSimpleAncestorBox)
|
|
323
|
+
.box('trak', onSimpleAncestorBox)
|
|
324
|
+
.box('mdia', onSimpleAncestorBox)
|
|
325
|
+
.box('minf', onSimpleAncestorBox)
|
|
326
|
+
.box('stbl', onSimpleAncestorBox)
|
|
327
|
+
.box('stsd', (box) => {
|
|
328
|
+
ancestorBoxes.push({start: box.start, size: box.size});
|
|
329
|
+
const stsdBoxView = shaka.util.BufferUtils.toDataView(
|
|
330
|
+
initSegment, box.start);
|
|
331
|
+
// "size - 3" is because we immediately read a uint32.
|
|
332
|
+
for (let i = 0; i < box.size -3; i++) {
|
|
333
|
+
const codecTag = stsdBoxView.getUint32(i);
|
|
334
|
+
if (codecTag == ContentWorkarounds.BOX_TYPE_AC_3_) {
|
|
335
|
+
stsdBoxView.setUint32(i, ContentWorkarounds.BOX_TYPE_EC_3_);
|
|
336
|
+
} else if (codecTag == ContentWorkarounds.BOX_TYPE_DAC3_) {
|
|
337
|
+
stsdBoxView.setUint32(i, ContentWorkarounds.BOX_TYPE_DEC3_);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}).parse(initSegment);
|
|
341
|
+
|
|
342
|
+
return initSegment;
|
|
343
|
+
}
|
|
338
344
|
};
|
|
339
345
|
|
|
340
346
|
/**
|
|
@@ -470,3 +476,35 @@ shaka.media.ContentWorkarounds.BOX_TYPE_ENCV_ = 0x656e6376;
|
|
|
470
476
|
* @private
|
|
471
477
|
*/
|
|
472
478
|
shaka.media.ContentWorkarounds.BOX_TYPE_ENCA_ = 0x656e6361;
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Box type for "ac-3".
|
|
482
|
+
*
|
|
483
|
+
* @const {number}
|
|
484
|
+
* @private
|
|
485
|
+
*/
|
|
486
|
+
shaka.media.ContentWorkarounds.BOX_TYPE_AC_3_ = 0x61632d33;
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Box type for "dac3".
|
|
490
|
+
*
|
|
491
|
+
* @const {number}
|
|
492
|
+
* @private
|
|
493
|
+
*/
|
|
494
|
+
shaka.media.ContentWorkarounds.BOX_TYPE_DAC3_ = 0x64616333;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Box type for "ec-3".
|
|
498
|
+
*
|
|
499
|
+
* @const {number}
|
|
500
|
+
* @private
|
|
501
|
+
*/
|
|
502
|
+
shaka.media.ContentWorkarounds.BOX_TYPE_EC_3_ = 0x65632d33;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Box type for "dec3".
|
|
506
|
+
*
|
|
507
|
+
* @const {number}
|
|
508
|
+
* @private
|
|
509
|
+
*/
|
|
510
|
+
shaka.media.ContentWorkarounds.BOX_TYPE_DEC3_ = 0x64656333;
|