Comment obtenir des données d'aperçu de caméra Android?

Mon application appareil photo affiche une prévisualisation de la caméra sur l'écran et également les processus en arrière-plan. Voici le code correspondant, résumés autant que possible (par exemple, pas d'erreur de manipulation ou d'un champ déclarations montré):

public final class CameraView extends SurfaceView implements
SurfaceHolder.Callback, Runnable, PreviewCallback {
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
void openCamera() {
//Called from parent activity after setting content view to CameraView
mCamera = Camera.open();
mCamera.setPreviewCallbackWithBuffer(this);
}
public void surfaceCreated(SurfaceHolder holder) {
new Thread(this).start(); 
//Set CameraView to the optimal camera preview size
final Camera.Parameters params = mCamera.getParameters();
final List<Camera.Size> sizes = params.getSupportedPreviewSizes();
final int screenWidth = ((View) getParent()).getWidth();
int minDiff = Integer.MAX_VALUE;
Camera.Size bestSize = null;
if (getResources().getConfiguration().orientation 
== Configuration.ORIENTATION_LANDSCAPE) {
//Find the camera preview width that best matches the
//width of the surface.
for (Camera.Size size : sizes) {
final int diff = Math.abs(size.width - screenWidth);
if (diff < minDiff) {
minDiff = diff;
bestSize = size;
}
}
} else {
//Find the camera preview HEIGHT that best matches the 
//width of the surface, since the camera preview is rotated.
mCamera.setDisplayOrientation(90);
for (Camera.Size size : sizes) {
final int diff = Math.abs(size.height - screenWidth);
if (Math.abs(size.height - screenWidth) < minDiff) {
minDiff = diff;
bestSize = size;
}
}
}
final int previewWidth = bestSize.width;
final int previewHeight = bestSize.height;
ViewGroup.LayoutParams layoutParams = getLayoutParams();
layoutParams.height = previewHeight;
layoutParams.width = previewWidth;
setLayoutParams(layoutParams);
params.setPreviewFormat(ImageFormat.NV21);
mCamera.setParameters(params);
int size = previewWidth * previewHeight * 
ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
public void onPreviewFrame(byte[] data, Camera camera) {
CameraView.this.notify();
}
public void run() {
mThreadRun = true;
while (mThreadRun) {
synchronized (this) {
this.wait();
processFrame(mBuffer); //convert to RGB and rotate - not shown
}
//Request a new frame from the camera by putting 
//the buffer back into the queue
mCamera.addCallbackBuffer(mBuffer);
}
mHolder.removeCallback(this);
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
public void surfaceDestroyed(SurfaceHolder holder) {
mThreadRun = false;
}
}

Sur tous les appareils, l'aperçu de la caméra s'affiche correctement, et sur la plupart des (émulateur, Samsung Galaxy S3, etc.) les données stockées dans mBuffer est également correcte (après NV21 de conversion RGB et de la rotation, bien sûr). Cependant, un certain nombre de dispositifs ne fournissent pas les données correctes dans onPreviewFrame. Je suis sûr que les données sont converties au format RVB correctement après qu'il est reçu, de sorte que le problème semble être dans les données brutes fournies à mBuffer. J'ai remarqué ce rapport de bug relatives à la YV12 (alias YUV420p) aperçu de l'appareil photo de format, mais je suis en utilisant l'ancienne valeur par défaut, NV21 (alias YUV420sp), qui doit être pris en charge selon les compatibilité standard (voir 7.5.3.2, en bas de page 29).

Par exemple, pour la scène (ici, dans la Prévisualisation de la Caméra sur la Samsung Galaxy Tab 2):

Comment obtenir des données d'aperçu de caméra Android?

les données transmises à mBuffer sur l'Onglet 2 ressemble:

Comment obtenir des données d'aperçu de caméra Android?

et sur le Motorola Droid 4 ressemble à:

Comment obtenir des données d'aperçu de caméra Android?

Quelle est la bonne façon d'obtenir de l'appareil photo Android aperçu des données sur tous les appareils?

Edit: pour processFrame()j'ai utilisé OpenCV pour convertir RVB et de rotation. Voir cette réponse et cette réponse.

source d'informationauteur 1''