我的SurfaceView
的子类实现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;
}
即使相机预览非常流畅,onPreviewFrame()
方法也只会被调用大约5次。为什么不是每个帧都被调用?
答案 0 :(得分:6)
你可能已经知道了:Camera.setPreviewCallback()对垃圾收集器施加了太大的压力。您可以使用Camera.setPreviewCallbackWithBuffer()代替。
其次,如果onPreviewFrame()到达主(UI)线程,那么它会与触摸,布局甚至渲染等UI事件竞争单个CPU时间。要在单独的线程上保持onPreviewFrame(),你应该在辅助Looper线程上打开()相机,参见例如https://stackoverflow.com/a/19154438/192373
第三,即使在这种情况下,预览回调也是序列化的。如果fpscounter.logFrame()
和Log().d
需要X毫秒,则FPS不会超过1000 / X.
答案 1 :(得分:0)
每帧都需要它。您可以参考相机的在线reference。看看这句话“除了在屏幕上显示之外,还为每个预览帧安装一个回调函数。”