1

MOTO XT910 Android フォンのカメラに問題があります。カメラの(フレーム)バッファにのみアクセスしたいのですが、「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");
    }
}

}

4

1 に答える 1

2

まず、例外が発生せず、使用したカメラ パラメーター (PixelFormat.YCbCr_420_SP) がカメラでサポートされていると仮定します。

この問題を解決するには、mCamera.setPreviewDisplay(view); を追加してみてください。null ではなくサーフェス ビューを使用します。残念ながら、アンドロイドの連中によると、プレビューはサーフェスビューなしでは開始されるべきではありません:

残念ながら、3.0 より前のデバイスをターゲットにしている場合、SurfaceView を使用せずにプレビュー フレームを取得する方法はありません。3.0 以降では、 Camera#setPreviewTexture() メソッドを使用してプレビュー データを GPU テクスチャに送信できます。GPU で RGB データの代わりに YUV データを使用したい場合でも、必須の UI 要素なしでストリーミングできます。SurfaceTexture を完全に無視してください。

現在のアプローチに固執すると、残念ながらアプリが多くのデバイスで適切に機能しないことがわかります。プレビュー データを送信する前に setPreviewDisplay() または setPreviewTexture() を設定する必要があるという API の制限に従うものもいくつかあります。

ここで完全なバグレポートを参照してください: http://code.google.com/p/android/issues/detail?id=28238

ただし、このバグ レポートで述べたように、Surface ビューがなくても機能しますが、保証はありません。

于 2012-04-16T14:35:01.503 に答える