Skip to content

Commit aefba44

Browse files
committed
Merge remote-tracking branch 'origin/development' into feature/certurl
# Conflicts: # src/streaming/protection/controllers/ProtectionController.js
2 parents 70268b6 + 2e7e9a9 commit aefba44

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+6078
-4334
lines changed

index.d.ts

Lines changed: 4255 additions & 4220 deletions
Large diffs are not rendered by default.

samples/dash-if-reference-player/app/contributors.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@
6868
"name": "Broadpeak",
6969
"logo": "app/img/broadpeak.png",
7070
"link": "https://broadpeak.tv/"
71+
},
72+
{
73+
"name": "V-Nova",
74+
"logo": "app/img/v-nova.png",
75+
"link": "https://v-nova.com/"
7176
}
7277
]
7378
}

samples/dash-if-reference-player/app/css/main.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ a:hover {
153153

154154
.dash-video-player {
155155
background-color: #000000;
156+
position: relative;
156157
}
157158

158159
.col-md-9 video {
@@ -179,6 +180,10 @@ a:hover {
179180
margin-top: -5px !important;
180181
}
181182

183+
.element-hidden {
184+
display: none !important;
185+
}
186+
182187
.btn-play-pause,
183188
.control-icon-layout {
184189
padding: 4px 10px !important;
91.5 KB
Loading

samples/dash-if-reference-player/app/main.js

Lines changed: 193 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,22 +184,34 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
184184
drmKeySystem: 'com.microsoft.playready',
185185
licenseServerUrl: '',
186186
httpRequestHeaders: {},
187-
priority: 1
187+
serverCertificate: '',
188+
httpTimeout: 5000,
189+
priority: 1,
190+
audioRobustness: '',
191+
videoRobustness: '',
192+
isCustomRobustness: false
188193
}
189194

190195
$scope.drmWidevine = {
191196
isActive: false,
192197
drmKeySystem: 'com.widevine.alpha',
193198
licenseServerUrl: '',
194199
httpRequestHeaders: {},
195-
priority: 0
200+
serverCertificate: '',
201+
httpTimeout: 5000,
202+
priority: 0,
203+
audioRobustness: '',
204+
videoRobustness: '',
205+
isCustomRobustness: false
196206
}
197207

198208
$scope.drmClearkey = {
199209
isActive: false,
200210
drmKeySystem: 'org.w3.clearkey',
201211
licenseServerUrl: '',
202212
httpRequestHeaders: {},
213+
serverCertificate: '',
214+
httpTimeout: 5000,
203215
kid: '',
204216
key: '',
205217
clearkeys: {},
@@ -226,6 +238,8 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
226238

227239
$scope.conformanceViolations = [];
228240

241+
$scope.enhancementDecoder = null;
242+
229243
var defaultExternalSettings = {
230244
mpd: encodeURIComponent('https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd'),
231245
loop: true,
@@ -282,6 +296,12 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
282296
$scope.audioLiveLatency = 0;
283297
$scope.audioPlaybackRate = 1.00;
284298

299+
$scope.activePeriod = '';
300+
$scope.bufferingPeriod = '';
301+
302+
$scope.mpdType = '';
303+
$scope.numberOfPeriods = 0;
304+
285305
// Starting Options
286306
$scope.autoPlaySelected = true;
287307
$scope.autoLoadSelected = false;
@@ -422,6 +442,12 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
422442

423443
$scope.player.on(dashjs.MediaPlayer.events.MANIFEST_LOADED, function (e) {
424444
$scope.isDynamic = e.data.type === 'dynamic';
445+
if (e.data.Period) {
446+
$scope.numberOfPeriods = e.data.Period.length;
447+
}
448+
if (e.data.type) {
449+
$scope.mpdType = e.data.type;
450+
}
425451
}, $scope);
426452

427453

@@ -438,11 +464,16 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
438464
$scope[e.mediaType + 'Bitrate'] = bitrate;
439465
$scope.plotPoint('pendingIndex', e.mediaType, e.newQuality + 1, getTimeForPlot());
440466
$scope.safeApply();
467+
468+
if (e.currentRepresentation && e.currentRepresentation.adaptation && e.currentRepresentation.adaptation.period) {
469+
$scope.bufferingPeriod = e.currentRepresentation.adaptation.period.id;
470+
}
441471
}, $scope);
442472

443473

444474
$scope.player.on(dashjs.MediaPlayer.events.PERIOD_SWITCH_COMPLETED, function (e) {
445475
$scope.currentStreamInfo = e.toStreamInfo;
476+
$scope.activePeriod = e.toStreamInfo.id;
446477
}, $scope);
447478

448479
$scope.player.on(dashjs.MediaPlayer.events.QUALITY_CHANGE_RENDERED, function (e) {
@@ -1023,6 +1054,126 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
10231054
});
10241055
};
10251056

1057+
$scope.toggleEnhancementEnabled = function () {
1058+
const video = document.querySelector('video');
1059+
const canvas = document.querySelector('canvas');
1060+
1061+
if ($scope.enhancementEnabled) {
1062+
canvas.classList.remove('element-hidden');
1063+
video.classList.add('element-hidden');
1064+
} else {
1065+
canvas.classList.add('element-hidden');
1066+
video.classList.remove('element-hidden');
1067+
}
1068+
};
1069+
1070+
$scope.setupEnhancementDecoder = function () {
1071+
/**
1072+
* MPEG-5 LCEVC Integration for Dash.js Player.
1073+
*
1074+
* These are the changes needed for passing the correct
1075+
* data to lcevc_dec.js and trigger the correct methods
1076+
* at the correct time.
1077+
*/
1078+
1079+
/**
1080+
* Let the LCEVC Decoder Library make the decision as to when to switch, based on the currently
1081+
* rendered frame. If disabled, the player needs to signal LCEVC when there is a render change
1082+
* after an ABR switch happens.
1083+
*
1084+
* @readonly
1085+
* @enum {number}
1086+
* @public
1087+
*/
1088+
const AutoRenderMode = {
1089+
DISABLED: 0,
1090+
ENABLED: 1
1091+
};
1092+
1093+
dashjs.Extensions = {
1094+
...dashjs.Extensions,
1095+
/**
1096+
* Attaches LCEVC functionality and methods to the provided Dash.js player instance.
1097+
*
1098+
* @param {object} player the Dash.js player instance to attach LCEVC to
1099+
*/
1100+
useLcevc: function useLcevc(player) {
1101+
if (!player) {
1102+
throw new TypeError('The provided Dash.js player instance was null or undefined.');
1103+
}
1104+
const { LCEVCdec } = window;
1105+
if (!LCEVCdec) {
1106+
throw new TypeError('LCEVC Decoder Libraries could not be loaded.');
1107+
}
1108+
1109+
let abrIndex = -1;
1110+
1111+
player.attachLcevc = function attachLcevc(media, canvas, LCEVCdecConfig) {
1112+
player.LCEVCdec = new LCEVCdec.LCEVCdec(
1113+
media,
1114+
canvas,
1115+
LCEVCdecConfig
1116+
);
1117+
1118+
/* Signal profile information and switches to LCEVCdecJS */
1119+
player.on(dashjs.MediaPlayer.events.QUALITY_CHANGE_REQUESTED, handleQualityChange);
1120+
player.on(dashjs.MediaPlayer.events.FRAGMENT_LOADING_COMPLETED, handleFragmentLoadingCompleted);
1121+
player.on(dashjs.MediaPlayer.events.REPRESENTATION_SWITCH, handleRepresentationSwitch);
1122+
player.on('externalSourceBufferUpdateStart', handleBufferUpdates);
1123+
};
1124+
1125+
function handleFragmentLoadingCompleted(event) {
1126+
if (event.mediaType === 'enhancement') {
1127+
abrIndex = event.request.representation.absoluteIndex;
1128+
}
1129+
}
1130+
1131+
function handleQualityChange(event) {
1132+
if (event.mediaType === 'video' || event.mediaType === 'enhancement') {
1133+
const index = event.newRepresentation.absoluteIndex;
1134+
console.log('>>> requested:', event.mediaType, index);
1135+
player.LCEVCdec.setLevelSwitching(index, AutoRenderMode.ENABLED);
1136+
}
1137+
}
1138+
1139+
function handleRepresentationSwitch(event) {
1140+
if (event.mediaType === 'video' || event.mediaType === 'enhancement') {
1141+
const rep = event.currentRepresentation;
1142+
const index = rep.absoluteIndex;
1143+
// Workaround for very first representation played for which no QUALITY_CHANGE_REQUESTED arrives
1144+
if (rep && rep.dependentRepresentation) {
1145+
console.log('>>> rep switch:', event.mediaType, index);
1146+
player.LCEVCdec.setLevelSwitching(index, AutoRenderMode.ENABLED);
1147+
}
1148+
}
1149+
}
1150+
1151+
function handleBufferUpdates(event) {
1152+
if (event.request === 'appendBuffer') {
1153+
player.LCEVCdec.appendBuffer(event.data, 'video', abrIndex, 0, /* isMuxed */ false);
1154+
}
1155+
else if (event.request === 'remove') {
1156+
player.LCEVCdec.flushBuffer(event.start, event.end);
1157+
}
1158+
}
1159+
}
1160+
};
1161+
1162+
const video = document.querySelector('video');
1163+
const canvas = document.querySelector('canvas');
1164+
const LCEVCdecConfig = {
1165+
dynamicPerformanceScaling: false
1166+
};
1167+
1168+
window.LCEVCdec.ready.then(() => {
1169+
/* Attach LCEVC to the Dash.js player instance */
1170+
const player = $scope.player;
1171+
dashjs.Extensions.useLcevc(player);
1172+
player.attachLcevc(video, canvas, LCEVCdecConfig);
1173+
$scope.enhancementDecoder = player.LCEVCdec;
1174+
});
1175+
};
1176+
10261177
$scope.toggleCmsdApplyMb = function () {
10271178
$scope.player.updateSettings({
10281179
streaming: {
@@ -1092,7 +1243,8 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
10921243
liveDelay: $scope.defaultLiveDelay
10931244
},
10941245
abr: {},
1095-
cmcd: {}
1246+
cmcd: {},
1247+
enhancement: {}
10961248
}
10971249
};
10981250

@@ -1158,6 +1310,21 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
11581310
config.streaming.cmcd.rtpSafetyFactor = $scope.cmcdRtpSafetyFactor ? $scope.cmcdRtpSafetyFactor : null;
11591311
config.streaming.cmcd.enabledKeys = $scope.cmcdEnabledKeys ? $scope._getFormatedCmcdEnabledKeys() : [];
11601312

1313+
// Cleanup enhancement decoder if it exists from previous playback
1314+
if ($scope.enhancementDecoder) {
1315+
$scope.enhancementDecoder.close();
1316+
$scope.enhancementDecoder = null;
1317+
}
1318+
1319+
// Setup enhancement decoder if checkbox is checked or if stream is from V-Nova
1320+
if ($scope.enhancementEnabled || $scope.selectedItem.provider === 'v-nova') {
1321+
config.streaming.enhancement.enabled = true;
1322+
$scope.enhancementEnabled = true;
1323+
$scope.setupEnhancementDecoder();
1324+
}
1325+
1326+
$scope.toggleEnhancementEnabled();
1327+
11611328
$scope.player.updateSettings(config);
11621329

11631330
$scope.controlbar.reset();
@@ -1330,6 +1497,14 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
13301497
if (!angular.equals(input.httpRequestHeaders, {})) {
13311498
protectionData[input.drmKeySystem]['httpRequestHeaders'] = input.httpRequestHeaders;
13321499
}
1500+
1501+
if (input.audioRobustness) {
1502+
protectionData[input.drmKeySystem]['audioRobustness'] = input.audioRobustness;
1503+
}
1504+
1505+
if (input.videoRobustness) {
1506+
protectionData[input.drmKeySystem]['videoRobustness'] = input.videoRobustness;
1507+
}
13331508
} else {
13341509
alert('Kid and Key must be specified!');
13351510
}
@@ -1370,12 +1545,21 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
13701545
if (!angular.equals(input.httpRequestHeaders, {})) {
13711546
protectionData[input.drmKeySystem]['httpRequestHeaders'] = input.httpRequestHeaders;
13721547
}
1548+
1549+
if (input.audioRobustness) {
1550+
protectionData[input.drmKeySystem]['audioRobustness'] = input.audioRobustness;
1551+
}
1552+
1553+
if (input.videoRobustness) {
1554+
protectionData[input.drmKeySystem]['videoRobustness'] = input.videoRobustness;
1555+
}
13731556
}
13741557
}
13751558
}
13761559

