2012-04-11 3 views
0

Ich habe ein Problem mit der Kamera meines MOTO XT910 Android-Handy. Ich möchte nur auf den (Rahmen-) Puffer der Kamera zugreifen, aber "onPreviewFrame" wird nie aufgerufen. Auf meinem Emulator funktioniert es gut.Kamera onPreviewFrame nicht auf XT910

Vielen Dank im Voraus,

Mein Code ist als unten:

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

}

Antwort

1

Zuerst habe ich nehme an, Sie nicht eine Ausnahme und dass die Kameraparameter Sie (Pixelformat verwendet bekommen haben. YCbCr_420_SP) wird von Ihrer Kamera unterstützt.

Um das Problem zu beheben, sollten Sie versuchen, mCamera.setPreviewDisplay (view); mit einer Oberflächenansicht und nicht mit null. Leider sollte die Vorschau nicht ohne eine Oberflächenansicht starten:

Leider gibt es keine Möglichkeit, Vorschaubilder ohne eine SurfaceView zu erhalten, um sie anzuzeigen, wenn Sie Pre-3.0-Geräte ausrichten. Ab 3.0 können Sie die Camera # setPreviewTexture() -Methode verwenden, um Vorschaudaten an eine GPU-Textur zu senden. Auch wenn Sie nur die YUV-Daten anstelle von RGB-Daten in der GPU verwenden möchten, können Sie ohne ein obligatorisches UI-Element streamen. Ignoriere die SurfaceTexture vollständig.

Wenn Sie bei Ihrem derzeitigen Ansatz bleiben, werden Sie leider feststellen, dass Ihre App auf vielen Geräten nicht richtig funktioniert. Es gibt mehrere, die der API-Beschränkung folgen, dass setPreviewDisplay() oder setPreviewTexture() gesetzt sein muss, bevor Vorschaudaten gesendet werden.

Den gesamten Fehlerbericht hier: http://code.google.com/p/android/issues/detail?id=28238

Doch wie ich in diesem Fehlerbericht sagte, dass es ohne eine Oberflächenansicht arbeiten kann, aber es gibt keine Garantie.