在previewFrame不会被调用为显示在SurfaceView每一帧 [英] onPreviewFrame not being called for every frame that is displayed on SurfaceView

查看:1052
本文介绍了在previewFrame不会被调用为显示在SurfaceView每一帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 SurfaceView 工具相机previewCallback &安培的子类; SurfaceHolder.Callback

My subclass of SurfaceView implements Camera.PreviewCallback & SurfaceHolder.Callback.

private SurfaceHolder mHolder;
private Camera mCamera;

private final FPSCounter fpscounter = new FPSCounter();

public MySurfaceView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mHolder = getHolder();
    mHolder.addCallback(this);
}

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    fpscounter.logFrame();
    Log.d("fps", String.valueOf(fpscounter.getLastFrameCount()));
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    synchronized (this) {
        mCamera.stopPreview();

        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setRecordingHint(true);
        parameters.setPreviewFormat(ImageFormat.NV21);

        mCamera.setParameters(parameters);

        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.setPreviewCallback(this);
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    synchronized (this) {
        setWillNotDraw(false);
        mCamera = Camera.open();
    }
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    synchronized (this) {
        try {
            if (mCamera != null) {
                mCamera.stopPreview();
                mCamera.release();
            }
        } catch (Exception e) {
            Log.e("cam error", e.getMessage());
        }
    }
}

FPSCounter

private long startTime; 
private int frames, lastFrameCount;

public void logFrame() {
    frames++;
    if (System.nanoTime() - startTime >= 1000000000) {
        lastFrameCount = frames;
        frames = 0;
        startTime = System.nanoTime();
    }
}

public int getLastFrameCount() {
    return lastFrameCount;
}

即使相机preVIEW极为流畅,上previewFrame()只调用了第二个5次左右。为什么是不是被要求对每一帧?

Even though the camera preview is extremely smooth, the onPreviewFrame() method is only called about 5 times a second. Why isn't it being called for every frame?

推荐答案

您可能想通了已经:Camera.set previewCallback()把太多pressure的垃圾收集器。您可以使用Camera.set previewCallbackWithBuffer()代替。

You probably figured it out already: Camera.setPreviewCallback() puts too much pressure on Garbage Collector. You can use Camera.setPreviewCallbackWithBuffer() instead.

二,如果previewFrame()到达主(UI)线程,那么它的竞争对手的单CPU时间像触摸,布局,甚至渲染UI事件。为了保持在previewFrame()在一个单独的线程,你应该打开()在二级弯针线相机,例如见<一href=\"http://stackoverflow.com/a/19154438/192373\">http://stackoverflow.com/a/19154438/192373.

Second, if onPreviewFrame() arrives on the main (UI) thread, then it competes for single CPU time with UI events like touch, layout, or even rendering. To keep onPreviewFrame() on a separate thread, you should open() the camera on a secondary Looper thread, see e.g. http://stackoverflow.com/a/19154438/192373.

第三,即使在这种情况下,preVIEW回调被序列。如果 fpscounter.logFrame()日志()。ð拍X毫秒,那么FPS将不会超过1000 / [X]。

Third, even in this case, the preview callbacks are serialized. If fpscounter.logFrame() and Log().d take X milliseconds, then the FPS will not exceed 1000/X.

这篇关于在previewFrame不会被调用为显示在SurfaceView每一帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