Skip to content

Commit

Permalink
feat(DASH): Expose accessibility purpose in track
Browse files Browse the repository at this point in the history
  • Loading branch information
theodab committed May 6, 2023
1 parent fecb11a commit 5ec18b5
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 2 deletions.
3 changes: 3 additions & 0 deletions externs/shaka/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ shaka.extern.FetchCryptoKeysFunction;
* trickModeVideo: ?shaka.extern.Stream,
* emsgSchemeIdUris: ?Array.<string>,
* roles: !Array.<string>,
* accessibilityPurpose: ?shaka.dash.DashParser.AccessibilityPurpose,
* forced: boolean,
* channelsCount: ?number,
* audioSamplingRate: ?number,
Expand Down Expand Up @@ -424,6 +425,8 @@ shaka.extern.FetchCryptoKeysFunction;
* @property {!Array.<string>} roles
* The roles of the stream as they appear on the manifest,
* e.g. 'main', 'caption', or 'commentary'.
* @property {?shaka.dash.DashParser.AccessibilityPurpose} accessibilityPurpose
* The DASH accessibility descriptor, if one was provided for this stream.
* @property {boolean} forced
* <i>Defaults to false.</i> <br>
* Whether the stream set was forced
Expand Down
4 changes: 4 additions & 0 deletions externs/shaka/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ shaka.extern.BufferedInfo;
* primary: boolean,
* roles: !Array.<string>,
* audioRoles: Array.<string>,
* accessibilityPurpose: ?shaka.dash.DashParser.AccessibilityPurpose,
* forced: boolean,
* videoId: ?number,
* audioId: ?number,
Expand Down Expand Up @@ -301,6 +302,9 @@ shaka.extern.BufferedInfo;
* The roles of the audio in the track, e.g. <code>'main'</code> or
* <code>'commentary'</code>. Will be null for text tracks or variant tracks
* without audio.
* @property {?shaka.dash.DashParser.AccessibilityPurpose} accessibilityPurpose
* The DASH accessibility descriptor, if one was provided for this track.
* For text tracks, this describes the text; otherwise, this is for the audio.
* @property {boolean} forced
* True indicates that this in the forced text language for the content.
* This flag is based on signals from the manifest.
Expand Down
28 changes: 26 additions & 2 deletions lib/dash/dash_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,8 @@ shaka.dash.DashParser = class {
const accessibilities = XmlUtils.findChildren(elem, 'Accessibility');
const LanguageUtils = shaka.util.LanguageUtils;
const closedCaptions = new Map();
/** @type {?shaka.dash.DashParser.AccessibilityPurpose} */
let accessibilityPurpose;
for (const prop of accessibilities) {
const schemeId = prop.getAttribute('schemeIdUri');
const value = prop.getAttribute('value');
Expand Down Expand Up @@ -1015,6 +1017,15 @@ shaka.dash.DashParser = class {
kind = ManifestParserUtils.TextStreamKind.CLOSED_CAPTION;
}
}
} else if (schemeId == 'urn:tva:metadata:cs:AudioPurposeCS:2007') {
// See DASH DVB Document A168 Rev.6 Table 5.
if (value == '1') {
accessibilityPurpose =
shaka.dash.DashParser.AccessibilityPurpose.VISUALLY_IMPAIRED;
} else if (value == '2') {
accessibilityPurpose =
shaka.dash.DashParser.AccessibilityPurpose.HARD_OF_HEARING;
}
}
}

