shaka-player 4.9.13 → 4.10.1
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/README.md +4 -0
- package/dist/controls.css +2 -2
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +24 -19
- package/dist/locales.js +46 -35
- package/dist/shaka-player.compiled.d.ts +291 -12
- package/dist/shaka-player.compiled.debug.d.ts +291 -12
- package/dist/shaka-player.compiled.debug.externs.js +443 -6
- package/dist/shaka-player.compiled.debug.js +651 -556
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +443 -6
- package/dist/shaka-player.compiled.js +1325 -1270
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +306 -13
- package/dist/shaka-player.ui.debug.d.ts +306 -13
- package/dist/shaka-player.ui.debug.externs.js +477 -18
- package/dist/shaka-player.ui.debug.js +799 -681
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +477 -18
- package/dist/shaka-player.ui.js +1600 -1533
- package/dist/shaka-player.ui.map +4 -4
- package/externs/shaka/ads.js +21 -1
- package/externs/shaka/manifest.js +20 -1
- package/externs/shaka/manifest_parser.js +18 -1
- package/externs/shaka/player.js +164 -50
- package/lib/ads/ad_manager.js +225 -10
- package/lib/ads/ad_utils.js +323 -0
- package/lib/ads/ads_stats.js +24 -0
- package/lib/ads/client_side_ad_manager.js +42 -34
- package/lib/ads/interstitial_ad.js +292 -0
- package/lib/ads/interstitial_ad_manager.js +772 -0
- package/lib/ads/media_tailor_ad_manager.js +19 -22
- package/lib/ads/server_side_ad_manager.js +12 -15
- package/lib/cast/cast_utils.js +1 -0
- package/lib/cea/cea_utils.js +12 -0
- package/lib/cea/mp4_cea_parser.js +17 -0
- package/lib/dash/dash_parser.js +81 -28
- package/lib/dash/segment_base.js +3 -0
- package/lib/hls/hls_parser.js +429 -121
- package/lib/hls/manifest_text_parser.js +1 -0
- package/lib/media/adaptation_set_criteria.js +31 -1
- package/lib/media/drm_engine.js +16 -2
- package/lib/media/manifest_filterer.js +7 -5
- package/lib/media/preload_manager.js +8 -10
- package/lib/media/presentation_timeline.js +37 -5
- package/lib/media/quality_observer.js +68 -2
- package/lib/media/segment_reference.js +1 -1
- package/lib/media/segment_utils.js +33 -1
- package/lib/media/streaming_engine.js +120 -43
- package/lib/mss/mss_parser.js +13 -2
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/manifest_converter.js +3 -0
- package/lib/offline/offline_manifest_parser.js +5 -0
- package/lib/offline/storage.js +2 -0
- package/lib/player.js +498 -165
- package/lib/util/fake_event.js +1 -0
- package/lib/util/manifest_parser_utils.js +9 -2
- package/lib/util/mp4_box_parsers.js +32 -0
- package/lib/util/player_configuration.js +21 -9
- package/lib/util/stats.js +43 -0
- package/package.json +1 -1
- package/shaka-player.uncompiled.js +2 -0
- package/ui/ad_counter.js +3 -3
- package/ui/ad_position.js +3 -3
- package/ui/ad_statistics_button.js +237 -0
- package/ui/audio_language_selection.js +8 -4
- package/ui/controls.js +6 -3
- package/ui/element.js +3 -3
- package/ui/enums.js +1 -0
- package/ui/externs/ui.js +3 -0
- package/ui/language_utils.js +48 -3
- package/ui/less/containers.less +32 -0
- package/ui/less/thumbnails.less +13 -0
- package/ui/locales/en.json +2 -0
- package/ui/locales/es-419.json +2 -0
- package/ui/locales/es.json +3 -0
- package/ui/locales/fr.json +1 -0
- package/ui/locales/pl.json +1 -0
- package/ui/locales/pt-BR.json +1 -0
- package/ui/locales/pt-PT.json +1 -0
- package/ui/locales/source.json +8 -0
- package/ui/mute_button.js +4 -4
- package/ui/overflow_menu.js +3 -3
- package/ui/play_button.js +5 -7
- package/ui/presentation_time.js +3 -3
- package/ui/save_video_frame_button.js +196 -0
- package/ui/seek_bar.js +75 -20
- package/ui/skip_ad_button.js +4 -4
- package/ui/statistics_button.js +14 -2
- package/ui/ui.js +15 -0
- package/ui/volume_bar.js +4 -4
|
@@ -4,15 +4,12 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @fileoverview
|
|
9
|
-
* @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
|
|
10
|
-
*/
|
|
11
7
|
|
|
12
8
|
goog.provide('shaka.ads.MediaTailorAdManager');
|
|
13
9
|
|
|
14
10
|
goog.require('goog.asserts');
|
|
15
11
|
goog.require('shaka.ads.MediaTailorAd');
|
|
12
|
+
goog.require('shaka.ads.Utils');
|
|
16
13
|
goog.require('shaka.log');
|
|
17
14
|
goog.require('shaka.net.NetworkingEngine');
|
|
18
15
|
goog.require('goog.Uri');
|
|
@@ -135,7 +132,7 @@ shaka.ads.MediaTailorAdManager = class {
|
|
|
135
132
|
*/
|
|
136
133
|
addTrackingUrl(url) {
|
|
137
134
|
this.trackingUrl_ = url;
|
|
138
|
-
this.onEvent_(new shaka.util.FakeEvent(shaka.ads.
|
|
135
|
+
this.onEvent_(new shaka.util.FakeEvent(shaka.ads.Utils.ADS_LOADED,
|
|
139
136
|
(new Map()).set('loadTime', 0)));
|
|
140
137
|
}
|
|
141
138
|
|
|
@@ -227,7 +224,7 @@ shaka.ads.MediaTailorAdManager = class {
|
|
|
227
224
|
this.trackingUrl_ = baseUri.resolve(relativeTrackingUri).toString();
|
|
228
225
|
const now = Date.now() / 1000;
|
|
229
226
|
const loadTime = now - this.streamRequestStartTime_;
|
|
230
|
-
this.onEvent_(new shaka.util.FakeEvent(shaka.ads.
|
|
227
|
+
this.onEvent_(new shaka.util.FakeEvent(shaka.ads.Utils.ADS_LOADED,
|
|
231
228
|
(new Map()).set('loadTime', loadTime)));
|
|
232
229
|
const relativeManifestUri = new goog.Uri(dataAsJson.manifestUrl);
|
|
233
230
|
this.streamPromise_.resolve(
|
|
@@ -282,13 +279,13 @@ shaka.ads.MediaTailorAdManager = class {
|
|
|
282
279
|
}
|
|
283
280
|
cuepoints = this.getCuePoints();
|
|
284
281
|
this.onEvent_(new shaka.util.FakeEvent(
|
|
285
|
-
shaka.ads.
|
|
282
|
+
shaka.ads.Utils.CUEPOINTS_CHANGED,
|
|
286
283
|
(new Map()).set('cuepoints', cuepoints)));
|
|
287
284
|
}
|
|
288
285
|
} else {
|
|
289
286
|
if (this.adBreaks_.length) {
|
|
290
287
|
this.onEvent_(new shaka.util.FakeEvent(
|
|
291
|
-
shaka.ads.
|
|
288
|
+
shaka.ads.Utils.CUEPOINTS_CHANGED,
|
|
292
289
|
(new Map()).set('cuepoints', cuepoints)));
|
|
293
290
|
}
|
|
294
291
|
this.onEnded_();
|
|
@@ -727,52 +724,52 @@ shaka.ads.MediaTailorAdManager = class {
|
|
|
727
724
|
switch (eventType) {
|
|
728
725
|
case shaka.ads.MediaTailorAdManager.IMPRESSION_:
|
|
729
726
|
this.onEvent_(
|
|
730
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
727
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_IMPRESSION));
|
|
731
728
|
break;
|
|
732
729
|
case shaka.ads.MediaTailorAdManager.START_:
|
|
733
730
|
this.onEvent_(
|
|
734
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
731
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_STARTED,
|
|
735
732
|
(new Map()).set('ad', this.ad_)));
|
|
736
733
|
break;
|
|
737
734
|
case shaka.ads.MediaTailorAdManager.MUTE_:
|
|
738
735
|
this.onEvent_(
|
|
739
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
736
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_MUTED));
|
|
740
737
|
break;
|
|
741
738
|
case shaka.ads.MediaTailorAdManager.UNMUTE_:
|
|
742
739
|
this.onEvent_(
|
|
743
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
740
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_VOLUME_CHANGED));
|
|
744
741
|
break;
|
|
745
742
|
case shaka.ads.MediaTailorAdManager.RESUME_:
|
|
746
743
|
this.onEvent_(
|
|
747
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
744
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_RESUMED));
|
|
748
745
|
break;
|
|
749
746
|
case shaka.ads.MediaTailorAdManager.PAUSE_:
|
|
750
747
|
this.onEvent_(
|
|
751
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
748
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_PAUSED));
|
|
752
749
|
break;
|
|
753
750
|
case shaka.ads.MediaTailorAdManager.FIRSTQUARTILE_:
|
|
754
751
|
this.onEvent_(
|
|
755
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
752
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_FIRST_QUARTILE));
|
|
756
753
|
break;
|
|
757
754
|
case shaka.ads.MediaTailorAdManager.MIDPOINT_:
|
|
758
755
|
this.onEvent_(
|
|
759
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
756
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_MIDPOINT));
|
|
760
757
|
break;
|
|
761
758
|
case shaka.ads.MediaTailorAdManager.THIRDQUARTILE_:
|
|
762
759
|
this.onEvent_(
|
|
763
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
760
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_THIRD_QUARTILE));
|
|
764
761
|
break;
|
|
765
762
|
case shaka.ads.MediaTailorAdManager.COMPLETE_:
|
|
766
763
|
this.onEvent_(
|
|
767
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
764
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_COMPLETE));
|
|
768
765
|
this.onEvent_(
|
|
769
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
766
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_STOPPED));
|
|
770
767
|
break;
|
|
771
768
|
case shaka.ads.MediaTailorAdManager.SKIPPED_:
|
|
772
769
|
this.onEvent_(
|
|
773
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
770
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_SKIPPED));
|
|
774
771
|
this.onEvent_(
|
|
775
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
772
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_STOPPED));
|
|
776
773
|
break;
|
|
777
774
|
case shaka.ads.MediaTailorAdManager.BREAKSTART_:
|
|
778
775
|
this.adContainer_.setAttribute('ad-active', 'true');
|
|
@@ -783,7 +780,7 @@ shaka.ads.MediaTailorAdManager = class {
|
|
|
783
780
|
case shaka.ads.MediaTailorAdManager.SKIP_STATE_CHANGED_:
|
|
784
781
|
this.onEvent_(
|
|
785
782
|
new shaka.util.FakeEvent(
|
|
786
|
-
shaka.ads.
|
|
783
|
+
shaka.ads.Utils.AD_SKIP_STATE_CHANGED));
|
|
787
784
|
break;
|
|
788
785
|
}
|
|
789
786
|
}
|
|
@@ -4,14 +4,11 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @fileoverview
|
|
9
|
-
* @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed
|
|
10
|
-
*/
|
|
11
7
|
|
|
12
8
|
goog.provide('shaka.ads.ServerSideAdManager');
|
|
13
9
|
|
|
14
10
|
goog.require('goog.asserts');
|
|
11
|
+
goog.require('shaka.ads.Utils');
|
|
15
12
|
goog.require('shaka.ads.ServerSideAd');
|
|
16
13
|
goog.require('shaka.log');
|
|
17
14
|
goog.require('shaka.util.EventManager');
|
|
@@ -86,7 +83,7 @@ shaka.ads.ServerSideAdManager = class {
|
|
|
86
83
|
this.video_, this.adContainer_, uiSettings);
|
|
87
84
|
|
|
88
85
|
this.onEvent_(new shaka.util.FakeEvent(
|
|
89
|
-
shaka.ads.
|
|
86
|
+
shaka.ads.Utils.IMA_STREAM_MANAGER_LOADED,
|
|
90
87
|
(new Map()).set('imaStreamManager', this.streamManager_)));
|
|
91
88
|
|
|
92
89
|
// Events
|
|
@@ -130,30 +127,30 @@ shaka.ads.ServerSideAdManager = class {
|
|
|
130
127
|
google.ima.dai.api.StreamEvent.Type.FIRST_QUARTILE, () => {
|
|
131
128
|
shaka.log.info('Ad event: First Quartile');
|
|
132
129
|
this.onEvent_(
|
|
133
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
130
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_FIRST_QUARTILE));
|
|
134
131
|
});
|
|
135
132
|
|
|
136
133
|
this.eventManager_.listen(this.streamManager_,
|
|
137
134
|
google.ima.dai.api.StreamEvent.Type.MIDPOINT, () => {
|
|
138
135
|
shaka.log.info('Ad event: Midpoint');
|
|
139
136
|
this.onEvent_(
|
|
140
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
137
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_MIDPOINT));
|
|
141
138
|
});
|
|
142
139
|
|
|
143
140
|
this.eventManager_.listen(this.streamManager_,
|
|
144
141
|
google.ima.dai.api.StreamEvent.Type.THIRD_QUARTILE, () => {
|
|
145
142
|
shaka.log.info('Ad event: Third Quartile');
|
|
146
143
|
this.onEvent_(
|
|
147
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
144
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_THIRD_QUARTILE));
|
|
148
145
|
});
|
|
149
146
|
|
|
150
147
|
this.eventManager_.listen(this.streamManager_,
|
|
151
148
|
google.ima.dai.api.StreamEvent.Type.COMPLETE, () => {
|
|
152
149
|
shaka.log.info('Ad event: Complete');
|
|
153
150
|
this.onEvent_(
|
|
154
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
151
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_COMPLETE));
|
|
155
152
|
this.onEvent_(
|
|
156
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
153
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_STOPPED));
|
|
157
154
|
this.adContainer_.removeAttribute('ad-active');
|
|
158
155
|
this.ad_ = null;
|
|
159
156
|
});
|
|
@@ -162,9 +159,9 @@ shaka.ads.ServerSideAdManager = class {
|
|
|
162
159
|
google.ima.dai.api.StreamEvent.Type.SKIPPED, () => {
|
|
163
160
|
shaka.log.info('Ad event: Skipped');
|
|
164
161
|
this.onEvent_(
|
|
165
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
162
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_SKIPPED));
|
|
166
163
|
this.onEvent_(
|
|
167
|
-
new shaka.util.FakeEvent(shaka.ads.
|
|
164
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_STOPPED));
|
|
168
165
|
});
|
|
169
166
|
|
|
170
167
|
this.eventManager_.listen(this.streamManager_,
|
|
@@ -323,7 +320,7 @@ shaka.ads.ServerSideAdManager = class {
|
|
|
323
320
|
this.ad_.setProgressData(this.adProgressData_);
|
|
324
321
|
}
|
|
325
322
|
|
|
326
|
-
this.onEvent_(new shaka.util.FakeEvent(shaka.ads.
|
|
323
|
+
this.onEvent_(new shaka.util.FakeEvent(shaka.ads.Utils.AD_STARTED,
|
|
327
324
|
(new Map()).set('ad', this.ad_)));
|
|
328
325
|
this.adContainer_.setAttribute('ad-active', 'true');
|
|
329
326
|
}
|
|
@@ -350,7 +347,7 @@ shaka.ads.ServerSideAdManager = class {
|
|
|
350
347
|
onLoaded_(e) {
|
|
351
348
|
const now = Date.now() / 1000;
|
|
352
349
|
const loadTime = now - this.streamRequestStartTime_;
|
|
353
|
-
this.onEvent_(new shaka.util.FakeEvent(shaka.ads.
|
|
350
|
+
this.onEvent_(new shaka.util.FakeEvent(shaka.ads.Utils.ADS_LOADED,
|
|
354
351
|
(new Map()).set('loadTime', loadTime)));
|
|
355
352
|
|
|
356
353
|
const streamData = e.getStreamData();
|
|
@@ -418,7 +415,7 @@ shaka.ads.ServerSideAdManager = class {
|
|
|
418
415
|
this.currentCuePoints_ = cuePoints;
|
|
419
416
|
|
|
420
417
|
this.onEvent_(new shaka.util.FakeEvent(
|
|
421
|
-
shaka.ads.
|
|
418
|
+
shaka.ads.Utils.CUEPOINTS_CHANGED,
|
|
422
419
|
(new Map()).set('cuepoints', cuePoints)));
|
|
423
420
|
}
|
|
424
421
|
};
|
package/lib/cast/cast_utils.js
CHANGED
package/lib/cea/cea_utils.js
CHANGED
|
@@ -288,6 +288,18 @@ shaka.cea.CeaUtils.H265_PREFIX_NALU_TYPE_SEI = 0x27;
|
|
|
288
288
|
*/
|
|
289
289
|
shaka.cea.CeaUtils.H265_SUFFIX_NALU_TYPE_SEI = 0x28;
|
|
290
290
|
|
|
291
|
+
/**
|
|
292
|
+
* NALU type for Supplemental Enhancement Information (SEI) for H.266.
|
|
293
|
+
* @const {number}
|
|
294
|
+
*/
|
|
295
|
+
shaka.cea.CeaUtils.H266_PREFIX_NALU_TYPE_SEI = 0x17;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* NALU type for Supplemental Enhancement Information (SEI) for H.266.
|
|
299
|
+
* @const {number}
|
|
300
|
+
*/
|
|
301
|
+
shaka.cea.CeaUtils.H266_SUFFIX_NALU_TYPE_SEI = 0x18;
|
|
302
|
+
|
|
291
303
|
/**
|
|
292
304
|
* Default timescale value for a track.
|
|
293
305
|
* @const {number}
|
|
@@ -111,6 +111,8 @@ shaka.cea.Mp4CeaParser = class {
|
|
|
111
111
|
.box('dva1', codecBoxParser)
|
|
112
112
|
.box('dvh1', codecBoxParser)
|
|
113
113
|
.box('dvhe', codecBoxParser)
|
|
114
|
+
.box('vvc1', codecBoxParser)
|
|
115
|
+
.box('vvi1', codecBoxParser)
|
|
114
116
|
|
|
115
117
|
// This signals an encrypted sample, which we can go inside of to find
|
|
116
118
|
// the codec used.
|
|
@@ -323,6 +325,15 @@ shaka.cea.Mp4CeaParser = class {
|
|
|
323
325
|
naluType == CeaUtils.H265_SUFFIX_NALU_TYPE_SEI;
|
|
324
326
|
break;
|
|
325
327
|
|
|
328
|
+
case BitstreamFormat.H266:
|
|
329
|
+
naluHeaderSize = 2;
|
|
330
|
+
reader.skip(1);
|
|
331
|
+
naluType = (naluHeader >> 1) & 0x3f;
|
|
332
|
+
isSeiMessage =
|
|
333
|
+
naluType == CeaUtils.H266_PREFIX_NALU_TYPE_SEI ||
|
|
334
|
+
naluType == CeaUtils.H266_SUFFIX_NALU_TYPE_SEI;
|
|
335
|
+
break;
|
|
336
|
+
|
|
326
337
|
default:
|
|
327
338
|
return;
|
|
328
339
|
}
|
|
@@ -387,12 +398,15 @@ shaka.cea.Mp4CeaParser.BitstreamFormat = {
|
|
|
387
398
|
UNKNOWN: 0,
|
|
388
399
|
H264: 1,
|
|
389
400
|
H265: 2,
|
|
401
|
+
H266: 3,
|
|
390
402
|
};
|
|
391
403
|
|
|
392
404
|
/** @private {Object.<string, shaka.cea.Mp4CeaParser.BitstreamFormat>} */
|
|
393
405
|
shaka.cea.Mp4CeaParser.CodecBitstreamMap_ = {
|
|
406
|
+
// AVC
|
|
394
407
|
'avc1': shaka.cea.Mp4CeaParser.BitstreamFormat.H264,
|
|
395
408
|
'avc3': shaka.cea.Mp4CeaParser.BitstreamFormat.H264,
|
|
409
|
+
// HEVC
|
|
396
410
|
'hev1': shaka.cea.Mp4CeaParser.BitstreamFormat.H265,
|
|
397
411
|
'hvc1': shaka.cea.Mp4CeaParser.BitstreamFormat.H265,
|
|
398
412
|
// Dolby Vision based in AVC
|
|
@@ -401,6 +415,9 @@ shaka.cea.Mp4CeaParser.CodecBitstreamMap_ = {
|
|
|
401
415
|
// Dolby Vision based in HEVC
|
|
402
416
|
'dvh1': shaka.cea.Mp4CeaParser.BitstreamFormat.H265,
|
|
403
417
|
'dvhe': shaka.cea.Mp4CeaParser.BitstreamFormat.H265,
|
|
418
|
+
// VVC
|
|
419
|
+
'vvc1': shaka.cea.Mp4CeaParser.BitstreamFormat.H266,
|
|
420
|
+
'vvi1': shaka.cea.Mp4CeaParser.BitstreamFormat.H266,
|
|
404
421
|
};
|
|
405
422
|
|
|
406
423
|
/**
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -24,6 +24,7 @@ goog.require('shaka.net.NetworkingEngine');
|
|
|
24
24
|
goog.require('shaka.text.TextEngine');
|
|
25
25
|
goog.require('shaka.util.ContentSteeringManager');
|
|
26
26
|
goog.require('shaka.util.Error');
|
|
27
|
+
goog.require('shaka.util.EventManager');
|
|
27
28
|
goog.require('shaka.util.Functional');
|
|
28
29
|
goog.require('shaka.util.LanguageUtils');
|
|
29
30
|
goog.require('shaka.util.ManifestParserUtils');
|
|
@@ -122,6 +123,14 @@ shaka.dash.DashParser = class {
|
|
|
122
123
|
|
|
123
124
|
/** @private {shaka.util.Timer} */
|
|
124
125
|
this.updateTimer_ = new shaka.util.Timer(() => {
|
|
126
|
+
if (this.mediaElement_ && !this.config_.continueLoadingWhenPaused) {
|
|
127
|
+
this.eventManager_.unlisten(this.mediaElement_, 'timeupdate');
|
|
128
|
+
if (this.mediaElement_.paused) {
|
|
129
|
+
this.eventManager_.listenOnce(
|
|
130
|
+
this.mediaElement_, 'timeupdate', () => this.onUpdate_());
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
125
134
|
this.onUpdate_();
|
|
126
135
|
});
|
|
127
136
|
|
|
@@ -152,6 +161,18 @@ shaka.dash.DashParser = class {
|
|
|
152
161
|
|
|
153
162
|
/** @private {?shaka.util.ContentSteeringManager} */
|
|
154
163
|
this.contentSteeringManager_ = null;
|
|
164
|
+
|
|
165
|
+
/** @private {number} */
|
|
166
|
+
this.gapCount_ = 0;
|
|
167
|
+
|
|
168
|
+
/** @private {boolean} */
|
|
169
|
+
this.isLowLatency_ = false;
|
|
170
|
+
|
|
171
|
+
/** @private {shaka.util.EventManager} */
|
|
172
|
+
this.eventManager_ = new shaka.util.EventManager();
|
|
173
|
+
|
|
174
|
+
/** @private {HTMLMediaElement} */
|
|
175
|
+
this.mediaElement_ = null;
|
|
155
176
|
}
|
|
156
177
|
|
|
157
178
|
/**
|
|
@@ -253,6 +274,11 @@ shaka.dash.DashParser = class {
|
|
|
253
274
|
this.contentSteeringManager_.destroy();
|
|
254
275
|
}
|
|
255
276
|
|
|
277
|
+
if (this.eventManager_) {
|
|
278
|
+
this.eventManager_.release();
|
|
279
|
+
this.eventManager_ = null;
|
|
280
|
+
}
|
|
281
|
+
|
|
256
282
|
return this.operationManager_.destroy();
|
|
257
283
|
}
|
|
258
284
|
|
|
@@ -317,6 +343,14 @@ shaka.dash.DashParser = class {
|
|
|
317
343
|
}
|
|
318
344
|
}
|
|
319
345
|
|
|
346
|
+
/**
|
|
347
|
+
* @override
|
|
348
|
+
* @exportInterface
|
|
349
|
+
*/
|
|
350
|
+
setMediaElement(mediaElement) {
|
|
351
|
+
this.mediaElement_ = mediaElement;
|
|
352
|
+
}
|
|
353
|
+
|
|
320
354
|
/**
|
|
321
355
|
* Makes a network request for the manifest and parses the resulting data.
|
|
322
356
|
*
|
|
@@ -326,13 +360,14 @@ shaka.dash.DashParser = class {
|
|
|
326
360
|
*/
|
|
327
361
|
async requestManifest_() {
|
|
328
362
|
const requestType = shaka.net.NetworkingEngine.RequestType.MANIFEST;
|
|
329
|
-
|
|
363
|
+
let type = shaka.net.NetworkingEngine.AdvancedRequestType.MPD;
|
|
330
364
|
let rootElement = 'MPD';
|
|
331
365
|
const patchLocationUris = this.getPatchLocationUris_();
|
|
332
366
|
let manifestUris = this.manifestUris_;
|
|
333
367
|
if (patchLocationUris.length) {
|
|
334
368
|
manifestUris = patchLocationUris;
|
|
335
369
|
rootElement = 'Patch';
|
|
370
|
+
type = shaka.net.NetworkingEngine.AdvancedRequestType.MPD_PATCH;
|
|
336
371
|
} else if (this.manifestUris_.length > 1 && this.contentSteeringManager_) {
|
|
337
372
|
const locations = this.contentSteeringManager_.getLocations(
|
|
338
373
|
'Location', /* ignoreBaseUrls= */ true);
|
|
@@ -687,8 +722,10 @@ shaka.dash.DashParser = class {
|
|
|
687
722
|
availabilityTimeOffset: availabilityTimeOffset,
|
|
688
723
|
mediaPresentationDuration: null,
|
|
689
724
|
profiles: profiles.split(','),
|
|
725
|
+
roles: null,
|
|
690
726
|
};
|
|
691
727
|
|
|
728
|
+
this.gapCount_ = 0;
|
|
692
729
|
const periodsAndDuration = this.parsePeriods_(context, getBaseUris, mpd);
|
|
693
730
|
const duration = periodsAndDuration.duration;
|
|
694
731
|
const periods = periodsAndDuration.periods;
|
|
@@ -704,7 +741,7 @@ shaka.dash.DashParser = class {
|
|
|
704
741
|
// lowLatencyMode, but if it has been configured to activate the
|
|
705
742
|
// lowLatencyMode if a stream of this type is detected, we automatically
|
|
706
743
|
// activate the lowLatencyMode.
|
|
707
|
-
if (this.
|
|
744
|
+
if (this.isLowLatency_ && !this.lowLatencyMode_) {
|
|
708
745
|
const autoLowLatencyMode = this.playerInterface_.isAutoLowLatencyMode();
|
|
709
746
|
if (autoLowLatencyMode) {
|
|
710
747
|
this.playerInterface_.enableLowLatencyMode();
|
|
@@ -715,14 +752,6 @@ shaka.dash.DashParser = class {
|
|
|
715
752
|
if (this.lowLatencyMode_) {
|
|
716
753
|
presentationTimeline.setAvailabilityTimeOffset(
|
|
717
754
|
this.minTotalAvailabilityTimeOffset_);
|
|
718
|
-
} else if (this.minTotalAvailabilityTimeOffset_) {
|
|
719
|
-
// If the playlist contains AvailabilityTimeOffset value, the
|
|
720
|
-
// streaming.lowLatencyMode value should be set to true to stream with low
|
|
721
|
-
// latency mode.
|
|
722
|
-
shaka.log.alwaysWarn('Low-latency DASH live stream detected, but ' +
|
|
723
|
-
'low-latency streaming mode is not enabled in Shaka Player. ' +
|
|
724
|
-
'Set streaming.lowLatencyMode configuration to true, and see ' +
|
|
725
|
-
'https://bit.ly/3clctcj for details.');
|
|
726
755
|
}
|
|
727
756
|
|
|
728
757
|
// Use @maxSegmentDuration to override smaller, derived values.
|
|
@@ -758,6 +787,9 @@ shaka.dash.DashParser = class {
|
|
|
758
787
|
type: shaka.media.ManifestParser.DASH,
|
|
759
788
|
serviceDescription: this.parseServiceDescription_(mpd),
|
|
760
789
|
nextUrl: this.parseMpdChaining_(mpd),
|
|
790
|
+
periodCount: periods.length,
|
|
791
|
+
gapCount: this.gapCount_,
|
|
792
|
+
isLowLatency: this.isLowLatency_,
|
|
761
793
|
};
|
|
762
794
|
|
|
763
795
|
// We only need to do clock sync when we're using presentation start
|
|
@@ -778,8 +810,9 @@ shaka.dash.DashParser = class {
|
|
|
778
810
|
// maintain consistency from here on.
|
|
779
811
|
presentationTimeline.lockStartTime();
|
|
780
812
|
} else {
|
|
781
|
-
|
|
782
|
-
|
|
813
|
+
this.manifest_.periodCount = periods.length;
|
|
814
|
+
this.manifest_.gapCount = this.gapCount_;
|
|
815
|
+
await this.postPeriodProcessing_(periods, /* isPatchUpdate= */ false);
|
|
783
816
|
}
|
|
784
817
|
|
|
785
818
|
// Add text streams to correspond to closed captions. This happens right
|
|
@@ -900,6 +933,8 @@ shaka.dash.DashParser = class {
|
|
|
900
933
|
}
|
|
901
934
|
|
|
902
935
|
if (newPeriods.length) {
|
|
936
|
+
this.manifest_.periodCount += newPeriods.length;
|
|
937
|
+
this.manifest_.gapCount = this.gapCount_;
|
|
903
938
|
await this.postPeriodProcessing_(newPeriods, /* isPatchUpdate= */ true);
|
|
904
939
|
}
|
|
905
940
|
if (this.manifestPatchContext_.type == 'static') {
|
|
@@ -966,6 +1001,7 @@ shaka.dash.DashParser = class {
|
|
|
966
1001
|
profiles: this.manifestPatchContext_.profiles,
|
|
967
1002
|
mediaPresentationDuration:
|
|
968
1003
|
this.manifestPatchContext_.mediaPresentationDuration,
|
|
1004
|
+
roles: null,
|
|
969
1005
|
};
|
|
970
1006
|
|
|
971
1007
|
const periodsAndDuration = this.parsePeriods_(context,
|
|
@@ -980,6 +1016,7 @@ shaka.dash.DashParser = class {
|
|
|
980
1016
|
*/
|
|
981
1017
|
removePatchPeriod_(periodId) {
|
|
982
1018
|
const SegmentTemplate = shaka.dash.SegmentTemplate;
|
|
1019
|
+
this.manifest_.periodCount--;
|
|
983
1020
|
for (const contextId of this.contextCache_.keys()) {
|
|
984
1021
|
if (contextId.startsWith(periodId)) {
|
|
985
1022
|
const context = this.contextCache_.get(contextId);
|
|
@@ -1264,6 +1301,12 @@ shaka.dash.DashParser = class {
|
|
|
1264
1301
|
if (periodDuration && givenDuration &&
|
|
1265
1302
|
Math.abs(periodDuration - givenDuration) > threshold) {
|
|
1266
1303
|
shaka.log.warning('There is a gap/overlap between Periods', elem);
|
|
1304
|
+
|
|
1305
|
+
// This means it's a gap, the distance between period starts is
|
|
1306
|
+
// larger than the period's duration
|
|
1307
|
+
if (periodDuration > givenDuration) {
|
|
1308
|
+
this.gapCount_++;
|
|
1309
|
+
}
|
|
1267
1310
|
}
|
|
1268
1311
|
// Only use the @duration in the MPD if we can't calculate it. We should
|
|
1269
1312
|
// favor the @start of the following Period. This ensures that there
|
|
@@ -1773,19 +1816,7 @@ shaka.dash.DashParser = class {
|
|
|
1773
1816
|
const language = shaka.util.LanguageUtils.normalize(
|
|
1774
1817
|
context.adaptationSet.language || 'und');
|
|
1775
1818
|
|
|
1776
|
-
|
|
1777
|
-
let label = elem.attributes['label'];
|
|
1778
|
-
|
|
1779
|
-
// See DASH IOP 4.3 here https://dashif.org/docs/DASH-IF-IOP-v4.3.pdf (page 35)
|
|
1780
|
-
const labelElements = TXml.findChildren(elem, 'Label');
|
|
1781
|
-
if (labelElements && labelElements.length) {
|
|
1782
|
-
// NOTE: Right now only one label field is supported.
|
|
1783
|
-
const firstLabelElement = labelElements[0];
|
|
1784
|
-
const textContent = shaka.util.TXml.getTextContents(firstLabelElement);
|
|
1785
|
-
if (textContent) {
|
|
1786
|
-
label = textContent;
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1819
|
+
const label = context.adaptationSet.label;
|
|
1789
1820
|
|
|
1790
1821
|
// Parse Representations into Streams.
|
|
1791
1822
|
const representations = TXml.findChildren(elem, 'Representation');
|
|
@@ -1873,7 +1904,7 @@ shaka.dash.DashParser = class {
|
|
|
1873
1904
|
* @param {shaka.dash.ContentProtection.Context} contentProtection
|
|
1874
1905
|
* @param {(string|undefined)} kind
|
|
1875
1906
|
* @param {string} language
|
|
1876
|
-
* @param {string} label
|
|
1907
|
+
* @param {?string} label
|
|
1877
1908
|
* @param {boolean} isPrimary
|
|
1878
1909
|
* @param {!Array.<string>} roles
|
|
1879
1910
|
* @param {Map.<string, string>} closedCaptions
|
|
@@ -1901,6 +1932,8 @@ shaka.dash.DashParser = class {
|
|
|
1901
1932
|
Math.min(this.minTotalAvailabilityTimeOffset_,
|
|
1902
1933
|
context.representation.availabilityTimeOffset);
|
|
1903
1934
|
|
|
1935
|
+
this.isLowLatency_ = this.minTotalAvailabilityTimeOffset_ > 0;
|
|
1936
|
+
|
|
1904
1937
|
if (!this.verifyRepresentation_(context.representation)) {
|
|
1905
1938
|
shaka.log.warning('Skipping Representation', context.representation);
|
|
1906
1939
|
return null;
|
|
@@ -1915,6 +1948,8 @@ shaka.dash.DashParser = class {
|
|
|
1915
1948
|
context.bandwidth =
|
|
1916
1949
|
TXml.parseAttr(node, 'bandwidth', TXml.parsePositiveInt) || 0;
|
|
1917
1950
|
|
|
1951
|
+
context.roles = roles;
|
|
1952
|
+
|
|
1918
1953
|
/** @type {?shaka.dash.DashParser.StreamInfo} */
|
|
1919
1954
|
let streamInfo;
|
|
1920
1955
|
|
|
@@ -2408,6 +2443,19 @@ shaka.dash.DashParser = class {
|
|
|
2408
2443
|
}
|
|
2409
2444
|
}
|
|
2410
2445
|
|
|
2446
|
+
// This attribute is currently non-standard, but it is supported by Kaltura.
|
|
2447
|
+
let label = elem.attributes['label'];
|
|
2448
|
+
|
|
2449
|
+
// See DASH IOP 4.3 here https://dashif.org/docs/DASH-IF-IOP-v4.3.pdf (page 35)
|
|
2450
|
+
const labelElements = TXml.findChildren(elem, 'Label');
|
|
2451
|
+
if (labelElements && labelElements.length) {
|
|
2452
|
+
// NOTE: Right now only one label field is supported.
|
|
2453
|
+
const firstLabelElement = labelElements[0];
|
|
2454
|
+
if (TXml.getTextContents(firstLabelElement)) {
|
|
2455
|
+
label = TXml.getTextContents(firstLabelElement);
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2411
2459
|
return {
|
|
2412
2460
|
getBaseUris:
|
|
2413
2461
|
() => ManifestParserUtils.resolveUris(getBaseUris(), getFrameUris()),
|
|
@@ -2431,6 +2479,7 @@ shaka.dash.DashParser = class {
|
|
|
2431
2479
|
initialization: null,
|
|
2432
2480
|
segmentSequenceCadence:
|
|
2433
2481
|
segmentSequenceCadence || parent.segmentSequenceCadence,
|
|
2482
|
+
label: label || null,
|
|
2434
2483
|
};
|
|
2435
2484
|
}
|
|
2436
2485
|
|
|
@@ -2934,7 +2983,8 @@ shaka.dash.DashParser.RequestSegmentCallback;
|
|
|
2934
2983
|
* availabilityTimeOffset: number,
|
|
2935
2984
|
* initialization: ?string,
|
|
2936
2985
|
* aesKey: (shaka.extern.aesKey|undefined),
|
|
2937
|
-
* segmentSequenceCadence: number
|
|
2986
|
+
* segmentSequenceCadence: number,
|
|
2987
|
+
* label: ?string
|
|
2938
2988
|
* }}
|
|
2939
2989
|
*
|
|
2940
2990
|
* @description
|
|
@@ -2982,6 +3032,8 @@ shaka.dash.DashParser.RequestSegmentCallback;
|
|
|
2982
3032
|
* @property {number} segmentSequenceCadence
|
|
2983
3033
|
* Specifies the cadence of independent segments in Segment Sequence
|
|
2984
3034
|
* Representation.
|
|
3035
|
+
* @property {?string} label
|
|
3036
|
+
* Label or null if unknown.
|
|
2985
3037
|
*/
|
|
2986
3038
|
shaka.dash.DashParser.InheritanceFrame;
|
|
2987
3039
|
|
|
@@ -2998,7 +3050,8 @@ shaka.dash.DashParser.InheritanceFrame;
|
|
|
2998
3050
|
* indexRangeWarningGiven: boolean,
|
|
2999
3051
|
* availabilityTimeOffset: number,
|
|
3000
3052
|
* mediaPresentationDuration: ?number,
|
|
3001
|
-
* profiles: !Array.<string
|
|
3053
|
+
* profiles: !Array.<string>,
|
|
3054
|
+
* roles: ?Array.<string>
|
|
3002
3055
|
* }}
|
|
3003
3056
|
*
|
|
3004
3057
|
* @description
|
package/lib/dash/segment_base.js
CHANGED
|
@@ -386,6 +386,9 @@ shaka.dash.SegmentBase = class {
|
|
|
386
386
|
channelsCount: representation.numChannels,
|
|
387
387
|
pixelAspectRatio: representation.pixelAspectRatio || null,
|
|
388
388
|
width: representation.width || null,
|
|
389
|
+
label: context.adaptationSet.label || null,
|
|
390
|
+
roles: context.roles || null,
|
|
391
|
+
language: context.adaptationSet.language || null,
|
|
389
392
|
};
|
|
390
393
|
}
|
|
391
394
|
};
|