在XT910上没有调用相机onPreviewFrame

时间:2012-04-11 04:09:10

标签: android-camera surfaceview

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

}

1 个答案:

答案 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

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