13771560
$scope.protectionData = protectionData;
13781561
$scope.player.setProtectionData(protectionData);
1562+
console.log(protectionData);
13791563
}
13801564

13811565
$scope.addPopupInput = function (keySystem) {
@@ -1843,7 +2027,8 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
18432027
key !== 'priority' &&
18442028
key !== 'kid' &&
18452029
key !== 'key' &&
1846-
key !== 'inputMode') {
2030+
key !== 'inputMode' &&
2031+
key !== 'isCustomRobustness') {
18472032
queryProtectionData[drmObject[drm].drmKeySystem][key] = drmObject[drm][key];
18482033
}
18492034
}
@@ -1876,7 +2061,8 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
18762061
key !== 'drmKeySystem' &&
18772062
key !== 'licenseServerUrl' &&
18782063
key !== 'httpRequestHeaders' &&
1879-
key !== 'priority') {
2064+
key !== 'priority' &&
2065+
key !== 'isCustomRobustness') {
18802066
queryProtectionData[drmObject[drm].drmKeySystem][key] = drmObject[drm][key];
18812067
}
18822068
}
@@ -2008,8 +2194,8 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
20082194
else if (value === 'null') typedValue = null;
20092195
else if (value === 'undefined') typedValue = undefined;
20102196
else integerRegEx.test(value) ? typedValue = parseInt(value) :
2011-
(floatRegEx.test(value) ? typedValue = parseFloat(value) :
2012-
typedValue = value);
2197+
(floatRegEx.test(value) ? typedValue = parseFloat(value) :
2198+
typedValue = value);
20132199

