diff --git a/doc/api/Miscellaneous/Local_Contents.md b/doc/api/Miscellaneous/Local_Contents.md
index f6bb5f4705..bf83b573ba 100644
--- a/doc/api/Miscellaneous/Local_Contents.md
+++ b/doc/api/Miscellaneous/Local_Contents.md
@@ -419,6 +419,7 @@ For audio tracks, it can looks like:
bitrate: 200000,
mimeType: "audio/mp4",
codecs: "mp4a.40.5",
+ isSpatialAudio: false,
index: {
loadInitSegment(callbacks) { /* ... */ },
loadSegment(segment, callbacks) { /* ... */,
@@ -470,6 +471,16 @@ We'll now explain what each property is for, before going deeper into the
- height (`number|undefined`): When relevant (mostly video contents), the
height of the media, in pixels
+- isSpatialAudio (`boolean|undefined`): When relevant (mostly audio contents),
+ it can be set to `true` if the corresponding media is linked to a spatial
+ audio technology, for example a content relying on Dolby Atmos technology.
+
+ If set to `false`, it means that it is known that this media does not contain
+ any spatial audio.
+
+ For cases where you don't know and for cases where no audio is contained, this
+ can just be left undefined.
+
- index (`object`): Object allowing the RxPlayer to know the list of segments
as well as to fetch them. Described in the next chapter.
diff --git a/doc/api/Player_Errors.md b/doc/api/Player_Errors.md
index c405903b0c..e380a80f08 100644
--- a/doc/api/Player_Errors.md
+++ b/doc/api/Player_Errors.md
@@ -352,6 +352,9 @@ contains the following properties:
- `codec` (`string|undefined`): The audio codec the Representation is
in, as announced in the corresponding Manifest.
+ - `isSpatialAudio` (`Boolean|undefined`): If set to `true`, this Representation
+ has spatial audio.
+
##### For text tracks
When `trackInfo.type` is set to `"text"`, `track` describes a text track. It
diff --git a/doc/api/Track_Selection/getAudioTrack.md b/doc/api/Track_Selection/getAudioTrack.md
index 3ceb90a34e..347cb1b043 100644
--- a/doc/api/Track_Selection/getAudioTrack.md
+++ b/doc/api/Track_Selection/getAudioTrack.md
@@ -51,6 +51,9 @@ return an object with the following properties:
- `codec` (`string|undefined`): The audio codec the Representation is
in, as announced in the corresponding Manifest.
+ - `isSpatialAudio` (`Boolean|undefined`): If set to `true`, this Representation
+ has spatial audio.
+
`undefined` if no audio content has been loaded yet or if its information is
unknown.
diff --git a/doc/api/Track_Selection/getAvailableAudioTracks.md b/doc/api/Track_Selection/getAvailableAudioTracks.md
index 0a439c512d..ab3b7dda0f 100644
--- a/doc/api/Track_Selection/getAvailableAudioTracks.md
+++ b/doc/api/Track_Selection/getAvailableAudioTracks.md
@@ -47,6 +47,9 @@ Each of the objects in the returned array have the following properties:
- `codec` (`string|undefined`): The audio codec the Representation is
in, as announced in the corresponding Manifest.
+ - `isSpatialAudio` (`Boolean|undefined`): If set to `true`, this Representation
+ has spatial audio.
+
Note for multi-Period contents:
diff --git a/src/manifest/representation.ts b/src/manifest/representation.ts
index bb371353e5..5c2aae8f2f 100644
--- a/src/manifest/representation.ts
+++ b/src/manifest/representation.ts
@@ -92,6 +92,19 @@ class Representation {
*/
public frameRate? : string;
+ /**
+ * `true` if this `Representation` is linked to a spatial audio technology.
+ * For example, it may be set to `true` if the Representation relies on the
+ * "Dolby Atmos". technology.
+ *
+ * `false` if it is known that this `Representation` does not contain any
+ * spatial audio.
+ *
+ * `undefined` if we do not know whether this `Representation` contains
+ * spatial audio or not.
+ */
+ public isSpatialAudio? : boolean | undefined;
+
/**
* A string describing the codec used for this Representation.
* undefined if we do not know.
@@ -148,6 +161,10 @@ class Representation {
this.bitrate = args.bitrate;
this.codec = args.codecs;
+ if (args.isSpatialAudio !== undefined) {
+ this.isSpatialAudio = args.isSpatialAudio;
+ }
+
if (args.height !== undefined) {
this.height = args.height;
}
@@ -370,8 +387,8 @@ class Representation {
* @returns {Object}
*/
public toAudioRepresentation(): IAudioRepresentation {
- const { id, bitrate, codec } = this;
- return { id, bitrate, codec };
+ const { id, isSpatialAudio, bitrate, codec } = this;
+ return { id, isSpatialAudio, bitrate, codec };
}
/**
diff --git a/src/parsers/manifest/dash/common/parse_representations.ts b/src/parsers/manifest/dash/common/parse_representations.ts
index 40ca70ca39..8379a7a3f2 100644
--- a/src/parsers/manifest/dash/common/parse_representations.ts
+++ b/src/parsers/manifest/dash/common/parse_representations.ts
@@ -192,6 +192,16 @@ export default function parseRepresentations(
index: representationIndex,
id: representationID };
+ if (
+ representation.children.supplementalProperties !== undefined &&
+ arrayFind(representation.children.supplementalProperties, r =>
+ r.schemeIdUri === "tag:dolby.com,2018:dash:EC3_ExtensionType:2018" &&
+ r.value === "JOC"
+ )
+ ) {
+ parsedRepresentation.isSpatialAudio = true;
+ }
+
// Add optional attributes
let codecs : string|undefined;
if (representation.attributes.codecs != null) {
diff --git a/src/parsers/manifest/dash/js-parser/node_parsers/Representation.ts b/src/parsers/manifest/dash/js-parser/node_parsers/Representation.ts
index 2e642db0d2..2f74e98586 100644
--- a/src/parsers/manifest/dash/js-parser/node_parsers/Representation.ts
+++ b/src/parsers/manifest/dash/js-parser/node_parsers/Representation.ts
@@ -93,6 +93,13 @@ function parseRepresentationChildren(
contentProtections.push(contentProtection);
}
break;
+ case "SupplementalProperty":
+ if (children.supplementalProperties == null) {
+ children.supplementalProperties = [parseScheme(currentElement)];
+ } else {
+ children.supplementalProperties.push(parseScheme(currentElement));
+ }
+ break;
}
}
}
diff --git a/src/parsers/manifest/dash/node_parser_types.ts b/src/parsers/manifest/dash/node_parser_types.ts
index dec2ec3cb7..dc24b076dd 100644
--- a/src/parsers/manifest/dash/node_parser_types.ts
+++ b/src/parsers/manifest/dash/node_parser_types.ts
@@ -253,6 +253,7 @@ export interface IRepresentationChildren {
segmentBase? : ISegmentBaseIntermediateRepresentation;
segmentList? : ISegmentListIntermediateRepresentation;
segmentTemplate? : ISegmentTemplateIntermediateRepresentation;
+ supplementalProperties? : IScheme[] | undefined;
}
/* Intermediate representation for A Representation node's attributes. */
diff --git a/src/parsers/manifest/dash/wasm-parser/ts/generators/Representation.ts b/src/parsers/manifest/dash/wasm-parser/ts/generators/Representation.ts
index d7b35707ed..266a16b630 100644
--- a/src/parsers/manifest/dash/wasm-parser/ts/generators/Representation.ts
+++ b/src/parsers/manifest/dash/wasm-parser/ts/generators/Representation.ts
@@ -84,6 +84,18 @@ export function generateRepresentationChildrenParser(
break;
}
+ case TagName.SupplementalProperty: {
+ const supplementalProperty = {};
+ if (childrenObj.supplementalProperties === undefined) {
+ childrenObj.supplementalProperties = [];
+ }
+ childrenObj.supplementalProperties.push(supplementalProperty);
+ const attributeParser = generateSchemeAttrParser(supplementalProperty,
+ linearMemory);
+ parsersStack.pushParsers(nodeId, noop, attributeParser);
+ break;
+ }
+
case TagName.SegmentBase: {
const segmentBaseObj = {};
childrenObj.segmentBase = segmentBaseObj;
diff --git a/src/parsers/manifest/local/parse_local_manifest.ts b/src/parsers/manifest/local/parse_local_manifest.ts
index d2fdf3e76a..488498741a 100644
--- a/src/parsers/manifest/local/parse_local_manifest.ts
+++ b/src/parsers/manifest/local/parse_local_manifest.ts
@@ -138,6 +138,7 @@ function parseRepresentation(
height: representation.height,
width: representation.width,
codecs: representation.codecs,
+ isSpatialAudio: representation.isSpatialAudio,
mimeType: representation.mimeType,
index: new LocalRepresentationIndex(representation.index, id),
contentProtections };
diff --git a/src/parsers/manifest/local/types.ts b/src/parsers/manifest/local/types.ts
index c76ef4dbe4..32d3b10511 100644
--- a/src/parsers/manifest/local/types.ts
+++ b/src/parsers/manifest/local/types.ts
@@ -193,6 +193,8 @@ export interface ILocalRepresentation {
height? : number;
/** Interface allowing to retrieve media segments for this quality. */
index : ILocalIndex;
+ /** `true` if audio has Dolby Atmos. */
+ isSpatialAudio? : boolean;
}
/** A "track"" of a "local" Manifest. */
diff --git a/src/parsers/manifest/metaplaylist/metaplaylist_parser.ts b/src/parsers/manifest/metaplaylist/metaplaylist_parser.ts
index ddc9726644..26894e14e8 100644
--- a/src/parsers/manifest/metaplaylist/metaplaylist_parser.ts
+++ b/src/parsers/manifest/metaplaylist/metaplaylist_parser.ts
@@ -221,6 +221,7 @@ function createManifest(
mimeType: currentRepresentation.mimeType,
frameRate: currentRepresentation.frameRate,
codecs: currentRepresentation.codec,
+ isSpatialAudio: currentRepresentation.isSpatialAudio,
contentProtections: currentRepresentation.contentProtections,
});
}
diff --git a/src/parsers/manifest/types.ts b/src/parsers/manifest/types.ts
index 73332dd8bf..28b8caa0f4 100644
--- a/src/parsers/manifest/types.ts
+++ b/src/parsers/manifest/types.ts
@@ -158,6 +158,8 @@ export interface IParsedRepresentation {
* Information about the HDR characteristic of a content.
*/
hdrInfo?: IHDRInformation | undefined;
+ /** `true` if audio has Dolby Atmos. */
+ isSpatialAudio?: boolean | undefined;
}
/** Every possible types an Adaptation can have. */
diff --git a/src/public_types.ts b/src/public_types.ts
index c1cd6a919f..60359211d4 100644
--- a/src/public_types.ts
+++ b/src/public_types.ts
@@ -759,6 +759,7 @@ export interface IBifObject { fileFormat : string;
* RxPlayer.
*/
export interface IAudioRepresentation { id : string|number;
+ isSpatialAudio? : boolean | undefined;
bitrate : number;
codec? : string | undefined; }