当前位置: 动力学知识库 > 问答 > 编程问答 >

surfaceview - Camera onPreviewFrame not called on XT910

问题描述:

I have a problem with the camera of my MOTO XT910 android phone. I would like only to access to the camera's (frame)buffer but "onPreviewFrame" is never called. On my emulator, it works fine.

Thanks in advance,

My code is as below:

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");

}

}

}

网友答案:

First I assume you didn't get an exception and that the camera parameters you used (PixelFormat.YCbCr_420_SP) is supported by your camera.

To fix the problem you should try to add mCamera.setPreviewDisplay(view); with a surface view and not with null. Unfortunately according to android guys the preview should not start without a surface view :

Unfortunately, there's no way to get preview frames without having a SurfaceView to display them, if you're targeting pre-3.0 devices. On 3.0 and later, you can use the Camera#setPreviewTexture() method to send preview data to a GPU texture. Even if just want to use the YUV data instead of RGB data in the GPU, this would allow you to stream without a mandatory UI element; just ignore the SurfaceTexture entirely.

If you stick with your current approach, you'll unfortunately find that your app will not function properly on many devices; there are several that follow the API's restriction on having to have setPreviewDisplay() or setPreviewTexture() set before preview data will be sent.

See the full bug report here : http://code.google.com/p/android/issues/detail?id=28238

However as I said in this bug report it can work without a surface view, but there is no guarantee.

分享给朋友:
您可能感兴趣的文章:
随机阅读: