shaka-player 3.1.5 → 3.1.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/.github/workflows/build_and_test.yaml +73 -0
- package/.github/workflows/release.yaml +53 -0
- package/CHANGELOG.md +13 -1
- package/build/checkversion.py +1 -1
- package/build/test.py +6 -0
- package/dist/controls.css +1 -1
- package/dist/deps.js +3 -3
- package/dist/locales.js +29 -29
- package/dist/shaka-player.compiled.d.ts +2 -1
- package/dist/shaka-player.compiled.debug.d.ts +2 -1
- package/dist/shaka-player.compiled.debug.externs.js +5 -0
- package/dist/shaka-player.compiled.debug.js +200 -198
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +5 -0
- package/dist/shaka-player.compiled.js +609 -608
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +4 -12
- package/dist/shaka-player.ui.debug.d.ts +4 -12
- package/dist/shaka-player.ui.debug.externs.js +19 -23
- package/dist/shaka-player.ui.debug.js +77 -76
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +19 -23
- package/dist/shaka-player.ui.js +901 -901
- package/dist/shaka-player.ui.map +2 -2
- package/karma.conf.js +19 -15
- package/lib/ads/ad_manager.js +1 -0
- package/lib/cast/cast_proxy.js +3 -0
- package/lib/cast/cast_receiver.js +3 -0
- package/lib/dash/dash_parser.js +31 -19
- package/lib/hls/manifest_text_parser.js +1 -0
- package/lib/media/region_observer.js +39 -33
- package/lib/media/region_timeline.js +17 -19
- package/lib/media/streaming_engine.js +1 -1
- package/lib/net/networking_engine.js +4 -0
- package/lib/offline/storage.js +10 -11
- package/lib/player.js +25 -9
- package/lib/util/fake_event_target.js +21 -1
- package/package.json +3 -6
- package/test/dash/dash_parser_live_unit.js +43 -0
- package/test/dash/dash_parser_manifest_unit.js +2 -1
- package/test/hls/hls_parser_unit.js +74 -0
- package/test/media/region_observer_unit.js +40 -5
- package/test/media/region_timeline_unit.js +40 -22
- package/test/test/util/util.js +10 -7
- package/test/ui/text_displayer_layout_unit.js +8 -7
- package/ui/controls.js +3 -0
- package/ui/localization.js +12 -36
package/karma.conf.js
CHANGED
|
@@ -11,6 +11,7 @@ const Jimp = require('jimp');
|
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const path = require('path');
|
|
13
13
|
const rimraf = require('rimraf');
|
|
14
|
+
const {ssim} = require('ssim.js');
|
|
14
15
|
const util = require('karma/common/util');
|
|
15
16
|
const which = require('which');
|
|
16
17
|
|
|
@@ -336,6 +337,10 @@ module.exports = (config) => {
|
|
|
336
337
|
|
|
337
338
|
config.set({reporters: reporters});
|
|
338
339
|
|
|
340
|
+
if (reporters.includes('spec') && settings.spec_hide_passed) {
|
|
341
|
+
config.set({specReporter: {suppressPassed: true}});
|
|
342
|
+
}
|
|
343
|
+
|
|
339
344
|
if (settings.random) {
|
|
340
345
|
// If --seed was specified use that value, else generate a seed so that the
|
|
341
346
|
// exact order can be reproduced if it catches an issue.
|
|
@@ -518,8 +523,7 @@ function WebDriverScreenshotMiddlewareFactory(launcher) {
|
|
|
518
523
|
*
|
|
519
524
|
* @param {karma.Launcher.Browser} browser
|
|
520
525
|
* @param {!Object.<string, string>} params
|
|
521
|
-
* @return {!Promise.<number>}
|
|
522
|
-
* and new screenshots, after cropping and scaling.
|
|
526
|
+
* @return {!Promise.<number>} A similarity score between 0 and 1.
|
|
523
527
|
*/
|
|
524
528
|
async function diffScreenshot(browser, params) {
|
|
525
529
|
const webDriverClient = getWebDriverClient(browser);
|
|
@@ -604,22 +608,22 @@ function WebDriverScreenshotMiddlewareFactory(launcher) {
|
|
|
604
608
|
// Compare the new screenshot to the old one and produce a diff image.
|
|
605
609
|
// Initially, the image data will be raw pixels, 4 bytes per pixel.
|
|
606
610
|
// The threshold parameter affects the sensitivity of individual pixel
|
|
607
|
-
// comparisons.
|
|
608
|
-
//
|
|
609
|
-
//
|
|
610
|
-
|
|
611
|
-
const diff = Jimp.diff(oldScreenshot, newScreenshot,
|
|
611
|
+
// comparisons. This diff is only used for visual review, not for
|
|
612
|
+
// automated similarity checks, so the threshold setting is not so critical
|
|
613
|
+
// as it used to be.
|
|
614
|
+
const threshold = 0.10;
|
|
615
|
+
const diff = Jimp.diff(oldScreenshot, newScreenshot, threshold);
|
|
612
616
|
|
|
613
617
|
// Write the diff to disk. This is used to review when there are changes.
|
|
618
|
+
const fullSizeDiff =
|
|
619
|
+
diff.image.clone().resize(width, height, Jimp.RESIZE_BICUBIC);
|
|
614
620
|
fs.writeFileSync(
|
|
615
|
-
diffScreenshotPath, await
|
|
616
|
-
|
|
617
|
-
//
|
|
618
|
-
//
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
diff.percent * diff.image.bitmap.width * diff.image.bitmap.height;
|
|
622
|
-
return pixelsChanged;
|
|
621
|
+
diffScreenshotPath, await fullSizeDiff.getBufferAsync('image/png'));
|
|
622
|
+
|
|
623
|
+
// Compare with a structural similarity algorithm. This produces a
|
|
624
|
+
// similarity score that we will use to pass or fail the test.
|
|
625
|
+
const ssimResult = ssim(oldScreenshot.bitmap, newScreenshot.bitmap);
|
|
626
|
+
return ssimResult.mssim; // A score between 0 and 1.
|
|
623
627
|
}
|
|
624
628
|
|
|
625
629
|
/**
|
package/lib/ads/ad_manager.js
CHANGED
package/lib/cast/cast_proxy.js
CHANGED
|
@@ -238,6 +238,9 @@ shaka.cast.CastReceiver = class extends shaka.util.FakeEventTarget {
|
|
|
238
238
|
this.shakaBus_ = null;
|
|
239
239
|
this.genericBus_ = null;
|
|
240
240
|
|
|
241
|
+
// FakeEventTarget implements IReleasable
|
|
242
|
+
super.release();
|
|
243
|
+
|
|
241
244
|
await Promise.all(waitFor);
|
|
242
245
|
|
|
243
246
|
const manager = cast.receiver.CastReceiverManager.getInstance();
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -396,6 +396,24 @@ shaka.dash.DashParser = class {
|
|
|
396
396
|
this.config_.dash.autoCorrectDrift);
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
+
presentationTimeline.setStatic(mpdType == 'static');
|
|
400
|
+
|
|
401
|
+
const isLive = presentationTimeline.isLive();
|
|
402
|
+
|
|
403
|
+
// If it's live, we check for an override.
|
|
404
|
+
if (isLive && !isNaN(this.config_.availabilityWindowOverride)) {
|
|
405
|
+
segmentAvailabilityDuration = this.config_.availabilityWindowOverride;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// If it's null, that means segments are always available. This is always
|
|
409
|
+
// the case for VOD, and sometimes the case for live.
|
|
410
|
+
if (segmentAvailabilityDuration == null) {
|
|
411
|
+
segmentAvailabilityDuration = Infinity;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
presentationTimeline.setSegmentAvailabilityDuration(
|
|
415
|
+
segmentAvailabilityDuration);
|
|
416
|
+
|
|
399
417
|
const profiles = mpd.getAttribute('profiles') || '';
|
|
400
418
|
|
|
401
419
|
/** @type {shaka.dash.DashParser.Context} */
|
|
@@ -418,7 +436,6 @@ shaka.dash.DashParser = class {
|
|
|
418
436
|
const duration = periodsAndDuration.duration;
|
|
419
437
|
const periods = periodsAndDuration.periods;
|
|
420
438
|
|
|
421
|
-
presentationTimeline.setStatic(mpdType == 'static');
|
|
422
439
|
if (mpdType == 'static' ||
|
|
423
440
|
!periodsAndDuration.durationDerivedFromPeriods) {
|
|
424
441
|
// Ignore duration calculated from Period lengths if this is dynamic.
|
|
@@ -437,6 +454,7 @@ shaka.dash.DashParser = class {
|
|
|
437
454
|
this.lowLatencyMode_ = this.playerInterface_.isLowLatencyMode();
|
|
438
455
|
}
|
|
439
456
|
}
|
|
457
|
+
|
|
440
458
|
if (this.lowLatencyMode_) {
|
|
441
459
|
presentationTimeline.setAvailabilityTimeOffset(
|
|
442
460
|
this.minTotalAvailabilityTimeOffset_);
|
|
@@ -450,22 +468,6 @@ shaka.dash.DashParser = class {
|
|
|
450
468
|
'https://bit.ly/3clctcj for details.');
|
|
451
469
|
}
|
|
452
470
|
|
|
453
|
-
const isLive = presentationTimeline.isLive();
|
|
454
|
-
|
|
455
|
-
// If it's live, we check for an override.
|
|
456
|
-
if (isLive && !isNaN(this.config_.availabilityWindowOverride)) {
|
|
457
|
-
segmentAvailabilityDuration = this.config_.availabilityWindowOverride;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// If it's null, that means segments are always available. This is always
|
|
461
|
-
// the case for VOD, and sometimes the case for live.
|
|
462
|
-
if (segmentAvailabilityDuration == null) {
|
|
463
|
-
segmentAvailabilityDuration = Infinity;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
presentationTimeline.setSegmentAvailabilityDuration(
|
|
467
|
-
segmentAvailabilityDuration);
|
|
468
|
-
|
|
469
471
|
// Use @maxSegmentDuration to override smaller, derived values.
|
|
470
472
|
presentationTimeline.notifyMaxSegmentDuration(maxSegmentDuration || 1);
|
|
471
473
|
if (goog.DEBUG) {
|
|
@@ -700,8 +702,12 @@ shaka.dash.DashParser = class {
|
|
|
700
702
|
|
|
701
703
|
const eventStreamNodes =
|
|
702
704
|
XmlUtils.findChildren(periodInfo.node, 'EventStream');
|
|
705
|
+
const availabilityStart =
|
|
706
|
+
context.presentationTimeline.getSegmentAvailabilityStart();
|
|
707
|
+
|
|
703
708
|
for (const node of eventStreamNodes) {
|
|
704
|
-
this.parseEventStream_(
|
|
709
|
+
this.parseEventStream_(
|
|
710
|
+
periodInfo.start, periodInfo.duration, node, availabilityStart);
|
|
705
711
|
}
|
|
706
712
|
|
|
707
713
|
const adaptationSetNodes =
|
|
@@ -1732,9 +1738,10 @@ shaka.dash.DashParser = class {
|
|
|
1732
1738
|
* @param {number} periodStart
|
|
1733
1739
|
* @param {?number} periodDuration
|
|
1734
1740
|
* @param {!Element} elem
|
|
1741
|
+
* @param {number} availabilityStart
|
|
1735
1742
|
* @private
|
|
1736
1743
|
*/
|
|
1737
|
-
parseEventStream_(periodStart, periodDuration, elem) {
|
|
1744
|
+
parseEventStream_(periodStart, periodDuration, elem, availabilityStart) {
|
|
1738
1745
|
const XmlUtils = shaka.util.XmlUtils;
|
|
1739
1746
|
const parseNumber = XmlUtils.parseNonNegativeInt;
|
|
1740
1747
|
|
|
@@ -1757,6 +1764,11 @@ shaka.dash.DashParser = class {
|
|
|
1757
1764
|
endTime = Math.min(endTime, periodStart + periodDuration);
|
|
1758
1765
|
}
|
|
1759
1766
|
|
|
1767
|
+
// Don't add unavailable regions to the timeline.
|
|
1768
|
+
if (endTime < availabilityStart) {
|
|
1769
|
+
continue;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1760
1772
|
/** @type {shaka.extern.TimelineRegionInfo} */
|
|
1761
1773
|
const region = {
|
|
1762
1774
|
schemeIdUri: schemeIdUri,
|
|
@@ -8,16 +8,19 @@ goog.provide('shaka.media.RegionObserver');
|
|
|
8
8
|
|
|
9
9
|
goog.require('shaka.media.IPlayheadObserver');
|
|
10
10
|
goog.require('shaka.media.RegionTimeline');
|
|
11
|
+
goog.require('shaka.util.EventManager');
|
|
12
|
+
goog.require('shaka.util.FakeEvent');
|
|
13
|
+
goog.require('shaka.util.FakeEventTarget');
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
/**
|
|
14
17
|
* The region observer watches a region timeline and playhead, and fires events
|
|
15
|
-
* (
|
|
18
|
+
* ('enter', 'exit', 'skip') as the playhead moves.
|
|
16
19
|
*
|
|
17
20
|
* @implements {shaka.media.IPlayheadObserver}
|
|
18
21
|
* @final
|
|
19
22
|
*/
|
|
20
|
-
shaka.media.RegionObserver = class {
|
|
23
|
+
shaka.media.RegionObserver = class extends shaka.util.FakeEventTarget {
|
|
21
24
|
/**
|
|
22
25
|
* Create a region observer for the given timeline. The observer does not
|
|
23
26
|
* own the timeline, only uses it. This means that the observer should NOT
|
|
@@ -26,6 +29,8 @@ shaka.media.RegionObserver = class {
|
|
|
26
29
|
* @param {!shaka.media.RegionTimeline} timeline
|
|
27
30
|
*/
|
|
28
31
|
constructor(timeline) {
|
|
32
|
+
super();
|
|
33
|
+
|
|
29
34
|
/** @private {shaka.media.RegionTimeline} */
|
|
30
35
|
this.timeline_ = timeline;
|
|
31
36
|
|
|
@@ -39,13 +44,6 @@ shaka.media.RegionObserver = class {
|
|
|
39
44
|
*/
|
|
40
45
|
this.oldPosition_ = new Map();
|
|
41
46
|
|
|
42
|
-
/** @private {shaka.media.RegionObserver.EventListener} */
|
|
43
|
-
this.onEnter_ = (region, seeking) => {};
|
|
44
|
-
/** @private {shaka.media.RegionObserver.EventListener} */
|
|
45
|
-
this.onExit_ = (region, seeking) => {};
|
|
46
|
-
/** @private {shaka.media.RegionObserver.EventListener} */
|
|
47
|
-
this.onSkip_ = (region, seeking) => {};
|
|
48
|
-
|
|
49
47
|
// To make the rules easier to read, alias all the relative positions.
|
|
50
48
|
const RelativePosition = shaka.media.RegionObserver.RelativePosition_;
|
|
51
49
|
const BEFORE_THE_REGION = RelativePosition.BEFORE_THE_REGION;
|
|
@@ -62,39 +60,48 @@ shaka.media.RegionObserver = class {
|
|
|
62
60
|
{
|
|
63
61
|
weWere: null,
|
|
64
62
|
weAre: IN_THE_REGION,
|
|
65
|
-
invoke: (region, seeking) => this.
|
|
63
|
+
invoke: (region, seeking) => this.onEvent_('enter', region, seeking),
|
|
66
64
|
},
|
|
67
65
|
{
|
|
68
66
|
weWere: BEFORE_THE_REGION,
|
|
69
67
|
weAre: IN_THE_REGION,
|
|
70
|
-
invoke: (region, seeking) => this.
|
|
68
|
+
invoke: (region, seeking) => this.onEvent_('enter', region, seeking),
|
|
71
69
|
},
|
|
72
70
|
{
|
|
73
71
|
weWere: AFTER_THE_REGION,
|
|
74
72
|
weAre: IN_THE_REGION,
|
|
75
|
-
invoke: (region, seeking) => this.
|
|
73
|
+
invoke: (region, seeking) => this.onEvent_('enter', region, seeking),
|
|
76
74
|
},
|
|
77
75
|
{
|
|
78
76
|
weWere: IN_THE_REGION,
|
|
79
77
|
weAre: BEFORE_THE_REGION,
|
|
80
|
-
invoke: (region, seeking) => this.
|
|
78
|
+
invoke: (region, seeking) => this.onEvent_('exit', region, seeking),
|
|
81
79
|
},
|
|
82
80
|
{
|
|
83
81
|
weWere: IN_THE_REGION,
|
|
84
82
|
weAre: AFTER_THE_REGION,
|
|
85
|
-
invoke: (region, seeking) => this.
|
|
83
|
+
invoke: (region, seeking) => this.onEvent_('exit', region, seeking),
|
|
86
84
|
},
|
|
87
85
|
{
|
|
88
86
|
weWere: BEFORE_THE_REGION,
|
|
89
87
|
weAre: AFTER_THE_REGION,
|
|
90
|
-
invoke: (region, seeking) => this.
|
|
88
|
+
invoke: (region, seeking) => this.onEvent_('skip', region, seeking),
|
|
91
89
|
},
|
|
92
90
|
{
|
|
93
91
|
weWere: AFTER_THE_REGION,
|
|
94
92
|
weAre: BEFORE_THE_REGION,
|
|
95
|
-
invoke: (region, seeking) => this.
|
|
93
|
+
invoke: (region, seeking) => this.onEvent_('skip', region, seeking),
|
|
96
94
|
},
|
|
97
95
|
];
|
|
96
|
+
|
|
97
|
+
/** @private {shaka.util.EventManager} */
|
|
98
|
+
this.eventManager_ = new shaka.util.EventManager();
|
|
99
|
+
|
|
100
|
+
this.eventManager_.listen(this.timeline_, 'regionremove', (event) => {
|
|
101
|
+
/** @type {shaka.extern.TimelineRegionInfo} */
|
|
102
|
+
const region = event['region'];
|
|
103
|
+
this.oldPosition_.delete(region);
|
|
104
|
+
});
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
/** @override */
|
|
@@ -105,11 +112,10 @@ shaka.media.RegionObserver = class {
|
|
|
105
112
|
// needed.
|
|
106
113
|
this.oldPosition_.clear();
|
|
107
114
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
this.onSkip_ = (region, seeking) => {};
|
|
115
|
+
this.eventManager_.release();
|
|
116
|
+
this.eventManager_ = null;
|
|
117
|
+
|
|
118
|
+
super.release();
|
|
113
119
|
}
|
|
114
120
|
|
|
115
121
|
/** @override */
|
|
@@ -134,20 +140,20 @@ shaka.media.RegionObserver = class {
|
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
/**
|
|
137
|
-
*
|
|
143
|
+
* Dispatch events of the given type. All event types in this class have the
|
|
144
|
+
* same parameters: region and seeking.
|
|
138
145
|
*
|
|
139
|
-
* @param {
|
|
140
|
-
*
|
|
141
|
-
* @param {
|
|
142
|
-
*
|
|
143
|
-
* @param {shaka.media.RegionObserver.EventListener} onSkip
|
|
144
|
-
* The callback for when we move from before to after a region or from
|
|
145
|
-
* after to before a region.
|
|
146
|
+
* @param {string} eventType
|
|
147
|
+
* @param {shaka.extern.TimelineRegionInfo} region
|
|
148
|
+
* @param {boolean} seeking
|
|
149
|
+
* @private
|
|
146
150
|
*/
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
onEvent_(eventType, region, seeking) {
|
|
152
|
+
const event = new shaka.util.FakeEvent(eventType, new Map([
|
|
153
|
+
['region', region],
|
|
154
|
+
['seeking', seeking],
|
|
155
|
+
]));
|
|
156
|
+
this.dispatchEvent(event);
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
/**
|
|
@@ -6,26 +6,30 @@
|
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.media.RegionTimeline');
|
|
8
8
|
|
|
9
|
+
goog.require('shaka.util.FakeEvent');
|
|
10
|
+
goog.require('shaka.util.FakeEventTarget');
|
|
9
11
|
goog.require('shaka.util.IReleasable');
|
|
10
12
|
goog.require('shaka.util.Timer');
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* The region timeline is a set of unique timeline region info entries. When
|
|
15
|
-
* a new entry is added, the
|
|
17
|
+
* a new entry is added, the 'regionadd' event will be fired. When an entry is
|
|
18
|
+
* deleted, the 'regionremove' event will be fired.
|
|
16
19
|
*
|
|
17
20
|
* @implements {shaka.util.IReleasable}
|
|
18
21
|
* @final
|
|
19
22
|
*/
|
|
20
|
-
shaka.media.RegionTimeline = class {
|
|
23
|
+
shaka.media.RegionTimeline = class extends shaka.util.FakeEventTarget {
|
|
21
24
|
/**
|
|
22
25
|
* @param {!function():{start: number, end: number}} getSeekRange
|
|
23
26
|
*/
|
|
24
27
|
constructor(getSeekRange) {
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
super();
|
|
29
|
+
|
|
27
30
|
/** @private {!Set.<shaka.extern.TimelineRegionInfo>} */
|
|
28
31
|
this.regions_ = new Set();
|
|
32
|
+
|
|
29
33
|
/** @private {!function():{start: number, end: number}} */
|
|
30
34
|
this.getSeekRange_ = getSeekRange;
|
|
31
35
|
|
|
@@ -44,22 +48,9 @@ shaka.media.RegionTimeline = class {
|
|
|
44
48
|
|
|
45
49
|
/** @override */
|
|
46
50
|
release() {
|
|
47
|
-
// Prevent us from holding onto any external references via the callback.
|
|
48
|
-
this.onAddRegion_ = (region) => {};
|
|
49
51
|
this.regions_.clear();
|
|
50
52
|
this.filterTimer_.stop();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Set the callbacks for events. This will override any previous calls to
|
|
55
|
-
* |setListeners|.
|
|
56
|
-
*
|
|
57
|
-
* @param {function(shaka.extern.TimelineRegionInfo)} onAddRegion
|
|
58
|
-
* Set the callback for when we add a new region. This callback will only
|
|
59
|
-
* be called when a region is unique (we reject duplicate regions).
|
|
60
|
-
*/
|
|
61
|
-
setListeners(onAddRegion) {
|
|
62
|
-
this.onAddRegion_ = onAddRegion;
|
|
53
|
+
super.release();
|
|
63
54
|
}
|
|
64
55
|
|
|
65
56
|
/**
|
|
@@ -72,7 +63,10 @@ shaka.media.RegionTimeline = class {
|
|
|
72
63
|
// instead of making the parser track it.
|
|
73
64
|
if (similarRegion == null) {
|
|
74
65
|
this.regions_.add(region);
|
|
75
|
-
|
|
66
|
+
const event = new shaka.util.FakeEvent('regionadd', new Map([
|
|
67
|
+
['region', region],
|
|
68
|
+
]));
|
|
69
|
+
this.dispatchEvent(event);
|
|
76
70
|
}
|
|
77
71
|
}
|
|
78
72
|
|
|
@@ -89,6 +83,10 @@ shaka.media.RegionTimeline = class {
|
|
|
89
83
|
// reson to store or process them.
|
|
90
84
|
if (region.endTime < seekRange.start) {
|
|
91
85
|
this.regions_.delete(region);
|
|
86
|
+
const event = new shaka.util.FakeEvent('regionremove', new Map([
|
|
87
|
+
['region', region],
|
|
88
|
+
]));
|
|
89
|
+
this.dispatchEvent(event);
|
|
92
90
|
}
|
|
93
91
|
}
|
|
94
92
|
}
|
|
@@ -1644,7 +1644,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1644
1644
|
// See DASH sec. 5.10.3.3.1
|
|
1645
1645
|
// If a DASH client detects an event message box with a scheme that is not
|
|
1646
1646
|
// defined in MPD, the client is expected to ignore it.
|
|
1647
|
-
if (emsgSchemeIdUris.includes(schemeId)) {
|
|
1647
|
+
if (emsgSchemeIdUris && emsgSchemeIdUris.includes(schemeId)) {
|
|
1648
1648
|
// See DASH sec. 5.10.4.1
|
|
1649
1649
|
// A special scheme in DASH used to signal manifest updates.
|
|
1650
1650
|
if (schemeId == 'urn:mpeg:dash:event:2012') {
|
|
@@ -222,6 +222,10 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
222
222
|
this.destroyed_ = true;
|
|
223
223
|
this.requestFilters_.clear();
|
|
224
224
|
this.responseFilters_.clear();
|
|
225
|
+
|
|
226
|
+
// FakeEventTarget implements IReleasable
|
|
227
|
+
super.release();
|
|
228
|
+
|
|
225
229
|
return this.operationManager_.destroy();
|
|
226
230
|
}
|
|
227
231
|
|
package/lib/offline/storage.js
CHANGED
|
@@ -477,23 +477,22 @@ shaka.offline.Storage = class {
|
|
|
477
477
|
* @private
|
|
478
478
|
*/
|
|
479
479
|
async filterManifest_(manifest, drmEngine, config) {
|
|
480
|
-
const StreamUtils = shaka.util.StreamUtils;
|
|
481
|
-
|
|
482
480
|
// Filter the manifest based on the restrictions given in the player
|
|
483
481
|
// configuration.
|
|
484
482
|
const maxHwRes = {width: Infinity, height: Infinity};
|
|
485
|
-
StreamUtils.filterByRestrictions(
|
|
483
|
+
shaka.util.StreamUtils.filterByRestrictions(
|
|
484
|
+
manifest, config.restrictions, maxHwRes);
|
|
486
485
|
|
|
487
486
|
// Filter the manifest based on what we know media source will be able to
|
|
488
487
|
// play later (no point storing something we can't play).
|
|
489
488
|
if (config.useMediaCapabilities) {
|
|
490
|
-
StreamUtils.filterManifestByMediaCapabilities(
|
|
489
|
+
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(
|
|
491
490
|
manifest, config.offline.usePersistentLicense);
|
|
492
491
|
} else {
|
|
493
|
-
StreamUtils.filterManifestByMediaSource(manifest);
|
|
492
|
+
shaka.util.StreamUtils.filterManifestByMediaSource(manifest);
|
|
494
493
|
// Filter the manifest based on what we know our drm system will support
|
|
495
494
|
// playing later.
|
|
496
|
-
StreamUtils.filterManifestByDrm(manifest, drmEngine);
|
|
495
|
+
shaka.util.StreamUtils.filterManifestByDrm(manifest, drmEngine);
|
|
497
496
|
}
|
|
498
497
|
|
|
499
498
|
// Gather all tracks.
|
|
@@ -501,23 +500,23 @@ shaka.offline.Storage = class {
|
|
|
501
500
|
|
|
502
501
|
// Choose the codec that has the lowest average bandwidth.
|
|
503
502
|
const preferredAudioChannelCount = config.preferredAudioChannelCount;
|
|
504
|
-
StreamUtils.chooseCodecsAndFilterManifest(
|
|
503
|
+
shaka.util.StreamUtils.chooseCodecsAndFilterManifest(
|
|
505
504
|
manifest, preferredAudioChannelCount);
|
|
506
505
|
|
|
507
506
|
for (const variant of manifest.variants) {
|
|
508
507
|
goog.asserts.assert(
|
|
509
|
-
StreamUtils.isPlayable(variant),
|
|
508
|
+
shaka.util.StreamUtils.isPlayable(variant),
|
|
510
509
|
'We should have already filtered by "is playable"');
|
|
511
510
|
|
|
512
|
-
allTracks.push(StreamUtils.variantToTrack(variant));
|
|
511
|
+
allTracks.push(shaka.util.StreamUtils.variantToTrack(variant));
|
|
513
512
|
}
|
|
514
513
|
|
|
515
514
|
for (const text of manifest.textStreams) {
|
|
516
|
-
allTracks.push(StreamUtils.textStreamToTrack(text));
|
|
515
|
+
allTracks.push(shaka.util.StreamUtils.textStreamToTrack(text));
|
|
517
516
|
}
|
|
518
517
|
|
|
519
518
|
for (const image of manifest.imageStreams) {
|
|
520
|
-
allTracks.push(StreamUtils.imageStreamToTrack(image));
|
|
519
|
+
allTracks.push(shaka.util.StreamUtils.imageStreamToTrack(image));
|
|
521
520
|
}
|
|
522
521
|
|
|
523
522
|
// Let the application choose which tracks to store.
|
package/lib/player.js
CHANGED
|
@@ -726,6 +726,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
726
726
|
await this.networkingEngine_.destroy();
|
|
727
727
|
this.networkingEngine_ = null;
|
|
728
728
|
}
|
|
729
|
+
|
|
730
|
+
// FakeEventTarget implements IReleasable
|
|
731
|
+
super.release();
|
|
729
732
|
}
|
|
730
733
|
|
|
731
734
|
/**
|
|
@@ -1627,8 +1630,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1627
1630
|
// initialize it now even through it appears a little out-of-place.
|
|
1628
1631
|
this.regionTimeline_ =
|
|
1629
1632
|
new shaka.media.RegionTimeline(() => this.seekRange());
|
|
1630
|
-
this.regionTimeline_.
|
|
1633
|
+
this.regionTimeline_.addEventListener('regionadd', (event) => {
|
|
1634
|
+
/** @type {shaka.extern.TimelineRegionInfo} */
|
|
1635
|
+
const region = event['region'];
|
|
1631
1636
|
this.onRegionEvent_(shaka.Player.EventName.TimelineRegionAdded, region);
|
|
1637
|
+
|
|
1632
1638
|
if (this.adManager_) {
|
|
1633
1639
|
this.adManager_.onDashTimedMetadata(region);
|
|
1634
1640
|
}
|
|
@@ -2519,21 +2525,31 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2519
2525
|
// Create the region observer. This will allow us to notify the app when we
|
|
2520
2526
|
// move in and out of timeline regions.
|
|
2521
2527
|
const regionObserver = new shaka.media.RegionObserver(this.regionTimeline_);
|
|
2522
|
-
|
|
2528
|
+
|
|
2529
|
+
regionObserver.addEventListener('enter', (event) => {
|
|
2530
|
+
/** @type {shaka.extern.TimelineRegionInfo} */
|
|
2531
|
+
const region = event['region'];
|
|
2523
2532
|
this.onRegionEvent_(shaka.Player.EventName.TimelineRegionEnter, region);
|
|
2524
|
-
};
|
|
2525
|
-
|
|
2533
|
+
});
|
|
2534
|
+
|
|
2535
|
+
regionObserver.addEventListener('exit', (event) => {
|
|
2536
|
+
/** @type {shaka.extern.TimelineRegionInfo} */
|
|
2537
|
+
const region = event['region'];
|
|
2526
2538
|
this.onRegionEvent_(shaka.Player.EventName.TimelineRegionExit, region);
|
|
2527
|
-
};
|
|
2528
|
-
|
|
2539
|
+
});
|
|
2540
|
+
|
|
2541
|
+
regionObserver.addEventListener('skip', (event) => {
|
|
2542
|
+
/** @type {shaka.extern.TimelineRegionInfo} */
|
|
2543
|
+
const region = event['region'];
|
|
2544
|
+
/** @type {boolean} */
|
|
2545
|
+
const seeking = event['seeking'];
|
|
2529
2546
|
// If we are seeking, we don't want to surface the enter/exit events since
|
|
2530
2547
|
// they didn't play through them.
|
|
2531
2548
|
if (!seeking) {
|
|
2532
2549
|
this.onRegionEvent_(shaka.Player.EventName.TimelineRegionEnter, region);
|
|
2533
2550
|
this.onRegionEvent_(shaka.Player.EventName.TimelineRegionExit, region);
|
|
2534
2551
|
}
|
|
2535
|
-
};
|
|
2536
|
-
regionObserver.setListeners(onEnterRegion, onExitRegion, onSkipRegion);
|
|
2552
|
+
});
|
|
2537
2553
|
|
|
2538
2554
|
// Now that we have all our observers, create a manager for them.
|
|
2539
2555
|
const manager = new shaka.media.PlayheadObserverManager(this.video_);
|
|
@@ -6102,7 +6118,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6102
6118
|
* @define {string} A version number taken from git at compile time.
|
|
6103
6119
|
* @export
|
|
6104
6120
|
*/
|
|
6105
|
-
shaka.Player.version = 'v3.1.
|
|
6121
|
+
shaka.Player.version = 'v3.1.6-uncompiled'; // x-release-please-version
|
|
6106
6122
|
|
|
6107
6123
|
// Initialize the deprecation system using the version string we just set
|
|
6108
6124
|
// on the player.
|
|
@@ -9,6 +9,7 @@ goog.provide('shaka.util.FakeEventTarget');
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.log');
|
|
11
11
|
goog.require('shaka.util.FakeEvent');
|
|
12
|
+
goog.require('shaka.util.IReleasable');
|
|
12
13
|
goog.require('shaka.util.MultiMap');
|
|
13
14
|
|
|
14
15
|
|
|
@@ -18,13 +19,14 @@ goog.require('shaka.util.MultiMap');
|
|
|
18
19
|
* to non-DOM classes. Only FakeEvents should be dispatched.
|
|
19
20
|
*
|
|
20
21
|
* @implements {EventTarget}
|
|
22
|
+
* @implements {shaka.util.IReleasable}
|
|
21
23
|
* @exportInterface
|
|
22
24
|
*/
|
|
23
25
|
shaka.util.FakeEventTarget = class {
|
|
24
26
|
/** */
|
|
25
27
|
constructor() {
|
|
26
28
|
/**
|
|
27
|
-
* @private {
|
|
29
|
+
* @private {shaka.util.MultiMap.<shaka.util.FakeEventTarget.ListenerType>}
|
|
28
30
|
*/
|
|
29
31
|
this.listeners_ = new shaka.util.MultiMap();
|
|
30
32
|
|
|
@@ -46,6 +48,9 @@ shaka.util.FakeEventTarget = class {
|
|
|
46
48
|
* @exportInterface
|
|
47
49
|
*/
|
|
48
50
|
addEventListener(type, listener, options) {
|
|
51
|
+
if (!this.listeners_) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
49
54
|
this.listeners_.push(type, listener);
|
|
50
55
|
}
|
|
51
56
|
|
|
@@ -73,6 +78,9 @@ shaka.util.FakeEventTarget = class {
|
|
|
73
78
|
* @exportInterface
|
|
74
79
|
*/
|
|
75
80
|
removeEventListener(type, listener, options) {
|
|
81
|
+
if (!this.listeners_) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
76
84
|
this.listeners_.remove(type, listener);
|
|
77
85
|
}
|
|
78
86
|
|
|
@@ -90,6 +98,10 @@ shaka.util.FakeEventTarget = class {
|
|
|
90
98
|
goog.asserts.assert(event instanceof shaka.util.FakeEvent,
|
|
91
99
|
'FakeEventTarget can only dispatch FakeEvents!');
|
|
92
100
|
|
|
101
|
+
if (!this.listeners_) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
|
|
93
105
|
let listeners = this.listeners_.get(event.type) || [];
|
|
94
106
|
const universalListeners =
|
|
95
107
|
this.listeners_.get(shaka.util.FakeEventTarget.ALL_EVENTS_);
|
|
@@ -129,6 +141,14 @@ shaka.util.FakeEventTarget = class {
|
|
|
129
141
|
|
|
130
142
|
return event.defaultPrevented;
|
|
131
143
|
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @override
|
|
147
|
+
* @exportInterface
|
|
148
|
+
*/
|
|
149
|
+
release() {
|
|
150
|
+
this.listeners_ = null;
|
|
151
|
+
}
|
|
132
152
|
};
|
|
133
153
|
|
|
134
154
|
/**
|