perf: Use Map.getOrInsert/getOrInsertComputed native methods (#9546)

Added polyfills for `Map.getOrInsert()` and
`Map.getOrInsertComputed()` from the TC39 upsert proposal and refactor
the codebase to use them.
These methods replace the common "check if key exists, then set default"
pattern with a single atomic operation. This improves code readability
and eliminates redundant map lookups throughout the player.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
This commit is contained in:
Andy(김규회)
2026-01-13 18:57:25 +09:00
committed by GitHub
parent dd3f6829f7
commit 05b09728c7
24 changed files with 281 additions and 191 deletions
+1
View File
@@ -3,6 +3,7 @@
+../../lib/polyfill/eme_encryption_scheme.js
+../../lib/polyfill/encryption_scheme_media_key_system_access.js
+../../lib/polyfill/encryption_scheme_utils.js
+../../lib/polyfill/map.js
+../../lib/polyfill/mcap_encryption_scheme.js
+../../lib/polyfill/mediasource.js
+../../lib/polyfill/media_capabilities.js
+59
View File
@@ -0,0 +1,59 @@
/*! @license
* Shaka Player
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Externs for Map getOrInsert/getOrInsertComputed methods
*
* @externs
*/
/**
* Returns the value for the given key if present; otherwise inserts
* the default value, and returns that.
* @param {K} key
* @param {V} defaultValue
* @return {V}
* @this {Map<K, V>}
* @template K, V
*/
// eslint-disable-next-line no-extend-native
Map.prototype.getOrInsert = function(key, defaultValue) {};
/**
* Returns the value for the given key if present; otherwise calls
* the callback with the key, inserts the returned value, and returns that.
* @param {K} key
* @param {function(K): V} callbackFunction
* @return {V}
* @this {Map<K, V>}
* @template K, V
*/
// eslint-disable-next-line no-extend-native
Map.prototype.getOrInsertComputed = function(key, callbackFunction) {};
/**
* Returns the value for the given key if present; otherwise inserts
* the default value, and returns that.
* @param {K} key
* @param {V} defaultValue
* @return {V}
* @this {WeakMap<K, V>}
* @template K, V
*/
// eslint-disable-next-line no-extend-native
WeakMap.prototype.getOrInsert = function(key, defaultValue) {};
/**
* Returns the value for the given key if present; otherwise calls
* the callback with the key, inserts the returned value, and returns that.
* @param {K} key
* @param {function(K): V} callbackFunction
* @return {V}
* @this {WeakMap<K, V>}
* @template K, V
*/
// eslint-disable-next-line no-extend-native
WeakMap.prototype.getOrInsertComputed = function(key, callbackFunction) {};
+1 -2
View File
@@ -258,8 +258,7 @@ shaka.ads.SvtaAdManager = class {
let cuepointsChanged = false;
for (const tracking of trackings) {
const id = JSON.stringify(tracking);
if (!this.trackings_.has(id)) {
this.trackings_.set(id, tracking);
if (this.trackings_.getOrInsert(id, tracking) === tracking) {
cuepointsChanged = true;
}
}
+3 -5
View File
@@ -359,11 +359,9 @@ shaka.cea.CeaDecoder = class {
if (serviceNumber != 0) {
this.streams_.add('svc'+ serviceNumber);
// If the service doesn't already exist, create it.
if (!this.serviceNumberToService_.has(serviceNumber)) {
const service = new shaka.cea.Cea708Service(serviceNumber);
this.serviceNumberToService_.set(serviceNumber, service);
}
const service = this.serviceNumberToService_.get(serviceNumber);
const service = this.serviceNumberToService_.getOrInsertComputed(
serviceNumber,
(num) => new shaka.cea.Cea708Service(num));
// Process all control codes.
const startPos = dtvccPacket.getPosition();
+4 -5
View File
@@ -543,13 +543,12 @@ shaka.dash.ContentProtection = class {
try {
// Try parsing PSSH data.
init = psshs.map((pssh) => {
if (!this.psshToInitData_.has(pssh)) {
const initData = shaka.util.Uint8ArrayUtils.fromBase64(pssh);
this.psshToInitData_.set(pssh, initData);
}
const initData = this.psshToInitData_.getOrInsertComputed(pssh, () => {
return shaka.util.Uint8ArrayUtils.fromBase64(pssh);
});
return {
initDataType: 'cenc',
initData: this.psshToInitData_.get(pssh),
initData,
keyId: null,
};
});
+2 -4
View File
@@ -2555,11 +2555,9 @@ shaka.dash.DashParser = class {
if (contextId && context.dynamic && !this.streamMap_.has(contextId)) {
const periodId = context.period.id || '';
if (!this.indexStreamMap_.has(periodId)) {
this.indexStreamMap_.set(periodId, []);
}
this.streamMap_.set(contextId, stream);
this.indexStreamMap_.get(periodId).push(contextId);
this.indexStreamMap_.getOrInsertComputed(periodId, () => [])
.push(contextId);
}
return stream;
+2 -4
View File
@@ -1099,10 +1099,8 @@ shaka.drm.DrmEngine = class {
// Get all the key systems in the variant that shouldHaveLicenseServer.
const drmInfos = this.getVariantDrmInfos_(variant);
for (const info of drmInfos) {
if (!drmInfosByKeySystem.has(info.keySystem)) {
drmInfosByKeySystem.set(info.keySystem, []);
}
drmInfosByKeySystem.get(info.keySystem).push(info);
drmInfosByKeySystem.getOrInsertComputed(info.keySystem, () => [])
.push(info);
}
}
+56 -70
View File
@@ -1311,9 +1311,7 @@ shaka.hls.HlsParser = class {
const value = variableTag.getAttributeValue('VALUE');
const queryParam = variableTag.getAttributeValue('QUERYPARAM');
if (name && value) {
if (!this.globalVariables_.has(name)) {
this.globalVariables_.set(name, value);
}
this.globalVariables_.getOrInsert(name, value);
}
if (queryParam) {
const queryParamValue = queryParams.get(queryParam)[0];
@@ -1340,9 +1338,7 @@ shaka.hls.HlsParser = class {
const queryParam = variableTag.getAttributeValue('QUERYPARAM');
const mediaImport = variableTag.getAttributeValue('IMPORT');
if (name && value) {
if (!mediaVariables.has(name)) {
mediaVariables.set(name, value);
}
mediaVariables.getOrInsert(name, value);
}
if (queryParam) {
const queryParamValue = queryParams.get(queryParam)[0];
@@ -1652,10 +1648,8 @@ shaka.hls.HlsParser = class {
} else if ((i + 1) < chapterList.length) {
item.endTime = chapterList[i + 1]['start-time'];
}
if (!chapterByLanguage.has(title.language)) {
chapterByLanguage.set(title.language, []);
}
chapterByLanguage.get(title.language).push(item);
chapterByLanguage.getOrInsertComputed(title.language, () => [])
.push(item);
}
}
@@ -1801,14 +1795,12 @@ shaka.hls.HlsParser = class {
const keyUris = shaka.hls.Utils.constructSegmentUris(
getUris(), drmTag.getRequiredAttrValue('URI'), variables);
const keyMapKey = keyUris.sort().join('');
if (!this.aesKeyMap_.has(keyMapKey)) {
this.aesKeyMap_.getOrInsertComputed(keyMapKey, () => {
const requestType = shaka.net.NetworkingEngine.RequestType.KEY;
const request = shaka.net.NetworkingEngine.makeRequest(
keyUris, this.config_.retryParameters);
const keyResponse = this.makeNetworkRequest_(request, requestType)
.promise;
this.aesKeyMap_.set(keyMapKey, keyResponse);
}
return this.makeNetworkRequest_(request, requestType).promise;
});
continue;
} else if (keyFormat == 'identity') {
// eslint-disable-next-line no-await-in-loop
@@ -3581,7 +3573,7 @@ shaka.hls.HlsParser = class {
const keyMapKey = keyUris.sort().join('');
const aesKeyInfoKey =
`${drmTag.toString()}-${firstMediaSequenceNumber}-${keyMapKey}`;
if (!this.aesKeyInfoMap_.has(aesKeyInfoKey)) {
return this.aesKeyInfoMap_.getOrInsertComputed(aesKeyInfoKey, () => {
// Default AES-128
const keyInfo = {
bitsKey: 128,
@@ -3604,15 +3596,13 @@ shaka.hls.HlsParser = class {
// Don't download the key object until the segment is parsed, to avoid a
// startup delay for long manifests with lots of keys.
keyInfo.fetchKey = async () => {
if (!this.aesKeyMap_.has(keyMapKey)) {
const requestType = shaka.net.NetworkingEngine.RequestType.KEY;
const request = shaka.net.NetworkingEngine.makeRequest(
keyUris, this.config_.retryParameters);
const keyResponse = this.makeNetworkRequest_(request, requestType)
.promise;
this.aesKeyMap_.set(keyMapKey, keyResponse);
}
const keyResponse = await this.aesKeyMap_.get(keyMapKey);
const keyResponse = await this.aesKeyMap_.getOrInsertComputed(
keyMapKey, () => {
const requestType = shaka.net.NetworkingEngine.RequestType.KEY;
const request = shaka.net.NetworkingEngine.makeRequest(
keyUris, this.config_.retryParameters);
return this.makeNetworkRequest_(request, requestType).promise;
});
// keyResponse.status is undefined when URI is "data:text/plain;base64,"
if (!keyResponse.data ||
@@ -3631,9 +3621,8 @@ shaka.hls.HlsParser = class {
'raw', keyResponse.data, algorithm, true, ['decrypt']);
keyInfo.fetchKey = undefined; // No longer needed.
};
this.aesKeyInfoMap_.set(aesKeyInfoKey, keyInfo);
}
return this.aesKeyInfoMap_.get(aesKeyInfoKey);
return keyInfo;
});
}
@@ -3843,30 +3832,31 @@ shaka.hls.HlsParser = class {
absoluteInitSegmentUris.toString(),
mapTag.getAttributeValue('BYTERANGE', ''),
].join('-');
if (!this.mapTagToInitSegmentRefMap_.has(mapTagKey)) {
/** @type {shaka.extern.aesKey|undefined} */
let aesKey = undefined;
let byteRangeTag = null;
let encrypted = false;
for (const tag of tags) {
if (tag.name == 'EXT-X-KEY') {
const method = tag.getRequiredAttrValue('METHOD');
if (this.isAesMethod_(method) && tag.id < mapTag.id) {
encrypted = false;
aesKey =
this.parseAESDrmTag_(tag, playlist, getUris, variables);
} else {
encrypted = method != 'NONE';
return this.mapTagToInitSegmentRefMap_.getOrInsertComputed(
mapTagKey, () => {
goog.asserts.assert(mapTag, 'mapTag should be non-null');
/** @type {shaka.extern.aesKey|undefined} */
let aesKey = undefined;
/** @type {shaka.hls.Tag|undefined} */
let byteRangeTag = undefined;
let encrypted = false;
for (const tag of tags) {
if (tag.name == 'EXT-X-KEY') {
const method = tag.getRequiredAttrValue('METHOD');
if (this.isAesMethod_(method) && tag.id < mapTag.id) {
encrypted = false;
aesKey =
this.parseAESDrmTag_(tag, playlist, getUris, variables);
} else {
encrypted = method != 'NONE';
}
} else if (tag.name == 'EXT-X-BYTERANGE' && tag.id < mapTag.id) {
byteRangeTag = tag;
}
}
} else if (tag.name == 'EXT-X-BYTERANGE' && tag.id < mapTag.id) {
byteRangeTag = tag;
}
}
const initSegmentRef = this.createInitSegmentReference_(
absoluteInitSegmentUris, mapTag, byteRangeTag, aesKey, encrypted);
this.mapTagToInitSegmentRefMap_.set(mapTagKey, initSegmentRef);
}
return this.mapTagToInitSegmentRefMap_.get(mapTagKey);
return this.createInitSegmentReference_(
absoluteInitSegmentUris, mapTag, byteRangeTag, aesKey, encrypted);
});
}
/**
@@ -5224,16 +5214,15 @@ shaka.hls.HlsParser = class {
const parsedData = shaka.net.DataUriPlugin.parseRaw(uri.split('?')[0]);
const psshKey = uri.split('?')[0];
if (!this.psshToInitData_.has(psshKey)) {
const initData = this.psshToInitData_.getOrInsertComputed(psshKey, () => {
// The data encoded in the URI is a PSSH box to be used as init data.
const initData = shaka.util.BufferUtils.toUint8(parsedData.data);
this.psshToInitData_.set(psshKey, initData);
}
return shaka.util.BufferUtils.toUint8(parsedData.data);
});
const drmInfo = shaka.util.ManifestParserUtils.createDrmInfo(
'com.widevine.alpha',
encryptionScheme,
/* initData= */ [
{initDataType: 'cenc', initData: this.psshToInitData_.get(psshKey)},
{initDataType: 'cenc', initData},
],
/* keySystemUri= */ undefined,
/* mediaTypeList= */ parsedData.typeInfoList);
@@ -5333,16 +5322,15 @@ shaka.hls.HlsParser = class {
const parsedData = shaka.net.DataUriPlugin.parseRaw(uri.split('?')[0]);
const psshKey = uri.split('?')[0];
if (!this.psshToInitData_.has(psshKey)) {
const initData = this.psshToInitData_.getOrInsertComputed(psshKey, () => {
// The data encoded in the URI is a PSSH box to be used as init data.
const initData = shaka.util.BufferUtils.toUint8(parsedData.data);
this.psshToInitData_.set(psshKey, initData);
}
return shaka.util.BufferUtils.toUint8(parsedData.data);
});
const drmInfo = shaka.util.ManifestParserUtils.createDrmInfo(
/* keySystem= */ 'com.huawei.wiseplay',
encryptionScheme,
/* initData= */ [
{initDataType: 'cenc', initData: this.psshToInitData_.get(psshKey)},
{initDataType: 'cenc', initData},
],
/* keySystemUri= */ undefined,
/* mediaTypeList= */ parsedData.typeInfoList);
@@ -5405,15 +5393,13 @@ shaka.hls.HlsParser = class {
keyUris[0].split('data:text/plain;base64,').pop()));
} else {
const keyMapKey = keyUris.sort().join('');
if (!this.identityKeyMap_.has(keyMapKey)) {
const requestType = shaka.net.NetworkingEngine.RequestType.KEY;
const request = shaka.net.NetworkingEngine.makeRequest(
keyUris, this.config_.retryParameters);
const keyResponse = this.makeNetworkRequest_(request, requestType)
.promise;
this.identityKeyMap_.set(keyMapKey, keyResponse);
}
const keyResponse = await this.identityKeyMap_.get(keyMapKey);
const keyResponse = await this.identityKeyMap_.getOrInsertComputed(
keyMapKey, () => {
const requestType = shaka.net.NetworkingEngine.RequestType.KEY;
const request = shaka.net.NetworkingEngine.makeRequest(
keyUris, this.config_.retryParameters);
return this.makeNetworkRequest_(request, requestType).promise;
});
key = shaka.util.Uint8ArrayUtils.toHex(keyResponse.data);
}
+4 -10
View File
@@ -20,16 +20,10 @@ shaka.media.Capabilities = class {
*/
static isTypeSupported(type) {
const supportMap = shaka.media.Capabilities.MediaSourceTypeSupportMap;
if (supportMap.has(type)) {
return supportMap.get(type);
}
const mediaSource = window.ManagedMediaSource || window.MediaSource;
if (mediaSource) {
const currentSupport = mediaSource.isTypeSupported(type);
supportMap.set(type, currentSupport);
return currentSupport;
}
return false;
return supportMap.getOrInsertComputed(type, () => {
const mediaSource = window.ManagedMediaSource || window.MediaSource;
return mediaSource?.isTypeSupported(type) ?? false;
});
}
/**
+2 -4
View File
@@ -941,10 +941,8 @@ shaka.media.MediaSourceEngine = class {
}
} else if (!mimeType.includes('/mp4') && !mimeType.includes('/webm') &&
shaka.util.TsParser.probe(uint8ArrayData)) {
if (!this.tsParsers_.has(contentType)) {
this.tsParsers_.set(contentType, new shaka.util.TsParser());
}
const tsParser = this.tsParsers_.get(contentType);
const tsParser = this.tsParsers_.getOrInsertComputed(
contentType, () => new shaka.util.TsParser());
tsParser.clearData();
tsParser.setDiscontinuitySequence(reference.discontinuitySequence);
tsParser.parse(uint8ArrayData);
+11 -13
View File
@@ -685,17 +685,15 @@ shaka.media.StreamingEngine = class {
if (mediaState.performingUpdate) {
const oldStreamTag =
shaka.media.StreamingEngine.logPrefix_(mediaState);
if (!this.deferredCloseSegmentIndex_.has(oldStreamTag)) {
// The ongoing update is still using the old stream's segment
// reference information.
// If we close the old stream now, the update will not complete
// correctly.
// The next onUpdate_() for this content type will resume the
// closeSegmentIndex() operation for the old stream once the ongoing
// update has finished, then immediately create a new segment index.
this.deferredCloseSegmentIndex_.set(
oldStreamTag, mediaState.stream.closeSegmentIndex);
}
// The ongoing update is still using the old stream's segment
// reference information.
// If we close the old stream now, the update will not complete
// correctly.
// The next onUpdate_() for this content type will resume the
// closeSegmentIndex() operation for the old stream once the ongoing
// update has finished, then immediately create a new segment index.
this.deferredCloseSegmentIndex_.getOrInsert(
oldStreamTag, mediaState.stream.closeSegmentIndex);
} else {
mediaState.stream.closeSegmentIndex();
}
@@ -1117,8 +1115,8 @@ shaka.media.StreamingEngine = class {
const stream = streamsByType.get(type);
if (!this.mediaStates_.has(type)) {
const mediaState = this.createMediaState_(stream);
if (segmentPrefetchById.has(stream.id)) {
const segmentPrefetch = segmentPrefetchById.get(stream.id);
const segmentPrefetch = segmentPrefetchById.get(stream.id);
if (segmentPrefetch) {
segmentPrefetch.replaceFetchDispatcher(
(reference, stream, streamDataCallback) => {
return this.dispatchFetch_(
+95
View File
@@ -0,0 +1,95 @@
/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
goog.provide('shaka.polyfill.Map');
goog.require('shaka.log');
goog.require('shaka.polyfill');
/**
* @summary A polyfill to provide Map.prototype.getOrInsert,
* Map.prototype.getOrInsertComputed, WeakMap.prototype.getOrInsert,
* and WeakMap.prototype.getOrInsertComputed methods.
* @see https://github.com/tc39/proposal-upsert
* @export
*/
shaka.polyfill.Map = class {
/**
* Install the polyfill if needed.
* @export
*/
static install() {
shaka.log.debug('Map.install');
// eslint-disable-next-line no-restricted-syntax
if (!('getOrInsert' in Map.prototype)) {
shaka.log.debug('Map: Installing getOrInsert polyfill.');
// eslint-disable-next-line no-extend-native, no-restricted-syntax
Map.prototype.getOrInsert = shaka.polyfill.Map.mapGetOrInsert_;
}
// eslint-disable-next-line no-restricted-syntax
if (!('getOrInsertComputed' in Map.prototype)) {
shaka.log.debug('Map: Installing getOrInsertComputed polyfill.');
// eslint-disable-next-line no-extend-native, no-restricted-syntax
Map.prototype.getOrInsertComputed =
shaka.polyfill.Map.mapGetOrInsertComputed_;
}
shaka.log.debug('WeakMap.install');
// eslint-disable-next-line no-restricted-syntax
if (!('getOrInsert' in WeakMap.prototype)) {
shaka.log.debug('WeakMap: Installing getOrInsert polyfill.');
// eslint-disable-next-line no-extend-native, no-restricted-syntax
WeakMap.prototype.getOrInsert = shaka.polyfill.Map.mapGetOrInsert_;
}
// eslint-disable-next-line no-restricted-syntax
if (!('getOrInsertComputed' in WeakMap.prototype)) {
shaka.log.debug('WeakMap: Installing getOrInsertComputed polyfill.');
// eslint-disable-next-line no-extend-native, no-restricted-syntax
WeakMap.prototype.getOrInsertComputed =
shaka.polyfill.Map.mapGetOrInsertComputed_;
}
}
/**
* Returns the value for the given key if present; otherwise inserts
* the default value, and returns that.
* @param {K} key
* @param {V} defaultValue
* @return {V}
* @this {Map<K, V>|WeakMap<K, V>}
* @template K, V
* @private
*/
static mapGetOrInsert_(key, defaultValue) {
if (!this.has(key)) {
this.set(key, defaultValue);
}
return this.get(key);
}
/**
* Returns the value for the given key if present; otherwise calls
* the callback with the key, inserts the returned value, and returns that.
* @param {K} key
* @param {function(K): V} callbackFunction
* @return {V}
* @this {Map<K, V>|WeakMap<K, V>}
* @template K, V
* @private
*/
static mapGetOrInsertComputed_(key, callbackFunction) {
if (!this.has(key)) {
this.set(key, callbackFunction(key));
}
return this.get(key);
}
};
shaka.polyfill.register(shaka.polyfill.Map.install);
+21 -16
View File
@@ -473,23 +473,28 @@ shaka.text.SpeechToText = class {
if (!mediaElement) {
return null;
}
if (!shaka.text.SpeechToText.audioObjectMap_.has(mediaElement)) {
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
const sourceNode = audioContext.createMediaElementSource(mediaElement);
const destinationNode = audioContext.createMediaStreamDestination();
sourceNode.connect(destinationNode);
sourceNode.connect(audioContext.destination);
const audioTrack = destinationNode.stream.getAudioTracks()[0];
shaka.text.SpeechToText.audioObjectMap_.set(mediaElement, {
audioContext,
sourceNode,
destinationNode,
audioTrack,
});
}
const audioObject =
shaka.text.SpeechToText.audioObjectMap_.get(mediaElement);
shaka.text.SpeechToText.audioObjectMap_.getOrInsertComputed(
mediaElement,
() => {
const AudioContext =
window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
goog.asserts.assert(mediaElement, 'MediaElement should be null');
const sourceNode =
audioContext.createMediaElementSource(mediaElement);
const destinationNode =
audioContext.createMediaStreamDestination();
sourceNode.connect(destinationNode);
sourceNode.connect(audioContext.destination);
const audioTrack = destinationNode.stream.getAudioTracks()[0];
return {
audioContext,
sourceNode,
destinationNode,
audioTrack,
};
});
return audioObject.audioTrack;
}
+4 -7
View File
@@ -392,9 +392,7 @@ shaka.text.TextEngine = class {
for (const caption of closedCaptions) {
const id = caption.stream;
const cue = caption.cue;
if (!captionsMap.has(id)) {
captionsMap.set(id, []);
}
captionsMap.getOrInsert(id, []);
// Adjust CEA captions with respect to the timestamp offset of the video
// stream in which they were embedded.
@@ -414,11 +412,10 @@ shaka.text.TextEngine = class {
}
for (const id of captionsMap.keys()) {
if (!this.closedCaptionsMap_.has(id)) {
this.closedCaptionsMap_.set(id, []);
}
const closedCaptions = this.closedCaptionsMap_.getOrInsertComputed(
id, () => []);
for (const cue of captionsMap.get(id)) {
this.closedCaptionsMap_.get(id).push(cue);
closedCaptions.push(cue);
}
}
+2 -7
View File
@@ -207,14 +207,9 @@ shaka.transmuxer.AacTransmuxer = class {
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
let initSegment;
const initSegmentKey = stream.id + '_' + reference.discontinuitySequence;
if (!this.initSegments.has(initSegmentKey)) {
initSegment = mp4Generator.initSegment();
this.initSegments.set(initSegmentKey, initSegment);
} else {
initSegment = this.initSegments.get(initSegmentKey);
}
const initSegment = this.initSegments.getOrInsertComputed(
initSegmentKey, () => mp4Generator.initSegment());
const appendInitSegment = this.lastInitSegment_ !== initSegment;
const segmentData = mp4Generator.segmentData();
this.lastInitSegment_ = initSegment;
+2 -7
View File
@@ -201,14 +201,9 @@ shaka.transmuxer.Ac3Transmuxer = class {
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
let initSegment;
const initSegmentKey = stream.id + '_' + reference.discontinuitySequence;
if (!this.initSegments.has(initSegmentKey)) {
initSegment = mp4Generator.initSegment();
this.initSegments.set(initSegmentKey, initSegment);
} else {
initSegment = this.initSegments.get(initSegmentKey);
}
const initSegment = this.initSegments.getOrInsertComputed(
initSegmentKey, () => mp4Generator.initSegment());
const appendInitSegment = this.lastInitSegment_ !== initSegment;
const segmentData = mp4Generator.segmentData();
this.lastInitSegment_ = initSegment;
+2 -7
View File
@@ -195,14 +195,9 @@ shaka.transmuxer.Ec3Transmuxer = class {
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
let initSegment;
const initSegmentKey = stream.id + '_' + reference.discontinuitySequence;
if (!this.initSegments.has(initSegmentKey)) {
initSegment = mp4Generator.initSegment();
this.initSegments.set(initSegmentKey, initSegment);
} else {
initSegment = this.initSegments.get(initSegmentKey);
}
const initSegment = this.initSegments.getOrInsertComputed(
initSegmentKey, () => mp4Generator.initSegment());
const appendInitSegment = this.lastInitSegment_ !== initSegment;
const segmentData = mp4Generator.segmentData();
this.lastInitSegment_ = initSegment;
+2 -7
View File
@@ -188,14 +188,9 @@ shaka.transmuxer.Mp3Transmuxer = class {
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
let initSegment;
const initSegmentKey = stream.id + '_' + reference.discontinuitySequence;
if (!this.initSegments.has(initSegmentKey)) {
initSegment = mp4Generator.initSegment();
this.initSegments.set(initSegmentKey, initSegment);
} else {
initSegment = this.initSegments.get(initSegmentKey);
}
const initSegment = this.initSegments.getOrInsertComputed(
initSegmentKey, () => mp4Generator.initSegment());
const appendInitSegment = this.lastInitSegment_ !== initSegment;
const segmentData = mp4Generator.segmentData();
this.lastInitSegment_ = initSegment;
+2 -7
View File
@@ -288,14 +288,9 @@ shaka.transmuxer.TsTransmuxer = class {
}
const mp4Generator = new shaka.util.Mp4Generator(streamInfos);
let initSegment;
const initSegmentKey = stream.id + '_' + reference.discontinuitySequence;
if (!this.initSegments.has(initSegmentKey)) {
initSegment = mp4Generator.initSegment();
this.initSegments.set(initSegmentKey, initSegment);
} else {
initSegment = this.initSegments.get(initSegmentKey);
}
const initSegment = this.initSegments.getOrInsertComputed(
initSegmentKey, () => mp4Generator.initSegment());
const appendInitSegment = this.lastInitSegment_ !== initSegment;
const segmentData = mp4Generator.segmentData();
this.lastInitSegment_ = initSegment;
+1 -5
View File
@@ -24,11 +24,7 @@ shaka.util.MultiMap = class {
* @param {T} value
*/
push(key, value) {
if (this.map_.has(key)) {
this.map_.get(key).push(value);
} else {
this.map_.set(key, [value]);
}
this.map_.getOrInsertComputed(key, () => []).push(value);
}
+2 -5
View File
@@ -1947,11 +1947,8 @@ shaka.util.PeriodCombiner = class {
* @private
*/
static getCodec_(codecs) {
if (!shaka.util.PeriodCombiner.memoizedCodecs.has(codecs)) {
const normalizedCodec = shaka.util.MimeUtils.getNormalizedCodec(codecs);
shaka.util.PeriodCombiner.memoizedCodecs.set(codecs, normalizedCodec);
}
return shaka.util.PeriodCombiner.memoizedCodecs.get(codecs);
return shaka.util.PeriodCombiner.memoizedCodecs.getOrInsertComputed(
codecs, () => shaka.util.MimeUtils.getNormalizedCodec(codecs));
}
/**
+1
View File
@@ -46,6 +46,7 @@ goog.require('shaka.offline.indexeddb.StorageMechanism');
goog.require('shaka.polyfill.Aria');
goog.require('shaka.polyfill.EmeEncryptionScheme');
goog.require('shaka.polyfill.Fullscreen');
goog.require('shaka.polyfill.Map');
goog.require('shaka.polyfill.MCapEncryptionScheme');
goog.require('shaka.polyfill.MediaSource');
goog.require('shaka.polyfill.MediaCapabilities');
+1 -4
View File
@@ -80,10 +80,7 @@ shaka.ui.LanguageUtils = class {
if (!track.codecs) {
continue;
}
if (!codecsByLanguage.has(track.language)) {
codecsByLanguage.set(track.language, new Set());
}
codecsByLanguage.get(track.language).add(
codecsByLanguage.getOrInsertComputed(track.language, () => new Set()).add(
shaka.util.MimeUtils.getNormalizedCodec(track.codecs));
}
const hasDifferentAudioCodecs = (language) =>
+1 -2
View File
@@ -155,7 +155,7 @@ shaka.ui.Localization = class extends shaka.util.FakeEventTarget {
// Make sure we have an entry for the locale because we are about to
// write to it.
const table = this.localizations_.get(locale) || new Map();
const table = this.localizations_.getOrInsert(locale, new Map());
localizations.forEach((value, id) => {
// Set the value if we don't have an old value or if we are to replace
// the old value with the new value.
@@ -163,7 +163,6 @@ shaka.ui.Localization = class extends shaka.util.FakeEventTarget {
table.set(id, value);
}
});
this.localizations_.set(locale, table);
// The data we use to make our map may have changed, update the map we pull
// data from.