shaka-player 3.2.0 → 3.2.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/.github/workflows/build_and_test.yaml +73 -0
- package/.github/workflows/release.yaml +53 -0
- package/AUTHORS +3 -0
- package/CHANGELOG.md +182 -1
- package/CONTRIBUTORS +3 -0
- package/README.md +4 -4
- package/build/checkversion.py +1 -1
- package/build/generateExterns.js +1 -1
- package/build/misspellings.txt +1 -0
- package/build/shakaBuildHelpers.py +6 -5
- package/build/subprocessWindowsPatch.py +103 -0
- package/build/test.py +6 -0
- package/demo/common/assets.js +1 -1
- package/demo/index.html +1 -1
- package/dist/controls.css +2 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +1 -1
- package/dist/demo.compiled.js +1 -1
- package/dist/deps.js +8 -8
- package/dist/locales.js +37 -37
- package/dist/receiver.compiled.debug.js +1 -1
- package/dist/receiver.compiled.js +1 -1
- package/dist/shaka-player.compiled.d.ts +195 -5
- package/dist/shaka-player.compiled.debug.d.ts +195 -5
- package/dist/shaka-player.compiled.debug.externs.js +226 -14
- package/dist/shaka-player.compiled.debug.js +424 -399
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +226 -14
- package/dist/shaka-player.compiled.js +826 -812
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +197 -16
- package/dist/shaka-player.ui.debug.d.ts +197 -16
- package/dist/shaka-player.ui.debug.externs.js +230 -27
- package/dist/shaka-player.ui.debug.js +466 -442
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +230 -27
- package/dist/shaka-player.ui.js +946 -932
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/fairplay.md +1 -1
- package/docs/tutorials/faq.md +14 -0
- package/docs/tutorials/ui.md +5 -5
- package/externs/ima.js +4 -0
- package/externs/shaka/ads.js +25 -0
- package/externs/shaka/player.js +8 -0
- package/externs/shaka/text.js +10 -0
- package/karma.conf.js +20 -15
- package/lib/ads/ad_manager.js +46 -26
- package/lib/ads/client_side_ad_manager.js +82 -88
- package/lib/ads/server_side_ad_manager.js +45 -13
- package/lib/cast/cast_proxy.js +6 -2
- package/lib/cast/cast_receiver.js +5 -1
- package/lib/cast/cast_sender.js +2 -2
- package/lib/cea/sei_processor.js +24 -17
- package/lib/dash/dash_parser.js +131 -24
- package/lib/dash/segment_list.js +1 -1
- package/lib/dash/segment_template.js +1 -1
- package/lib/hls/hls_parser.js +74 -17
- package/lib/hls/manifest_text_parser.js +1 -0
- package/lib/media/closed_caption_parser.js +3 -1
- package/lib/media/content_workarounds.js +12 -0
- package/lib/media/drm_engine.js +20 -1
- package/lib/media/gap_jumping_controller.js +8 -4
- package/lib/media/media_source_engine.js +1 -2
- package/lib/media/playhead.js +1 -1
- package/lib/media/region_observer.js +39 -33
- package/lib/media/region_timeline.js +17 -19
- package/lib/media/segment_index.js +2 -1
- package/lib/media/segment_reference.js +19 -1
- package/lib/media/streaming_engine.js +8 -4
- package/lib/net/networking_engine.js +6 -1
- package/lib/offline/download_manager.js +1 -2
- package/lib/offline/storage.js +8 -9
- package/lib/player.js +129 -59
- package/lib/polyfill/aria.js +12 -2
- package/lib/polyfill/encryption_scheme.js +2 -0
- package/lib/polyfill/fullscreen.js +2 -0
- package/lib/polyfill/mathround.js +2 -0
- package/lib/polyfill/media_capabilities.js +73 -21
- package/lib/polyfill/mediasource.js +8 -0
- package/lib/polyfill/orientation.js +3 -1
- package/lib/polyfill/patchedmediakeys_apple.js +6 -4
- package/lib/polyfill/patchedmediakeys_ms.js +6 -4
- package/lib/polyfill/patchedmediakeys_nop.js +2 -0
- package/lib/polyfill/patchedmediakeys_webkit.js +6 -4
- package/lib/polyfill/pip_webkit.js +2 -0
- package/lib/polyfill/storage_estimate.js +2 -0
- package/lib/polyfill/video_play_promise.js +2 -0
- package/lib/polyfill/videoplaybackquality.js +2 -0
- package/lib/polyfill/vttcue.js +2 -0
- package/lib/text/cue.js +6 -0
- package/lib/text/mp4_ttml_parser.js +3 -0
- package/lib/text/text_engine.js +14 -2
- package/lib/text/ttml_text_parser.js +135 -87
- package/lib/text/ui_text_displayer.js +213 -80
- package/lib/text/vtt_text_parser.js +4 -2
- package/lib/text/web_vtt_generator.js +21 -12
- package/lib/util/fake_event.js +53 -7
- package/lib/util/fake_event_target.js +21 -1
- package/lib/util/mp4_box_parsers.js +1 -1
- package/lib/util/periods.js +4 -1
- package/lib/util/platform.js +13 -1
- package/lib/util/stream_utils.js +105 -13
- package/lib/util/xml_utils.js +50 -12
- package/package.json +3 -6
- package/roadmap.md +24 -22
- package/test/cast/cast_proxy_unit.js +12 -6
- package/test/cast/cast_receiver_integration.js +1 -1
- package/test/cast/cast_utils_unit.js +1 -1
- package/test/cea/mp4_cea_parser_unit.js +26 -0
- package/test/dash/dash_parser_live_unit.js +43 -0
- package/test/dash/dash_parser_manifest_unit.js +222 -3
- package/test/hls/hls_parser_unit.js +79 -1
- package/test/media/closed_caption_parser_unit.js +20 -0
- package/test/media/drm_engine_integration.js +86 -2
- package/test/media/drm_engine_unit.js +57 -0
- package/test/media/playhead_unit.js +27 -1
- package/test/media/region_observer_unit.js +40 -5
- package/test/media/region_timeline_unit.js +40 -22
- package/test/media/streaming_engine_integration.js +2 -1
- package/test/media/streaming_engine_unit.js +145 -0
- package/test/player_integration.js +79 -8
- package/test/player_src_equals_integration.js +41 -8
- package/test/player_unit.js +14 -4
- package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
- package/test/test/assets/3675/dash_0.mpd +30 -0
- package/test/test/assets/3675/dash_1.mpd +30 -0
- package/test/test/assets/3675/dash_2.mpd +30 -0
- package/test/test/assets/3675/dash_3.mpd +30 -0
- package/test/test/assets/3675/dash_4.mpd +30 -0
- package/test/test/assets/3675/dash_5.mpd +26 -0
- package/test/test/assets/3675/init-stream0.m4s +0 -0
- package/test/test/assets/chapters.vtt +2 -2
- package/test/test/assets/chapters2.vtt +10 -0
- package/test/test/assets/empty_caption_video_init.mp4 +0 -0
- package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
- package/test/test/util/fake_ad_manager.js +11 -1
- package/test/test/util/ttml_utils.js +81 -0
- package/test/test/util/util.js +10 -7
- package/test/text/mp4_ttml_parser_unit.js +11 -18
- package/test/text/ttml_text_parser_unit.js +542 -220
- package/test/text/ui_text_displayer_unit.js +93 -20
- package/test/text/vtt_text_parser_unit.js +17 -1
- package/test/text/web_vtt_generator_unit.js +58 -3
- package/test/ui/localization_unit.js +15 -14
- package/test/ui/text_displayer_layout_unit.js +21 -8
- package/test/util/mp4_box_parsers_unit.js +28 -0
- package/test/util/stream_utils_unit.js +60 -3
- package/ui/cast_button.js +2 -3
- package/ui/controls.js +11 -6
- package/ui/less/buttons.less +0 -4
- package/ui/less/containers.less +6 -7
- package/ui/locales/ru.json +6 -6
- package/ui/localization.js +40 -87
- package/ui/pip_button.js +2 -3
- package/ui/seek_bar.js +1 -2
- package/ui/text_selection.js +1 -0
|
@@ -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
|
}
|
|
@@ -347,7 +347,8 @@ shaka.media.SegmentIndex = class {
|
|
|
347
347
|
lastReference.appendWindowStart,
|
|
348
348
|
lastReference.appendWindowEnd,
|
|
349
349
|
lastReference.partialReferences,
|
|
350
|
-
lastReference.tilesLayout
|
|
350
|
+
lastReference.tilesLayout,
|
|
351
|
+
lastReference.tileDuration);
|
|
351
352
|
}
|
|
352
353
|
|
|
353
354
|
|
|
@@ -140,11 +140,15 @@ shaka.media.SegmentReference = class {
|
|
|
140
140
|
* The value is a grid-item-dimension consisting of two positive decimal
|
|
141
141
|
* integers in the format: column-x-row ('4x3'). It describes the
|
|
142
142
|
* arrangement of Images in a Grid. The minimum valid LAYOUT is '1x1'.
|
|
143
|
+
* @param {?number=} tileDuration
|
|
144
|
+
* The explicit duration of an individual tile within the tiles grid.
|
|
145
|
+
* If not provided, the duration should be automatically calculated based on
|
|
146
|
+
* the duration of the reference.
|
|
143
147
|
*/
|
|
144
148
|
constructor(
|
|
145
149
|
startTime, endTime, uris, startByte, endByte, initSegmentReference,
|
|
146
150
|
timestampOffset, appendWindowStart, appendWindowEnd,
|
|
147
|
-
partialReferences = [], tilesLayout = '') {
|
|
151
|
+
partialReferences = [], tilesLayout = '', tileDuration = null) {
|
|
148
152
|
// A preload hinted Partial Segment has the same startTime and endTime.
|
|
149
153
|
goog.asserts.assert(startTime <= endTime,
|
|
150
154
|
'startTime must be less than or equal to endTime');
|
|
@@ -191,6 +195,9 @@ shaka.media.SegmentReference = class {
|
|
|
191
195
|
|
|
192
196
|
/** @type {?string} */
|
|
193
197
|
this.tilesLayout = tilesLayout;
|
|
198
|
+
|
|
199
|
+
/** @type {?number} */
|
|
200
|
+
this.tileDuration = tileDuration;
|
|
194
201
|
}
|
|
195
202
|
|
|
196
203
|
/**
|
|
@@ -275,6 +282,17 @@ shaka.media.SegmentReference = class {
|
|
|
275
282
|
getTilesLayout() {
|
|
276
283
|
return this.tilesLayout;
|
|
277
284
|
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Returns the segment's explicit tile duration.
|
|
288
|
+
* Only defined in image segments.
|
|
289
|
+
*
|
|
290
|
+
* @return {?number}
|
|
291
|
+
* @export
|
|
292
|
+
*/
|
|
293
|
+
getTileDuration() {
|
|
294
|
+
return this.tileDuration;
|
|
295
|
+
}
|
|
278
296
|
};
|
|
279
297
|
|
|
280
298
|
|
|
@@ -623,7 +623,7 @@ shaka.media.StreamingEngine = class {
|
|
|
623
623
|
|
|
624
624
|
// Don't clear the buffer unless something is buffered. This extra
|
|
625
625
|
// check prevents extra, useless calls to clear the buffer.
|
|
626
|
-
if (somethingBuffered) {
|
|
626
|
+
if (somethingBuffered || mediaState.performingUpdate) {
|
|
627
627
|
this.forceClearBuffer_(mediaState);
|
|
628
628
|
streamCleared = true;
|
|
629
629
|
}
|
|
@@ -977,7 +977,10 @@ shaka.media.StreamingEngine = class {
|
|
|
977
977
|
unscaledBufferingGoal * this.bufferingGoalScale_;
|
|
978
978
|
|
|
979
979
|
// Check if we've buffered to the end of the presentation.
|
|
980
|
-
|
|
980
|
+
const timeUntilEnd =
|
|
981
|
+
this.manifest_.presentationTimeline.getDuration() - timeNeeded;
|
|
982
|
+
const oneMicrosecond = 1e-6;
|
|
983
|
+
if (timeUntilEnd < oneMicrosecond) {
|
|
981
984
|
// We shouldn't rebuffer if the playhead is close to the end of the
|
|
982
985
|
// presentation.
|
|
983
986
|
shaka.log.debug(logPrefix, 'buffered to end of presentation');
|
|
@@ -1641,7 +1644,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1641
1644
|
// See DASH sec. 5.10.3.3.1
|
|
1642
1645
|
// If a DASH client detects an event message box with a scheme that is not
|
|
1643
1646
|
// defined in MPD, the client is expected to ignore it.
|
|
1644
|
-
if (emsgSchemeIdUris.includes(schemeId)) {
|
|
1647
|
+
if (emsgSchemeIdUris && emsgSchemeIdUris.includes(schemeId)) {
|
|
1645
1648
|
// See DASH sec. 5.10.4.1
|
|
1646
1649
|
// A special scheme in DASH used to signal manifest updates.
|
|
1647
1650
|
if (schemeId == 'urn:mpeg:dash:event:2012') {
|
|
@@ -1662,7 +1665,8 @@ shaka.media.StreamingEngine = class {
|
|
|
1662
1665
|
|
|
1663
1666
|
// Dispatch an event to notify the application about the emsg box.
|
|
1664
1667
|
const eventName = shaka.Player.EventName.Emsg;
|
|
1665
|
-
const
|
|
1668
|
+
const data = (new Map()).set('detail', emsg);
|
|
1669
|
+
const event = new shaka.util.FakeEvent(eventName, data);
|
|
1666
1670
|
this.playerInterface_.onEvent(event);
|
|
1667
1671
|
}
|
|
1668
1672
|
}
|
|
@@ -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
|
|
|
@@ -544,7 +548,8 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
544
548
|
}
|
|
545
549
|
|
|
546
550
|
if (error.severity == shaka.util.Error.Severity.RECOVERABLE) {
|
|
547
|
-
const
|
|
551
|
+
const data = (new Map()).set('error', error);
|
|
552
|
+
const event = new shaka.util.FakeEvent('retry', data);
|
|
548
553
|
this.dispatchEvent(event);
|
|
549
554
|
|
|
550
555
|
// Move to the next URI.
|
|
@@ -44,9 +44,8 @@ shaka.offline.DownloadManager = class {
|
|
|
44
44
|
|
|
45
45
|
/** @private {!shaka.util.Destroyer} */
|
|
46
46
|
this.destroyer_ = new shaka.util.Destroyer(() => {
|
|
47
|
-
const promises = Array.from(this.groups_.values());
|
|
48
47
|
// Add a "catch" block to stop errors from being returned.
|
|
49
|
-
return
|
|
48
|
+
return this.abortAll().catch(() => {});
|
|
50
49
|
});
|
|
51
50
|
|
|
52
51
|
/**
|
package/lib/offline/storage.js
CHANGED
|
@@ -477,16 +477,15 @@ 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 MediaCapabilities will be able
|
|
488
487
|
// to play later (no point storing something we can't play).
|
|
489
|
-
StreamUtils.filterManifestByMediaCapabilities(
|
|
488
|
+
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(
|
|
490
489
|
manifest, config.offline.usePersistentLicense);
|
|
491
490
|
|
|
492
491
|
// Gather all tracks.
|
|
@@ -498,24 +497,24 @@ shaka.offline.Storage = class {
|
|
|
498
497
|
const preferredVideoCodecs = config.preferredVideoCodecs;
|
|
499
498
|
const preferredAudioCodecs = config.preferredAudioCodecs;
|
|
500
499
|
|
|
501
|
-
StreamUtils.chooseCodecsAndFilterManifest(
|
|
500
|
+
shaka.util.StreamUtils.chooseCodecsAndFilterManifest(
|
|
502
501
|
manifest, preferredVideoCodecs, preferredAudioCodecs,
|
|
503
502
|
preferredAudioChannelCount, preferredDecodingAttributes);
|
|
504
503
|
|
|
505
504
|
for (const variant of manifest.variants) {
|
|
506
505
|
goog.asserts.assert(
|
|
507
|
-
StreamUtils.isPlayable(variant),
|
|
506
|
+
shaka.util.StreamUtils.isPlayable(variant),
|
|
508
507
|
'We should have already filtered by "is playable"');
|
|
509
508
|
|
|
510
|
-
allTracks.push(StreamUtils.variantToTrack(variant));
|
|
509
|
+
allTracks.push(shaka.util.StreamUtils.variantToTrack(variant));
|
|
511
510
|
}
|
|
512
511
|
|
|
513
512
|
for (const text of manifest.textStreams) {
|
|
514
|
-
allTracks.push(StreamUtils.textStreamToTrack(text));
|
|
513
|
+
allTracks.push(shaka.util.StreamUtils.textStreamToTrack(text));
|
|
515
514
|
}
|
|
516
515
|
|
|
517
516
|
for (const image of manifest.imageStreams) {
|
|
518
|
-
allTracks.push(StreamUtils.imageStreamToTrack(image));
|
|
517
|
+
allTracks.push(shaka.util.StreamUtils.imageStreamToTrack(image));
|
|
519
518
|
}
|
|
520
519
|
|
|
521
520
|
// Let the application choose which tracks to store.
|