Android:相机、onSurfaceTextureUpdated、Bitmap.getPixels - 帧率从 30 下降到 3

Joh*_*ohn 5 performance camera android bitmap

尝试获取相机预览的像素时,我的表现非常糟糕。

图像格式约为 600x900。在我的 HTC 上,预览速率非常稳定,为 30fps。

一旦我尝试获取图像的像素,帧率就会下降到 5 以下!

public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
    Bitmap bmp = mTextureView.getBitmap();
    int width = bmp.getWidth();
    int height = bmp.getHeight();
    int[] pixels = new int[bmp.getHeight() * bmp.getWidth()];
    bmp.getPixels(pixels, 0, width, 0, 0, width, height);
}
Run Code Online (Sandbox Code Playgroud)

性能太慢了,真的不能忍受。

现在我唯一的“简单”解决方案是跳过帧以至少保持一些视觉性能。但我实际上想让该代码执行得更快。

我很感激任何想法和建议,也许有人已经解决了这个问题?

更新

getbitmap: 188.341ms
array: 122ms 
getPixels: 12.330ms
recycle: 152ms
Run Code Online (Sandbox Code Playgroud)

仅获取位图就需要 190 毫秒!!那就是问题所在

Joh*_*ohn 3

我对此进行了几个小时的研究。

简短的回答:我发现没有办法避免 getBitmap() 并提高性能。众所周知,该功能很慢,我发现了很多类似的问题,但没有结果。

然而,我找到了另一种解决方案,速度快了大约 3 倍,并为我解决了问题。我一直使用TextureView方法,我使用它是因为它在如何显示相机预览方面提供了更多自由(例如我可以在我自己的宽高比的小窗口中显示相机实时预览而不失真)

但为了处理图像数据,我不再使用 onSurefaceTextureUpdated() 。

我注册了cameraPreviewFrame的回调,它为我提供了我需要的像素数据。因此不再需要 getBitmap,并且速度更快。

快速、新的代码:

myCamera.setPreviewCallback(preview);

Camera.PreviewCallback preview = new Camera.PreviewCallback()
{
    public void onPreviewFrame(byte[] data, Camera camera)
    {
        Camera.Parameters parameters = camera.getParameters();
        Camera.Size size = parameters.getPreviewSize();
        Image img = new Image(size.width, size.height, "Y800");
    }
};
Run Code Online (Sandbox Code Playgroud)

慢的:

private int[] surface_pixels=null;
private int surface_width=0;
private int surface_height=0;
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture)
{
    int width,height;

    Bitmap bmp= mTextureView.getBitmap();
    height=barcodeBmp.getHeight();
    width=barcodeBmp.getWidth();
    if (surface_pixels == null)
    {
        surface_pixels = new int[height * width];
    } else
    {
        if ((width != surface_width) || (height != surface_height))
        {
            surface_pixels = null;
            surface_pixels = new int[height * width];
        }
    }
    if ((width != surface_width) || (height != surface_height))
    {
        surface_height = barcodeBmp.getHeight();
        surface_width = barcodeBmp.getWidth();
    }

    bmp.getPixels(surface_pixels, 0, width, 0, 0, width, height);
    bmp.recycle();

    Image img = new Image(width, height, "RGB4");
 }
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助一些遇到同样问题的人。

如果有人应该找到一种在 onSurfaceTextureUpdated 中快速创建位图的方法,请回复代码示例。