我在我的应用程序中实现了SurfaceTexture.OnFrameAvailableListener接口,因此我可以将视频帧用作OpenGL纹理。所有设置都应该设置它并且它完美地工作但是onFrameAvailable(SurfaceTexture surfaceTexture)在几秒钟后停止被调用,有效且看似冻结OpenGL中的视频,因为没有通过SurfaceTexture.updateTextImage上传新的纹理数据。
我在onFrameAvailable中设置了一个标志,用于从GL线程进行updateTextImage调用,并且仅在需要时进行。目前我在每次绘制调用时都将标志设置为true,因此在跳过onFrameAvailable检查时,每帧都会上传视频纹理数据。像这样,一切都像它应该运行但似乎效率低,因为如果它仍然是相同的(电影帧),则不需要上传新的纹理数据。
AFAIK没有内存泄漏,logcat没有显示任何错误。此外,媒体播放器设置为循环,但问题发生在单次运行完成之前。
什么会导致onFrameAvailable在几秒钟后不再被调用?
答案 0 :(得分:13)
我在某些设备上遇到了同样的问题。找到了解决方案并想到我会分享。基本上它是@ user2254894建议的,除了因为计数器可以被2个不同的线程改变所以最好使用2个不同的vars。以下是一些示例代码:
private int _updateTexImageCounter = 0;
private int _updateTexImageCompare = 0;
和onFrameAvailable()很简单。
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture)
{
// increment every time a new frame is avail
_updateTexImageCounter++;
}
然后在您的GL更新中,您将执行以下操作...
public void update()
{
.... create texture... etc.
..
// compare _updateTexImageCompare and _updateTexImageCounter
if( _surfaceTexture!=null && _updateTexImageCompare != _updateTexImageCounter )
{
// loop and call updateTexImage() for each time the onFrameAvailable() method was called below.
while(_updateTexImageCompare != _updateTexImageCounter) {
_surfaceTexture.updateTexImage();
_surfaceTexture.getTransformMatrix(x);
_updateTexImageCompare++; // increment the compare value until it's the same as _updateTexImageCounter
}
}
}
这对我有用。如果有更好的方法,请告诉我。
答案 1 :(得分:12)
我刚刚看到类似的问题,并对其进行了调试。我和你一样,有一个布尔标志,表示准备好使用一个(或多个!)帧。
当我在一对OpenGL帧之间收到两个相机帧时出现问题(可能是因为我的OpenGL重绘处理速度太慢)。这意味着我将布尔标志设置了两次。但是,我只读了一次这个帧数据,似乎updateTexImage实现了某种排队功能。
用待处理相机帧的整数计数器替换布尔标志解决了我的问题。也许这对你也有用吗?
(我怀疑这比每帧调用updateTexImage更有效。至少在我的代码中,OpenGL帧非常罕见(1-2%)需要足够长的时间才能跨越两个相机帧。)