Skip to content

Commit 789101c

Browse files
authored
feat(DASH): Add DVB Font downloads (#6971)
1 parent f56f7ba commit 789101c

20 files changed

+148
-1
lines changed

demo/common/assets.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ shakaAssets.Source = {
4141
EZDRM: 'EZDRM',
4242
THEO_PLAYER: 'THEOplayer',
4343
JWPLAYER: 'JW Player',
44+
BBC: 'BBC',
4445
};
4546

4647

@@ -1686,5 +1687,39 @@ shakaAssets.testAssets = [
16861687
defaultVrProjectionMode: 'equirectangular',
16871688
}),
16881689
// }}}
1690+
1691+
// BBC assets {{{
1692+
/* BBC Contents */
1693+
new ShakaDemoAssetInfo(
1694+
/* name= */ 'On-demand Testcard - WOFF Font Download signalled with supplemental property descriptor',
1695+
/* iconUri= */ '',
1696+
/* manifestUri= */ 'https://rdmedia.bbc.co.uk/testcard/vod/manifests/avc-ctv-stereo-en-sfdt-woff.mpd',
1697+
/* source= */ shakaAssets.Source.BBC)
1698+
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
1699+
.addFeature(shakaAssets.Feature.MP4),
1700+
new ShakaDemoAssetInfo(
1701+
/* name= */ 'On-demand Testcard - WOFF Font Download signalled with essential property descriptor',
1702+
/* iconUri= */ '',
1703+
/* manifestUri= */ 'https://rdmedia.bbc.co.uk/testcard/vod/manifests/avc-ctv-stereo-en-efdt-woff.mpd',
1704+
/* source= */ shakaAssets.Source.BBC)
1705+
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
1706+
.addFeature(shakaAssets.Feature.MP4),
1707+
new ShakaDemoAssetInfo(
1708+
/* name= */ 'Live Testcard - WOFF Font Download signalled with supplemental property descriptor',
1709+
/* iconUri= */ '',
1710+
/* manifestUri= */ 'https://rdmedia.bbc.co.uk/testcard/simulcast/manifests/avc-ctv-stereo-en-sfdt-woff.mpd',
1711+
/* source= */ shakaAssets.Source.BBC)
1712+
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
1713+
.addFeature(shakaAssets.Feature.MP4)
1714+
.addFeature(shakaAssets.Feature.LIVE),
1715+
new ShakaDemoAssetInfo(
1716+
/* name= */ 'Live Testcard - WOFF Font Download signalled with essential property descriptor',
1717+
/* iconUri= */ '',
1718+
/* manifestUri= */ 'https://rdmedia.bbc.co.uk/testcard/simulcast/manifests/avc-ctv-stereo-en-efdt-woff.mpd',
1719+
/* source= */ shakaAssets.Source.BBC)
1720+
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
1721+
.addFeature(shakaAssets.Feature.MP4)
1722+
.addFeature(shakaAssets.Feature.LIVE),
1723+
// }}}
16891724
];
16901725
/* eslint-enable max-len */

externs/font_face_set.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*! @license
2+
* Shaka Player
3+
* Copyright 2016 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @fileoverview Externs for FontFaceSet which were missing in the
9+
* Closure compiler.
10+
*
11+
* @externs
12+
*/
13+
14+
/**
15+
* @return {!Array.<FontFace>}
16+
*/
17+
FontFaceSet.prototype.values = function() {};

