@@ -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 }
0 commit comments