Android guarda la imagen de vista previa de la cámara en tiempo real

Estoy tratando de guardar la imagen de vista previa de la cámara en tiempo real, mi objetivo es guardar al menos 1 fps de la vista previa colocada en la vista de superficie. estoy atascado en esto

mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
        private long timestamp=0;
        public synchronized void onPreviewFrame(byte[] data, Camera camera) {
            Log.v("CameraTest","Time Gap = "+(System.currentTimeMillis()-timestamp));
            timestamp=System.currentTimeMillis();
            try{
                FileOutputStream out;
                try {
                    Bitmap bmp=BitmapFactory.decodeByteArray(data,0,data.length);
                    out = new FileOutputStream("/mnt/sdcard/data/pippo.png");
                    bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
                } catch (FileNotFoundException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }           
                camera.addCallbackBuffer(data);
            }catch (Exception e) {
                Log.e("CameraTest", "addCallbackBuffer error");
                return;
            }
            return;
        }
    });

Supongo que la matriz de bytes pasó

public synchronized void onPreviewFrame(byte[] data, Camera camera)

contiene las imágenes de datos sin procesar, así que estoy tratando de convertirlo en un mapa de bits y guardarlo en la tarjeta SD. Mis preguntas son:

  1. ¿Es este el camino correcto hacia el barbecho para lograr mi objetivo?
  2. Recibo este error en el registro SkImageDecoder::Factory devolvió nulo, supongo que está relacionado con la conversión de mapa de bits, ¿es correcto?

Cualquier sugerencia es bienvenida. Gracias

Aquí abajo el código completo:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import android.app.Activity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;

public class Demo extends Activity {
    SurfaceView mVideoCaptureView;
    private Camera mCamera;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
        SurfaceHolder videoCaptureViewHolder = mVideoCaptureView.getHolder();
        videoCaptureViewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        videoCaptureViewHolder.addCallback(new Callback() {
            public void surfaceDestroyed(SurfaceHolder holder) {
            }

            public void surfaceCreated(SurfaceHolder holder) {
                startVideo();
            }

            public void surfaceChanged(SurfaceHolder holder, int format,
                    int width, int height) {
            }
        });
    }
    private void startVideo() {
        SurfaceHolder videoCaptureViewHolder = null;
        try {
            mCamera = Camera.open();
        } catch (RuntimeException e) {
            Log.e("CameraTest", "Camera Open filed");
            return;
        }
        mCamera.setErrorCallback(new ErrorCallback() {
            public void onError(int error, Camera camera) {
            }
        }); 
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewFrameRate(30);
        parameters.setPreviewFpsRange(15000,30000);
        List<int[]> supportedPreviewFps=parameters.getSupportedPreviewFpsRange();
        Iterator<int[]> supportedPreviewFpsIterator=supportedPreviewFps.iterator();
        while(supportedPreviewFpsIterator.hasNext()){
            int[] tmpRate=supportedPreviewFpsIterator.next();
            StringBuffer sb=new StringBuffer();
            sb.append("supportedPreviewRate: ");
            for(int i=tmpRate.length,j=0;j<i;j++){
                sb.append(tmpRate[j]+", ");
            }
            Log.v("CameraTest",sb.toString());
        }

        List<Size> supportedPreviewSizes=parameters.getSupportedPreviewSizes();
        Iterator<Size> supportedPreviewSizesIterator=supportedPreviewSizes.iterator();
        while(supportedPreviewSizesIterator.hasNext()){
            Size tmpSize=supportedPreviewSizesIterator.next();
            Log.v("CameraTest","supportedPreviewSize.width = "+tmpSize.width+"supportedPreviewSize.height = "+tmpSize.height);
        }

        mCamera.setParameters(parameters);
        if (null != mVideoCaptureView)
            videoCaptureViewHolder = mVideoCaptureView.getHolder();
        try {
            mCamera.setPreviewDisplay(videoCaptureViewHolder);
        } catch (Throwable t) {
        }

        Log.v("CameraTest","Camera PreviewFrameRate = "+mCamera.getParameters().getPreviewFrameRate());
        Size previewSize=mCamera.getParameters().getPreviewSize();
        int dataBufferSize=(int)(previewSize.height*previewSize.width*
                               (ImageFormat.getBitsPerPixel(mCamera.getParameters().getPreviewFormat())/8.0));

        mCamera.addCallbackBuffer(new byte[dataBufferSize]);
        mCamera.addCallbackBuffer(new byte[dataBufferSize]);
        mCamera.addCallbackBuffer(new byte[dataBufferSize]);

        mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
            private long timestamp=0;
            public synchronized void onPreviewFrame(byte[] data, Camera camera) {
                Log.v("CameraTest","Time Gap = "+(System.currentTimeMillis()-timestamp));
                timestamp=System.currentTimeMillis();
                try{
                    FileOutputStream out;
                    try {
                        Bitmap bmp=BitmapFactory.decodeByteArray(data,0,data.length);
                        out = new FileOutputStream("/mnt/sdcard/data/pippo.png");
                        bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
                    } catch (FileNotFoundException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }           
                    camera.addCallbackBuffer(data);
                }catch (Exception e) {
                    Log.e("CameraTest", "addCallbackBuffer error");
                    return;
                }
                return;
            }
        });
        try {
            mCamera.startPreview();
        } catch (Throwable e) {
            mCamera.release();
            mCamera = null;
            return;
        }
    }
    private void stopVideo() {
        if(null==mCamera)
            return;
        try {
            mCamera.stopPreview();
            mCamera.setPreviewDisplay(null);
            mCamera.setPreviewCallbackWithBuffer(null);
            mCamera.release();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        mCamera = null;
    }
    public void finish(){
        stopVideo();
        super.finish();
    };
}

preguntado el 04 de julio de 12 a las 09:07

1 Respuestas

BitmapFactory no sabe cómo decodificar los datos de vista previa de la cámara, porque es una matriz de píxeles sin procesar, sin información de identificación. Es por eso que está lanzando una excepción.

Tiene que convertir/interpretar los datos usted mismo en un formato RGB y construir un mapa de bits a partir de eso. De forma predeterminada, la cámara proporciona datos de vista previa en el NV21 formato. Puede encontrar más detalles sobre NV21 aquí. Para crear una imagen RGB a todo color, necesitará muestrear los dos canales de crominancia y luego convertir el resultado en RGB.

Si está de acuerdo con guardar un archivo JPEG, puede usar el YuvImagen clase para esto también.

Respondido el 15 de Septiembre de 12 a las 23:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.