2

カメラのプレビュー画像をリアルタイムで保存しようとしています。目標は、サーフェスビューに配置されたプレビューから少なくとも1fpsを保存することです。私はこれで立ち往生しています

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

バイト配列が渡されたと思います

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

生データの画像が含まれているので、ビットマップに変換してSDカードに保存しようとしています。私の質問は次のとおりです。

  1. これは私の目標を達成するために休耕する正しい道ですか?
  2. ログにこのエラーが表示されますSkImageDecoder::Factoryがnullを返しましたビットマップ変換に関連していると思いますが、正しいですか?

どんな提案でも大歓迎です。ありがとうございました

ここに完全なコードがあります:

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();
    };
}
4

1 に答える 1

4

BitmapFactoryは、カメラからのプレビューデータをデコードする方法を認識していません。これは、ピクセルの生の配列であり、識別情報がないためです。そのため、例外がスローされます。

データを自分でRGB形式に変換/解釈し、そこからビットマップを作成する必要があります。デフォルトでは、カメラはNV21形式でプレビューデータを提供します。NV21の詳細については、こちらをご覧ください。フルカラーRGB画像を作成するには、2つのクロミナンスチャネルをアップサンプリングしてから、結果をRGBに変換する必要があります。

JPEGの保存に問題がない場合は、YuvImageクラスを使用することもできます。

于 2012-09-15T22:50:57.240 に答える