shaka-player 4.12.4 → 4.12.6
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/deps.js +2 -2
- package/dist/locales.js +35 -35
- package/dist/shaka-player.compiled.d.ts +11 -3
- package/dist/shaka-player.compiled.debug.d.ts +11 -3
- package/dist/shaka-player.compiled.debug.externs.js +8 -5
- package/dist/shaka-player.compiled.debug.js +340 -331
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +8 -5
- package/dist/shaka-player.compiled.js +1383 -1378
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +11 -3
- package/dist/shaka-player.ui.debug.d.ts +11 -3
- package/dist/shaka-player.ui.debug.externs.js +8 -5
- package/dist/shaka-player.ui.debug.js +357 -348
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +8 -5
- package/dist/shaka-player.ui.js +1605 -1599
- package/dist/shaka-player.ui.map +3 -3
- package/externs/shaka/codecs.js +21 -0
- package/externs/shaka/offline.js +4 -0
- package/lib/cast/cast_utils.js +1 -0
- package/lib/dash/dash_parser.js +3 -0
- package/lib/hls/hls_parser.js +26 -5
- package/lib/media/drm_engine.js +70 -29
- package/lib/media/manifest_filterer.js +2 -1
- package/lib/media/media_source_engine.js +138 -129
- package/lib/media/segment_utils.js +50 -44
- package/lib/media/streaming_engine.js +9 -1
- package/lib/offline/download_info.js +5 -0
- package/lib/offline/download_manager.js +54 -0
- package/lib/offline/manifest_converter.js +1 -0
- package/lib/offline/storage.js +12 -3
- package/lib/player.js +52 -29
- package/lib/polyfill/media_capabilities.js +1 -1
- package/lib/text/simple_text_displayer.js +9 -1
- package/lib/text/ui_text_displayer.js +2 -14
- package/lib/transmuxer/aac_transmuxer.js +11 -3
- package/lib/transmuxer/ac3_transmuxer.js +11 -3
- package/lib/transmuxer/ec3_transmuxer.js +11 -3
- package/lib/transmuxer/h264.js +143 -70
- package/lib/transmuxer/mp3_transmuxer.js +11 -3
- package/lib/transmuxer/ts_transmuxer.js +68 -28
- package/lib/util/drm_utils.js +20 -0
- package/lib/util/mime_utils.js +3 -0
- package/lib/util/object_utils.js +83 -0
- package/lib/util/platform.js +48 -40
- package/lib/util/stream_utils.js +37 -113
- package/lib/util/ts_parser.js +111 -85
- package/package.json +1 -1
- package/ui/ad_counter.js +5 -0
- package/ui/controls.js +4 -2
- package/ui/fast_forward_button.js +7 -0
- package/ui/play_button.js +1 -1
- package/ui/playback_rate_selection.js +1 -1
- package/ui/rewind_button.js +7 -0
package/lib/util/stream_utils.js
CHANGED
|
@@ -146,9 +146,10 @@ shaka.util.StreamUtils = class {
|
|
|
146
146
|
'vp09': 0.9,
|
|
147
147
|
'hevc': 0.85,
|
|
148
148
|
'dovi-hevc': 0.8,
|
|
149
|
-
'
|
|
150
|
-
'
|
|
151
|
-
'
|
|
149
|
+
'dovi-p5': 0.75,
|
|
150
|
+
'av01': 0.7,
|
|
151
|
+
'dovi-av1': 0.65,
|
|
152
|
+
'vvc': 0.6,
|
|
152
153
|
};
|
|
153
154
|
|
|
154
155
|
const videoStreams = Array.from(videoStreamsSet)
|
|
@@ -393,11 +394,13 @@ shaka.util.StreamUtils = class {
|
|
|
393
394
|
* @param {shaka.media.DrmEngine} drmEngine
|
|
394
395
|
* @param {shaka.extern.Manifest} manifest
|
|
395
396
|
* @param {!Array<string>=} preferredKeySystems
|
|
397
|
+
* @param {!Object.<string, string>=} keySystemsMapping
|
|
396
398
|
*/
|
|
397
|
-
static async filterManifest(drmEngine, manifest, preferredKeySystems = []
|
|
399
|
+
static async filterManifest(drmEngine, manifest, preferredKeySystems = [],
|
|
400
|
+
keySystemsMapping = {}) {
|
|
398
401
|
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(
|
|
399
402
|
drmEngine, manifest, manifest.offlineSessionIds.length > 0,
|
|
400
|
-
preferredKeySystems);
|
|
403
|
+
preferredKeySystems, keySystemsMapping);
|
|
401
404
|
shaka.util.StreamUtils.filterTextStreams_(manifest);
|
|
402
405
|
await shaka.util.StreamUtils.filterImageStreams_(manifest);
|
|
403
406
|
}
|
|
@@ -411,9 +414,11 @@ shaka.util.StreamUtils = class {
|
|
|
411
414
|
* @param {shaka.extern.Manifest} manifest
|
|
412
415
|
* @param {boolean} usePersistentLicenses
|
|
413
416
|
* @param {!Array<string>} preferredKeySystems
|
|
417
|
+
* @param {!Object.<string, string>} keySystemsMapping
|
|
414
418
|
*/
|
|
415
419
|
static async filterManifestByMediaCapabilities(
|
|
416
|
-
drmEngine, manifest, usePersistentLicenses, preferredKeySystems
|
|
420
|
+
drmEngine, manifest, usePersistentLicenses, preferredKeySystems,
|
|
421
|
+
keySystemsMapping) {
|
|
417
422
|
goog.asserts.assert(navigator.mediaCapabilities,
|
|
418
423
|
'MediaCapabilities should be valid.');
|
|
419
424
|
|
|
@@ -435,7 +440,8 @@ shaka.util.StreamUtils = class {
|
|
|
435
440
|
const StreamUtils = shaka.util.StreamUtils;
|
|
436
441
|
|
|
437
442
|
manifest.variants = manifest.variants.filter((variant) => {
|
|
438
|
-
const supported = StreamUtils.checkVariantSupported_(
|
|
443
|
+
const supported = StreamUtils.checkVariantSupported_(
|
|
444
|
+
variant, keySystem, keySystemsMapping);
|
|
439
445
|
// Filter out all unsupported variants.
|
|
440
446
|
if (!supported) {
|
|
441
447
|
shaka.log.debug('Dropping variant - not compatible with platform',
|
|
@@ -485,15 +491,31 @@ shaka.util.StreamUtils = class {
|
|
|
485
491
|
/**
|
|
486
492
|
* @param {!shaka.extern.Variant} variant
|
|
487
493
|
* @param {?string} keySystem
|
|
494
|
+
* @param {!Object.<string, string>} keySystemsMapping
|
|
488
495
|
* @return {boolean}
|
|
489
496
|
* @private
|
|
490
497
|
*/
|
|
491
|
-
static checkVariantSupported_(variant, keySystem) {
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
498
|
+
static checkVariantSupported_(variant, keySystem, keySystemsMapping) {
|
|
499
|
+
const variantSupported = variant.decodingInfos.some((decodingInfo) => {
|
|
500
|
+
if (!decodingInfo.supported) {
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
if (keySystem) {
|
|
504
|
+
const keySystemAccess = decodingInfo.keySystemAccess;
|
|
505
|
+
if (keySystemAccess) {
|
|
506
|
+
const currentKeySystem =
|
|
507
|
+
keySystemsMapping[keySystemAccess.keySystem] ||
|
|
508
|
+
keySystemAccess.keySystem;
|
|
509
|
+
if (currentKeySystem != keySystem) {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return true;
|
|
515
|
+
});
|
|
516
|
+
if (!variantSupported) {
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
497
519
|
|
|
498
520
|
const isXboxOne = shaka.util.Platform.isXboxOne();
|
|
499
521
|
const isFirefoxAndroid = shaka.util.Platform.isFirefox() &&
|
|
@@ -511,43 +533,6 @@ shaka.util.StreamUtils = class {
|
|
|
511
533
|
return false;
|
|
512
534
|
}
|
|
513
535
|
|
|
514
|
-
if (video) {
|
|
515
|
-
let videoCodecs = StreamUtils.getCorrectVideoCodecs(video.codecs);
|
|
516
|
-
// For multiplexed streams. Here we must check the audio of the
|
|
517
|
-
// stream to see if it is compatible.
|
|
518
|
-
if (video.codecs.includes(',')) {
|
|
519
|
-
const allCodecs = video.codecs.split(',');
|
|
520
|
-
|
|
521
|
-
videoCodecs = ManifestParserUtils.guessCodecs(
|
|
522
|
-
ContentType.VIDEO, allCodecs);
|
|
523
|
-
videoCodecs = StreamUtils.getCorrectVideoCodecs(videoCodecs);
|
|
524
|
-
let audioCodecs = ManifestParserUtils.guessCodecs(
|
|
525
|
-
ContentType.AUDIO, allCodecs);
|
|
526
|
-
audioCodecs = StreamUtils.getCorrectAudioCodecs(
|
|
527
|
-
audioCodecs, video.mimeType);
|
|
528
|
-
|
|
529
|
-
const audioFullType = MimeUtils.getFullOrConvertedType(
|
|
530
|
-
video.mimeType, audioCodecs, ContentType.AUDIO);
|
|
531
|
-
|
|
532
|
-
if (!Capabilities.isTypeSupported(audioFullType)) {
|
|
533
|
-
return false;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// Update the codec string with the (possibly) converted codecs.
|
|
537
|
-
videoCodecs = [videoCodecs, audioCodecs].join(',');
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
const fullType = MimeUtils.getFullOrConvertedType(
|
|
541
|
-
video.mimeType, videoCodecs, ContentType.VIDEO);
|
|
542
|
-
|
|
543
|
-
if (!Capabilities.isTypeSupported(fullType)) {
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// Update the codec string with the (possibly) converted codecs.
|
|
548
|
-
video.codecs = videoCodecs;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
536
|
const audio = variant.audio;
|
|
552
537
|
|
|
553
538
|
// See: https://github.com/shaka-project/shaka-player/issues/6111
|
|
@@ -559,68 +544,7 @@ shaka.util.StreamUtils = class {
|
|
|
559
544
|
return false;
|
|
560
545
|
}
|
|
561
546
|
|
|
562
|
-
|
|
563
|
-
const codecs = StreamUtils.getCorrectAudioCodecs(
|
|
564
|
-
audio.codecs, audio.mimeType);
|
|
565
|
-
const fullType = MimeUtils.getFullOrConvertedType(
|
|
566
|
-
audio.mimeType, codecs, ContentType.AUDIO);
|
|
567
|
-
|
|
568
|
-
if (!Capabilities.isTypeSupported(fullType)) {
|
|
569
|
-
return false;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
// Update the codec string with the (possibly) converted codecs.
|
|
573
|
-
audio.codecs = codecs;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
return variant.decodingInfos.some((decodingInfo) => {
|
|
577
|
-
if (!decodingInfo.supported) {
|
|
578
|
-
return false;
|
|
579
|
-
}
|
|
580
|
-
if (keySystem) {
|
|
581
|
-
const keySystemAccess = decodingInfo.keySystemAccess;
|
|
582
|
-
if (keySystemAccess) {
|
|
583
|
-
if (keySystemAccess.keySystem != keySystem) {
|
|
584
|
-
return false;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return true;
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
/**
|
|
594
|
-
* Constructs a string out of an object, similar to the JSON.stringify method.
|
|
595
|
-
* Unlike that method, this guarantees that the order of the keys is
|
|
596
|
-
* alphabetical, so it can be used as a way to reliably compare two objects.
|
|
597
|
-
*
|
|
598
|
-
* @param {!Object} obj
|
|
599
|
-
* @return {string}
|
|
600
|
-
* @private
|
|
601
|
-
*/
|
|
602
|
-
static alphabeticalKeyOrderStringify_(obj) {
|
|
603
|
-
const keys = [];
|
|
604
|
-
for (const key in obj) {
|
|
605
|
-
keys.push(key);
|
|
606
|
-
}
|
|
607
|
-
// Alphabetically sort the keys, so they will be in a reliable order.
|
|
608
|
-
keys.sort();
|
|
609
|
-
|
|
610
|
-
const terms = [];
|
|
611
|
-
for (const key of keys) {
|
|
612
|
-
const escapedKey = JSON.stringify(key);
|
|
613
|
-
const value = obj[key];
|
|
614
|
-
if (value instanceof Object) {
|
|
615
|
-
const stringifiedValue =
|
|
616
|
-
shaka.util.StreamUtils.alphabeticalKeyOrderStringify_(value);
|
|
617
|
-
terms.push(escapedKey + ':' + stringifiedValue);
|
|
618
|
-
} else {
|
|
619
|
-
const escapedValue = JSON.stringify(value);
|
|
620
|
-
terms.push(escapedKey + ':' + escapedValue);
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
return '{' + terms.join(',') + '}';
|
|
547
|
+
return true;
|
|
624
548
|
}
|
|
625
549
|
|
|
626
550
|
|
|
@@ -659,7 +583,7 @@ shaka.util.StreamUtils = class {
|
|
|
659
583
|
const promises = [];
|
|
660
584
|
for (const decodingConfig of decodingConfigs) {
|
|
661
585
|
const cacheKey =
|
|
662
|
-
|
|
586
|
+
shaka.util.ObjectUtils.alphabeticalKeyOrderStringify(decodingConfig);
|
|
663
587
|
|
|
664
588
|
const cache = StreamUtils.decodingConfigCache_;
|
|
665
589
|
if (cache[cacheKey]) {
|
package/lib/util/ts_parser.js
CHANGED
|
@@ -517,7 +517,11 @@ shaka.util.TsParser = class {
|
|
|
517
517
|
shaka.Deprecate.deprecateFeature(5,
|
|
518
518
|
'TsParser.parseAvcNalus',
|
|
519
519
|
'Please use parseNalus function instead.');
|
|
520
|
-
|
|
520
|
+
const lastInfo = {
|
|
521
|
+
nalu: null,
|
|
522
|
+
state: null,
|
|
523
|
+
};
|
|
524
|
+
return this.parseNalus(pes, lastInfo);
|
|
521
525
|
}
|
|
522
526
|
|
|
523
527
|
/**
|
|
@@ -527,12 +531,11 @@ shaka.util.TsParser = class {
|
|
|
527
531
|
* Credit to https://github.com/video-dev/hls.js/blob/master/src/demux/tsdemuxer.ts
|
|
528
532
|
*
|
|
529
533
|
* @param {shaka.extern.MPEG_PES} pes
|
|
530
|
-
* @param {?shaka.extern.VideoNalu
|
|
531
|
-
* @param {?number=} lastState
|
|
534
|
+
* @param {{nalu: ?shaka.extern.VideoNalu, state: ?number}} lastInfo
|
|
532
535
|
* @return {!Array.<shaka.extern.VideoNalu>}
|
|
533
536
|
* @export
|
|
534
537
|
*/
|
|
535
|
-
parseNalus(pes,
|
|
538
|
+
parseNalus(pes, lastInfo) {
|
|
536
539
|
const timescale = shaka.util.TsParser.Timescale;
|
|
537
540
|
const time = pes.pts ? pes.pts / timescale : null;
|
|
538
541
|
const data = pes.data;
|
|
@@ -548,7 +551,12 @@ shaka.util.TsParser = class {
|
|
|
548
551
|
// precede each NALU. A start code is 2 or 3 0x00 bytes followed with a
|
|
549
552
|
// 0x01 byte. e.g. 0x000001 or 0x00000001.
|
|
550
553
|
// More info in: https://stackoverflow.com/questions/24884827/possible-locations-for-sequence-picture-parameter-sets-for-h-264-stream/24890903#24890903
|
|
551
|
-
let numZeros =
|
|
554
|
+
let numZeros = lastInfo.state || 0;
|
|
555
|
+
|
|
556
|
+
const initialNumZeros = numZeros;
|
|
557
|
+
|
|
558
|
+
/** @type {number} */
|
|
559
|
+
let i = 0;
|
|
552
560
|
|
|
553
561
|
/** @type {!Array.<shaka.extern.VideoNalu>} */
|
|
554
562
|
const nalus = [];
|
|
@@ -559,103 +567,119 @@ shaka.util.TsParser = class {
|
|
|
559
567
|
// Extracted from the first byte.
|
|
560
568
|
let lastNaluType = 0;
|
|
561
569
|
|
|
562
|
-
|
|
563
|
-
|
|
570
|
+
const getNaluType = (offset) => {
|
|
571
|
+
if (this.videoCodec_ == 'hvc') {
|
|
572
|
+
return (data[offset] >> 1) & 0x3f;
|
|
573
|
+
} else {
|
|
574
|
+
return data[offset] & 0x1f;
|
|
575
|
+
}
|
|
576
|
+
};
|
|
564
577
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
// If we are scanning the next PES, we need append the data to the
|
|
572
|
-
// previous Nalu and don't scan for more nalus.
|
|
573
|
-
const startCodeSize = numZeros > 3 ? 3 : numZeros;
|
|
574
|
-
const lastByteToKeep = i - startCodeSize;
|
|
575
|
-
// Optimization
|
|
576
|
-
if (lastState && lastByteToKeep != 0) {
|
|
577
|
-
const prevData = data.subarray(0, lastByteToKeep);
|
|
578
|
-
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
|
|
579
|
-
lastNalu.data, prevData);
|
|
580
|
-
lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
|
|
581
|
-
lastNalu.fullData, prevData);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
// We just read a start code. Consume the NALU we passed, if any.
|
|
585
|
-
if (lastNaluStart >= 0) {
|
|
586
|
-
// Because the start position includes the header size.
|
|
587
|
-
const firstByteToKeep = lastNaluStart + naluHeaderSize;
|
|
578
|
+
const getLastNalu = () => {
|
|
579
|
+
if (nalus.length) {
|
|
580
|
+
return nalus[nalus.length - 1];
|
|
581
|
+
}
|
|
582
|
+
return lastInfo.nalu;
|
|
583
|
+
};
|
|
588
584
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
585
|
+
if (numZeros == -1) {
|
|
586
|
+
// special use case where we found 3 or 4-byte start codes exactly at the
|
|
587
|
+
// end of previous PES packet
|
|
588
|
+
lastNaluStart = 0;
|
|
589
|
+
// NALu type is value read from offset 0
|
|
590
|
+
lastNaluType = getNaluType(0);
|
|
591
|
+
numZeros = 0;
|
|
592
|
+
i = 1;
|
|
593
|
+
}
|
|
593
594
|
|
|
595
|
+
while (i < len) {
|
|
596
|
+
const value = data[i++];
|
|
597
|
+
// Optimization. numZeros 0 and 1 are the predominant case.
|
|
598
|
+
if (!numZeros) {
|
|
599
|
+
numZeros = value ? 0 : 1;
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
if (numZeros === 1) {
|
|
603
|
+
numZeros = value ? 0 : 2;
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
if (!value) {
|
|
607
|
+
numZeros = 3;
|
|
608
|
+
} else if (value == 1) {
|
|
609
|
+
const overflow = i - numZeros - 1;
|
|
610
|
+
if (lastNaluStart >= 0) {
|
|
594
611
|
/** @type {shaka.extern.VideoNalu} */
|
|
595
612
|
const nalu = {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
fullData: data.subarray(lastNaluStart, lastByteToKeep + 1),
|
|
613
|
+
data: data.subarray(lastNaluStart + naluHeaderSize, overflow),
|
|
614
|
+
fullData: data.subarray(lastNaluStart, overflow),
|
|
599
615
|
type: lastNaluType,
|
|
600
616
|
time: time,
|
|
617
|
+
state: null,
|
|
601
618
|
};
|
|
602
619
|
nalus.push(nalu);
|
|
603
|
-
} else
|
|
604
|
-
const
|
|
605
|
-
if (
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
620
|
+
} else {
|
|
621
|
+
const lastNalu = getLastNalu();
|
|
622
|
+
if (lastNalu) {
|
|
623
|
+
if (initialNumZeros && i <= 4 - initialNumZeros) {
|
|
624
|
+
// Start delimiter overlapping between PES packets
|
|
625
|
+
// strip start delimiter bytes from the end of last NAL unit
|
|
626
|
+
// check if lastNalu had a state different from zero
|
|
627
|
+
if (lastNalu.state) {
|
|
628
|
+
// strip last bytes
|
|
629
|
+
lastNalu.data = lastNalu.data.subarray(
|
|
630
|
+
0, lastNalu.data.byteLength - initialNumZeros);
|
|
631
|
+
lastNalu.fullData = lastNalu.fullData.subarray(
|
|
632
|
+
0, lastNalu.fullData.byteLength - initialNumZeros);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
// If NAL units are not starting right at the beginning of the PES
|
|
636
|
+
// packet, push preceding data into previous NAL unit.
|
|
637
|
+
if (overflow > 0) {
|
|
638
|
+
const prevData = data.subarray(0, overflow);
|
|
639
|
+
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
|
|
640
|
+
lastNalu.data, prevData);
|
|
641
|
+
lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
|
|
642
|
+
lastNalu.fullData, prevData);
|
|
643
|
+
lastNalu.state = 0;
|
|
644
|
+
}
|
|
611
645
|
}
|
|
612
646
|
}
|
|
613
647
|
|
|
614
|
-
//
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// Advance and read the type of the next NALU.
|
|
622
|
-
i++;
|
|
623
|
-
lastNaluStart = i;
|
|
624
|
-
if (this.videoCodec_ == 'hvc') {
|
|
625
|
-
lastNaluType = (data[i] >> 1) & 0x3f;
|
|
648
|
+
// Check if we can read unit type
|
|
649
|
+
if (i < len) {
|
|
650
|
+
lastNaluType = getNaluType(i);
|
|
651
|
+
lastNaluStart = i;
|
|
652
|
+
numZeros = 0;
|
|
626
653
|
} else {
|
|
627
|
-
|
|
654
|
+
// Not enough byte to read unit type.
|
|
655
|
+
// Let's read it on next PES parsing.
|
|
656
|
+
numZeros = -1;
|
|
628
657
|
}
|
|
629
|
-
numZeros = 0;
|
|
630
658
|
} else {
|
|
631
659
|
numZeros = 0;
|
|
632
660
|
}
|
|
633
|
-
// If we have gone through all the data from the PES and we have an
|
|
634
|
-
// unfinished Nalu, we will try to use the next PES to complete the
|
|
635
|
-
// unfinished Nalu.
|
|
636
|
-
if (i >= (len - 1) && lastNaluStart >= 0 && numZeros >= 0) {
|
|
637
|
-
// The rest of the buffer was a NALU.
|
|
638
|
-
// Because the start position includes the header size.
|
|
639
|
-
const firstByteToKeep = lastNaluStart + naluHeaderSize;
|
|
640
|
-
infoOfLastNalu = {
|
|
641
|
-
data: data.subarray(firstByteToKeep, len),
|
|
642
|
-
fullData: data.subarray(lastNaluStart, len),
|
|
643
|
-
type: lastNaluType,
|
|
644
|
-
time: time,
|
|
645
|
-
};
|
|
646
|
-
}
|
|
647
661
|
}
|
|
648
662
|
|
|
649
|
-
if (
|
|
650
|
-
|
|
663
|
+
if (lastNaluStart >= 0 && numZeros >= 0) {
|
|
664
|
+
const nalu = {
|
|
665
|
+
data: data.subarray(lastNaluStart + naluHeaderSize, len),
|
|
666
|
+
fullData: data.subarray(lastNaluStart, len),
|
|
667
|
+
type: lastNaluType,
|
|
668
|
+
time: time,
|
|
669
|
+
state: numZeros,
|
|
670
|
+
};
|
|
671
|
+
nalus.push(nalu);
|
|
651
672
|
}
|
|
652
|
-
if (!nalus.length &&
|
|
653
|
-
lastNalu
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
673
|
+
if (!nalus.length && lastInfo.nalu) {
|
|
674
|
+
const lastNalu = getLastNalu();
|
|
675
|
+
if (lastNalu) {
|
|
676
|
+
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
|
|
677
|
+
lastNalu.data, data);
|
|
678
|
+
lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
|
|
679
|
+
lastNalu.fullData, data);
|
|
680
|
+
}
|
|
657
681
|
}
|
|
658
|
-
|
|
682
|
+
lastInfo.state = numZeros;
|
|
659
683
|
return nalus;
|
|
660
684
|
}
|
|
661
685
|
|
|
@@ -759,14 +783,16 @@ shaka.util.TsParser = class {
|
|
|
759
783
|
}
|
|
760
784
|
}
|
|
761
785
|
if (naluProcessing) {
|
|
762
|
-
|
|
763
|
-
|
|
786
|
+
const lastInfo = {
|
|
787
|
+
nalu: null,
|
|
788
|
+
state: null,
|
|
789
|
+
};
|
|
764
790
|
const pesWithLength = [];
|
|
765
791
|
for (const pes of this.videoPes_) {
|
|
766
|
-
pes.nalus = this.parseNalus(pes,
|
|
792
|
+
pes.nalus = this.parseNalus(pes, lastInfo);
|
|
767
793
|
if (pes.nalus.length) {
|
|
768
794
|
pesWithLength.push(pes);
|
|
769
|
-
|
|
795
|
+
lastInfo.nalu = pes.nalus[pes.nalus.length - 1];
|
|
770
796
|
}
|
|
771
797
|
}
|
|
772
798
|
this.videoPes_ = pesWithLength;
|
package/package.json
CHANGED
package/ui/ad_counter.js
CHANGED
|
@@ -100,6 +100,11 @@ shaka.ui.AdCounter = class extends shaka.ui.Element {
|
|
|
100
100
|
goog.asserts.assert(this.ad != null,
|
|
101
101
|
'this.ad should exist at this point');
|
|
102
102
|
|
|
103
|
+
if (!this.ad.isLinear()) {
|
|
104
|
+
// Do not show information for non-linear ads.
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
103
108
|
const secondsLeft = Math.round(this.ad.getRemainingTime());
|
|
104
109
|
const adDuration = this.ad.getDuration();
|
|
105
110
|
if (secondsLeft == -1 || adDuration == -1) {
|
package/ui/controls.js
CHANGED
|
@@ -868,9 +868,11 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
868
868
|
return;
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
-
this.player_.cancelTrickPlay();
|
|
872
|
-
|
|
873
871
|
if (this.presentationIsPaused()) {
|
|
872
|
+
// If we are at the end, go back to the beginning.
|
|
873
|
+
if (this.player_.isEnded()) {
|
|
874
|
+
this.video_.currentTime = this.player_.seekRange().start;
|
|
875
|
+
}
|
|
874
876
|
this.video_.play();
|
|
875
877
|
} else {
|
|
876
878
|
this.video_.pause();
|
|
@@ -81,6 +81,13 @@ shaka.ui.FastForwardButton = class extends shaka.ui.Element {
|
|
|
81
81
|
// selected. If no more rates are available, the first one is set.
|
|
82
82
|
const newRate = (newRateIndex != this.fastForwardRates_.length) ?
|
|
83
83
|
this.fastForwardRates_[newRateIndex] : this.fastForwardRates_[0];
|
|
84
|
+
|
|
85
|
+
if (this.video.paused) {
|
|
86
|
+
// Our fast forward is implemented with playbackRate and needs the video
|
|
87
|
+
// to be playing (to not be paused) to take immediate effect.
|
|
88
|
+
// If the video is paused, "unpause" it.
|
|
89
|
+
this.video.play();
|
|
90
|
+
}
|
|
84
91
|
this.player.trickPlay(newRate);
|
|
85
92
|
|
|
86
93
|
this.button_.setAttribute('shaka-status', newRate + 'x');
|
package/ui/play_button.js
CHANGED
|
@@ -121,7 +121,7 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
|
|
|
121
121
|
|
|
122
122
|
this.eventManager.listen(button, 'click', () => {
|
|
123
123
|
const rate = this.playbackRates_.get(rateStr);
|
|
124
|
-
if (rate ==
|
|
124
|
+
if (rate == this.video.defaultPlaybackRate) {
|
|
125
125
|
this.player.cancelTrickPlay();
|
|
126
126
|
} else {
|
|
127
127
|
this.player.trickPlay(rate, /* useTrickPlayTrack= */ false);
|
package/ui/rewind_button.js
CHANGED
|
@@ -82,6 +82,13 @@ shaka.ui.RewindButton = class extends shaka.ui.Element {
|
|
|
82
82
|
// selected. If no more rates are available, the first one is set.
|
|
83
83
|
const newRate = (newRateIndex != this.rewindRates_.length) ?
|
|
84
84
|
this.rewindRates_[newRateIndex] : this.rewindRates_[0];
|
|
85
|
+
|
|
86
|
+
if (this.video.paused) {
|
|
87
|
+
// Our fast forward is implemented with playbackRate and needs the video
|
|
88
|
+
// to be playing (to not be paused) to take immediate effect.
|
|
89
|
+
// If the video is paused, "unpause" it.
|
|
90
|
+
this.video.play();
|
|
91
|
+
}
|
|
85
92
|
this.player.trickPlay(newRate);
|
|
86
93
|
|
|
87
94
|
this.button_.setAttribute('shaka-status', newRate + 'x');
|