【问题标题】:Measure framerate for video playback测量视频播放的帧率
【发布时间】:2015-09-09 09:55:29
【问题描述】:

我是 Android 新手,想编写一个在播放视频时测量帧速率的应用。为此,我使用 MediaPlayer 并将其显示在 SurfaceView 上。在这个星座中,是否有可能获得所需的渲染统计数据来计算帧率?谢谢

【问题讨论】:

    标签: android video surfaceview frame-rate


    【解决方案1】:

    MediaPlayer 的重点是隐藏视频解码和呈现的细节,所以你根本无法获得所有细节。例如,没有每帧回调。

    解决该问题的一种方法是使用 MediaPlayer 将视频播放到 SurfaceTexture 上,并使用 OpenGL ES 将每一帧渲染到 SurfaceView 的 Surface 上。 SurfaceTexture 提供每帧的呈现时间戳。

    另一种方法是使用 MediaCodec 代替 MediaPlayer,让您完全控制解码和演示过程。这更复杂,如果视频有音频,就会变得棘手。

    您可能还想考虑使用 MediaExtractor 检查视频文件本身,并使用前几帧来检测帧速率。

    正如@Mick 所指出的,某些视频具有可变帧速率,您无法为整个流建立单个值。 screenrecord 拍摄的视频就是一个很好的例子。在这种情况下,您能做的最好的事情就是显示“最近的”帧速率,并且您必须动态计算它(因此 MediaExtractor 不会削减它)。

    【讨论】:

    • 我想你也可以显示平均帧率,这也可能有用。
    • 感谢您的概述。使用 MediaExtractor 和 MediaCodec 时使用 Exoplayer 会更好吗?
    【解决方案2】:

    有报道(我自己没有测试过)VideoView的onDraw方法会在每个视频帧写入的时候被调用。

    这允许您覆盖并添加一些代码到 onDraw 方法,以记录每帧的写入时间并计算运行的 fps 值。

    要允许调用 onDraw 方法,您必须设置一个标志:

    setWillNotDraw(假)

    在您的视图构造函数中 - 请参阅:https://stackoverflow.com/a/17595671/334402

    顺便说一句,值得注意的是,某些视频的帧速率会发生变化。这通常是因为他们试图在给定的带宽预算内最大限度地提高质量。

    【讨论】:

    • 每次将新的视频帧发送到 Surface 时更新视图会效率低下,而且相当愚蠢。每帧都调用onDraw() 的唯一原因是,如果有人为每一帧发出 View invalidates,这只有在视频在软件中被解码并渲染到 View 本身时才有用。 (这是从哪里来的?)
    • 好的 - 我会给 OP 时间来阅读你的 cmets,如果它是错误的,然后删除这个答案。我自己没有测试过,但据普遍报道这种方法适用于这类问题的答案。如果您查看您的 cmets 提要,您会看到我在对另一个答案的评论中向您提出了一个问题 - 如果您看到它,我会对您的回复感兴趣。
    • 我看到了 (stackoverflow.com/questions/23133739) 并回复了(所以可能不会发送通知)。 onDraw() 可用于指示帧速率的唯一方法是 VideoView 是否每帧都在其视图中更新某些内容。浏览android.googlesource.com/platform/frameworks/base/+/…draw() 的唯一用途是用于字幕。
    • 谢谢 - 很好的清晰解释。顺便说一句 - 这是一个用于 fps 计算的 onDraw 示例:stackoverflow.com/q/10210439/334402 - 如果你 100% 确定这不起作用(或者我可能读错了??)
    • 我的猜测是问题中提到的“第三方框架”正在使用软件编解码器渲染到视图。这将使您每帧无效。与那个 (stackoverflow.com/questions/13498184) 链接的问题有类似的答案,但 OP 使用的是 VideoView,显然没有让它工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    相关资源
    最近更新 更多