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

    在 “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();
	}
	@Override
	protected void onDraw(Canvas pCanvas)
	{
		Log.v(TAG, "onDraw()");
		if (mCamera != null) {
			pCanvas.drawBitmap(mBackBuffer, 0, 0, mPaint);
			mCamera.addCallbackBuffer(mVideoSource);
		}
	}
}

    注意
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值