关于 setPreviewDisplay(null) 无法正常显示的问题

来源:互联网 发布:易玩游戏盒子网络异常 编辑:程序博客网 时间:2024/06/05 20:02

    在 “Android NDK Beginner Guide”中第4章有段例程展示在Java中调用JNI的C代码,使用了CameraView类演示了用JNI C代码自己转换YUV420到RGB888的过程,但是实际这段代码在模拟器上倒是没问题,在很多实机上却无法显示。

    在国外网站上一般就说是 Android3.0后的版本中CAmera对象的setPreviewDisplay不能使用null作为参数,否则 onPreviewFrame 回调函数不会被调用。按这个提示修改后,将在界面上看到两个预览图案,类似画中画效果,小的画面是通过 onPreviewFrame -> OnDraw调用的。大的是setPreviewDisplay绑定当前SurfaceView自动刷新的。不知道大家还有没有更好的解决办法。

public class CameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback{static {System.loadLibrary("livaCamera");}public static final String TAG = "CameraView";public native void decode(Bitmap pTarget, byte[] pSource);private Camera mCamera;private byte[] mVideoSource;private Bitmap mBackBuffer;private Paint mPaint;public CameraView(Context context) {super(context);getHolder().addCallback(this);setWillNotDraw(false);}public void surfaceCreated(SurfaceHolder holder) {Log.v(TAG, "surfaceCreated()");try {mCamera = Camera.open();mCamera.setDisplayOrientation(0);
// mCamera.setPreviewDisplay(null); // 使用空的SurfaceHolder参数无法显示 
mCamera.setPreviewDisplay(this.getHolder()); //null
mCamera.setPreviewCallbackWithBuffer(this);
Log.d(TAG, "surfaceCreated() startPreview Success ");            } catch (Exception e) {mCamera.release();mCamera = null;throw new IllegalStateException();}}public void surfaceChanged(SurfaceHolder pHolder, int pFormat,int pWidth,int pHeight) {Log.v(TAG, "surfaceChanged()");
try {
mCamera.stopPreview();

Log.d(TAG, "surfaceChanged() stopPreview Success ");            
} catch (Exception e){
// ignore: tried to stop a non-existent preview
Log.d(TAG, "surfaceChanged() stopPreview Failed ");
}Size lSize = findBestResolution(pWidth, pHeight);PixelFormat lPixelFormat = new PixelFormat();PixelFormat.getPixelFormatInfo(mCamera.getParameters().getPreviewFormat(),lPixelFormat);int lSourceSize = lSize.width * lSize.height * lPixelFormat.bitsPerPixel / 8;if( mVideoSource == null  ){mVideoSource = new byte[lSourceSize];}if( mBackBuffer == null  ){mBackBuffer = Bitmap.createBitmap(lSize.width, lSize.height,Bitmap.Config.ARGB_8888);}Camera.Parameters lParameters = mCamera.getParameters();lParameters.setPreviewSize(lSize.width, lSize.height);lParameters.setPreviewFormat(ImageFormat.NV21); // PixelFormat.YCbCr_422_I deprecated in API level 8.mCamera.setParameters(lParameters);mCamera.addCallbackBuffer(mVideoSource);        try {        //mCamera.setPreviewDisplay(null);            mCamera.startPreview();            Log.d(TAG, "surfaceChanged() startPreview Success ");                    } catch (Exception e){          // ignore: tried to stop a non-existent preview            Log.d(TAG, "surfaceChanged() startPreview Failed ");        }    }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) {Log.v(TAG, "surfaceDestroyed()");if (mCamera != null) {mCamera.stopPreview();try {mCamera.reconnect();} catch (IOException e) {e.printStackTrace();}mCamera.release();mCamera = null;mVideoSource = null;mBackBuffer = null;}}public void onPreviewFrame(byte[] pData, Camera pCamera){int[] px = new int[100];Log.v(TAG, "onPreviewFrame()");decode(mBackBuffer, pData);mFrameCnt++;invalidate();}@Overrideprotected void onDraw(Canvas pCanvas){Log.v(TAG, "onDraw()");if (mCamera != null) {pCanvas.drawBitmap(mBackBuffer, 0, 0, mPaint);mCamera.addCallbackBuffer(mVideoSource);}}}
    注意