SurfaceTexture.OnFrameAvailableListener停止被调用

时间:2013-01-06 19:04:59

标签: android opengl-es

我在我的应用程序中实现了SurfaceTexture.OnFrameAvailableListener接口,因此我可以将视频帧用作OpenGL纹理。所有设置都应该设置它并且它完美地工作但是onFrameAvailable(SurfaceTexture surfaceTexture)在几秒钟后停止被调用,有效且看似冻结OpenGL中的视频,因为没有通过SurfaceTexture.updateTextImage上传新的纹理数据。

我在onFrameAvailable中设置了一个标志,用于从GL线程进行updateTextImage调用,并且仅在需要时进行。目前我在每次绘制调用时都将标志设置为true,因此在跳过onFrameAvailable检查时,每帧都会上传视频纹理数据。像这样,一切都像它应该运行但似乎效率低,因为如果它仍然是相同的(电影帧),则不需要上传新的纹理数据。

AFAIK没有内存泄漏,logcat没有显示任何错误。此外,媒体播放器设置为循环,但问题发生在单次运行完成之前。

什么会导致onFrameAvailable在几秒钟后不再被调用?

2 个答案:

答案 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%)需要足够长的时间才能跨越两个相机帧。)