externs/shaka/manifest_parser.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ shaka.extern.ManifestParser = class {
139139
* getBandwidthEstimate: function():number,
140140
* onMetadata: function(string, number, ?number,
141141
* !Array.<shaka.extern.MetadataFrame>),
142-
* disableStream: function(!shaka.extern.Stream)
142+
* disableStream: function(!shaka.extern.Stream),
143+
* addFont: function(string, string)
143144
* }}
144145
*
145146
* @description
@@ -184,6 +185,8 @@ shaka.extern.ManifestParser = class {
184185
* @property {function(!shaka.extern.Stream)} disableStream
185186
* Called to temporarily disable a stream i.e. disabling all variant
186187
* containing said stream.
188+
* @property {function(string, string)} addFont
189+
* Called when a new font needs to be added.
187190
* @exportDoc
188191
*/
189192
shaka.extern.ManifestParser.PlayerInterface;

lib/dash/dash_parser.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,12 @@ shaka.dash.DashParser = class {
16731673
} else if (schemeId == 'urn:mpeg:dash:ssr:2023' &&
16741674
this.config_.dash.enableFastSwitching) {
16751675
isFastSwitching = true;
1676+
} else if (schemeId == 'urn:dvb:dash:fontdownload:2014') {
1677+
const fontFamily = prop.attributes['dvb:fontFamily'];
1678+
const fontUrl = prop.attributes['dvb:url'];
1679+
if (fontFamily && fontUrl) {
1680+
this.playerInterface_.addFont(fontFamily, fontUrl);
1681+
}
16761682
} else {
16771683
unrecognizedEssentialProperty = true;
16781684
}
@@ -1694,6 +1700,12 @@ shaka.dash.DashParser = class {
16941700
colorGamut = getColorGamutFromColourPrimariesCICP(
16951701
parseInt(prop.attributes['value'], 10),
16961702
);
1703+
} else if (schemeId == 'urn:dvb:dash:fontdownload:2014') {
1704+
const fontFamily = prop.attributes['dvb:fontFamily'];
1705+
const fontUrl = prop.attributes['dvb:url'];
1706+
if (fontFamily && fontUrl) {
1707+
this.playerInterface_.addFont(fontFamily, fontUrl);
1708+
}
16971709
}
16981710
}
16991711

lib/offline/storage.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,7 @@ shaka.offline.Storage = class {
11801180
getBandwidthEstimate: () => config.abr.defaultBandwidthEstimate,
11811181
onMetadata: () => {},
11821182
disableStream: (stream) => {},
1183+
addFont: (name, url) => {},
11831184
};
11841185

11851186
parser.configure(config.manifest);

lib/player.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,6 +2109,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
21092109
},
21102110
disableStream: (stream) => this.disableStream(
21112111
stream, this.config_.streaming.maxDisabledTime),
2112+
addFont: (name, url) => this.addFont(name, url),
21122113
};
21132114
const regionTimeline =
21142115
new shaka.media.RegionTimeline(() => this.seekRange());
@@ -7329,6 +7330,30 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
73297330
}
73307331
}
73317332

