shaka-player 4.12.3 → 4.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deps.js +2 -2
- package/dist/locales.js +35 -35
- package/dist/shaka-player.compiled.debug.js +243 -241
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +1309 -1308
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.debug.js +327 -324
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +1516 -1514
- package/dist/shaka-player.ui.map +3 -3
- package/lib/ads/interstitial_ad.js +4 -2
- package/lib/ads/interstitial_ad_manager.js +15 -18
- package/lib/dash/dash_parser.js +3 -0
- package/lib/media/drm_engine.js +61 -23
- package/lib/media/manifest_filterer.js +2 -1
- package/lib/media/media_source_engine.js +23 -96
- package/lib/media/preload_manager.js +9 -3
- package/lib/media/streaming_engine.js +9 -1
- package/lib/offline/storage.js +1 -1
- package/lib/player.js +6 -13
- package/lib/util/functional.js +27 -0
- package/lib/util/mime_utils.js +3 -0
- package/lib/util/object_utils.js +83 -0
- package/lib/util/platform.js +48 -40
- package/lib/util/stream_utils.js +62 -71
- package/package.json +1 -1
- package/ui/ad_counter.js +5 -0
- package/ui/ad_position.js +2 -2
- package/ui/controls.js +5 -5
- package/ui/play_button.js +5 -3
- package/ui/presentation_time.js +1 -1
|
@@ -144,7 +144,7 @@ shaka.ads.InterstitialAd = class {
|
|
|
144
144
|
* @export
|
|
145
145
|
*/
|
|
146
146
|
canSkipNow() {
|
|
147
|
-
return this.getTimeUntilSkippable() == 0;
|
|
147
|
+
return this.isSkippable_ && this.getTimeUntilSkippable() == 0;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
/**
|
|
@@ -152,7 +152,9 @@ shaka.ads.InterstitialAd = class {
|
|
|
152
152
|
* @export
|
|
153
153
|
*/
|
|
154
154
|
skip() {
|
|
155
|
-
this.
|
|
155
|
+
if (this.canSkipNow()) {
|
|
156
|
+
this.onSkip_();
|
|
157
|
+
}
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
/**
|
|
@@ -704,7 +704,6 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
704
704
|
this.onEvent_(new shaka.util.FakeEvent(
|
|
705
705
|
shaka.ads.Utils.AD_SKIP_STATE_CHANGED));
|
|
706
706
|
}
|
|
707
|
-
const eventsSent = new Set();
|
|
708
707
|
this.adEventManager_.listenOnce(this.player_, 'error', error);
|
|
709
708
|
this.adEventManager_.listen(this.video_, 'timeupdate', () => {
|
|
710
709
|
const duration = this.video_.duration;
|
|
@@ -718,23 +717,21 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
718
717
|
new shaka.util.FakeEvent(shaka.ads.Utils.AD_SKIP_STATE_CHANGED));
|
|
719
718
|
}
|
|
720
719
|
prevCanSkipNow = currentCanSkipNow;
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
eventsSent.add('thirdquartile');
|
|
737
|
-
}
|
|
720
|
+
});
|
|
721
|
+
this.adEventManager_.listenOnce(this.player_, 'firstquartile', () => {
|
|
722
|
+
updateBaseVideoTime();
|
|
723
|
+
this.onEvent_(
|
|
724
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_FIRST_QUARTILE));
|
|
725
|
+
});
|
|
726
|
+
this.adEventManager_.listenOnce(this.player_, 'midpoint', () => {
|
|
727
|
+
updateBaseVideoTime();
|
|
728
|
+
this.onEvent_(
|
|
729
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_MIDPOINT));
|
|
730
|
+
});
|
|
731
|
+
this.adEventManager_.listenOnce(this.player_, 'thirdquartile', () => {
|
|
732
|
+
updateBaseVideoTime();
|
|
733
|
+
this.onEvent_(
|
|
734
|
+
new shaka.util.FakeEvent(shaka.ads.Utils.AD_THIRD_QUARTILE));
|
|
738
735
|
});
|
|
739
736
|
this.adEventManager_.listenOnce(this.player_, 'complete', complete);
|
|
740
737
|
this.adEventManager_.listen(this.video_, 'play', () => {
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -1505,6 +1505,9 @@ shaka.dash.DashParser = class {
|
|
|
1505
1505
|
let shouldDeleteIndex = true;
|
|
1506
1506
|
for (const contextId of this.indexStreamMap_[pId]) {
|
|
1507
1507
|
const stream = this.streamMap_[contextId];
|
|
1508
|
+
if (!stream) {
|
|
1509
|
+
continue;
|
|
1510
|
+
}
|
|
1508
1511
|
if (stream.segmentIndex && !stream.segmentIndex.isEmpty()) {
|
|
1509
1512
|
shouldDeleteIndex = false;
|
|
1510
1513
|
continue;
|
package/lib/media/drm_engine.js
CHANGED
|
@@ -9,12 +9,14 @@ goog.provide('shaka.media.DrmEngine');
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.log');
|
|
11
11
|
goog.require('shaka.net.NetworkingEngine');
|
|
12
|
+
goog.require('shaka.util.ArrayUtils');
|
|
12
13
|
goog.require('shaka.util.BufferUtils');
|
|
13
14
|
goog.require('shaka.util.Destroyer');
|
|
14
15
|
goog.require('shaka.util.DrmUtils');
|
|
15
16
|
goog.require('shaka.util.Error');
|
|
16
17
|
goog.require('shaka.util.EventManager');
|
|
17
18
|
goog.require('shaka.util.FakeEvent');
|
|
19
|
+
goog.require('shaka.util.Functional');
|
|
18
20
|
goog.require('shaka.util.IDestroyable');
|
|
19
21
|
goog.require('shaka.util.Iterables');
|
|
20
22
|
goog.require('shaka.util.ManifestParserUtils');
|
|
@@ -66,12 +68,18 @@ shaka.media.DrmEngine = class {
|
|
|
66
68
|
*/
|
|
67
69
|
this.activeSessions_ = new Map();
|
|
68
70
|
|
|
71
|
+
/** @private {!Array.<!shaka.net.NetworkingEngine.PendingRequest>} */
|
|
72
|
+
this.activeRequests_ = [];
|
|
73
|
+
|
|
69
74
|
/**
|
|
70
75
|
* @private {!Map<string,
|
|
71
76
|
* {initData: ?Uint8Array, initDataType: ?string}>}
|
|
72
77
|
*/
|
|
73
78
|
this.storedPersistentSessions_ = new Map();
|
|
74
79
|
|
|
80
|
+
/** @private {boolean} */
|
|
81
|
+
this.hasInitData_ = false;
|
|
82
|
+
|
|
75
83
|
/** @private {!shaka.util.PublicPromise} */
|
|
76
84
|
this.allSessionsLoaded_ = new shaka.util.PublicPromise();
|
|
77
85
|
|
|
@@ -705,6 +713,7 @@ shaka.media.DrmEngine = class {
|
|
|
705
713
|
|
|
706
714
|
// Reset the promise for the next sessions to come if key needs aren't
|
|
707
715
|
// satisfied with persistent sessions
|
|
716
|
+
this.hasInitData_ = false;
|
|
708
717
|
this.allSessionsLoaded_ = new shaka.util.PublicPromise();
|
|
709
718
|
this.allSessionsLoaded_.catch(() => {});
|
|
710
719
|
}
|
|
@@ -766,11 +775,16 @@ shaka.media.DrmEngine = class {
|
|
|
766
775
|
}
|
|
767
776
|
}
|
|
768
777
|
|
|
778
|
+
// Mark that there is init data, so that the preloader will know to wait
|
|
779
|
+
// for sessions to be loaded.
|
|
780
|
+
this.hasInitData_ = true;
|
|
781
|
+
|
|
769
782
|
// If there are pre-existing sessions that have all been loaded
|
|
770
783
|
// then reset the allSessionsLoaded_ promise, which can now be
|
|
771
784
|
// used to wait for new sesssions to be loaded
|
|
772
785
|
if (this.activeSessions_.size > 0 && this.areAllSessionsLoaded_()) {
|
|
773
786
|
this.allSessionsLoaded_.resolve();
|
|
787
|
+
this.hasInitData_ = false;
|
|
774
788
|
this.allSessionsLoaded_ = new shaka.util.PublicPromise();
|
|
775
789
|
this.allSessionsLoaded_.catch(() => {});
|
|
776
790
|
}
|
|
@@ -914,14 +928,16 @@ shaka.media.DrmEngine = class {
|
|
|
914
928
|
'Got MediaKeySystemAccess with configuration',
|
|
915
929
|
realConfig);
|
|
916
930
|
|
|
931
|
+
const keySystem =
|
|
932
|
+
this.config_.keySystemsMapping[mediaKeySystemAccess.keySystem] ||
|
|
933
|
+
mediaKeySystemAccess.keySystem;
|
|
934
|
+
|
|
917
935
|
if (variants.length) {
|
|
918
936
|
this.currentDrmInfo_ = this.createDrmInfoByInfos_(
|
|
919
|
-
|
|
920
|
-
drmInfosByKeySystem.get(mediaKeySystemAccess.keySystem));
|
|
937
|
+
keySystem, drmInfosByKeySystem.get(keySystem));
|
|
921
938
|
} else {
|
|
922
939
|
this.currentDrmInfo_ = shaka.media.DrmEngine.createDrmInfoByConfigs_(
|
|
923
|
-
|
|
924
|
-
configsByKeySystem.get(mediaKeySystemAccess.keySystem));
|
|
940
|
+
keySystem, configsByKeySystem.get(keySystem));
|
|
925
941
|
}
|
|
926
942
|
if (!this.currentDrmInfo_.licenseServerUri) {
|
|
927
943
|
throw new shaka.util.Error(
|
|
@@ -1036,8 +1052,12 @@ shaka.media.DrmEngine = class {
|
|
|
1036
1052
|
if (!decodingInfo.supported || !decodingInfo.keySystemAccess) {
|
|
1037
1053
|
continue;
|
|
1038
1054
|
}
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1055
|
+
const originalKeySystem = decodingInfo.keySystemAccess.keySystem;
|
|
1056
|
+
let drmInfos = drmInfosByKeySystem.get(originalKeySystem);
|
|
1057
|
+
if (!drmInfos && this.config_.keySystemsMapping[originalKeySystem]) {
|
|
1058
|
+
drmInfos = drmInfosByKeySystem.get(
|
|
1059
|
+
this.config_.keySystemsMapping[originalKeySystem]);
|
|
1060
|
+
}
|
|
1041
1061
|
for (const info of drmInfos) {
|
|
1042
1062
|
if (!!info.licenseServerUri == shouldHaveLicenseServer) {
|
|
1043
1063
|
return decodingInfo.keySystemAccess;
|
|
@@ -1380,6 +1400,14 @@ shaka.media.DrmEngine = class {
|
|
|
1380
1400
|
this.video_.paused && !this.initialRequestsSent_);
|
|
1381
1401
|
}
|
|
1382
1402
|
|
|
1403
|
+
/** @return {!Promise} */
|
|
1404
|
+
async waitForActiveRequests() {
|
|
1405
|
+
if (this.hasInitData_) {
|
|
1406
|
+
await this.allSessionsLoaded_;
|
|
1407
|
+
await Promise.all(this.activeRequests_.map((req) => req.promise));
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1383
1411
|
/**
|
|
1384
1412
|
* Sends a license request.
|
|
1385
1413
|
* @param {!MediaKeyMessageEvent} event
|
|
@@ -1439,7 +1467,9 @@ shaka.media.DrmEngine = class {
|
|
|
1439
1467
|
try {
|
|
1440
1468
|
const req = this.playerInterface_.netEngine.request(
|
|
1441
1469
|
requestType, request, {isPreload: this.isPreload_()});
|
|
1470
|
+
this.activeRequests_.push(req);
|
|
1442
1471
|
response = await req.promise;
|
|
1472
|
+
shaka.util.ArrayUtils.remove(this.activeRequests_, req);
|
|
1443
1473
|
} catch (error) {
|
|
1444
1474
|
if (this.destroyer_.destroyed()) {
|
|
1445
1475
|
return;
|
|
@@ -1859,9 +1889,16 @@ shaka.media.DrmEngine = class {
|
|
|
1859
1889
|
offlineConfig.sessionTypes = ['persistent-license'];
|
|
1860
1890
|
|
|
1861
1891
|
const configs = [offlineConfig, basicConfig];
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1892
|
+
// On some (Android) WebView environments,
|
|
1893
|
+
// requestMediaKeySystemAccess will
|
|
1894
|
+
// not resolve or reject, at least if RESOURCE_PROTECTED_MEDIA_ID
|
|
1895
|
+
// is not set. This is a workaround for that issue.
|
|
1896
|
+
const TIMEOUT_FOR_CHECKACCESS_IN_SECONDS = 1;
|
|
1897
|
+
const access =
|
|
1898
|
+
await shaka.util.Functional.promiseWithTimeout(
|
|
1899
|
+
TIMEOUT_FOR_CHECKACCESS_IN_SECONDS,
|
|
1900
|
+
navigator.requestMediaKeySystemAccess(keySystem, configs),
|
|
1901
|
+
);
|
|
1865
1902
|
await processMediaKeySystemAccess(keySystem, access);
|
|
1866
1903
|
} catch (error) {} // Ignore errors.
|
|
1867
1904
|
};
|
|
@@ -1896,13 +1933,22 @@ shaka.media.DrmEngine = class {
|
|
|
1896
1933
|
},
|
|
1897
1934
|
},
|
|
1898
1935
|
};
|
|
1899
|
-
|
|
1936
|
+
// On some (Android) WebView environments, decodingInfo will
|
|
1937
|
+
// not resolve or reject, at least if RESOURCE_PROTECTED_MEDIA_ID
|
|
1938
|
+
// is not set. This is a workaround for that issue.
|
|
1939
|
+
const TIMEOUT_FOR_DECODING_INFO_IN_SECONDS = 1;
|
|
1900
1940
|
const decodingInfo =
|
|
1901
|
-
|
|
1941
|
+
await shaka.util.Functional.promiseWithTimeout(
|
|
1942
|
+
TIMEOUT_FOR_DECODING_INFO_IN_SECONDS,
|
|
1943
|
+
navigator.mediaCapabilities.decodingInfo(decodingConfig),
|
|
1944
|
+
);
|
|
1902
1945
|
|
|
1903
1946
|
const access = decodingInfo.keySystemAccess;
|
|
1904
1947
|
await processMediaKeySystemAccess(keySystem, access);
|
|
1905
|
-
} catch (error) {
|
|
1948
|
+
} catch (error) {
|
|
1949
|
+
// Ignore errors.
|
|
1950
|
+
shaka.log.v2('Failed to probe support for', keySystem, error);
|
|
1951
|
+
}
|
|
1906
1952
|
};
|
|
1907
1953
|
|
|
1908
1954
|
// Initialize the support structure for each key system.
|
|
@@ -1961,18 +2007,10 @@ shaka.media.DrmEngine = class {
|
|
|
1961
2007
|
* @private
|
|
1962
2008
|
*/
|
|
1963
2009
|
async closeSession_(session) {
|
|
1964
|
-
const DrmEngine = shaka.media.DrmEngine;
|
|
1965
|
-
|
|
1966
|
-
const timeout = new Promise((resolve, reject) => {
|
|
1967
|
-
const timer = new shaka.util.Timer(reject);
|
|
1968
|
-
timer.tickAfter(DrmEngine.CLOSE_TIMEOUT_);
|
|
1969
|
-
});
|
|
1970
|
-
|
|
1971
2010
|
try {
|
|
1972
|
-
await
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
]);
|
|
2011
|
+
await shaka.util.Functional.promiseWithTimeout(
|
|
2012
|
+
shaka.media.DrmEngine.CLOSE_TIMEOUT_,
|
|
2013
|
+
Promise.all([session.close(), session.closed]));
|
|
1976
2014
|
} catch (e) {
|
|
1977
2015
|
shaka.log.warning('Timeout waiting for session close');
|
|
1978
2016
|
}
|
|
@@ -50,7 +50,8 @@ shaka.media.ManifestFilterer = class {
|
|
|
50
50
|
async filterManifest(manifest) {
|
|
51
51
|
goog.asserts.assert(manifest, 'Manifest should exist!');
|
|
52
52
|
await shaka.util.StreamUtils.filterManifest(this.drmEngine_, manifest,
|
|
53
|
-
this.config_.drm.preferredKeySystems
|
|
53
|
+
this.config_.drm.preferredKeySystems,
|
|
54
|
+
this.config_.drm.keySystemsMapping);
|
|
54
55
|
if (!this.config_.streaming.dontChooseCodecs) {
|
|
55
56
|
shaka.util.StreamUtils.chooseCodecsAndFilterManifest(
|
|
56
57
|
manifest,
|
|
@@ -466,12 +466,12 @@ shaka.media.MediaSourceEngine = class {
|
|
|
466
466
|
cleanup.push(this.textEngine_.destroy());
|
|
467
467
|
}
|
|
468
468
|
|
|
469
|
+
await Promise.all(cleanup);
|
|
470
|
+
|
|
469
471
|
for (const contentType in this.transmuxers_) {
|
|
470
|
-
|
|
472
|
+
this.transmuxers_[contentType].destroy();
|
|
471
473
|
}
|
|
472
474
|
|
|
473
|
-
|
|
474
|
-
await Promise.all(cleanup);
|
|
475
475
|
if (this.eventManager_) {
|
|
476
476
|
this.eventManager_.release();
|
|
477
477
|
this.eventManager_ = null;
|
|
@@ -692,7 +692,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
692
692
|
* @return {boolean}
|
|
693
693
|
*/
|
|
694
694
|
isStreamingAllowed() {
|
|
695
|
-
return this.streamingAllowed_ && !this.usingRemotePlayback_
|
|
695
|
+
return this.streamingAllowed_ && !this.usingRemotePlayback_ &&
|
|
696
|
+
!this.reloadingMediaSource_;
|
|
696
697
|
}
|
|
697
698
|
|
|
698
699
|
/**
|
|
@@ -1859,11 +1860,13 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1859
1860
|
|
|
1860
1861
|
/** @type {!Array.<!shaka.util.PublicPromise>} */
|
|
1861
1862
|
const allWaiters = [];
|
|
1863
|
+
/** @type {!Array.<!shaka.util.ManifestParserUtils.ContentType>} */
|
|
1864
|
+
const contentTypes = Object.keys(this.sourceBuffers_);
|
|
1862
1865
|
|
|
1863
1866
|
// Enqueue a 'wait' operation onto each queue.
|
|
1864
1867
|
// This operation signals its readiness when it starts.
|
|
1865
1868
|
// When all wait operations are ready, the real operation takes place.
|
|
1866
|
-
for (const contentType
|
|
1869
|
+
for (const contentType of contentTypes) {
|
|
1867
1870
|
const ready = new shaka.util.PublicPromise();
|
|
1868
1871
|
const operation = {
|
|
1869
1872
|
start: () => ready.resolve(),
|
|
@@ -1893,7 +1896,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1893
1896
|
// assert at the end of destroy passes. In compiled mode, the queues
|
|
1894
1897
|
// are wiped in destroy.
|
|
1895
1898
|
if (goog.DEBUG) {
|
|
1896
|
-
for (const contentType
|
|
1899
|
+
for (const contentType of contentTypes) {
|
|
1897
1900
|
if (this.queues_[contentType].length) {
|
|
1898
1901
|
goog.asserts.assert(
|
|
1899
1902
|
this.queues_[contentType].length == 1,
|
|
@@ -1910,7 +1913,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1910
1913
|
|
|
1911
1914
|
if (goog.DEBUG) {
|
|
1912
1915
|
// If we did it correctly, nothing is updating.
|
|
1913
|
-
for (const contentType
|
|
1916
|
+
for (const contentType of contentTypes) {
|
|
1914
1917
|
goog.asserts.assert(
|
|
1915
1918
|
this.sourceBuffers_[contentType].updating == false,
|
|
1916
1919
|
'SourceBuffers should not be updating after a blocking op!');
|
|
@@ -1930,7 +1933,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1930
1933
|
null);
|
|
1931
1934
|
} finally {
|
|
1932
1935
|
// Unblock the queues.
|
|
1933
|
-
for (const contentType
|
|
1936
|
+
for (const contentType of contentTypes) {
|
|
1934
1937
|
this.popFromQueue_(contentType);
|
|
1935
1938
|
}
|
|
1936
1939
|
}
|
|
@@ -1942,6 +1945,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1942
1945
|
* @private
|
|
1943
1946
|
*/
|
|
1944
1947
|
popFromQueue_(contentType) {
|
|
1948
|
+
goog.asserts.assert(this.queues_[contentType], 'Queue should exist');
|
|
1945
1949
|
// Remove the in-progress operation, which is now complete.
|
|
1946
1950
|
this.queues_[contentType].shift();
|
|
1947
1951
|
this.startOperation_(contentType);
|
|
@@ -2099,48 +2103,6 @@ shaka.media.MediaSourceEngine = class {
|
|
|
2099
2103
|
null);
|
|
2100
2104
|
}
|
|
2101
2105
|
|
|
2102
|
-
/**
|
|
2103
|
-
* Returns the source buffer parameters
|
|
2104
|
-
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
2105
|
-
* @return {?shaka.media.MediaSourceEngine.SourceBufferParams}
|
|
2106
|
-
* @private
|
|
2107
|
-
*/
|
|
2108
|
-
getSourceBufferParams_(contentType) {
|
|
2109
|
-
if (!this.sourceBuffers_[contentType]) {
|
|
2110
|
-
return null;
|
|
2111
|
-
}
|
|
2112
|
-
return {
|
|
2113
|
-
timestampOffset: this.sourceBuffers_[contentType].timestampOffset,
|
|
2114
|
-
appendWindowStart: this.sourceBuffers_[contentType].appendWindowStart,
|
|
2115
|
-
appendWindowEnd: this.sourceBuffers_[contentType].appendWindowEnd,
|
|
2116
|
-
};
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
/**
|
|
2120
|
-
* Restore source buffer parameters
|
|
2121
|
-
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
2122
|
-
* @param {?shaka.media.MediaSourceEngine.SourceBufferParams} params
|
|
2123
|
-
* @private
|
|
2124
|
-
*/
|
|
2125
|
-
restoreSourceBufferParams_(contentType, params) {
|
|
2126
|
-
if (!params) {
|
|
2127
|
-
return;
|
|
2128
|
-
}
|
|
2129
|
-
|
|
2130
|
-
if (!this.sourceBuffers_[contentType]) {
|
|
2131
|
-
shaka.log.warning('Attempted to restore a non-existent source buffer');
|
|
2132
|
-
return;
|
|
2133
|
-
}
|
|
2134
|
-
|
|
2135
|
-
this.sourceBuffers_[contentType].timestampOffset =
|
|
2136
|
-
params.timestampOffset;
|
|
2137
|
-
// `end` needs to be set before `start`
|
|
2138
|
-
this.sourceBuffers_[contentType].appendWindowEnd =
|
|
2139
|
-
params.appendWindowEnd;
|
|
2140
|
-
this.sourceBuffers_[contentType].appendWindowStart =
|
|
2141
|
-
params.appendWindowStart;
|
|
2142
|
-
}
|
|
2143
|
-
|
|
2144
2106
|
/**
|
|
2145
2107
|
* Resets the MediaSource and re-adds source buffers due to codec mismatch
|
|
2146
2108
|
*
|
|
@@ -2149,7 +2111,6 @@ shaka.media.MediaSourceEngine = class {
|
|
|
2149
2111
|
* @private
|
|
2150
2112
|
*/
|
|
2151
2113
|
async reset_(streamsByType) {
|
|
2152
|
-
const Functional = shaka.util.Functional;
|
|
2153
2114
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
2154
2115
|
this.reloadingMediaSource_ = true;
|
|
2155
2116
|
this.needSplitMuxedContent_ = false;
|
|
@@ -2171,36 +2132,19 @@ shaka.media.MediaSourceEngine = class {
|
|
|
2171
2132
|
try {
|
|
2172
2133
|
this.eventManager_.removeAll();
|
|
2173
2134
|
|
|
2174
|
-
const cleanup = [];
|
|
2175
2135
|
for (const contentType in this.transmuxers_) {
|
|
2176
|
-
|
|
2177
|
-
}
|
|
2178
|
-
for (const contentType in this.queues_) {
|
|
2179
|
-
// Make a local copy of the queue and the first item.
|
|
2180
|
-
const q = this.queues_[contentType];
|
|
2181
|
-
const inProgress = q[0];
|
|
2182
|
-
|
|
2183
|
-
// Drop everything else out of the original queue.
|
|
2184
|
-
this.queues_[contentType] = q.slice(0, 1);
|
|
2185
|
-
|
|
2186
|
-
// We will wait for this item to complete/fail.
|
|
2187
|
-
if (inProgress) {
|
|
2188
|
-
cleanup.push(inProgress.p.catch(Functional.noop));
|
|
2189
|
-
}
|
|
2190
|
-
|
|
2191
|
-
// The rest will be rejected silently if possible.
|
|
2192
|
-
for (const item of q.slice(1)) {
|
|
2193
|
-
item.p.reject(shaka.util.Destroyer.destroyedError());
|
|
2194
|
-
}
|
|
2136
|
+
this.transmuxers_[contentType].destroy();
|
|
2195
2137
|
}
|
|
2196
2138
|
for (const contentType in this.sourceBuffers_) {
|
|
2197
2139
|
const sourceBuffer = this.sourceBuffers_[contentType];
|
|
2198
2140
|
try {
|
|
2199
2141
|
this.mediaSource_.removeSourceBuffer(sourceBuffer);
|
|
2200
|
-
} catch (e) {
|
|
2142
|
+
} catch (e) {
|
|
2143
|
+
shaka.log.debug('Exception on removeSourceBuffer', e);
|
|
2144
|
+
}
|
|
2201
2145
|
}
|
|
2202
|
-
await Promise.all(cleanup);
|
|
2203
2146
|
this.transmuxers_ = {};
|
|
2147
|
+
this.sourceBuffers_ = {};
|
|
2204
2148
|
|
|
2205
2149
|
const previousDuration = this.mediaSource_.duration;
|
|
2206
2150
|
this.mediaSourceOpen_ = new shaka.util.PublicPromise();
|
|
@@ -2231,23 +2175,17 @@ shaka.media.MediaSourceEngine = class {
|
|
|
2231
2175
|
onSourceBufferAdded);
|
|
2232
2176
|
|
|
2233
2177
|
for (const contentType of streamsByType.keys()) {
|
|
2234
|
-
const previousParams = this.getSourceBufferParams_(contentType);
|
|
2235
2178
|
const stream = streamsByType.get(contentType);
|
|
2236
2179
|
// eslint-disable-next-line no-await-in-loop
|
|
2237
2180
|
await this.initSourceBuffer_(contentType, stream, stream.codecs);
|
|
2238
|
-
if (this.needSplitMuxedContent_) {
|
|
2239
|
-
this.queues_[ContentType.AUDIO] = [];
|
|
2240
|
-
this.queues_[ContentType.VIDEO] = [];
|
|
2241
|
-
} else {
|
|
2242
|
-
this.queues_[contentType] = [];
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
|
-
this.restoreSourceBufferParams_(contentType, previousParams);
|
|
2246
2181
|
}
|
|
2247
2182
|
const audio = streamsByType.get(ContentType.AUDIO);
|
|
2248
2183
|
if (audio && audio.isAudioMuxedInVideo) {
|
|
2249
2184
|
this.needSplitMuxedContent_ = true;
|
|
2250
2185
|
}
|
|
2186
|
+
if (this.needSplitMuxedContent_ && !this.queues_[ContentType.AUDIO]) {
|
|
2187
|
+
this.queues_[ContentType.AUDIO] = [];
|
|
2188
|
+
}
|
|
2251
2189
|
|
|
2252
2190
|
// Fake a seek to catchup the playhead.
|
|
2253
2191
|
this.video_.currentTime = currentTime;
|
|
@@ -2393,13 +2331,12 @@ shaka.media.MediaSourceEngine = class {
|
|
|
2393
2331
|
* Returns true if it's necessary codec switch to load the new stream.
|
|
2394
2332
|
*
|
|
2395
2333
|
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
2396
|
-
* @param {shaka.extern.Stream} stream
|
|
2397
2334
|
* @param {string} refMimeType
|
|
2398
2335
|
* @param {string} refCodecs
|
|
2399
2336
|
* @return {boolean}
|
|
2400
2337
|
* @private
|
|
2401
2338
|
*/
|
|
2402
|
-
isCodecSwitchNecessary_(contentType,
|
|
2339
|
+
isCodecSwitchNecessary_(contentType, refMimeType, refCodecs) {
|
|
2403
2340
|
if (contentType == shaka.util.ManifestParserUtils.ContentType.TEXT) {
|
|
2404
2341
|
return false;
|
|
2405
2342
|
}
|
|
@@ -2443,13 +2380,12 @@ shaka.media.MediaSourceEngine = class {
|
|
|
2443
2380
|
* new stream.
|
|
2444
2381
|
*
|
|
2445
2382
|
* @param {shaka.util.ManifestParserUtils.ContentType} contentType
|
|
2446
|
-
* @param {shaka.extern.Stream} stream
|
|
2447
2383
|
* @param {string} mimeType
|
|
2448
2384
|
* @param {string} codecs
|
|
2449
2385
|
* @return {boolean}
|
|
2450
2386
|
*/
|
|
2451
|
-
isResetMediaSourceNecessary(contentType,
|
|
2452
|
-
if (!this.isCodecSwitchNecessary_(contentType,
|
|
2387
|
+
isResetMediaSourceNecessary(contentType, mimeType, codecs) {
|
|
2388
|
+
if (!this.isCodecSwitchNecessary_(contentType, mimeType, codecs)) {
|
|
2453
2389
|
return false;
|
|
2454
2390
|
}
|
|
2455
2391
|
|
|
@@ -2540,12 +2476,3 @@ shaka.media.MediaSourceEngine.SourceBufferMode_ = {
|
|
|
2540
2476
|
* Called when an embedded 'emsg' box should trigger a manifest update.
|
|
2541
2477
|
*/
|
|
2542
2478
|
shaka.media.MediaSourceEngine.PlayerInterface;
|
|
2543
|
-
|
|
2544
|
-
/**
|
|
2545
|
-
* @typedef {{
|
|
2546
|
-
* timestampOffset: number,
|
|
2547
|
-
* appendWindowStart: number,
|
|
2548
|
-
* appendWindowEnd: number
|
|
2549
|
-
* }}
|
|
2550
|
-
*/
|
|
2551
|
-
shaka.media.MediaSourceEngine.SourceBufferParams;
|
|
@@ -398,7 +398,13 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
|
|
|
398
398
|
await this.initializeDrmInner_();
|
|
399
399
|
this.throwIfDestroyed_();
|
|
400
400
|
|
|
401
|
-
await this.
|
|
401
|
+
await this.chooseInitialVariantAndPrefetchInner_();
|
|
402
|
+
this.throwIfDestroyed_();
|
|
403
|
+
|
|
404
|
+
// We don't need the drm keys to load completely for the initial variant
|
|
405
|
+
// to be chosen, but we won't mark the load as a success until it has
|
|
406
|
+
// been loaded. So wait for it here, not inside initializeDrmInner_.
|
|
407
|
+
await this.drmEngine_.waitForActiveRequests();
|
|
402
408
|
this.throwIfDestroyed_();
|
|
403
409
|
|
|
404
410
|
this.successPromise_.resolve();
|
|
@@ -610,12 +616,12 @@ shaka.media.PreloadManager = class extends shaka.util.FakeEventTarget {
|
|
|
610
616
|
|
|
611
617
|
/**
|
|
612
618
|
* Performs a final filtering of the manifest, and chooses the initial
|
|
613
|
-
* variant.
|
|
619
|
+
* variant. Also prefetches segments.
|
|
614
620
|
*
|
|
615
621
|
* @return {!Promise}
|
|
616
622
|
* @private
|
|
617
623
|
*/
|
|
618
|
-
async
|
|
624
|
+
async chooseInitialVariantAndPrefetchInner_() {
|
|
619
625
|
goog.asserts.assert(
|
|
620
626
|
this.manifest_, 'The manifest should already be parsed.');
|
|
621
627
|
|
|
@@ -2011,7 +2011,7 @@ shaka.media.StreamingEngine = class {
|
|
|
2011
2011
|
const isResetMediaSourceNecessary =
|
|
2012
2012
|
mediaState.lastCodecs && mediaState.lastMimeType &&
|
|
2013
2013
|
this.playerInterface_.mediaSourceEngine.isResetMediaSourceNecessary(
|
|
2014
|
-
mediaState.type,
|
|
2014
|
+
mediaState.type, mimeType, fullCodecs);
|
|
2015
2015
|
if (isResetMediaSourceNecessary) {
|
|
2016
2016
|
let otherState = null;
|
|
2017
2017
|
if (mediaState.type === ContentType.VIDEO) {
|
|
@@ -2025,6 +2025,10 @@ shaka.media.StreamingEngine = class {
|
|
|
2025
2025
|
// Then clear our cache of the last init segment, since MSE will be
|
|
2026
2026
|
// reloaded and no init segment will be there post-reload.
|
|
2027
2027
|
otherState.lastInitSegmentReference = null;
|
|
2028
|
+
// Clear cache of append window start and end, since they will need
|
|
2029
|
+
// to be reapplied post-reload by streaming engine.
|
|
2030
|
+
otherState.lastAppendWindowStart = null;
|
|
2031
|
+
otherState.lastAppendWindowEnd = null;
|
|
2028
2032
|
// Now force the existing buffer to be cleared. It is not necessary
|
|
2029
2033
|
// to perform the MSE clear operation, but this has the side-effect
|
|
2030
2034
|
// that our state for that stream will then match MSE's post-reload
|
|
@@ -2729,6 +2733,8 @@ shaka.media.StreamingEngine = class {
|
|
|
2729
2733
|
const audioMediaState = this.mediaStates_.get(ContentType.AUDIO);
|
|
2730
2734
|
if (audioMediaState) {
|
|
2731
2735
|
audioMediaState.lastInitSegmentReference = null;
|
|
2736
|
+
audioMediaState.lastAppendWindowStart = null;
|
|
2737
|
+
audioMediaState.lastAppendWindowEnd = null;
|
|
2732
2738
|
if (clearBuffer) {
|
|
2733
2739
|
this.forceClearBuffer_(audioMediaState);
|
|
2734
2740
|
}
|
|
@@ -2740,6 +2746,8 @@ shaka.media.StreamingEngine = class {
|
|
|
2740
2746
|
const videoMediaState = this.mediaStates_.get(ContentType.VIDEO);
|
|
2741
2747
|
if (videoMediaState) {
|
|
2742
2748
|
videoMediaState.lastInitSegmentReference = null;
|
|
2749
|
+
videoMediaState.lastAppendWindowStart = null;
|
|
2750
|
+
videoMediaState.lastAppendWindowEnd = null;
|
|
2743
2751
|
if (clearBuffer) {
|
|
2744
2752
|
this.forceClearBuffer_(videoMediaState);
|
|
2745
2753
|
}
|
package/lib/offline/storage.js
CHANGED
|
@@ -702,7 +702,7 @@ shaka.offline.Storage = class {
|
|
|
702
702
|
// to play later (no point storing something we can't play).
|
|
703
703
|
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(
|
|
704
704
|
drmEngine, manifest, config.offline.usePersistentLicense,
|
|
705
|
-
config.drm.preferredKeySystems);
|
|
705
|
+
config.drm.preferredKeySystems, config.drm.keySystemsMapping);
|
|
706
706
|
|
|
707
707
|
// Gather all tracks.
|
|
708
708
|
const allTracks = [];
|
package/lib/player.js
CHANGED
|
@@ -1508,7 +1508,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1508
1508
|
// after several playbacks, and they are not able anymore to properly
|
|
1509
1509
|
// create MediaKeys objects. To prevent it, clear the cache after
|
|
1510
1510
|
// each playback.
|
|
1511
|
-
if (this.config_.streaming.clearDecodingCache) {
|
|
1511
|
+
if (this.config_ && this.config_.streaming.clearDecodingCache) {
|
|
1512
1512
|
shaka.util.StreamUtils.clearDecodingConfigCache();
|
|
1513
1513
|
shaka.util.DrmUtils.clearMediaKeySystemAccessMap();
|
|
1514
1514
|
}
|
|
@@ -3136,15 +3136,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3136
3136
|
fullyLoaded.reject(this.videoErrorToShakaError_());
|
|
3137
3137
|
});
|
|
3138
3138
|
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
timer.tickAfter(this.config_.streaming.loadTimeout);
|
|
3142
|
-
});
|
|
3143
|
-
|
|
3144
|
-
await Promise.race([
|
|
3145
|
-
fullyLoaded,
|
|
3146
|
-
timeout,
|
|
3147
|
-
]);
|
|
3139
|
+
await shaka.util.Functional.promiseWithTimeout(
|
|
3140
|
+
this.config_.streaming.loadTimeout, fullyLoaded);
|
|
3148
3141
|
|
|
3149
3142
|
const isLive = this.isLive();
|
|
3150
3143
|
|
|
@@ -6984,7 +6977,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6984
6977
|
's). Updating playbackRate to ' + minPlaybackRate);
|
|
6985
6978
|
this.trickPlay(minPlaybackRate, /* useTrickPlayTrack= */ false);
|
|
6986
6979
|
}
|
|
6987
|
-
} else if (maxLatency && maxPlaybackRate &&
|
|
6980
|
+
} else if (maxLatency != undefined && maxPlaybackRate &&
|
|
6988
6981
|
(latency - offset) > maxLatency) {
|
|
6989
6982
|
if (playbackRate != maxPlaybackRate) {
|
|
6990
6983
|
shaka.log.debug('Latency (' + latency + 's) is greater than ' +
|
|
@@ -6993,7 +6986,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6993
6986
|
this.trickPlay(maxPlaybackRate, /* useTrickPlayTrack= */ false);
|
|
6994
6987
|
}
|
|
6995
6988
|
this.targetLatencyReached_ = null;
|
|
6996
|
-
} else if (minLatency && minPlaybackRate &&
|
|
6989
|
+
} else if (minLatency != undefined && minPlaybackRate &&
|
|
6997
6990
|
(latency - offset) < minLatency) {
|
|
6998
6991
|
if (playbackRate != minPlaybackRate) {
|
|
6999
6992
|
shaka.log.debug('Latency (' + latency + 's) is smaller than ' +
|
|
@@ -8275,7 +8268,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
8275
8268
|
* @export
|
|
8276
8269
|
*/
|
|
8277
8270
|
// eslint-disable-next-line no-useless-concat, max-len
|
|
8278
|
-
shaka.Player.version = 'v4.12.
|
|
8271
|
+
shaka.Player.version = 'v4.12.5' + '-uncompiled'; // x-release-please-version
|
|
8279
8272
|
|
|
8280
8273
|
// Initialize the deprecation system using the version string we just set
|
|
8281
8274
|
// on the player.
|