From 14a0d3369aef47ba4cca08e9262e325016b38f16 Mon Sep 17 00:00:00 2001 From: Casey Occhialini <1508707+littlespex@users.noreply.github.com> Date: Tue, 23 Jan 2024 23:22:53 -0800 Subject: [PATCH] Refactor CMSD to use Common Media Library (#4351) --- package-lock.json | 8 +-- package.json | 2 +- src/streaming/models/CmsdModel.js | 88 ++++++++----------------------- 3 files changed, 26 insertions(+), 72 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc48093a48..6e070d3c91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "5.0.0", "license": "BSD-3-Clause", "dependencies": { - "@svta/common-media-library": "^0.5.0", + "@svta/common-media-library": "^0.6.2", "bcp-47-match": "^2.0.3", "bcp-47-normalize": "^2.3.0", "codem-isoboxer": "0.3.9", @@ -2018,9 +2018,9 @@ "dev": true }, "node_modules/@svta/common-media-library": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.5.0.tgz", - "integrity": "sha512-up4bpVbbeYxkbEt2zbjmEBO1o/VpvdhHg4181JtnCvJfn27yjl+RmrXNVYPMeK6kIqK5kceEh8E3vIRhUmHtpg==" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.6.2.tgz", + "integrity": "sha512-v8wYt1hgVbvzbK0T3sIFFTLjZSUbMwQLAn7P+yUCrZHOLIxG4iwZ+tSdbXLCNP2vrMRp0zAAykC/Jdyk6o691A==" }, "node_modules/@theintern/common": { "version": "0.3.0", diff --git a/package.json b/package.json index 3b244c0496..29e5936ebf 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "yargs": "16.0.3" }, "dependencies": { - "@svta/common-media-library": "^0.5.0", + "@svta/common-media-library": "^0.6.2", "bcp-47-match": "^2.0.3", "bcp-47-normalize": "^2.3.0", "codem-isoboxer": "0.3.9", diff --git a/src/streaming/models/CmsdModel.js b/src/streaming/models/CmsdModel.js index 2343afc574..10adce1481 100644 --- a/src/streaming/models/CmsdModel.js +++ b/src/streaming/models/CmsdModel.js @@ -32,13 +32,15 @@ import FactoryMaker from '../../core/FactoryMaker.js'; import EventBus from '../../core/EventBus.js'; import Events from '../../core/events/Events.js'; import Debug from '../../core/Debug.js'; +import { CMSD_DYNAMIC } from '@svta/common-media-library/cmsd/CMSD_DYNAMIC.js'; +import { CMSD_STATIC } from '@svta/common-media-library/cmsd/CMSD_STATIC.js'; +import { CmsdObjectType } from '@svta/common-media-library/cmsd/CmsdObjectType.js'; +import { decodeCmsdDynamic } from '@svta/common-media-library/cmsd/decodeCmsdDynamic.js'; +import { decodeCmsdStatic } from '@svta/common-media-library/cmsd/decodeCmsdStatic.js'; // Note: in modern browsers, the header names are returned in all lower case -const CMSD_STATIC = 'static'; -const CMSD_DYNAMIC = 'dynamic'; -const CMSD_RESPONSE_FIELD_BASENAME = 'cmsd-'; -const CMSD_STATIC_RESPONSE_FIELD_NAME = CMSD_RESPONSE_FIELD_BASENAME + CMSD_STATIC; -const CMSD_DYNAMIC_RESPONSE_FIELD_NAME = CMSD_RESPONSE_FIELD_BASENAME + CMSD_DYNAMIC; +const CMSD_STATIC_RESPONSE_FIELD_NAME = CMSD_STATIC.toLowerCase(); +const CMSD_DYNAMIC_RESPONSE_FIELD_NAME = CMSD_DYNAMIC.toLowerCase(); const CMSD_KEYS = { AVAILABILITY_TIME: 'at', DURESS: 'du', @@ -58,17 +60,6 @@ const CMSD_KEYS = { STREAMING_FORMAT: 'sf', VERSION: 'v' } -const OBJECT_TYPES = { - MANIFEST: 'm', - AUDIO: 'a', - VIDEO: 'v', - INIT: 'i', - CAPTION: 'c', - ISOBMFF_TEXT_TRACK: 'tt', - ENCRYPTION_KEY: 'k', - OTHER: 'o', - STREAM: 'stream' // Specific value for parameters without object type, which apply for all media/objects -}; const PERSISTENT_PARAMS = [ CMSD_KEYS.MAX_SUGGESTED_BITRATE, @@ -77,15 +68,15 @@ const PERSISTENT_PARAMS = [ CMSD_KEYS.VERSION ]; +const STREAM = 'stream' + const MEDIATYPE_TO_OBJECTTYPE = { - 'video': OBJECT_TYPES.VIDEO, - 'audio': OBJECT_TYPES.AUDIO, - 'text': OBJECT_TYPES.ISOBMFF_TEXT_TRACK, - 'stream': OBJECT_TYPES.STREAM + 'video': CmsdObjectType.VIDEO, + 'audio': CmsdObjectType.AUDIO, + 'text': CmsdObjectType.TIMED_TEXT, + 'stream': STREAM // Specific value for parameters without object type, which apply for all media/objects } -const integerRegex = /^[-0-9]/ - function CmsdModel() { const context = this.context; @@ -121,35 +112,9 @@ function CmsdModel() { }) } - function _parseParameterValue(value) { - // If the value type is BOOLEAN and the value is TRUE, then the equals sign and the value are omitted - if (!value) { - return true; - } - // Check if boolean 'false' - if (value.toLowerCase() === 'false') { - return false; - } - // Check if a number - if (integerRegex.test(value)) { - return parseInt(value, 10); - } - // Value is a string, remove double quotes from string value - return value.replace(/["]+/g, ''); - } - function _parseCMSDStatic(value) { try { - const params = {}; - const items = value.split(','); - for (let i = 0; i < items.length; i++) { - // = - const substrs = items[i].split('='); - const key = substrs[0]; - const v = _parseParameterValue(substrs[1]); - params[key] = v; - } - return params; + return decodeCmsdStatic(value); } catch (e) { logger.error('Failed to parse CMSD-Static response header value:', e); } @@ -157,34 +122,23 @@ function CmsdModel() { function _parseCMSDDynamic(value) { try { - const params = {}; - const entries = value.split(','); - // Consider only last CMSD-Dynamic entry - const entry = entries[entries.length - 1]; - const items = entry.split(';'); - // Server identifier as 1st item - for (let i = 1; i < items.length; i++) { - // = - const substrs = items[i].split('='); - const key = substrs[0]; - const v = _parseParameterValue(substrs[1]); - params[key] = v; - } - return params; + const items = decodeCmsdDynamic(value); + const last = items[items.length - 1]; + return last?.params || {}; } catch (e) { logger.error('Failed to parse CMSD-Dynamic response header value:', e); - return []; + return {}; } } function _mediaTypetoObjectType(mediaType) { - return MEDIATYPE_TO_OBJECTTYPE[mediaType] || OBJECT_TYPES.OTHER; + return MEDIATYPE_TO_OBJECTTYPE[mediaType] || CmsdObjectType.OTHER; } function _getParamValueForObjectType(paramsType, ot, key) { const params = paramsType === CMSD_STATIC ? _staticParamsDict : _dynamicParamsDict; const otParams = params[ot] || {}; - const streamParams = params[OBJECT_TYPES.STREAM] || {}; + const streamParams = params[STREAM] || {}; const value = otParams[key] || streamParams[key]; return value; } @@ -212,7 +166,7 @@ function CmsdModel() { } // Get object type - let ot = OBJECT_TYPES.STREAM; + let ot = STREAM; if (staticParams && staticParams[CMSD_KEYS.OBJECT_TYPE]) { ot = staticParams[CMSD_KEYS.OBJECT_TYPE]; } else if (mediaType) {