shaka-player 4.9.7 → 4.9.9
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/dist/locales.js +57 -37
- package/dist/shaka-player.compiled.debug.js +339 -337
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +1189 -1188
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.debug.js +414 -412
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +1453 -1451
- package/dist/shaka-player.ui.map +3 -3
- package/lib/cea/mp4_cea_parser.js +67 -31
- package/lib/hls/hls_parser.js +30 -17
- package/lib/hls/manifest_text_parser.js +1 -0
- package/lib/media/segment_utils.js +41 -49
- package/lib/media/streaming_engine.js +27 -3
- package/lib/player.js +3 -1
- package/lib/util/mime_utils.js +6 -1
- package/lib/util/mp4_box_parsers.js +40 -4
- package/package.json +1 -1
- package/ui/locales/es.json +2 -0
- package/ui/locales/fr.json +12 -3
- package/ui/locales/pt-BR.json +9 -0
- package/ui/locales/pt-PT.json +9 -0
|
@@ -164,53 +164,62 @@ shaka.cea.Mp4CeaParser = class {
|
|
|
164
164
|
/** @type {!Array<!shaka.extern.ICeaParser.CaptionPacket>} **/
|
|
165
165
|
const captionPackets = [];
|
|
166
166
|
|
|
167
|
-
// Fields that are found in MOOF boxes
|
|
168
|
-
let defaultSampleDuration = this.defaultSampleDuration_;
|
|
169
|
-
let defaultSampleSize = this.defaultSampleSize_;
|
|
170
167
|
let moofOffset = 0;
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
let
|
|
174
|
-
let timescale = shaka.cea.CeaUtils.DEFAULT_TIMESCALE_VALUE;
|
|
168
|
+
|
|
169
|
+
/** @type {!Array<!shaka.cea.Mp4CeaParser.ParsedTRAF>} */
|
|
170
|
+
let parsedTRAFs = [];
|
|
175
171
|
|
|
176
172
|
new Mp4Parser()
|
|
177
173
|
.box('moof', (box) => {
|
|
178
174
|
moofOffset = box.start;
|
|
179
|
-
//
|
|
180
|
-
|
|
175
|
+
// traf box parsing is reset on each moof.
|
|
176
|
+
parsedTRAFs = [];
|
|
177
|
+
Mp4Parser.children(box);
|
|
178
|
+
})
|
|
179
|
+
.box('traf', (box) => {
|
|
180
|
+
parsedTRAFs.push({
|
|
181
|
+
baseMediaDecodeTime: null,
|
|
182
|
+
defaultSampleDuration: this.defaultSampleDuration_,
|
|
183
|
+
defaultSampleSize: this.defaultSampleSize_,
|
|
184
|
+
parsedTRUNs: [],
|
|
185
|
+
timescale: shaka.cea.CeaUtils.DEFAULT_TIMESCALE_VALUE,
|
|
186
|
+
});
|
|
181
187
|
Mp4Parser.children(box);
|
|
182
188
|
})
|
|
183
|
-
.box('traf', Mp4Parser.children)
|
|
184
189
|
.fullBox('trun', (box) => {
|
|
185
190
|
goog.asserts.assert(
|
|
186
|
-
box.version != null && box.flags!=null,
|
|
191
|
+
box.version != null && box.flags != null,
|
|
187
192
|
'TRUN is a full box and should have a valid version & flags.');
|
|
188
193
|
|
|
194
|
+
const lastTRAF = parsedTRAFs[parsedTRAFs.length - 1];
|
|
195
|
+
|
|
189
196
|
const parsedTRUN = shaka.util.Mp4BoxParsers.parseTRUN(
|
|
190
197
|
box.reader, box.version, box.flags);
|
|
191
|
-
parsedTRUNs.push(parsedTRUN);
|
|
198
|
+
lastTRAF.parsedTRUNs.push(parsedTRUN);
|
|
192
199
|
})
|
|
193
200
|
.fullBox('tfhd', (box) => {
|
|
194
201
|
goog.asserts.assert(
|
|
195
202
|
box.flags != null,
|
|
196
203
|
'TFHD is a full box and should have valid flags.');
|
|
197
204
|
|
|
205
|
+
const lastTRAF = parsedTRAFs[parsedTRAFs.length - 1];
|
|
206
|
+
|
|
198
207
|
const parsedTFHD = shaka.util.Mp4BoxParsers.parseTFHD(
|
|
199
208
|
box.reader, box.flags);
|
|
200
209
|
|
|
201
210
|
// If specified, defaultSampleDuration and defaultSampleSize
|
|
202
211
|
// override the ones specified in the TREX box
|
|
203
|
-
defaultSampleDuration = parsedTFHD.defaultSampleDuration ||
|
|
212
|
+
lastTRAF.defaultSampleDuration = parsedTFHD.defaultSampleDuration ||
|
|
204
213
|
this.defaultSampleDuration_;
|
|
205
214
|
|
|
206
|
-
defaultSampleSize = parsedTFHD.defaultSampleSize ||
|
|
215
|
+
lastTRAF.defaultSampleSize = parsedTFHD.defaultSampleSize ||
|
|
207
216
|
this.defaultSampleSize_;
|
|
208
217
|
|
|
209
218
|
const trackId = parsedTFHD.trackId;
|
|
210
219
|
|
|
211
220
|
// Get the timescale from the track Id
|
|
212
221
|
if (this.trackIdToTimescale_.has(trackId)) {
|
|
213
|
-
timescale = this.trackIdToTimescale_.get(trackId);
|
|
222
|
+
lastTRAF.timescale = this.trackIdToTimescale_.get(trackId);
|
|
214
223
|
}
|
|
215
224
|
})
|
|
216
225
|
.fullBox('tfdt', (box) => {
|
|
@@ -218,27 +227,37 @@ shaka.cea.Mp4CeaParser = class {
|
|
|
218
227
|
box.version != null,
|
|
219
228
|
'TFDT is a full box and should have a valid version.');
|
|
220
229
|
|
|
230
|
+
const lastTRAF = parsedTRAFs[parsedTRAFs.length - 1];
|
|
231
|
+
|
|
221
232
|
const parsedTFDT = shaka.util.Mp4BoxParsers.parseTFDTInaccurate(
|
|
222
233
|
box.reader, box.version);
|
|
223
234
|
|
|
224
|
-
baseMediaDecodeTime = parsedTFDT.baseMediaDecodeTime;
|
|
235
|
+
lastTRAF.baseMediaDecodeTime = parsedTFDT.baseMediaDecodeTime;
|
|
225
236
|
})
|
|
226
237
|
.box('mdat', (box) => {
|
|
227
|
-
if (baseMediaDecodeTime === null) {
|
|
228
|
-
// This field should have been populated by the Base Media Decode
|
|
229
|
-
// Time in the tfdt box.
|
|
230
|
-
shaka.log.alwaysWarn(
|
|
231
|
-
'Unable to find base media decode time for CEA captions!');
|
|
232
|
-
throw new shaka.util.Error(
|
|
233
|
-
shaka.util.Error.Severity.CRITICAL,
|
|
234
|
-
shaka.util.Error.Category.TEXT,
|
|
235
|
-
shaka.util.Error.Code.INVALID_MP4_CEA);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
238
|
const offset = moofOffset - box.start - 8;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
const initialPosition = box.reader.getPosition();
|
|
240
|
+
for (const parsedTRAF of parsedTRAFs) {
|
|
241
|
+
if (parsedTRAF.baseMediaDecodeTime === null) {
|
|
242
|
+
// This field should have been populated by the Base Media Decode
|
|
243
|
+
// Time in the tfdt box.
|
|
244
|
+
shaka.log.alwaysWarn(
|
|
245
|
+
'Unable to find base media decode time for CEA captions!');
|
|
246
|
+
throw new shaka.util.Error(
|
|
247
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
248
|
+
shaka.util.Error.Category.TEXT,
|
|
249
|
+
shaka.util.Error.Code.INVALID_MP4_CEA);
|
|
250
|
+
}
|
|
251
|
+
box.reader.seek(initialPosition);
|
|
252
|
+
this.parseMdat_(box.reader,
|
|
253
|
+
parsedTRAF.baseMediaDecodeTime,
|
|
254
|
+
parsedTRAF.timescale,
|
|
255
|
+
parsedTRAF.defaultSampleDuration,
|
|
256
|
+
parsedTRAF.defaultSampleSize,
|
|
257
|
+
offset,
|
|
258
|
+
parsedTRAF.parsedTRUNs,
|
|
259
|
+
captionPackets);
|
|
260
|
+
}
|
|
242
261
|
})
|
|
243
262
|
.parse(mediaSegment, /* partialOkay= */ false);
|
|
244
263
|
|
|
@@ -315,7 +334,7 @@ shaka.cea.Mp4CeaParser = class {
|
|
|
315
334
|
timeOffset = sampleData[sampleIndex].sampleCompositionTimeOffset || 0;
|
|
316
335
|
}
|
|
317
336
|
|
|
318
|
-
const pts = (time + timeOffset)/timescale;
|
|
337
|
+
const pts = (time + timeOffset) / timescale;
|
|
319
338
|
for (const packet of this.seiProcessor_
|
|
320
339
|
.process(reader.readBytes(naluSize - naluHeaderSize))) {
|
|
321
340
|
captionPackets.push({
|
|
@@ -384,5 +403,22 @@ shaka.cea.Mp4CeaParser.CodecBitstreamMap_ = {
|
|
|
384
403
|
'dvhe': shaka.cea.Mp4CeaParser.BitstreamFormat.H265,
|
|
385
404
|
};
|
|
386
405
|
|
|
406
|
+
/**
|
|
407
|
+
* @typedef {{
|
|
408
|
+
* baseMediaDecodeTime: ?number,
|
|
409
|
+
* defaultSampleDuration: number,
|
|
410
|
+
* defaultSampleSize: number,
|
|
411
|
+
* parsedTRUNs: !Array<shaka.util.ParsedTRUNBox>,
|
|
412
|
+
* timescale: number
|
|
413
|
+
* }}
|
|
414
|
+
*
|
|
415
|
+
* @property {?number} baseMediaDecodeTime
|
|
416
|
+
* @property {number} defaultSampleDuration
|
|
417
|
+
* @property {number} defaultSampleSize
|
|
418
|
+
* @property {!Array<shaka.util.ParsedTRUNBox>} parsedTRUNs
|
|
419
|
+
* @property {?number} timescale
|
|
420
|
+
*/
|
|
421
|
+
shaka.cea.Mp4CeaParser.ParsedTRAF;
|
|
422
|
+
|
|
387
423
|
shaka.media.ClosedCaptionParser.registerParser('video/mp4',
|
|
388
424
|
() => new shaka.cea.Mp4CeaParser());
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -2319,24 +2319,32 @@ shaka.hls.HlsParser = class {
|
|
|
2319
2319
|
this.config_.hls.disableCodecGuessing) ||
|
|
2320
2320
|
(this.needsClosedCaptionsDetection_ && type == ContentType.VIDEO &&
|
|
2321
2321
|
!this.config_.hls.disableClosedCaptionsDetection)) {
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
type === basicInfo.type, 'Media types should match!');
|
|
2329
|
-
|
|
2330
|
-
if (basicInfo.closedCaptions.size && (!closedCaptions ||
|
|
2331
|
-
closedCaptions.size != basicInfo.closedCaptions.size)) {
|
|
2332
|
-
closedCaptions = basicInfo.closedCaptions;
|
|
2333
|
-
closedCaptionsUpdated = true;
|
|
2322
|
+
let canRequestBasicInfo = playlist.segments.length > 0;
|
|
2323
|
+
if (canRequestBasicInfo) {
|
|
2324
|
+
const segment = playlist.segments[0];
|
|
2325
|
+
if (shaka.hls.Utils.getFirstTagWithName(segment.tags, 'EXT-X-GAP')) {
|
|
2326
|
+
canRequestBasicInfo = false;
|
|
2327
|
+
}
|
|
2334
2328
|
}
|
|
2329
|
+
if (canRequestBasicInfo) {
|
|
2330
|
+
this.needsClosedCaptionsDetection_ = false;
|
|
2331
|
+
const basicInfo = await this.getMediaPlaylistBasicInfo_(
|
|
2332
|
+
playlist, getUris, mediaVariables);
|
|
2333
|
+
|
|
2334
|
+
goog.asserts.assert(
|
|
2335
|
+
type === basicInfo.type, 'Media types should match!');
|
|
2336
|
+
|
|
2337
|
+
if (basicInfo.closedCaptions.size && (!closedCaptions ||
|
|
2338
|
+
closedCaptions.size != basicInfo.closedCaptions.size)) {
|
|
2339
|
+
closedCaptions = basicInfo.closedCaptions;
|
|
2340
|
+
closedCaptionsUpdated = true;
|
|
2341
|
+
}
|
|
2335
2342
|
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2343
|
+
if (!this.codecInfoInManifest_ &&
|
|
2344
|
+
this.config_.hls.disableCodecGuessing) {
|
|
2345
|
+
mimeType = basicInfo.mimeType;
|
|
2346
|
+
codecs = basicInfo.codecs;
|
|
2347
|
+
}
|
|
2340
2348
|
}
|
|
2341
2349
|
}
|
|
2342
2350
|
|
|
@@ -3944,9 +3952,14 @@ shaka.hls.HlsParser = class {
|
|
|
3944
3952
|
'Playlist should have segments!');
|
|
3945
3953
|
const middleSegmentIdx = Math.trunc((playlist.segments.length - 1) / 2);
|
|
3946
3954
|
|
|
3955
|
+
const middleSegment = playlist.segments[middleSegmentIdx];
|
|
3956
|
+
if (shaka.hls.Utils.getFirstTagWithName(middleSegment.tags, 'EXT-X-GAP')) {
|
|
3957
|
+
return this.guessMimeTypeFallback_(contentType);
|
|
3958
|
+
}
|
|
3959
|
+
|
|
3947
3960
|
const middleSegmentUris = shaka.hls.Utils.constructSegmentUris(
|
|
3948
3961
|
getUris(),
|
|
3949
|
-
|
|
3962
|
+
middleSegment.verbatimSegmentUri,
|
|
3950
3963
|
variables);
|
|
3951
3964
|
|
|
3952
3965
|
const parsedUri = new goog.Uri(middleSegmentUris[0]);
|
|
@@ -140,7 +140,7 @@ shaka.media.SegmentUtils = class {
|
|
|
140
140
|
const SegmentUtils = shaka.media.SegmentUtils;
|
|
141
141
|
|
|
142
142
|
const audioCodecs = [];
|
|
143
|
-
|
|
143
|
+
let videoCodecs = [];
|
|
144
144
|
|
|
145
145
|
let hasAudio = false;
|
|
146
146
|
let hasVideo = false;
|
|
@@ -179,6 +179,7 @@ shaka.media.SegmentUtils = class {
|
|
|
179
179
|
break;
|
|
180
180
|
case 'ac-3':
|
|
181
181
|
case 'ec-3':
|
|
182
|
+
case 'ac-4':
|
|
182
183
|
case 'opus':
|
|
183
184
|
case 'flac':
|
|
184
185
|
audioCodecs.push(codecLC);
|
|
@@ -207,6 +208,19 @@ shaka.media.SegmentUtils = class {
|
|
|
207
208
|
/** @type {?string} */
|
|
208
209
|
let baseBox;
|
|
209
210
|
|
|
211
|
+
const genericAudioBox = (box) => {
|
|
212
|
+
const parsedAudioSampleEntryBox =
|
|
213
|
+
shaka.util.Mp4BoxParsers.audioSampleEntry(box.reader);
|
|
214
|
+
channelCount = parsedAudioSampleEntryBox.channelCount;
|
|
215
|
+
sampleRate = parsedAudioSampleEntryBox.sampleRate;
|
|
216
|
+
codecBoxParser(box);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const genericVideoBox = (box) => {
|
|
220
|
+
baseBox = box.name;
|
|
221
|
+
Mp4Parser.visualSampleEntry(box);
|
|
222
|
+
};
|
|
223
|
+
|
|
210
224
|
new Mp4Parser()
|
|
211
225
|
.box('moov', Mp4Parser.children)
|
|
212
226
|
.box('trak', Mp4Parser.children)
|
|
@@ -235,9 +249,10 @@ shaka.media.SegmentUtils = class {
|
|
|
235
249
|
// AUDIO
|
|
236
250
|
// These are the various boxes that signal a codec.
|
|
237
251
|
.box('mp4a', (box) => {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
252
|
+
const parsedAudioSampleEntryBox =
|
|
253
|
+
shaka.util.Mp4BoxParsers.audioSampleEntry(box.reader);
|
|
254
|
+
channelCount = parsedAudioSampleEntryBox.channelCount;
|
|
255
|
+
sampleRate = parsedAudioSampleEntryBox.sampleRate;
|
|
241
256
|
if (box.reader.hasMoreData()) {
|
|
242
257
|
Mp4Parser.children(box);
|
|
243
258
|
} else {
|
|
@@ -249,54 +264,24 @@ shaka.media.SegmentUtils = class {
|
|
|
249
264
|
audioCodecs.push(parsedESDSBox.codec);
|
|
250
265
|
hasAudio = true;
|
|
251
266
|
})
|
|
252
|
-
.box('ac-3',
|
|
253
|
-
.box('ec-3',
|
|
254
|
-
.box('
|
|
255
|
-
.box('Opus',
|
|
256
|
-
.box('fLaC',
|
|
267
|
+
.box('ac-3', genericAudioBox)
|
|
268
|
+
.box('ec-3', genericAudioBox)
|
|
269
|
+
.box('ac-4', genericAudioBox)
|
|
270
|
+
.box('Opus', genericAudioBox)
|
|
271
|
+
.box('fLaC', genericAudioBox)
|
|
257
272
|
|
|
258
273
|
// VIDEO
|
|
259
274
|
// These are the various boxes that signal a codec.
|
|
260
|
-
.box('avc1',
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
.box('
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
.box('
|
|
269
|
-
|
|
270
|
-
Mp4Parser.visualSampleEntry(box);
|
|
271
|
-
})
|
|
272
|
-
.box('hvc1', (box) => {
|
|
273
|
-
baseBox = box.name;
|
|
274
|
-
Mp4Parser.visualSampleEntry(box);
|
|
275
|
-
})
|
|
276
|
-
.box('dva1', (box) => {
|
|
277
|
-
baseBox = box.name;
|
|
278
|
-
Mp4Parser.visualSampleEntry(box);
|
|
279
|
-
})
|
|
280
|
-
.box('dvav', (box) => {
|
|
281
|
-
baseBox = box.name;
|
|
282
|
-
Mp4Parser.visualSampleEntry(box);
|
|
283
|
-
})
|
|
284
|
-
.box('dvh1', (box) => {
|
|
285
|
-
baseBox = box.name;
|
|
286
|
-
Mp4Parser.visualSampleEntry(box);
|
|
287
|
-
})
|
|
288
|
-
.box('dvhe', (box) => {
|
|
289
|
-
baseBox = box.name;
|
|
290
|
-
Mp4Parser.visualSampleEntry(box);
|
|
291
|
-
})
|
|
292
|
-
.box('vp09', (box) => {
|
|
293
|
-
baseBox = box.name;
|
|
294
|
-
Mp4Parser.visualSampleEntry(box);
|
|
295
|
-
})
|
|
296
|
-
.box('av01', (box) => {
|
|
297
|
-
baseBox = box.name;
|
|
298
|
-
Mp4Parser.visualSampleEntry(box);
|
|
299
|
-
})
|
|
275
|
+
.box('avc1', genericVideoBox)
|
|
276
|
+
.box('avc3', genericVideoBox)
|
|
277
|
+
.box('hev1', genericVideoBox)
|
|
278
|
+
.box('hvc1', genericVideoBox)
|
|
279
|
+
.box('dva1', genericVideoBox)
|
|
280
|
+
.box('dvav', genericVideoBox)
|
|
281
|
+
.box('dvh1', genericVideoBox)
|
|
282
|
+
.box('dvhe', genericVideoBox)
|
|
283
|
+
.box('vp09', genericVideoBox)
|
|
284
|
+
.box('av01', genericVideoBox)
|
|
300
285
|
.box('avcC', (box) => {
|
|
301
286
|
let codecBase = baseBox || '';
|
|
302
287
|
switch (baseBox) {
|
|
@@ -375,6 +360,13 @@ shaka.media.SegmentUtils = class {
|
|
|
375
360
|
})
|
|
376
361
|
|
|
377
362
|
.box('colr', (box) => {
|
|
363
|
+
videoCodecs = videoCodecs.map((codec) => {
|
|
364
|
+
if (codec.startsWith('av01.')) {
|
|
365
|
+
return shaka.util.Mp4BoxParsers.updateAV1CodecWithCOLRBox(
|
|
366
|
+
codec, box.reader);
|
|
367
|
+
}
|
|
368
|
+
return codec;
|
|
369
|
+
});
|
|
378
370
|
const {videoRange, colorGamut} =
|
|
379
371
|
shaka.util.Mp4BoxParsers.parseCOLR(box.reader);
|
|
380
372
|
realVideoRange = videoRange;
|
|
@@ -134,6 +134,12 @@ shaka.media.StreamingEngine = class {
|
|
|
134
134
|
projection: null,
|
|
135
135
|
hfov: null,
|
|
136
136
|
};
|
|
137
|
+
|
|
138
|
+
/** @private {number} */
|
|
139
|
+
this.playRangeStart_ = 0;
|
|
140
|
+
|
|
141
|
+
/** @private {number} */
|
|
142
|
+
this.playRangeEnd_ = Infinity;
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
/** @override */
|
|
@@ -251,6 +257,20 @@ shaka.media.StreamingEngine = class {
|
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Applies a playback range. This will only affect non-live content.
|
|
262
|
+
*
|
|
263
|
+
* @param {number} playRangeStart
|
|
264
|
+
* @param {number} playRangeEnd
|
|
265
|
+
*/
|
|
266
|
+
applyPlayRange(playRangeStart, playRangeEnd) {
|
|
267
|
+
if (!this.manifest_.presentationTimeline.isLive()) {
|
|
268
|
+
this.playRangeStart_ = playRangeStart;
|
|
269
|
+
this.playRangeEnd_ = playRangeEnd;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
254
274
|
/**
|
|
255
275
|
* Initialize and start streaming.
|
|
256
276
|
*
|
|
@@ -1899,10 +1919,11 @@ shaka.media.StreamingEngine = class {
|
|
|
1899
1919
|
// Rounding issues can cause us to remove the first frame of a Period, so
|
|
1900
1920
|
// reduce the window start time slightly.
|
|
1901
1921
|
const appendWindowStart = Math.max(0,
|
|
1902
|
-
reference.appendWindowStart -
|
|
1922
|
+
Math.max(reference.appendWindowStart, this.playRangeStart_) -
|
|
1903
1923
|
StreamingEngine.APPEND_WINDOW_START_FUDGE_);
|
|
1904
1924
|
const appendWindowEnd =
|
|
1905
|
-
reference.appendWindowEnd +
|
|
1925
|
+
Math.min(reference.appendWindowEnd, this.playRangeEnd_) +
|
|
1926
|
+
StreamingEngine.APPEND_WINDOW_END_FUDGE_;
|
|
1906
1927
|
|
|
1907
1928
|
goog.asserts.assert(
|
|
1908
1929
|
reference.startTime <= appendWindowEnd,
|
|
@@ -2670,7 +2691,10 @@ shaka.media.StreamingEngine = class {
|
|
|
2670
2691
|
}
|
|
2671
2692
|
|
|
2672
2693
|
// First fire an error event.
|
|
2673
|
-
|
|
2694
|
+
if (!error.handled ||
|
|
2695
|
+
error.code != shaka.util.Error.Code.SEGMENT_MISSING) {
|
|
2696
|
+
this.playerInterface_.onError(error);
|
|
2697
|
+
}
|
|
2674
2698
|
|
|
2675
2699
|
// If the error was not handled by the application, call the failure
|
|
2676
2700
|
// callback.
|
package/lib/player.js
CHANGED
|
@@ -2401,6 +2401,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2401
2401
|
this.config_.playRangeStart,
|
|
2402
2402
|
this.config_.playRangeEnd);
|
|
2403
2403
|
|
|
2404
|
+
this.streamingEngine_.applyPlayRange(
|
|
2405
|
+
this.config_.playRangeStart, this.config_.playRangeEnd);
|
|
2404
2406
|
|
|
2405
2407
|
const setupPlayhead = (startTime) => {
|
|
2406
2408
|
this.playhead_ = this.createPlayhead(startTime);
|
|
@@ -7457,7 +7459,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
7457
7459
|
* @export
|
|
7458
7460
|
*/
|
|
7459
7461
|
// eslint-disable-next-line no-useless-concat
|
|
7460
|
-
shaka.Player.version = 'v4.9.
|
|
7462
|
+
shaka.Player.version = 'v4.9.9' + '-uncompiled'; // x-release-please-version
|
|
7461
7463
|
|
|
7462
7464
|
// Initialize the deprecation system using the version string we just set
|
|
7463
7465
|
// on the player.
|
package/lib/util/mime_utils.js
CHANGED
|
@@ -174,7 +174,12 @@ shaka.util.MimeUtils = class {
|
|
|
174
174
|
return 'hevc'; // H265
|
|
175
175
|
case base === 'dvh1':
|
|
176
176
|
case base === 'dvhe':
|
|
177
|
-
return 'dovi'; // Dolby Vision
|
|
177
|
+
return 'dovi-hevc'; // Dolby Vision based in HEVC
|
|
178
|
+
case base === 'dvav':
|
|
179
|
+
case base === 'dva1':
|
|
180
|
+
return 'dovi-avc'; // Dolby Vision based in AVC
|
|
181
|
+
case base === 'dav1':
|
|
182
|
+
return 'dovi-av1'; // Dolby Vision based in AV1
|
|
178
183
|
}
|
|
179
184
|
return base;
|
|
180
185
|
}
|
|
@@ -275,11 +275,11 @@ shaka.util.Mp4BoxParsers = class {
|
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
/**
|
|
278
|
-
* Parses
|
|
278
|
+
* Parses an audio sample entry box.
|
|
279
279
|
* @param {!shaka.util.DataViewReader} reader
|
|
280
|
-
* @return {!shaka.util.
|
|
280
|
+
* @return {!shaka.util.ParsedAudioSampleEntryBox}
|
|
281
281
|
*/
|
|
282
|
-
static
|
|
282
|
+
static audioSampleEntry(reader) {
|
|
283
283
|
reader.skip(6); // Skip "reserved"
|
|
284
284
|
reader.skip(2); // Skip "data_reference_index"
|
|
285
285
|
reader.skip(8); // Skip "reserved"
|
|
@@ -604,6 +604,42 @@ shaka.util.Mp4BoxParsers = class {
|
|
|
604
604
|
};
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
+
/**
|
|
608
|
+
* Parses AV1 codec string with COLR box information.
|
|
609
|
+
*
|
|
610
|
+
* AV1 codec info: https://aomediacodec.github.io/av1-isobmff/#codecsparam
|
|
611
|
+
*
|
|
612
|
+
* @param {string} codec
|
|
613
|
+
* @param {!shaka.util.DataViewReader} reader
|
|
614
|
+
* @return {string}
|
|
615
|
+
*/
|
|
616
|
+
static updateAV1CodecWithCOLRBox(codec, reader) {
|
|
617
|
+
const Mp4BoxParsers = shaka.util.Mp4BoxParsers;
|
|
618
|
+
const initialPosition = reader.getPosition();
|
|
619
|
+
const data = reader.readBytes(4);
|
|
620
|
+
let colorType = '';
|
|
621
|
+
colorType += String.fromCharCode(data[0]);
|
|
622
|
+
colorType += String.fromCharCode(data[1]);
|
|
623
|
+
colorType += String.fromCharCode(data[2]);
|
|
624
|
+
colorType += String.fromCharCode(data[3]);
|
|
625
|
+
if (colorType === 'nclx') {
|
|
626
|
+
const colorPrimaries = reader.readUint16();
|
|
627
|
+
const transferCharacteristics = reader.readUint16();
|
|
628
|
+
const matrixCoefficients = reader.readUint16();
|
|
629
|
+
const videoFullRangeFlag = reader.readUint8() >> 7;
|
|
630
|
+
const codecParts = codec.split('.');
|
|
631
|
+
if (codecParts.length == 10) {
|
|
632
|
+
codecParts[6] = Mp4BoxParsers.addLeadingZero_(colorPrimaries);
|
|
633
|
+
codecParts[7] = Mp4BoxParsers.addLeadingZero_(transferCharacteristics);
|
|
634
|
+
codecParts[8] = Mp4BoxParsers.addLeadingZero_(matrixCoefficients);
|
|
635
|
+
codecParts[9] = String(videoFullRangeFlag);
|
|
636
|
+
codec = codecParts.join('.');
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
reader.seek(initialPosition);
|
|
640
|
+
return codec;
|
|
641
|
+
}
|
|
642
|
+
|
|
607
643
|
/**
|
|
608
644
|
* Convert a number to hex
|
|
609
645
|
* @param {number} x
|
|
@@ -820,7 +856,7 @@ shaka.util.ParsedTENCBox;
|
|
|
820
856
|
*
|
|
821
857
|
* @exportDoc
|
|
822
858
|
*/
|
|
823
|
-
shaka.util.
|
|
859
|
+
shaka.util.ParsedAudioSampleEntryBox;
|
|
824
860
|
|
|
825
861
|
/**
|
|
826
862
|
* @typedef {{
|
package/package.json
CHANGED
package/ui/locales/es.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"AD_DURATION": "Duración del anuncio",
|
|
3
3
|
"AD_PROGRESS": "Anuncio [AD_ON] de [NUM_ADS]",
|
|
4
4
|
"AD_TIME": "Anuncio: [AD_TIME]",
|
|
5
|
+
"AIRPLAY": "AirPlay",
|
|
5
6
|
"AUTO_QUALITY": "Automático",
|
|
6
7
|
"BACK": "Atrás",
|
|
7
8
|
"CAPTIONS": "Subtítulos",
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
"PICTURE_IN_PICTURE": "Imagen en imagen",
|
|
27
28
|
"PLAY": "Reproducir",
|
|
28
29
|
"PLAYBACK_RATE": "Velocidad de reproducción",
|
|
30
|
+
"QUALITY": "Calidad",
|
|
29
31
|
"RECENTER_VR": "Recentrar",
|
|
30
32
|
"RESOLUTION": "Resolución",
|
|
31
33
|
"REWIND": "Rebobinar",
|
package/ui/locales/fr.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"AD_DURATION": "Durée de l'annonce",
|
|
3
|
-
"AD_PROGRESS": "Annonce
|
|
4
|
-
"
|
|
3
|
+
"AD_PROGRESS": "Annonce [AD_ON] sur [NUM_ADS]",
|
|
4
|
+
"AD_STATISTICS": "Statistiques de la annonce",
|
|
5
|
+
"AD_TIME": "Annonce : [AD_TIME]",
|
|
6
|
+
"AIRPLAY": "AirPlay",
|
|
5
7
|
"AUTO_QUALITY": "Automatique",
|
|
6
8
|
"BACK": "Retour",
|
|
7
9
|
"CAPTIONS": "Sous-titres",
|
|
@@ -10,7 +12,7 @@
|
|
|
10
12
|
"ENTER_PICTURE_IN_PICTURE": "Utiliser le mode Picture-in-Picture",
|
|
11
13
|
"EXIT_FULL_SCREEN": "Quitter le mode plein écran",
|
|
12
14
|
"EXIT_LOOP_MODE": "Arrêter la lecture en boucle de la vidéo en cours",
|
|
13
|
-
"EXIT_PICTURE_IN_PICTURE": "Quitter le mode
|
|
15
|
+
"EXIT_PICTURE_IN_PICTURE": "Quitter le mode PIP (Picture-in-picture)",
|
|
14
16
|
"FAST_FORWARD": "Avance rapide",
|
|
15
17
|
"FULL_SCREEN": "Plein écran",
|
|
16
18
|
"LANGUAGE": "Langue",
|
|
@@ -26,11 +28,18 @@
|
|
|
26
28
|
"PICTURE_IN_PICTURE": "Picture-in-Picture",
|
|
27
29
|
"PLAY": "Visionner",
|
|
28
30
|
"PLAYBACK_RATE": "Vitesse de lecture",
|
|
31
|
+
"QUALITY": "Qualité",
|
|
32
|
+
"RECENTER_VR": "Recentrer",
|
|
33
|
+
"REPLAY": "Rejouer",
|
|
29
34
|
"RESOLUTION": "Résolution",
|
|
30
35
|
"REWIND": "Retour arrière",
|
|
31
36
|
"SEEK": "Chercher",
|
|
32
37
|
"SKIP_AD": "Passer l'annonce",
|
|
33
38
|
"SKIP_TO_LIVE": "Accéder à la partie la plus récente du direct",
|
|
39
|
+
"STATISTICS": "Statistiques",
|
|
40
|
+
"SUBTITLE_FORCED": "Forcé",
|
|
41
|
+
"SURROUND": "Surround",
|
|
42
|
+
"TOGGLE_STEREOSCOPIC": "Stéréoscopique ON/OFF",
|
|
34
43
|
"UNDETERMINED_LANGUAGE": "Langue indéterminée",
|
|
35
44
|
"UNMUTE": "Réactiver le son",
|
|
36
45
|
"UNRECOGNIZED_LANGUAGE": "Non reconnu",
|
package/ui/locales/pt-BR.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"AD_DURATION": "Duração do anúncio",
|
|
3
3
|
"AD_PROGRESS": "Anúncio [AD_ON] de [NUM_ADS]",
|
|
4
|
+
"AD_STATISTICS": "Estatísticas de anúncios",
|
|
4
5
|
"AD_TIME": "Anúncio: [AD_TIME]",
|
|
6
|
+
"AIRPLAY": "AirPlay",
|
|
5
7
|
"AUTO_QUALITY": "Automática",
|
|
6
8
|
"BACK": "Voltar",
|
|
7
9
|
"CAPTIONS": "Legendas",
|
|
@@ -26,11 +28,18 @@
|
|
|
26
28
|
"PICTURE_IN_PICTURE": "Picture-in-picture",
|
|
27
29
|
"PLAY": "Reproduzir",
|
|
28
30
|
"PLAYBACK_RATE": "Velocidade da reprodução",
|
|
31
|
+
"QUALITY": "Qualidade",
|
|
32
|
+
"RECENTER_VR": "Recentralizar",
|
|
33
|
+
"REPLAY": "Replay",
|
|
29
34
|
"RESOLUTION": "Resolução",
|
|
30
35
|
"REWIND": "Retroceder",
|
|
31
36
|
"SEEK": "Procurar",
|
|
32
37
|
"SKIP_AD": "Pular anúncio",
|
|
33
38
|
"SKIP_TO_LIVE": "Pular para transmissão ao vivo",
|
|
39
|
+
"STATISTICS": "Estatísticas",
|
|
40
|
+
"SUBTITLE_FORCED": "Forçado",
|
|
41
|
+
"SURROUND": "Surround",
|
|
42
|
+
"TOGGLE_STEREOSCOPIC": "Alternar estereoscópico",
|
|
34
43
|
"UNDETERMINED_LANGUAGE": "Indeterminado",
|
|
35
44
|
"UNMUTE": "Ativar som",
|
|
36
45
|
"UNRECOGNIZED_LANGUAGE": "Não reconhecido",
|
package/ui/locales/pt-PT.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"AD_DURATION": "Duração do anúncio",
|
|
3
3
|
"AD_PROGRESS": "Anúncio [AD_ON] de [NUM_ADS]",
|
|
4
|
+
"AD_STATISTICS": "Estatísticas de anúncios",
|
|
4
5
|
"AD_TIME": "Anúncio: [AD_TIME]",
|
|
6
|
+
"AIRPLAY": "AirPlay",
|
|
5
7
|
"AUTO_QUALITY": "Automático",
|
|
6
8
|
"BACK": "Anterior",
|
|
7
9
|
"CAPTIONS": "Legendas",
|
|
@@ -26,11 +28,18 @@
|
|
|
26
28
|
"PICTURE_IN_PICTURE": "Ecrã no ecrã",
|
|
27
29
|
"PLAY": "Reproduzir",
|
|
28
30
|
"PLAYBACK_RATE": "Velocidade de reprodução",
|
|
31
|
+
"QUALITY": "Qualidade",
|
|
32
|
+
"RECENTER_VR": "Recentrar",
|
|
33
|
+
"REPLAY": "Repetição",
|
|
29
34
|
"RESOLUTION": "Resolução",
|
|
30
35
|
"REWIND": "Rebobinar",
|
|
31
36
|
"SEEK": "Procurar",
|
|
32
37
|
"SKIP_AD": "Ignorar anúncio",
|
|
33
38
|
"SKIP_TO_LIVE": "Avançar para o direto",
|
|
39
|
+
"STATISTICS": "Estatísticas",
|
|
40
|
+
"SUBTITLE_FORCED": "Forçado",
|
|
41
|
+
"SURROUND": "Envolvente",
|
|
42
|
+
"TOGGLE_STEREOSCOPIC": "Alternar estereoscópico",
|
|
34
43
|
"UNDETERMINED_LANGUAGE": "Indeterminado",
|
|
35
44
|
"UNMUTE": "Reativar o som",
|
|
36
45
|
"UNRECOGNIZED_LANGUAGE": "Não reconhecido",
|