@@ -238,6 +238,8 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
238238
239239 $scope . conformanceViolations = [ ] ;
240240
241+ $scope . enhancementDecoder = null ;
242+
241243 var defaultExternalSettings = {
242244 mpd : encodeURIComponent ( 'https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd' ) ,
243245 loop : true ,
@@ -1052,6 +1054,126 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
10521054 } ) ;
10531055 } ;
10541056
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+
10551177 $scope . toggleCmsdApplyMb = function ( ) {
10561178 $scope . player . updateSettings ( {
10571179 streaming : {
@@ -1121,7 +1243,8 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
11211243 liveDelay : $scope . defaultLiveDelay
11221244 } ,
11231245 abr : { } ,
1124- cmcd : { }
1246+ cmcd : { } ,
1247+ enhancement : { }
11251248 }
11261249 } ;
11271250
@@ -1187,6 +1310,21 @@ app.controller('DashController', ['$scope', '$window', 'sources', 'contributors'
11871310 config . streaming . cmcd . rtpSafetyFactor = $scope . cmcdRtpSafetyFactor ? $scope . cmcdRtpSafetyFactor : null ;
11881311 config . streaming . cmcd . enabledKeys = $scope . cmcdEnabledKeys ? $scope . _getFormatedCmcdEnabledKeys ( ) : [ ] ;
11891312
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+
11901328 $scope . player . updateSettings ( config ) ;
11911329
11921330 $scope . controlbar . reset ( ) ;
0 commit comments