Home Reference Source

src/controller/fps-controller.js

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