7333+
/**
7334+
* Load a new font on the page. If the font was already loaded, it does
7335+
* nothing.
7336+
*
7337+
* @param {string} name
7338+
* @param {string} url
7339+
*/
7340+
async addFont(name, url) {
7341+
if ('fonts' in document && 'FontFace' in window ) {
7342+
await document.fonts.ready;
7343+
if (!('values' in document.fonts)) {
7344+
return;
7345+
}
7346+
for (const fontFace of document.fonts.values()) {
7347+
if (fontFace.family == name && fontFace.display == 'swap') {
7348+
// Font already loaded.
7349+
return;
7350+
}
7351+
}
7352+
const fontFace = new FontFace(name, `url(${url})`, {display: 'swap'});
7353+
document.fonts.add(fontFace);
7354+
}
7355+
}
7356+
73327357
/**
73337358
* When we fire region events, we need to copy the information out of the
73347359
* region to break the connection with the player's internal data. We do the

test/cast/cast_utils_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ describe('CastUtils', () => {
3333
'preload',
3434
'destroyAllPreloads',
3535
'getNonDefaultConfiguration',
36+
'addFont',
3637

3738
// Test helper methods (not @export'd)
3839
'createDrmEngine',

test/dash/dash_parser_content_protection_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ describe('DashParser ContentProtection', () => {
4848
getBandwidthEstimate: () => 1e6,
4949
onMetadata: () => {},
5050
disableStream: (stream) => {},
51+
addFont: (name, url) => {},
5152
};
5253

5354
const actual = await dashParser.start(

test/dash/dash_parser_live_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ describe('DashParser Live', () => {
4040
getBandwidthEstimate: () => 1e6,
4141
onMetadata: () => {},
4242
disableStream: (stream) => {},
43+
addFont: (name, url) => {},
4344
};
4445
});
4546

test/dash/dash_parser_manifest_unit.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ describe('DashParser Manifest', () => {
1616
let parser;
1717
/** @type {!jasmine.Spy} */
1818
let onEventSpy;
19+
/** @type {!jasmine.Spy} */
20+
let addFontSpy;
1921
/** @type {shaka.extern.ManifestParser.PlayerInterface} */
2022
let playerInterface;
2123
/** @type {!ArrayBuffer} */
@@ -40,6 +42,7 @@ describe('DashParser Manifest', () => {
4042
fakeNetEngine = new shaka.test.FakeNetworkingEngine();
4143
parser = shaka.test.Dash.makeDashParser();
4244
onEventSpy = jasmine.createSpy('onEvent');
45+
addFontSpy = jasmine.createSpy('addFont');
4346
playerInterface = {
4447
networkingEngine: fakeNetEngine,
4548
modifyManifestRequest: (request, manifestInfo) => {},
@@ -58,6 +61,7 @@ describe('DashParser Manifest', () => {
5861
getBandwidthEstimate: () => 1e6,
5962
onMetadata: () => {},
6063
disableStream: (stream) => {},
64+
addFont: shaka.test.Util.spyFunc(addFontSpy),
6165
};
6266
});
6367

@@ -3190,4 +3194,39 @@ describe('DashParser Manifest', () => {
31903194
const manifest = await parser.start('dummy://foo', playerInterface);
31913195
expect(manifest.gapCount).toBe(1);
31923196
});
3197+
3198+
it('supports dvb fonts', async () => {
3199+
const manifestText = [
3200+
'<MPD type="static">',
3201+
' <Period id="1" duration="PT30S">',
3202+
' <AdaptationSet id="2" mimeType="video/mp4">',
3203+
' <SupplementalProperty',
3204+
' schemeIdUri="urn:dvb:dash:fontdownload:2014"',
3205+
' value="1" dvb:url="foo.woff"',
3206+
' dvb:mimeType="application/font-woff" dvb:fontFamily="foo"/>',
3207+
' <Representation id="video" bandwidth="1">',
3208+
' <SegmentBase indexRange="100-200" />',
3209+
' </Representation>',
3210+
' </AdaptationSet>',
3211+
' </Period>',
3212+
' <Period id="2" start="PT31S" duration="PT30S">',
3213+
' <AdaptationSet id="2" mimeType="video/mp4">',
3214+
' <EssentialProperty schemeIdUri="urn:dvb:dash:fontdownload:2014"',
3215+
' value="1" dvb:url="foo2.woff"',
3216+
' dvb:mimeType="application/font-woff" dvb:fontFamily="foo2"/>',
3217+
' <Representation id="video" bandwidth="1">',
3218+
' <SegmentBase indexRange="100-200" />',
3219+
' </Representation>',
3220+
' </AdaptationSet>',
3221+
' </Period>',
3222+
'</MPD>',
3223+
].join('\n');
3224+
3225+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
3226+
3227+
await parser.start('dummy://foo', playerInterface);
3228+
expect(addFontSpy).toHaveBeenCalledTimes(2);
3229+
expect(addFontSpy).toHaveBeenCalledWith('foo', 'foo.woff');
3230+
expect(addFontSpy).toHaveBeenCalledWith('foo2', 'foo2.woff');
3231+
});
31933232
});

