1

我的 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");
    }
}

}

4

1 回答 1

2

首先,我假设您没有遇到异常,并且您的相机支持您使用的相机参数 (PixelFormat.YCbCr_420_SP)。

要解决此问题,您应该尝试添加 mCamera.setPreviewDisplay(view); 具有表面视图而不是空值。不幸的是,根据 android 家伙的说法,预览不应该在没有表面视图的情况下开始:

不幸的是,如果您的目标是 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

然而,正如我在这个错误报告中所说,它可以在没有表面视图的情况下工作,但不能保证。

于 2012-04-16T14:35:01.503 回答