All files / src/controller fps-controller.js

2.63% Statements 1/38
0% Branches 0/25
20% Functions 1/5
2.63% Lines 1/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                    28x                                                                                                                                    
/*
 * FPS Controller
*/
 
import Event from '../events';
import EventHandler from '../event-handler';
import { logger } from '../utils/logger';
 
class FPSController extends EventHandler {
  constructor (hls) {
    super(hls, Event.MEDIA_ATTACHING);
  }
 
  destroy () {
    if (this.timer)
      clearInterval(this.timer);
 
    this.isVideoPlaybackQualityAvailable = false;
  }
 
  onMediaAttaching (data) {
    const config = this.hls.config;
    if (config.capLevelOnFPSDrop) {
      const video = this.video = data.media instanceof HTMLVideoElement ? data.media : null;
      if (typeof video.getVideoPlaybackQuality === 'function')
        this.isVideoPlaybackQualityAvailable = true;
 
      clearInterval(this.timer);
      this.timer = setInterval(this.checkFPSInterval.bind(this), config.fpsDroppedMonitoringPeriod);
    }
  }
 
  checkFPS (video, decodedFrames, droppedFrames) {
    let currentTime = performance.now();
    if (decodedFrames) {
      if (this.lastTime) {
        let currentPeriod = currentTime - this.lastTime,
          currentDropped = droppedFrames - this.lastDroppedFrames,
          currentDecoded = decodedFrames - this.lastDecodedFrames,
          droppedFPS = 1000 * currentDropped / currentPeriod,
          hls = this.hls;
        hls.trigger(Event.FPS_DROP, { currentDropped: currentDropped, currentDecoded: currentDecoded, totalDroppedFrames: droppedFrames });
        if (droppedFPS > 0) {
          // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
          if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
            let currentLevel = hls.currentLevel;
            logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
            if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
              currentLevel = currentLevel - 1;
              hls.trigger(Event.FPS_DROP_LEVEL_CAPPING, { level: currentLevel, droppedLevel: hls.currentLevel });
              hls.autoLevelCapping = currentLevel;
              hls.streamController.nextLevelSwitch();
            }
          }
        }
      }
      this.lastTime = currentTime;
      this.lastDroppedFrames = droppedFrames;
      this.lastDecodedFrames = decodedFrames;
    }
  }
 
  checkFPSInterval () {
    const video = this.video;
    if (video) {
      if (this.isVideoPlaybackQualityAvailable) {
        let videoPlaybackQuality = video.getVideoPlaybackQuality();
        this.checkFPS(video, videoPlaybackQuality.totalVideoFrames, videoPlaybackQuality.droppedVideoFrames);
      } else {
        this.checkFPS(video, video.webkitDecodedFrameCount, video.webkitDroppedFrameCount);
      }
    }
  }
}
 
export default FPSController;