SurfaceTexture.OnFrameAvailableListener停止被调用

Wil*_*Kru 6 android opengl-es

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

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

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

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

zin*_*gle 13

我在某些设备上遇到了同样的问题.找到了解决方案并想到我会分享.基本上它是@ user2254894建议的,除了因为计数器可以被2个不同的线程改变所以最好使用2个不同的vars.这是一些示例代码:

private int             _updateTexImageCounter = 0;
private int             _updateTexImageCompare = 0;
Run Code Online (Sandbox Code Playgroud)

和onFrameAvailable()很简单.

@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) 
{
    // increment every time a new frame is avail
    _updateTexImageCounter++;
}
Run Code Online (Sandbox Code Playgroud)

然后在您的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
        }
    }


}
Run Code Online (Sandbox Code Playgroud)

这对我有用.如果有更好的方法,请告诉我.

  • 哇.这修复了原始Android代码中甚至出现的错误.(即:MediaCodec的CTS) (2认同)
  • @LéonPelletier很高兴帮助. (2认同)

小智 12

我刚刚看到了类似的问题,并对其进行了调试.我和你一样,有一个布尔标志,表示准备好使用一个(或多个!)帧.

当我在一对OpenGL帧之间收到两个相机帧时(可能是因为我的OpenGL重绘处理太慢),问题就出现了.这意味着我将布尔标志设置了两次.但是,我只读了一次这个帧数据,似乎updateTexImage实现了某种排队功能.

用挂起的相机帧的整数计数器替换布尔标志解决了我的问题.也许这对你也有用吗?

(我怀疑这比只是每帧调用updateTexImage更有效.至少在我的代码中,OpenGL帧非常罕见(1-2%)需要足够长的时间才能跨越两个相机帧.)

  • 感谢您的工作调试.似乎分配了有限数量的缓冲区用于解码,并且被调用的onFrameAvailable()检出缓冲区,并且仅通过调用updateTexImage()将此缓冲区检回到可用池中.一个关键的事实,不在文档中! (4认同)