setPreviewDisplay(null)が正常に表示されない問題について


「Android NDK Beginner Guide」では4章でJavaでJNIを呼び出すCコードをセグメントルーチンで示し,JNI Cコードを用いてYUV 420からRGB 888に独自に変換する過程をCameraViewクラスで実証したが,実際にはこのコードはシミュレータでは問題なく,多くの実機では表示できない.
    海外サイトでは一般的にAndroid 3.0以降のバージョンではCAmeraオブジェクトのsetPreviewDisplayはnullをパラメータとして使用できません.そうしないとonPreviewFrameコールバック関数は呼び出されません.このヒントを押して修正すると、画面に2つのプレビューパターンが表示され、絵の中の絵のような効果があり、小さな画面はonPreviewFrame->OnDrawで呼び出されます.大きいのはsetPreviewDisplayバインドの現在のSurface Viewが自動的にリフレッシュされます.皆さんはまだもっと良い解決策があるかどうか分かりません.
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);
		}
	}
}