Expand Down Expand Up @@ -1057,7 +1068,7 @@ shaka.dash.DashParser = class {
const streams = representations.map((representation) => {
const parsedRepresentation = this.parseRepresentation_(context,
contentProtection, kind, language, label, main, roleValues,
closedCaptions, representation);
closedCaptions, representation, accessibilityPurpose);
if (parsedRepresentation) {
parsedRepresentation.hdr = parsedRepresentation.hdr || videoRange;
}
Expand Down Expand Up @@ -1133,12 +1144,14 @@ shaka.dash.DashParser = class {
* @param {!Array.<string>} roles
* @param {Map.<string, string>} closedCaptions
* @param {!Element} node
* @param {?shaka.dash.DashParser.AccessibilityPurpose} accessibilityPurpose
*
* @return {?shaka.extern.Stream} The Stream, or null when there is a
* non-critical parsing error.
* @private
*/
parseRepresentation_(context, contentProtection, kind, language, label,
isPrimary, roles, closedCaptions, node) {
isPrimary, roles, closedCaptions, node, accessibilityPurpose) {
const XmlUtils = shaka.util.XmlUtils;
const ContentType = shaka.util.ManifestParserUtils.ContentType;

Expand Down Expand Up @@ -1320,6 +1333,7 @@ shaka.dash.DashParser = class {
hdr,
tilesLayout,
matchedStreams: [],
accessibilityPurpose,
};
}

Expand Down Expand Up @@ -2072,6 +2086,16 @@ shaka.dash.DashParser.AdaptationInfo;
shaka.dash.DashParser.GenerateSegmentIndexFunction;


/**
* @enum {string}
* @export
*/
shaka.dash.DashParser.AccessibilityPurpose = {
VISUALLY_IMPAIRED: 'visually impaired',
HARD_OF_HEARING: 'hard of hearing',
};


/**
* @typedef {{
* generateSegmentIndex: shaka.dash.DashParser.GenerateSegmentIndexFunction
Expand Down
1 change: 1 addition & 0 deletions lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,7 @@ shaka.hls.HlsParser = class {
closedCaptions,
hdr: undefined,
tilesLayout: undefined,
accessibilityPurpose: null,
};
}

Expand Down
1 change: 1 addition & 0 deletions lib/mss/mss_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ shaka.mss.MssParser = class {
timescale: context.timescale,
codecPrivateData: null,
},
accessibilityPurpose: null,
};

// This is specifically for text tracks.
Expand Down
1 change: 1 addition & 0 deletions lib/offline/manifest_converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ shaka.offline.ManifestConverter = class {
spatialAudio: streamDB.spatialAudio,
closedCaptions: streamDB.closedCaptions,
tilesLayout: streamDB.tilesLayout,
accessibilityPurpose: null,
};

return stream;
Expand Down
4 changes: 4 additions & 0 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -2384,6 +2384,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
audioSamplingRate: null,
spatialAudio: false,
closedCaptions: null,
accessibilityPurpose: null,
},
bandwidth: 100,
allowedByApplication: true,
Expand Down Expand Up @@ -4860,6 +4861,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
audioSamplingRate: null,
spatialAudio: false,
closedCaptions: null,
accessibilityPurpose: null,
};

const fullMimeType = shaka.util.MimeUtils.getFullType(
Expand Down Expand Up @@ -5011,6 +5013,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
spatialAudio: false,
closedCaptions: null,
tilesLayout: '1x1',
accessibilityPurpose: null,
};

this.manifest_.imageStreams.push(stream);
Expand Down Expand Up @@ -5430,6 +5433,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
audioSamplingRate: null,
spatialAudio: false,
closedCaptions: null,
accessibilityPurpose: null,
};
manifest.textStreams.push(textStream);
closedCaptionsSet.add(id);
Expand Down
1 change: 1 addition & 0 deletions lib/util/periods.js
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,7 @@ shaka.util.PeriodCombiner = class {
audioSamplingRate: null,
spatialAudio: false,
closedCaptions: null,
accessibilityPurpose: null,
};
}

Expand Down
5 changes: 5 additions & 0 deletions lib/util/stream_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,7 @@ shaka.util.StreamUtils = class {
originalAudioId: null,
originalTextId: null,
originalImageId: null,
accessibilityPurpose: null,
};

if (video) {
Expand All @@ -1130,6 +1131,7 @@ shaka.util.StreamUtils = class {
track.spatialAudio = audio.spatialAudio;
track.label = audio.label;
track.audioRoles = audio.roles;
track.accessibilityPurpose = audio.accessibilityPurpose;
}

return track;
Expand Down Expand Up @@ -1179,6 +1181,7 @@ shaka.util.StreamUtils = class {
originalAudioId: null,
originalTextId: stream.originalId,
originalImageId: null,
accessibilityPurpose: stream.accessibilityPurpose,
};

return track;
Expand Down Expand Up @@ -1253,6 +1256,7 @@ shaka.util.StreamUtils = class {
originalAudioId: null,
originalTextId: null,
originalImageId: stream.originalId,
accessibilityPurpose: null,
};

return track;
Expand Down Expand Up @@ -1373,6 +1377,7 @@ shaka.util.StreamUtils = class {
originalAudioId: null,
originalTextId: null,
originalImageId: null,
accessibilityPurpose: null,
};

return track;
Expand Down
31 changes: 31 additions & 0 deletions test/dash/dash_parser_manifest_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -1864,6 +1864,37 @@ describe('DashParser Manifest', () => {
expect(stream).toBeUndefined();
});

it('reads accessibility purpose elements', async () => {
const manifestText = [
'<MPD minBufferTime="PT75S">',
' <Period id="1" duration="PT30S">',
' <AdaptationSet id="1" contentType="text">',
' <Accessibility ',
' schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007"',
' value="2" />',
' <Accessibility schemeIdUri="foobar" value="bar" />',
' <Representation id="text-en" mimeType="text/webvtt">',
' <BaseURL>t-en.vtt</BaseURL>',
' </Representation>',
' </AdaptationSet>',
' <AdaptationSet id="1" mimeType="video/mp4">',
' <Representation id="video-sd" width="640" height="480">',
' <BaseURL>v-sd.mp4</BaseURL>',
' <SegmentBase indexRange="100-200" />',
' </Representation>',
' </AdaptationSet>',
' </Period>',
'</MPD>',
].join('\n');

fakeNetEngine.setResponseText('dummy://foo', manifestText);
/** @type {shaka.extern.Manifest} */
const manifest = await parser.start('dummy://foo', playerInterface);
const textStream = manifest.textStreams[0];
expect(textStream.accessibilityPurpose)
.toBe(shaka.dash.DashParser.AccessibilityPurpose.HARD_OF_HEARING);
});

it('converts Accessibility element to "kind"', async () => {
const manifestText = [
'<MPD minBufferTime="PT75S">',
Expand Down
1 change: 1 addition & 0 deletions test/media/adaptation_set_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ describe('AdaptationSet', () => {
forced: false,
trickModeVideo: null,
type: '',
accessibilityPurpose: null,
};
}
});
Expand Down
2 changes: 2 additions & 0 deletions test/offline/storage_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,7 @@ filterDescribe('Storage', storageSupport, () => {
originalAudioId: audioId.toString(),
originalTextId: null,
originalImageId: null,
accessibilityPurpose: null,
};
}

Expand Down Expand Up @@ -1447,6 +1448,7 @@ filterDescribe('Storage', storageSupport, () => {
originalAudioId: null,
originalTextId: id.toString(),
originalImageId: null,
accessibilityPurpose: null,
};
}

Expand Down
2 changes: 2 additions & 0 deletions test/test/util/manifest_generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,8 @@ shaka.test.ManifestGenerator.Stream = class {
this.hdr = undefined;
/** @type {(string|undefined)} */
this.tilesLayout = undefined;
/** @type {?shaka.dash.DashParser.AccessibilityPurpose} */
this.accessibilityPurpose;
}

/** @type {shaka.extern.Stream} */
Expand Down
3 changes: 3 additions & 0 deletions test/test/util/streaming_engine_util.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ shaka.test.StreamingEngineUtil = class {
roles: [],
forced: false,
spatialAudio: false,
accessibilityPurpose: null,
};
}

Expand Down Expand Up @@ -449,6 +450,7 @@ shaka.test.StreamingEngineUtil = class {
roles: [],
forced: false,
spatialAudio: false,
accessibilityPurpose: null,
};
}

Expand Down Expand Up @@ -484,6 +486,7 @@ shaka.test.StreamingEngineUtil = class {
roles: [],
forced: false,
spatialAudio: false,
accessibilityPurpose: null,
};
}
};

0 comments on commit 5ec18b5

Please sign in to comment.