test/dash/dash_parser_patch_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ describe('DashParser Patch', () => {
5151
getBandwidthEstimate: () => 1e6,
5252
onMetadata: () => {},
5353
disableStream: (stream) => {},
54+
addFont: (name, url) => {},
5455
};
5556
Date.now = () => publishTime.getTime() + 10;
5657

test/dash/dash_parser_segment_base_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ describe('DashParser SegmentBase', () => {
4444
getBandwidthEstimate: () => 1e6,
4545
onMetadata: () => {},
4646
disableStream: (stream) => {},
47+
addFont: (name, url) => {},
4748
};
4849
});
4950

test/dash/dash_parser_segment_list_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ describe('DashParser SegmentList', () => {
354354
getBandwidthEstimate: () => 1e6,
355355
onMetadata: () => {},
356356
disableStream: (stream) => {},
357+
addFont: (name, url) => {},
357358
};
358359
try {
359360
const manifest = await dashParser.start('dummy://foo', playerInterface);

test/dash/dash_parser_segment_template_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ describe('DashParser SegmentTemplate', () => {
5353
getBandwidthEstimate: () => 1e6,
5454
onMetadata: () => {},
5555
disableStream: (stream) => {},
56+
addFont: (name, url) => {},
5657
};
5758
});
5859

test/hls/hls_live_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ describe('HlsParser live', () => {
8383
getBandwidthEstimate: () => 1e6,
8484
onMetadata: () => {},
8585
disableStream: (stream) => {},
86+
addFont: (name, url) => {},
8687
};
8788

8889
parser = new shaka.hls.HlsParser();

test/hls/hls_parser_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ describe('HlsParser', () => {
9797
getBandwidthEstimate: () => 1e6,
9898
onMetadata: shaka.test.Util.spyFunc(onMetadataSpy),
9999
disableStream: (stream) => {},
100+
addFont: (name, url) => {},
100101
};
101102

102103
parser = new shaka.hls.HlsParser();

test/mss/mss_parser_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ describe('MssParser Manifest', () => {
8383
getBandwidthEstimate: () => 1e6,
8484
onMetadata: () => {},
8585
disableStream: (stream) => {},
86+
addFont: (name, url) => {},
8687
};
8788
});
8889

test/test/util/dash_parser_util.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ shaka.test.Dash = class {
4949
getBandwidthEstimate: () => 1e6,
5050
onMetadata: () => {},
5151
disableStream: (stream) => {},
52+
addFont: (name, url) => {},
5253
};
5354
try {
5455
const manifest = await dashParser.start('dummy://foo', playerInterface);
@@ -93,6 +94,7 @@ shaka.test.Dash = class {
9394
getBandwidthEstimate: () => 1e6,
9495
onMetadata: () => {},
9596
disableStream: (stream) => {},
97+
addFont: (name, url) => {},
9698
};
9799

98100
try {

test/test/util/mss_parser_util.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ shaka.test.Mss = class {
4949
getBandwidthEstimate: () => 1e6,
5050
onMetadata: () => {},
5151
disableStream: (stream) => {},
52+
addFont: (name, url) => {},
5253
};
5354
const manifest = await mssParser.start('dummy://foo', playerInterface);
5455
const stream = manifest.variants[0].audio;
@@ -89,6 +90,7 @@ shaka.test.Mss = class {
8990
getBandwidthEstimate: () => 1e6,
9091
onMetadata: () => {},
9192
disableStream: (stream) => {},
93+
addFont: (name, url) => {},
9294
};
9395
const p = mssParser.start('dummy://foo', playerInterface);
9496
await expectAsync(p).toBeRejectedWith(

test/util/content_steering_manager_unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ describe('ContentSteeringManager', () => {
3131
getBandwidthEstimate: () => 1e6,
3232
onMetadata: () => {},
3333
disableStream: (stream) => {},
34+
addFont: (name, url) => {},
3435
};
3536
const config = shaka.util.PlayerConfiguration.createDefault().manifest;
3637
manager = new shaka.util.ContentSteeringManager(playerInterface);

0 commit comments

Comments
 (0)