我的MOTO XT910安卓手机的相机有问题。我只想访问相机的(帧)缓冲区,但从不调用“onPreviewFrame”。在我的模拟器上,它工作正常。
提前致谢,
我的代码如下:
public class Store extends SurfaceView implements SurfaceHolder.Callback, PreviewCallback {
static {
System.loadLibrary("hello-jni");
}
public native void decode(Bitmap pTarget, byte[] pSource);
private Camera mCamera;
private byte[] mVideoSource;
private Bitmap mBackBuffer;
private Paint mPaint;
private Size lSize;
private static String TAG = Store.class.getCanonicalName();
public Store(Context context) {
super(context);
getHolder().addCallback(this);
setWillNotDraw(false);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
mCamera.setDisplayOrientation(0);
mCamera.setPreviewDisplay(null);
mCamera.setPreviewCallbackWithBuffer(this);
Log.d(TAG,"surfaceCreated ok");
} catch (IOException eIOException) {
mCamera.release();
mCamera = null;
Log.d(TAG,"surfaceCreated failed");
throw new IllegalStateException();
}
}
public void surfaceChanged(SurfaceHolder pHolder, int pFormat, int pWidth, int pHeight) {
Log.d(TAG,"surfaceChanged in");
mCamera.stopPreview();
lSize = findBestResolution(pWidth, pHeight);
invalidate();
PixelFormat lPixelFormat = new PixelFormat();
PixelFormat.getPixelFormatInfo(mCamera.getParameters()
.getPreviewFormat(), lPixelFormat);
int lSourceSize = lSize.width * lSize.height * lPixelFormat.bitsPerPixel / 8;
mVideoSource = new byte[lSourceSize];
mBackBuffer = Bitmap.createBitmap(lSize.width, lSize.height,Bitmap.Config.ARGB_8888);
Camera.Parameters lParameters = mCamera.getParameters();
lParameters.setPreviewSize(lSize.width, lSize.height);
lParameters.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mCamera.setParameters(lParameters);
mCamera.addCallbackBuffer(mVideoSource);
mCamera.startPreview();
Log.d(TAG,"surfaceChanged out");
}
private Size findBestResolution(int pWidth, int pHeight) {
List<Size> lSizes = mCamera.getParameters().getSupportedPreviewSizes();
Size lSelectedSize = mCamera.new Size(0, 0);
for (Size lSize : lSizes) {
if ((lSize.width <= pWidth) && (lSize.height <= pHeight)
&& (lSize.width >= lSelectedSize.width)
&& (lSize.height >= lSelectedSize.height)) {
lSelectedSize = lSize;
}
}
if ((lSelectedSize.width == 0) || (lSelectedSize.height == 0)) {
lSelectedSize = lSizes.get(0);
}
return lSelectedSize;
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
Log.d(TAG,"surfaceDestroyed");
mCamera.stopPreview();
mCamera.release();
mCamera = null;
mVideoSource = null;
mBackBuffer = null;
}
}
public void onPreviewFrame(byte[] pData, Camera pCamera) {
Log.d(TAG,"onPreviewFrame");
decode(mBackBuffer, pData);
invalidate();
}
@Override
protected void onDraw(Canvas pCanvas) {
Log.d(TAG,"onDraw in");
if (mCamera != null) {
Paint paint = new Paint();
paint.setColor(Color.YELLOW);
String text = String.format("%dx%d", lSize.width, lSize.height);
pCanvas.drawText(text, 10, 10, paint);
pCanvas.drawLine(0, 0, 100, 100, paint);
pCanvas.drawLine(20, 0, 0, 20, paint);
pCanvas.drawBitmap(mBackBuffer, 0, 0, mPaint);
mCamera.addCallbackBuffer(mVideoSource);
Log.d(TAG,"onDraw out");
}
}
}
答案 0 :(得分:2)
首先我假设你没有得到异常,你的相机支持你使用的相机参数(PixelFormat.YCbCr_420_SP)。
要解决此问题,您应该尝试添加mCamera.setPreviewDisplay(view); 具有表面视图而不是null。不幸的是,根据安卓人员的说法,如果没有表面视图,预览不应该开始:
不幸的是,如果你的目标是3.0之前的设备,没有SurfaceView可以显示预览帧。在3.0及更高版本中,您可以使用Camera#setPreviewTexture()方法将预览数据发送到GPU纹理。即使只是想在GPU中使用YUV数据而不是RGB数据,这也允许您在没有强制UI元素的情况下进行流式传输;完全忽略SurfaceTexture。
如果您坚持使用当前的方法,很遗憾会发现您的应用无法在许多设备上正常运行;有几个遵循API的限制,必须在发送预览数据之前设置setPreviewDisplay()或setPreviewTexture()。
请在此处查看完整的错误报告:http://code.google.com/p/android/issues/detail?id=28238
然而正如我在这个错误报告中所说,它可以在没有表面视图的情况下工作,但不能保证。