shaka-player 4.0.1 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORS +1 -0
- package/CHANGELOG.md +37 -0
- package/CONTRIBUTORS +3 -0
- package/README.md +20 -6
- package/demo/common/assets.js +1 -1
- package/demo/demo.less +0 -1
- package/demo/index.html +0 -2
- package/demo/main.js +3 -3
- package/dist/controls.css +3 -3
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +3 -3
- package/dist/demo.compiled.debug.map +2 -2
- package/dist/demo.compiled.js +3 -3
- package/dist/demo.compiled.map +2 -2
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +4 -4
- package/dist/locales.js +34 -34
- package/dist/receiver.compiled.debug.js +1 -1
- package/dist/receiver.compiled.debug.map +1 -1
- package/dist/receiver.compiled.js +1 -1
- package/dist/receiver.compiled.map +1 -1
- package/dist/shaka-player.compiled.d.ts +11 -0
- package/dist/shaka-player.compiled.debug.d.ts +11 -0
- package/dist/shaka-player.compiled.debug.externs.js +51 -39
- package/dist/shaka-player.compiled.debug.js +247 -237
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +51 -39
- package/dist/shaka-player.compiled.js +799 -792
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +11 -0
- package/dist/shaka-player.ui.debug.d.ts +11 -0
- package/dist/shaka-player.ui.debug.externs.js +51 -39
- package/dist/shaka-player.ui.debug.js +273 -262
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +51 -39
- package/dist/shaka-player.ui.js +957 -952
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/upgrade.md +1 -0
- package/docs/tutorials/welcome.md +6 -3
- package/externs/shaka/player.js +4 -2
- package/lib/abr/simple_abr_manager.js +2 -1
- package/lib/dash/dash_parser.js +5 -0
- package/lib/hls/hls_parser.js +197 -73
- package/lib/media/drm_engine.js +3 -0
- package/lib/media/media_source_engine.js +57 -24
- package/lib/media/presentation_timeline.js +24 -1
- package/lib/media/segment_index.js +26 -1
- package/lib/media/segment_reference.js +10 -3
- package/lib/media/streaming_engine.js +3 -4
- package/lib/media/time_ranges_utils.js +46 -0
- package/lib/player.js +1 -1
- package/lib/polyfill/media_capabilities.js +3 -0
- package/lib/polyfill/videoplaybackquality.js +3 -1
- package/lib/util/mime_utils.js +14 -5
- package/lib/util/platform.js +19 -1
- package/lib/util/stream_utils.js +1 -0
- package/lib/util/string_utils.js +56 -14
- package/maintained-branches.md +15 -0
- package/package.json +3 -5
- package/test/hls/hls_live_unit.js +57 -7
- package/test/hls/hls_parser_unit.js +102 -8
- package/test/media/drm_engine_integration.js +24 -8
- package/test/media/media_source_engine_integration.js +24 -10
- package/test/media/media_source_engine_unit.js +53 -38
- package/test/media/streaming_engine_unit.js +28 -27
- package/test/test/util/fake_media_source_engine.js +10 -9
- package/ui/less/containers.less +1 -1
- package/ui/less/general.less +1 -1
- package/ui/less/range_elements.less +1 -0
- package/.github/pull_request_template.md +0 -10
- package/app-engine/README.md +0 -9
- package/app-engine/demo-version-index/README.md +0 -14
- package/app-engine/demo-version-index/app.yaml +0 -28
- package/app-engine/demo-version-index/generate.py +0 -164
- package/app-engine/demo-version-index/main.py +0 -11
- package/app-engine/demo-version-index/requirements.txt +0 -5
- package/app-engine/demo-version-index/templates/index.html +0 -114
- package/app-engine/shaka-player-demo/README.md +0 -18
- package/app-engine/shaka-player-demo/app.yaml +0 -61
- package/app-engine/shaka-player-demo/main.py +0 -95
- package/app-engine/shaka-player-demo/posters/10yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/10yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/1yo.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/2yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/2yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/3yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/3yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/4yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/4yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/5yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/5yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/6yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/6yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/7yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/7yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/8yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/8yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/9yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/9yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/audioOnly.gif +0 -0
- package/app-engine/shaka-player-demo/posters/audioRickRoll.gif +0 -0
- package/app-engine/shaka-player-demo/posters/colorbars.gif +0 -0
- package/app-engine/shaka-player-demo/posters/fireworks.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/party-hat.png +0 -0
- package/app-engine/shaka-player-demo/posters/sources.txt +0 -46
- package/app-engine/shaka-player-demo/posters/standard.png +0 -0
- package/app-engine/shaka-player-demo/posters/trek.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/valentines.png +0 -0
- package/app-engine/shaka-player-demo/posters/zombie.jpg +0 -0
- package/app-engine/shaka-player-demo/posters.py +0 -110
- package/app-engine/shaka-player-demo/requirements.txt +0 -5
- package/app-engine/shaka-player-demo/time.txt +0 -1
- package/build/README.md +0 -127
- package/build/__init__.py +0 -0
- package/build/all.py +0 -150
- package/build/apps.py +0 -186
- package/build/build.py +0 -392
- package/build/check.py +0 -354
- package/build/checkversion.py +0 -84
- package/build/compiler.py +0 -513
- package/build/conformance.textproto +0 -335
- package/build/docker/Dockerfile +0 -20
- package/build/docker/docker-compose.yml +0 -10
- package/build/docs.py +0 -54
- package/build/eslint-plugin-shaka-rules/arg-comment-spacing.js +0 -72
- package/build/eslint-plugin-shaka-rules/index.js +0 -24
- package/build/eslint-plugin-shaka-rules/package.json +0 -7
- package/build/eslint-plugin-shaka-rules/private.js +0 -109
- package/build/gendeps.py +0 -71
- package/build/generateExterns.js +0 -867
- package/build/generateLocalizations.py +0 -262
- package/build/generateTsDefs.py +0 -137
- package/build/install-linux-prereqs.sh +0 -136
- package/build/license-header +0 -5
- package/build/misspellings.txt +0 -39
- package/build/pixelsChanged.js +0 -35
- package/build/shaka-lab.yaml +0 -161
- package/build/shakaBuildHelpers.py +0 -356
- package/build/stats.py +0 -816
- package/build/subprocessWindowsPatch.py +0 -103
- package/build/test.py +0 -541
- package/build/types/ads +0 -8
- package/build/types/cast +0 -6
- package/build/types/cea +0 -13
- package/build/types/complete +0 -9
- package/build/types/core +0 -108
- package/build/types/dash +0 -8
- package/build/types/hls +0 -9
- package/build/types/manifests +0 -5
- package/build/types/networking +0 -6
- package/build/types/offline +0 -22
- package/build/types/polyfill +0 -18
- package/build/types/text +0 -11
- package/build/types/ui +0 -39
- package/build/updateScreenshots.py +0 -85
- package/build/wrapper.template.js +0 -52
|
@@ -10,6 +10,7 @@ goog.require('goog.asserts');
|
|
|
10
10
|
goog.require('shaka.log');
|
|
11
11
|
goog.require('shaka.media.ContentWorkarounds');
|
|
12
12
|
goog.require('shaka.media.IClosedCaptionParser');
|
|
13
|
+
goog.require('shaka.media.SegmentReference');
|
|
13
14
|
goog.require('shaka.media.TimeRangesUtils');
|
|
14
15
|
goog.require('shaka.media.Transmuxer');
|
|
15
16
|
goog.require('shaka.text.TextEngine');
|
|
@@ -466,13 +467,13 @@ shaka.media.MediaSourceEngine = class {
|
|
|
466
467
|
*/
|
|
467
468
|
getBufferedInfo() {
|
|
468
469
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
469
|
-
const
|
|
470
|
+
const TimeRangesUtils = shaka.media.TimeRangesUtils;
|
|
470
471
|
|
|
471
472
|
const info = {
|
|
472
|
-
total:
|
|
473
|
-
audio:
|
|
473
|
+
total: TimeRangesUtils.getBufferedInfo(this.video_.buffered),
|
|
474
|
+
audio: TimeRangesUtils.getBufferedInfo(
|
|
474
475
|
this.getBuffered_(ContentType.AUDIO)),
|
|
475
|
-
video:
|
|
476
|
+
video: TimeRangesUtils.getBufferedInfo(
|
|
476
477
|
this.getBuffered_(ContentType.VIDEO)),
|
|
477
478
|
text: [],
|
|
478
479
|
};
|
|
@@ -516,15 +517,14 @@ shaka.media.MediaSourceEngine = class {
|
|
|
516
517
|
*
|
|
517
518
|
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
518
519
|
* @param {!BufferSource} data
|
|
519
|
-
* @param {?
|
|
520
|
-
*
|
|
520
|
+
* @param {?shaka.media.SegmentReference} reference The segment reference
|
|
521
|
+
* we are appending, or null for init segments
|
|
521
522
|
* @param {?boolean} hasClosedCaptions True if the buffer contains CEA closed
|
|
522
|
-
*
|
|
523
|
+
* captions
|
|
523
524
|
* @param {boolean=} seeked True if we just seeked
|
|
524
525
|
* @return {!Promise}
|
|
525
526
|
*/
|
|
526
|
-
async appendBuffer(
|
|
527
|
-
contentType, data, startTime, endTime, hasClosedCaptions, seeked) {
|
|
527
|
+
async appendBuffer(contentType, data, reference, hasClosedCaptions, seeked) {
|
|
528
528
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
529
529
|
|
|
530
530
|
if (contentType == ContentType.TEXT) {
|
|
@@ -533,7 +533,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
533
533
|
const offset = await this.textSequenceModeOffset_;
|
|
534
534
|
this.textEngine_.setTimestampOffset(offset);
|
|
535
535
|
}
|
|
536
|
-
await this.textEngine_.appendBuffer(
|
|
536
|
+
await this.textEngine_.appendBuffer(
|
|
537
|
+
data,
|
|
538
|
+
reference ? reference.startTime : null,
|
|
539
|
+
reference ? reference.endTime : null);
|
|
537
540
|
return;
|
|
538
541
|
}
|
|
539
542
|
|
|
@@ -549,7 +552,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
549
552
|
if (transmuxedData.metadata) {
|
|
550
553
|
const timestampOffset =
|
|
551
554
|
this.sourceBuffers_[contentType].timestampOffset;
|
|
552
|
-
this.onMetadata_(
|
|
555
|
+
this.onMetadata_(
|
|
556
|
+
transmuxedData.metadata,
|
|
557
|
+
timestampOffset,
|
|
558
|
+
reference ? reference.endTime : null);
|
|
553
559
|
}
|
|
554
560
|
// This doesn't work for native TS support (ex. Edge/Chromecast),
|
|
555
561
|
// since no transmuxing is needed for native TS.
|
|
@@ -559,7 +565,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
559
565
|
const closedCaptions = this.textEngine_
|
|
560
566
|
.convertMuxjsCaptionsToShakaCaptions(transmuxedData.captions);
|
|
561
567
|
this.textEngine_.storeAndAppendClosedCaptions(
|
|
562
|
-
closedCaptions,
|
|
568
|
+
closedCaptions,
|
|
569
|
+
reference ? reference.startTime : null,
|
|
570
|
+
reference ? reference.endTime : null,
|
|
571
|
+
videoOffset);
|
|
563
572
|
}
|
|
564
573
|
|
|
565
574
|
data = transmuxedData.data;
|
|
@@ -569,7 +578,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
569
578
|
}
|
|
570
579
|
// If it is the init segment for closed captions, initialize the closed
|
|
571
580
|
// caption parser.
|
|
572
|
-
if (
|
|
581
|
+
if (!reference) {
|
|
573
582
|
this.captionParser_.init(data);
|
|
574
583
|
} else {
|
|
575
584
|
const closedCaptions = this.captionParser_.parseFrom(data);
|
|
@@ -577,18 +586,21 @@ shaka.media.MediaSourceEngine = class {
|
|
|
577
586
|
const videoOffset =
|
|
578
587
|
this.sourceBuffers_[ContentType.VIDEO].timestampOffset;
|
|
579
588
|
this.textEngine_.storeAndAppendClosedCaptions(
|
|
580
|
-
closedCaptions,
|
|
589
|
+
closedCaptions,
|
|
590
|
+
reference.startTime,
|
|
591
|
+
reference.endTime,
|
|
592
|
+
videoOffset);
|
|
581
593
|
}
|
|
582
594
|
}
|
|
583
595
|
}
|
|
584
596
|
|
|
585
|
-
data = this.workAroundBrokenPlatforms_(
|
|
597
|
+
data = this.workAroundBrokenPlatforms_(
|
|
598
|
+
data, reference ? reference.startTime : null, contentType);
|
|
586
599
|
|
|
587
600
|
const sourceBuffer = this.sourceBuffers_[contentType];
|
|
588
601
|
const SEQUENCE = shaka.media.MediaSourceEngine.SourceBufferMode_.SEQUENCE;
|
|
589
602
|
|
|
590
|
-
if (this.sequenceMode_ && sourceBuffer.mode != SEQUENCE &&
|
|
591
|
-
startTime != null) {
|
|
603
|
+
if (this.sequenceMode_ && sourceBuffer.mode != SEQUENCE && reference) {
|
|
592
604
|
// This is the first media segment to be appended to a SourceBuffer in
|
|
593
605
|
// sequence mode. We set the mode late so that we can trick MediaSource
|
|
594
606
|
// into extracting a timestamp for us to align text segments in sequence
|
|
@@ -623,7 +635,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
623
635
|
// segments.
|
|
624
636
|
const mediaStartTime = shaka.media.TimeRangesUtils.bufferStart(
|
|
625
637
|
this.getBuffered_(contentType));
|
|
626
|
-
const textOffset = (startTime || 0) - (mediaStartTime || 0);
|
|
638
|
+
const textOffset = (reference.startTime || 0) - (mediaStartTime || 0);
|
|
627
639
|
this.textSequenceModeOffset_.resolve(textOffset);
|
|
628
640
|
|
|
629
641
|
// Finally, clear the buffer.
|
|
@@ -636,22 +648,43 @@ shaka.media.MediaSourceEngine = class {
|
|
|
636
648
|
sourceBuffer.mode = SEQUENCE;
|
|
637
649
|
}
|
|
638
650
|
|
|
639
|
-
if (
|
|
640
|
-
contentType != ContentType.TEXT) {
|
|
651
|
+
if (reference && this.sequenceMode_ && contentType != ContentType.TEXT) {
|
|
641
652
|
// In sequence mode, for non-text streams, if we just cleared the buffer
|
|
642
653
|
// and are performing an unbuffered seek, we need to set a new
|
|
643
654
|
// timestampOffset on the sourceBuffer.
|
|
644
655
|
if (seeked) {
|
|
645
|
-
const timestampOffset =
|
|
656
|
+
const timestampOffset = reference.startTime;
|
|
646
657
|
this.enqueueOperation_(
|
|
647
658
|
contentType,
|
|
648
659
|
() => this.setTimestampOffset_(contentType, timestampOffset));
|
|
649
660
|
}
|
|
650
661
|
}
|
|
651
662
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
663
|
+
let bufferedBefore = null;
|
|
664
|
+
|
|
665
|
+
await this.enqueueOperation_(contentType, () => {
|
|
666
|
+
if (goog.DEBUG && reference) {
|
|
667
|
+
bufferedBefore = this.getBuffered_(contentType);
|
|
668
|
+
}
|
|
669
|
+
this.append_(contentType, data);
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
if (goog.DEBUG && reference) {
|
|
673
|
+
const bufferedAfter = this.getBuffered_(contentType);
|
|
674
|
+
const newBuffered = shaka.media.TimeRangesUtils.computeAddedRange(
|
|
675
|
+
bufferedBefore, bufferedAfter);
|
|
676
|
+
if (newBuffered) {
|
|
677
|
+
const segmentDuration = reference.endTime - reference.startTime;
|
|
678
|
+
if (Math.abs(newBuffered.start - reference.startTime) >
|
|
679
|
+
segmentDuration / 2) {
|
|
680
|
+
shaka.log.error('Possible encoding problem detected!',
|
|
681
|
+
'Unexpected buffered range for reference', reference,
|
|
682
|
+
'from URIs', reference.getUris(),
|
|
683
|
+
'should be', {start: reference.startTime, end: reference.endTime},
|
|
684
|
+
'but got', newBuffered);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
655
688
|
}
|
|
656
689
|
|
|
657
690
|
/**
|
|
@@ -93,6 +93,9 @@ shaka.media.PresentationTimeline = class {
|
|
|
93
93
|
* @private {number}
|
|
94
94
|
*/
|
|
95
95
|
this.availabilityTimeOffset_ = 0;
|
|
96
|
+
|
|
97
|
+
/** @private {boolean} */
|
|
98
|
+
this.startTimeLocked_ = false;
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
|
|
@@ -229,7 +232,8 @@ shaka.media.PresentationTimeline = class {
|
|
|
229
232
|
this.maxSegmentEndTime_ =
|
|
230
233
|
Math.max(this.maxSegmentEndTime_, lastReferenceEndTime);
|
|
231
234
|
|
|
232
|
-
if (this.presentationStartTime_ != null && this.autoCorrectDrift_
|
|
235
|
+
if (this.presentationStartTime_ != null && this.autoCorrectDrift_ &&
|
|
236
|
+
!this.startTimeLocked_) {
|
|
233
237
|
// Since we have explicit segment end times, calculate a presentation
|
|
234
238
|
// start based on them. This start time accounts for drift.
|
|
235
239
|
// Date.now() is in milliseconds, from which we compute "now" in seconds.
|
|
@@ -243,6 +247,25 @@ shaka.media.PresentationTimeline = class {
|
|
|
243
247
|
}
|
|
244
248
|
|
|
245
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Lock the presentation timeline's start time. After this is called, no
|
|
252
|
+
* further adjustments to presentationStartTime_ will be permitted.
|
|
253
|
+
*
|
|
254
|
+
* This should be called after all Periods have been parsed, and all calls to
|
|
255
|
+
* notifySegments() from the initial manifest parse have been made.
|
|
256
|
+
*
|
|
257
|
+
* Without this, we can get assertion failures in SegmentIndex for certain
|
|
258
|
+
* DAI content. If DAI adds ad segments to the manifest faster than
|
|
259
|
+
* real-time, adjustments to presentationStartTime_ can cause availability
|
|
260
|
+
* windows to jump around on updates.
|
|
261
|
+
*
|
|
262
|
+
* @export
|
|
263
|
+
*/
|
|
264
|
+
lockStartTime() {
|
|
265
|
+
this.startTimeLocked_ = true;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
|
|
246
269
|
/**
|
|
247
270
|
* Gives PresentationTimeline a Stream's minimum segment start time.
|
|
248
271
|
*
|
|
@@ -94,6 +94,25 @@ shaka.media.SegmentIndex = class {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Return the earliest reference, or null if empty.
|
|
99
|
+
* @return {shaka.media.SegmentReference}
|
|
100
|
+
*/
|
|
101
|
+
earliestReference() {
|
|
102
|
+
return this.references[0] || null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Drop the first N references.
|
|
108
|
+
* Used in early HLS synchronization, and does not count as eviction.
|
|
109
|
+
* @param {number} n
|
|
110
|
+
*/
|
|
111
|
+
dropFirstReferences(n) {
|
|
112
|
+
this.references.splice(0, n);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
97
116
|
/**
|
|
98
117
|
* Finds the position of the segment for the given time, in seconds, relative
|
|
99
118
|
* to the start of the presentation. Returns the position of the segment
|
|
@@ -166,7 +185,13 @@ shaka.media.SegmentIndex = class {
|
|
|
166
185
|
for (const ref of this.references) {
|
|
167
186
|
ref.startTime += offset;
|
|
168
187
|
ref.endTime += offset;
|
|
169
|
-
ref.
|
|
188
|
+
ref.trueEndTime += offset;
|
|
189
|
+
|
|
190
|
+
for (const partial of ref.partialReferences) {
|
|
191
|
+
partial.startTime += offset;
|
|
192
|
+
partial.endTime += offset;
|
|
193
|
+
partial.trueEndTime += offset;
|
|
194
|
+
}
|
|
170
195
|
}
|
|
171
196
|
}
|
|
172
197
|
}
|
|
@@ -160,8 +160,9 @@ shaka.media.SegmentReference = class {
|
|
|
160
160
|
* If not provided, the duration should be automatically calculated based on
|
|
161
161
|
* the duration of the reference.
|
|
162
162
|
* @param {?number=} syncTime
|
|
163
|
-
* A time value, expressed in
|
|
164
|
-
*
|
|
163
|
+
* A time value, expressed in seconds since 1970, which is used to
|
|
164
|
+
* synchronize between streams. Both produced and consumed by the HLS
|
|
165
|
+
* parser. Other components should not need this value.
|
|
165
166
|
* @param {shaka.media.SegmentReference.Status=} status
|
|
166
167
|
* The segment status is used to indicate that a segment does not exist or is
|
|
167
168
|
* not available.
|
|
@@ -221,7 +222,13 @@ shaka.media.SegmentReference = class {
|
|
|
221
222
|
/** @type {?number} */
|
|
222
223
|
this.tileDuration = tileDuration;
|
|
223
224
|
|
|
224
|
-
/**
|
|
225
|
+
/**
|
|
226
|
+
* A time value, expressed in seconds since 1970, which is used to
|
|
227
|
+
* synchronize between streams. Both produced and consumed by the HLS
|
|
228
|
+
* parser. Other components should not need this value.
|
|
229
|
+
*
|
|
230
|
+
* @type {?number}
|
|
231
|
+
*/
|
|
225
232
|
this.syncTime = syncTime;
|
|
226
233
|
|
|
227
234
|
/** @type {shaka.media.SegmentReference.Status} */
|
|
@@ -1548,8 +1548,8 @@ shaka.media.StreamingEngine = class {
|
|
|
1548
1548
|
const hasClosedCaptions = mediaState.stream.closedCaptions &&
|
|
1549
1549
|
mediaState.stream.closedCaptions.size > 0;
|
|
1550
1550
|
await this.playerInterface_.mediaSourceEngine.appendBuffer(
|
|
1551
|
-
mediaState.type, initSegment, /*
|
|
1552
|
-
|
|
1551
|
+
mediaState.type, initSegment, /* reference= */ null,
|
|
1552
|
+
hasClosedCaptions);
|
|
1553
1553
|
} catch (error) {
|
|
1554
1554
|
mediaState.lastInitSegmentReference = null;
|
|
1555
1555
|
throw error;
|
|
@@ -1602,8 +1602,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1602
1602
|
await this.playerInterface_.mediaSourceEngine.appendBuffer(
|
|
1603
1603
|
mediaState.type,
|
|
1604
1604
|
segment,
|
|
1605
|
-
reference
|
|
1606
|
-
reference.endTime,
|
|
1605
|
+
reference,
|
|
1607
1606
|
hasClosedCaptions,
|
|
1608
1607
|
seeked);
|
|
1609
1608
|
this.destroyer_.ensureNotDestroyed();
|
|
@@ -155,4 +155,50 @@ shaka.media.TimeRangesUtils = class {
|
|
|
155
155
|
}
|
|
156
156
|
return ret;
|
|
157
157
|
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* This operation can be potentially EXPENSIVE and should only be done in
|
|
161
|
+
* debug builds for debugging purposes.
|
|
162
|
+
*
|
|
163
|
+
* @param {TimeRanges} oldRanges
|
|
164
|
+
* @param {TimeRanges} newRanges
|
|
165
|
+
* @return {?shaka.extern.BufferedRange} The last added range,
|
|
166
|
+
* chronologically by presentation time.
|
|
167
|
+
*/
|
|
168
|
+
static computeAddedRange(oldRanges, newRanges) {
|
|
169
|
+
const TimeRangesUtils = shaka.media.TimeRangesUtils;
|
|
170
|
+
|
|
171
|
+
if (!oldRanges || !oldRanges.length) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
if (!newRanges || !newRanges.length) {
|
|
175
|
+
return TimeRangesUtils.getBufferedInfo(newRanges).pop();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const newRangesReversed =
|
|
179
|
+
TimeRangesUtils.getBufferedInfo(newRanges).reverse();
|
|
180
|
+
const oldRangesReversed =
|
|
181
|
+
TimeRangesUtils.getBufferedInfo(oldRanges).reverse();
|
|
182
|
+
for (const newRange of newRangesReversed) {
|
|
183
|
+
let foundOverlap = false;
|
|
184
|
+
|
|
185
|
+
for (const oldRange of oldRangesReversed) {
|
|
186
|
+
if (oldRange.end >= newRange.start && oldRange.end <= newRange.end) {
|
|
187
|
+
foundOverlap = true;
|
|
188
|
+
|
|
189
|
+
// If the new range goes beyond the corresponding old one, the
|
|
190
|
+
// difference is newly-added.
|
|
191
|
+
if (newRange.end > oldRange.end) {
|
|
192
|
+
return {start: oldRange.end, end: newRange.end};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (!foundOverlap) {
|
|
198
|
+
return newRange;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
158
204
|
};
|
package/lib/player.js
CHANGED
|
@@ -6450,7 +6450,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6450
6450
|
* @define {string} A version number taken from git at compile time.
|
|
6451
6451
|
* @export
|
|
6452
6452
|
*/
|
|
6453
|
-
shaka.Player.version = 'v4.0.
|
|
6453
|
+
shaka.Player.version = 'v4.0.4-uncompiled';
|
|
6454
6454
|
|
|
6455
6455
|
// Initialize the deprecation system using the version string we just set
|
|
6456
6456
|
// on the player.
|
|
@@ -37,9 +37,12 @@ shaka.polyfill.MediaCapabilities = class {
|
|
|
37
37
|
// See: https://github.com/shaka-project/shaka-player/issues/3582
|
|
38
38
|
// TODO: re-evaluate MediaCapabilities in the future versions of PS5
|
|
39
39
|
// Browsers.
|
|
40
|
+
// Since MediaCapabilities implementation does not exist in PS4 browsers, we
|
|
41
|
+
// should always install polyfill.
|
|
40
42
|
let canUseNativeMCap = true;
|
|
41
43
|
if (shaka.util.Platform.isApple() ||
|
|
42
44
|
shaka.util.Platform.isPS5() ||
|
|
45
|
+
shaka.util.Platform.isPS4() ||
|
|
43
46
|
shaka.util.Platform.isChromecast()) {
|
|
44
47
|
canUseNativeMCap = false;
|
|
45
48
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
goog.provide('shaka.polyfill.VideoPlaybackQuality');
|
|
8
8
|
|
|
9
9
|
goog.require('shaka.polyfill');
|
|
10
|
+
goog.require('shaka.util.Platform');
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -33,7 +34,8 @@ shaka.polyfill.VideoPlaybackQuality = class {
|
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
if ('webkitDroppedFrameCount' in proto
|
|
37
|
+
if ('webkitDroppedFrameCount' in proto ||
|
|
38
|
+
shaka.util.Platform.isWebOS3()) {
|
|
37
39
|
proto.getVideoPlaybackQuality =
|
|
38
40
|
shaka.polyfill.VideoPlaybackQuality.webkit_;
|
|
39
41
|
}
|
package/lib/util/mime_utils.js
CHANGED
|
@@ -8,6 +8,7 @@ goog.provide('shaka.util.MimeUtils');
|
|
|
8
8
|
|
|
9
9
|
goog.require('shaka.dependencies');
|
|
10
10
|
goog.require('shaka.media.Transmuxer');
|
|
11
|
+
goog.require('shaka.util.ManifestParserUtils');
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @summary A set of utility functions for dealing with MIME types.
|
|
@@ -34,6 +35,8 @@ shaka.util.MimeUtils = class {
|
|
|
34
35
|
/**
|
|
35
36
|
* Takes a MIME type and a codecs string and produces the full MIME
|
|
36
37
|
* type. If it's a transport stream, convert its codecs to MP4 codecs.
|
|
38
|
+
* Otherwise for multiplexed content, convert the video MIME types to
|
|
39
|
+
* their audio equivalents if the content type is audio.
|
|
37
40
|
*
|
|
38
41
|
* @param {string} mimeType
|
|
39
42
|
* @param {string} codecs
|
|
@@ -42,13 +45,19 @@ shaka.util.MimeUtils = class {
|
|
|
42
45
|
*/
|
|
43
46
|
static getFullOrConvertedType(mimeType, codecs, contentType) {
|
|
44
47
|
const fullMimeType = shaka.util.MimeUtils.getFullType(mimeType, codecs);
|
|
48
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
45
49
|
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
if (shaka.media.Transmuxer.isTsContainer(fullMimeType)) {
|
|
51
|
+
if (shaka.dependencies.muxjs()) {
|
|
52
|
+
return shaka.media.Transmuxer.convertTsCodecs(
|
|
53
|
+
contentType, fullMimeType);
|
|
54
|
+
}
|
|
55
|
+
} else if (contentType == ContentType.AUDIO) {
|
|
56
|
+
// video/mp2t is the correct mime type for TS audio, so only replace the
|
|
57
|
+
// word "video" with "audio" for non-TS audio content.
|
|
58
|
+
return fullMimeType.replace('video', 'audio');
|
|
49
59
|
}
|
|
50
|
-
|
|
51
|
-
return shaka.media.Transmuxer.convertTsCodecs(contentType, fullMimeType);
|
|
60
|
+
return fullMimeType;
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
|
package/lib/util/platform.js
CHANGED
|
@@ -197,7 +197,9 @@ shaka.util.Platform = class {
|
|
|
197
197
|
*/
|
|
198
198
|
static isApple() {
|
|
199
199
|
return !!navigator.vendor && navigator.vendor.includes('Apple') &&
|
|
200
|
-
!shaka.util.Platform.isTizen()
|
|
200
|
+
!shaka.util.Platform.isTizen() &&
|
|
201
|
+
!shaka.util.Platform.isEOS() &&
|
|
202
|
+
!shaka.util.Platform.isPS4();
|
|
201
203
|
}
|
|
202
204
|
|
|
203
205
|
/**
|
|
@@ -213,6 +215,13 @@ shaka.util.Platform = class {
|
|
|
213
215
|
return shaka.util.Platform.userAgentContains_('PlayStation 5');
|
|
214
216
|
}
|
|
215
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Check if the current platform is Playstation 4.
|
|
220
|
+
*/
|
|
221
|
+
static isPS4() {
|
|
222
|
+
return shaka.util.Platform.userAgentContains_('PlayStation 4');
|
|
223
|
+
}
|
|
224
|
+
|
|
216
225
|
/**
|
|
217
226
|
* Returns a major version number for Safari, or Safari-based iOS browsers.
|
|
218
227
|
*
|
|
@@ -260,6 +269,15 @@ shaka.util.Platform = class {
|
|
|
260
269
|
return !!shaka.util.Platform.safariVersion();
|
|
261
270
|
}
|
|
262
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Check if the current platform is an EOS set-top box.
|
|
274
|
+
*
|
|
275
|
+
* @return {boolean}
|
|
276
|
+
*/
|
|
277
|
+
static isEOS() {
|
|
278
|
+
return shaka.util.Platform.userAgentContains_('PC=EOS');
|
|
279
|
+
}
|
|
280
|
+
|
|
263
281
|
/**
|
|
264
282
|
* Guesses if the platform is a mobile one (iOS or Android).
|
|
265
283
|
*
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -1008,6 +1008,7 @@ shaka.util.StreamUtils = class {
|
|
|
1008
1008
|
track.channelsCount = audio.channelsCount;
|
|
1009
1009
|
track.audioSamplingRate = audio.audioSamplingRate;
|
|
1010
1010
|
track.audioBandwidth = audio.bandwidth || null;
|
|
1011
|
+
track.spatialAudio = audio.spatialAudio;
|
|
1011
1012
|
track.label = audio.label;
|
|
1012
1013
|
track.audioRoles = audio.roles;
|
|
1013
1014
|
}
|
package/lib/util/string_utils.js
CHANGED
|
@@ -11,6 +11,7 @@ goog.require('shaka.log');
|
|
|
11
11
|
goog.require('shaka.util.BufferUtils');
|
|
12
12
|
goog.require('shaka.util.Error');
|
|
13
13
|
goog.require('shaka.util.Lazy');
|
|
14
|
+
goog.require('shaka.util.Platform');
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -36,19 +37,38 @@ shaka.util.StringUtils = class {
|
|
|
36
37
|
if (uint8[0] == 0xef && uint8[1] == 0xbb && uint8[2] == 0xbf) {
|
|
37
38
|
uint8 = uint8.subarray(3);
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
if (window.TextDecoder && !shaka.util.Platform.isPS4()) {
|
|
41
|
+
// Use the TextDecoder interface to decode the text. This has the
|
|
42
|
+
// advantage compared to the previously-standard decodeUriComponent that
|
|
43
|
+
// it will continue parsing even if it finds an invalid UTF8 character,
|
|
44
|
+
// rather than stop and throw an error.
|
|
45
|
+
const utf8decoder = new TextDecoder();
|
|
46
|
+
const decoded = utf8decoder.decode(uint8);
|
|
47
|
+
if (decoded.includes('\uFFFD')) {
|
|
48
|
+
shaka.log.alwaysError('Decoded string contains an "unknown character' +
|
|
49
|
+
'" codepoint. That probably means the UTF8 ' +
|
|
50
|
+
'encoding was incorrect!');
|
|
51
|
+
}
|
|
52
|
+
return decoded;
|
|
53
|
+
} else {
|
|
54
|
+
// http://stackoverflow.com/a/13691499
|
|
55
|
+
const utf8 = shaka.util.StringUtils.fromCharCode(uint8);
|
|
56
|
+
// This converts each character in the string to an escape sequence. If
|
|
57
|
+
// the character is in the ASCII range, it is not converted; otherwise it
|
|
58
|
+
// is converted to a URI escape sequence.
|
|
59
|
+
// Example: '\x67\x35\xe3\x82\xac' -> 'g#%E3%82%AC'
|
|
60
|
+
const escaped = escape(utf8);
|
|
61
|
+
// Decode the escaped sequence. This will interpret UTF-8 sequences into
|
|
62
|
+
// the correct character.
|
|
63
|
+
// Example: 'g#%E3%82%AC' -> 'g#€'
|
|
64
|
+
try {
|
|
65
|
+
return decodeURIComponent(escaped);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
throw new shaka.util.Error(
|
|
68
|
+
shaka.util.Error.Severity.CRITICAL, shaka.util.Error.Category.TEXT,
|
|
69
|
+
shaka.util.Error.Code.BAD_ENCODING);
|
|
70
|
+
}
|
|
50
71
|
}
|
|
51
|
-
return decoded;
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
|
|
@@ -141,8 +161,30 @@ shaka.util.StringUtils = class {
|
|
|
141
161
|
* @export
|
|
142
162
|
*/
|
|
143
163
|
static toUTF8(str) {
|
|
144
|
-
|
|
145
|
-
|
|
164
|
+
if (window.TextEncoder && !shaka.util.Platform.isPS4()) {
|
|
165
|
+
const utf8Encoder = new TextEncoder();
|
|
166
|
+
return shaka.util.BufferUtils.toArrayBuffer(utf8Encoder.encode(str));
|
|
167
|
+
} else {
|
|
168
|
+
// http://stackoverflow.com/a/13691499
|
|
169
|
+
// Converts the given string to a URI encoded string. If a character
|
|
170
|
+
// falls in the ASCII range, it is not converted; otherwise it will be
|
|
171
|
+
// converted to a series of URI escape sequences according to UTF-8.
|
|
172
|
+
// Example: 'g#€' -> 'g#%E3%82%AC'
|
|
173
|
+
const encoded = encodeURIComponent(str);
|
|
174
|
+
// Convert each escape sequence individually into a character. Each
|
|
175
|
+
// escape sequence is interpreted as a code-point, so if an escape
|
|
176
|
+
// sequence happens to be part of a multi-byte sequence, each byte will
|
|
177
|
+
// be converted to a single character.
|
|
178
|
+
// Example: 'g#%E3%82%AC' -> '\x67\x35\xe3\x82\xac'
|
|
179
|
+
const utf8 = unescape(encoded);
|
|
180
|
+
|
|
181
|
+
const result = new Uint8Array(utf8.length);
|
|
182
|
+
for (let i = 0; i < utf8.length; i++) {
|
|
183
|
+
const item = utf8[i];
|
|
184
|
+
result[i] = item.charCodeAt(0);
|
|
185
|
+
}
|
|
186
|
+
return shaka.util.BufferUtils.toArrayBuffer(result);
|
|
187
|
+
}
|
|
146
188
|
}
|
|
147
189
|
|
|
148
190
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Maintained Shaka Player Branches
|
|
2
|
+
|
|
3
|
+
We are currently maintaining the following branches of Shaka Player:
|
|
4
|
+
|
|
5
|
+
- v4.1 (latest)
|
|
6
|
+
- v4.0 (previous)
|
|
7
|
+
- v3.3 (LTS until April 30, 2023)
|
|
8
|
+
- v3.2 (in use by the Cast Application Framework)
|
|
9
|
+
|
|
10
|
+
Other branches are no longer receiving bug fixes, and we recommend you upgrade
|
|
11
|
+
to a maintained branch. For details on upgrading, please see our
|
|
12
|
+
[upgrade guide](https://shaka-player-demo.appspot.com/docs/api/tutorial-upgrade.html).
|
|
13
|
+
|
|
14
|
+
For more information on how these branches are chosen, please refer to our
|
|
15
|
+
[Branch Maintenance Policy](https://shaka-project.github.io/maintenance/shaka-player.html#branch-maintenance-policy).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shaka-player",
|
|
3
3
|
"description": "DASH/EME video player library",
|
|
4
|
-
"version": "4.0.
|
|
4
|
+
"version": "4.0.4",
|
|
5
5
|
"homepage": "https://github.com/shaka-project/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
"eslint-config-google": "^0.14.0",
|
|
28
28
|
"eslint-plugin-shaka-rules": "file:./build/eslint-plugin-shaka-rules",
|
|
29
29
|
"esprima": "^4.0.1",
|
|
30
|
-
"fastestsmallesttextencoderdecoder": "^1.0.22",
|
|
31
30
|
"fontfaceonload": "^1.0.2",
|
|
32
31
|
"google-closure-compiler-java": "^20220301.0.0",
|
|
33
32
|
"google-closure-deps": "https://gitpkg.now.sh/google/closure-library/closure-deps?d7736da6",
|
|
@@ -50,7 +49,7 @@
|
|
|
50
49
|
"less": "https://gitpkg.now.sh/joeyparrish/less.js/packages/less?28c63a43",
|
|
51
50
|
"less-plugin-clean-css": "github:austingardner/less-plugin-clean-css#4e9e77bf",
|
|
52
51
|
"material-design-lite": "^1.3.0",
|
|
53
|
-
"mux.js": "^
|
|
52
|
+
"mux.js": "^6.2.0",
|
|
54
53
|
"open-sans-fonts": "^1.6.2",
|
|
55
54
|
"postcss-less": "^6.0.0",
|
|
56
55
|
"pwacompat": "^2.0.17",
|
|
@@ -71,7 +70,6 @@
|
|
|
71
70
|
"dialog-polyfill/dist/dialog-polyfill.js",
|
|
72
71
|
"eme-encryption-scheme-polyfill/index.js",
|
|
73
72
|
"es6-promise-polyfill/promise.min.js",
|
|
74
|
-
"fastestsmallesttextencoderdecoder/EncoderDecoderTogether.min.js",
|
|
75
73
|
"google-closure-library/closure/goog/base.js",
|
|
76
74
|
"less/dist/less.js",
|
|
77
75
|
"material-design-lite/dist/material.indigo-blue.min.css",
|
|
@@ -96,7 +94,7 @@
|
|
|
96
94
|
"prepublishOnly": "python build/checkversion.py && python build/all.py --force"
|
|
97
95
|
},
|
|
98
96
|
"dependencies": {
|
|
99
|
-
"eme-encryption-scheme-polyfill": "^2.0.
|
|
97
|
+
"eme-encryption-scheme-polyfill": "^2.0.5"
|
|
100
98
|
},
|
|
101
99
|
"engines": {
|
|
102
100
|
"node": ">=14"
|