Harmony Next 和 OpenHarmony 获取屏幕刷新率、fps 原创

msdone
发布于 2024-11-18 18:18
浏览
0收藏

@toc

概述

已在 Harmony Next 和 OpenHarmony 5.0+ 上测试通过

本功能使用 @ohos.graphics.displaySync 接口实现,并采用"帧间隔法"计算 fps(当然可以使用其他计算 fps 的方法):

这是一种基于时间戳差值(Time Delta)来计算 FPS 的方法,也称为"帧时间法"或"帧间隔法"。
具体计算过程如下:
获取相邻两帧的时间戳差值(Frame Time/Delta Time)
收集一定数量的帧时间样本(使用数组存储最近60帧的数据)
计算平均帧时间
let avg_frame_time = sum / this.frame_times.length;
使用公式 FPS = 1000/平均帧时间(毫秒) 计算最终的 FPS
let fps = 1000.0 / avg_frame_time;
这种方法的特点是:
	实时性好,能够反映当前实际的帧率状况
	通过收集多帧样本并平均,可以平滑瞬时波动
	计算简单,开销小
	适合用于性能监控和调试

代码

import displaySync from '@ohos.graphics.displaySync';

@Entry
@Component
struct Index {
  @State fps: number = 0;
  private frame_times: number[] = [];
  private last_time: number = 0;
  private sum: number = 0;
  private backDisplaySync: displaySync.DisplaySync = displaySync.create();
  private round(value: number, decimals: number): number {
    const factor = Math.pow(10, decimals);
    return Math.round(value * factor) / factor;
  }

  private callback = (frameInfo: displaySync.IntervalInfo) => {
    console.info("20241113DisplaySync", 'TimeStamp:' + frameInfo.timestamp + ' TargetTimeStamp: ' + frameInfo.targetTimestamp);
    if (this.last_time === 0) {
      this.last_time = Number(frameInfo.timestamp);
      return;
    }

    // 计算帧时间(转换为毫秒)
    let current_time = Number(frameInfo.timestamp);
    console.info("20241113DisplaySync", "1111111111111111111111: " + current_time);
    let frame_time = (current_time - this.last_time) / 1000000; // 转换纳秒为毫秒
    console.info("20241113DisplaySync", "2222222222222222222222: " + frame_time);
    this.last_time = current_time;
    console.info("20241113DisplaySync", "3333333333333333333333: " + this.last_time);

    if (frame_time > 0 && frame_time < 1000) {  // 添加合理性检查,帧时间应该在 0-1000ms 之间
      this.frame_times.push(frame_time);
      console.info("20241113DisplaySync", "AAAAAAAAAAAAAAAAAAAAAA: " + this.frame_times);
      if (this.frame_times.length > 60) {
        this.sum -= this.frame_times.shift()!;
        this.sum += frame_time;
      } else {
        this.sum += frame_time;
      }
      console.info("20241113DisplaySync", "BBBBBBBBBBBBBBBBBBBBBB: " + this.sum);
      let avg_frame_time = this.sum / this.frame_times.length;
      console.info("20241113DisplaySync", "CCCCCCCCCCCCCCCCCCCCCC: " + avg_frame_time);
      let fps = 1000.0 / avg_frame_time; // 毫秒转换为秒并计算 FPS
      console.info("20241113DisplaySync", "DDDDDDDDDDDDDDDDDDDDDD: " + fps);
      this.fps = this.round(fps, 1);
      console.info("20241113DisplaySync", "EEEEEEEEEEEEEEEEEEEEEE: " + this.fps);
    }
  }

  build() {
    Row() {
      Text(this.fps.toString())
        .fontColor(Color.Red)
        .fontSize(40)
      Button("stop")
        .onClick(() => {
          try {
            this.backDisplaySync?.off("frame", this.callback);
            this.backDisplaySync?.stop();
            console.info("20241113DisplaySync", ' stop successfully!');
          } catch (e) {
            console.info("20241113DisplaySync", ' stop Error:' + JSON.stringify(e));
          }
        })
      Button("start")
        .onClick(() => {
          try {
            this.frame_times = []; // 清空历史数据
            this.last_time = 0;    // 重置时间戳
            this.backDisplaySync.on("frame", this.callback)
            this.backDisplaySync?.start()
          } catch (e) {
            console.info("20241113DisplaySync", 'Error:' + JSON.stringify(e));
          }
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

效果

低帧率
Harmony Next 和 OpenHarmony 获取屏幕刷新率、fps-鸿蒙开发者社区
高帧率
Harmony Next 和 OpenHarmony 获取屏幕刷新率、fps-鸿蒙开发者社区
系统设置帧率
Harmony Next 和 OpenHarmony 获取屏幕刷新率、fps-鸿蒙开发者社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
已于2024-11-18 18:34:54修改
收藏
回复
举报
回复
    相关推荐