1

我有一个简单的 NDK Android 代码来解码和播放简单的视频文件。我注意到Android有 native_window_set_buffers_timestamp(ANativeWindow, int64_t); 方法。

我读到它为添加到队列中的帧提供时间戳。是否有可能使用这些标记在我计划的时间段内导致出队和渲染帧?我有类似于描述的代码:在这个例子中, 我正在设置演示时间戳,如示例(我确定我有正确的值,我以纳秒为单位设置它们),但视频的渲染速度与它一样快解码(太快了)。设置时间戳没有任何效果。有没有人解决这个问题?

4

1 回答 1

2

该字段作为通过系统传递时间戳的一种方式而存在。它可能会或可能不会影响帧的处理方式。

IIRC,该字段的最初用途是用于相机捕获的视频帧。通过包含捕获帧时的时间戳,生成编码视频的应用程序可以输出准确的时间戳。如果应用程序使用应用程序接收帧的时间,您会得到时间值的显着变化。

旧版本的 Android 在显示帧时会忽略时间戳。在 Android 4.4(“KitKat”)中,SurfaceFlinger 合成器添加了一项功能,允许它根据时间戳保存或丢弃帧。这样做的目的是使 A/V 同步更容易。这在Grafika 的“计划交换”活动的评论中进行了详细讨论,特别是上述doFrame()方法的评论。

简而言之,该功能的目标是允许视频播放器稍微提前提交每一帧,以便在音频播放到达适当时间时准备好并在合成队列中等待。当系统繁忙时,尝试在应用程序本身中进行细粒度同步是有问题的。(SurfaceFlinger 以更高的优先级运行。)

当应用程序向整个视频文件发送垃圾邮件时提供适当节奏的播放不是目标。为了向后兼容向嵌入式 PTS 提供帧的应用程序,并避免在应用程序提交未来几年的时间戳时出现很长时间的停顿,SurfaceFlinger 会忽略当前时间不到一秒左右的时间戳。所以你仍然需要用勺子喂帧,但时间戳可以帮助避免停顿和掉线。

所以...如果您想管理自己的视频播放,您必须自己调整输出速度。您可以在 Grafika 的SpeedControlCallback类中看到一个示例。

于 2015-07-06T20:22:19.863 回答