From a09d8c9869d5246af540d562f36546a294c2d9e9 Mon Sep 17 00:00:00 2001 From: Nick Michael Date: Fri, 15 Oct 2021 19:50:26 +0100 Subject: [PATCH] fix: Dedupe DRM init data (#3695) Linear streams accumulate init data over time because the init data is pushed to an array regardless of whether or not it already exists as part of the logic to combine periods. This PR dedupes the init data based on keyId to help reduce memory usage over extended playouts. --- lib/media/drm_engine.js | 7 ++++++ test/media/drm_engine_unit.js | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/lib/media/drm_engine.js b/lib/media/drm_engine.js index 200011c088..f1de943ba1 100644 --- a/lib/media/drm_engine.js +++ b/lib/media/drm_engine.js @@ -1825,9 +1825,16 @@ shaka.media.DrmEngine = class { // audio adaptations, so we shouldn't have to worry about checking // robustness. if (drm1.keySystem == drm2.keySystem) { + /** @type {Array} */ let initData = []; initData = initData.concat(drm1.initData || []); initData = initData.concat(drm2.initData || []); + initData = initData.filter((d, i) => { + return d.keyId === undefined || i === initData.findIndex((d2) => { + return d2.keyId === d.keyId; + }); + }); + const keyIds = drm1.keyIds && drm2.keyIds ? new Set([...drm1.keyIds, ...drm2.keyIds]) : drm1.keyIds || drm2.keyIds; diff --git a/test/media/drm_engine_unit.js b/test/media/drm_engine_unit.js index 4cb204d9cb..c6208b651d 100644 --- a/test/media/drm_engine_unit.js +++ b/test/media/drm_engine_unit.js @@ -2152,6 +2152,50 @@ describe('DrmEngine', () => { [drmInfoAudio]); expect(returned).toEqual([drmInfoDesired]); }); + + it('dedupes the merged init data based on keyId matching', () => { + const serverCert = new Uint8Array(0); + const drmInfoVideo = { + keySystem: 'drm.abc', + licenseServerUri: 'http://abc.drm/license', + distinctiveIdentifierRequired: false, + persistentStateRequired: true, + videoRobustness: 'really_really_ridiculously_good', + serverCertificate: serverCert, + serverCertificateUri: '', + initData: [{keyId: 'v-init'}], + keyIds: new Set(['deadbeefdeadbeefdeadbeefdeadbeef']), + }; + const drmInfoAudio = { + keySystem: 'drm.abc', + licenseServerUri: undefined, + distinctiveIdentifierRequired: true, + persistentStateRequired: false, + audioRobustness: 'good', + serverCertificate: undefined, + serverCertificateUri: '', + initData: [{keyId: 'v-init'}, {keyId: 'a-init'}], + keyIds: new Set(['eadbeefdeadbeefdeadbeefdeadbeefd']), + }; + const drmInfoDesired = { + keySystem: 'drm.abc', + licenseServerUri: 'http://abc.drm/license', + distinctiveIdentifierRequired: true, + persistentStateRequired: true, + audioRobustness: 'good', + videoRobustness: 'really_really_ridiculously_good', + serverCertificate: serverCert, + serverCertificateUri: '', + initData: [{keyId: 'v-init'}, {keyId: 'a-init'}], + keyIds: new Set([ + 'deadbeefdeadbeefdeadbeefdeadbeef', + 'eadbeefdeadbeefdeadbeefdeadbeefd', + ]), + }; + const returned = shaka.media.DrmEngine.getCommonDrmInfos([drmInfoVideo], + [drmInfoAudio]); + expect(returned).toEqual([drmInfoDesired]); + }); }); // describe('getCommonDrmInfos') describe('configure', () => {