20142200
return typedValue;
20152201
}

samples/dash-if-reference-player/app/sources.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@
9393
"acronym": "ARTE",
9494
"name": "ARTE",
9595
"url": "https://www.arte.tv/en/"
96+
},
97+
"v-nova": {
98+
"acronym": "V-Nova",
99+
"name": "V-Nova",
100+
"url": "https://v-nova.com/"
96101
}
97102
},
98103
"items": [
@@ -1303,6 +1308,21 @@
13031308
"provider": "microsoft"
13041309
}
13051310
]
1311+
},
1312+
{
1313+
"name": "MPEG-5 Part 2 - LCEVC",
1314+
"submenu": [
1315+
{
1316+
"url": "https://s3.eu-west-1.amazonaws.com/origin-prod-lon-v-nova.com/lcevcDualTrack/1080p30_4Mbps_no_dR/master.mpd",
1317+
"name": "Scalable Carriage",
1318+
"provider": "v-nova"
1319+
},
1320+
{
1321+
"url": "https://s3.eu-west-1.amazonaws.com/origin-prod-lon-v-nova.com/lcevcDualTrack/1080p30_4Mbps_with_dR/master.mpd",
1322+
"name": "Scalable with Debug Residuals",
1323+
"provider": "v-nova"
1324+
}
1325+
]
13061326
}
13071327
]
13081328
}

0 commit comments

Comments
 (0)