一种基于Android Camera无预览采集YUV帧的实现方式

栏目: IOS · Android · 发布时间: 5年前

内容简介:限于硬件成本,有时需要使用Android原生的camera无预览采集YUV数据,用于生成图片与h.264编码。要实现该功能,只需要调用setPreviewTexture即可。

限于硬件成本,有时需要使用Android原生的camera无预览采集YUV数据,用于生成图片与h.264编码。要实现该功能,只需要调用setPreviewTexture即可。

1、相机CameraHelper

public class CameraHelper implements Camera.PreviewCallback {

    private static final String TAG = "CameraHelper";
    public static final int WIDTH = 640;
    public static final int HEIGHT = 480;

    private int mCameraId;
    private Camera mCamera;
    private byte[] buffer;
    private SurfaceTexture surfaceTexture = new SurfaceTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
    private boolean shut = false;
    private OnPictureRawCapture pictureRawCaptureListener;

    public void setPictureRawCaptureListener(OnPictureRawCapture pictureRawCaptureListener) {
        this.pictureRawCaptureListener = pictureRawCaptureListener;
    }

    public CameraHelper(int cameraId){
        mCameraId = cameraId;
    }

    public void switchCamera(){
        if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
            mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
        }else{
            mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
        }
        stopPreview();
        startPreview();
    }

    public void startPreview() {
        try {
            mCamera = Camera.open(mCameraId);
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setPreviewFormat(ImageFormat.NV21);
            parameters.setPreviewSize(WIDTH, HEIGHT);

            mCamera.setParameters(parameters);
            buffer = new byte[WIDTH * HEIGHT *3/2];

            mCamera.addCallbackBuffer(buffer);
            mCamera.setPreviewCallbackWithBuffer(this);

            mCamera.setPreviewTexture(surfaceTexture);//
            mCamera.startPreview();
        } catch (IOException e) {
            Log.e(TAG, "start preview failed");
            e.printStackTrace();
        }
    }

    public void stopPreview() {
        if (mCamera == null){
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        if(shut){
            shut = false;
            if(pictureRawCaptureListener != null){
                pictureRawCaptureListener.onCapture(data);//生成图片
            }
        }
        //to do
        //h.264编码、模式识别等
        camera.addCallbackBuffer(buffer);
    }

    public void takePicture(){//拍照
        shut = true;
    }

    public interface OnPictureRawCapture{
        void onCapture(byte[] data);
    }

    public Camera.Size getPreviewSize(){
        Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
        return previewSize;
    }
}
复制代码

2、相机启动线程

public class CameraRunnable implements Runnable{
    private CameraHelper cameraHelper;

    public CameraRunnable(CameraHelper cameraHelper) {
        this.cameraHelper = cameraHelper;
    }

        @Override
        public void run() {
            cameraHelper.startPreview();
        }
}
复制代码

3、生成图片文件线程

public class PictureRunnable implements Runnable{
        private static final String CAPTRUE_PATH = "sdcard/img/";
        private static final String TEMPLATE = "yyyy_MM_dd_HH_mm_ss";
        private SimpleDateFormat sdf = new SimpleDateFormat("", Locale.SIMPLIFIED_CHINESE);

        private Camera.Size previewSize;
        private byte[] imgRaw;

        public PictureRunnable(byte[] data,Camera.Size size){
            this.imgRaw = data;
            this.previewSize = size;
        }

        @Override
        public void run() {
            createBmpAndSaveFile(imgRaw);
        }

        private void createBmpAndSaveFile(byte[] data) {
            BitmapFactory.Options newOpts = new BitmapFactory.Options();
            newOpts.inJustDecodeBounds = true;
            YuvImage yuvimage = new YuvImage(
                    data,
                    ImageFormat.NV21,
                    previewSize.width,
                    previewSize.height,
                    null);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);
            byte[] rawImage = baos.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
            try {
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
![](https://user-gold-cdn.xitu.io/2019/7/1/16baca01448739cb?w=559&h=276&f=png&s=193437)
            if (bitmap == null)
                return;
            else {
                try {
                    saveFile(bitmap);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void saveFile(Bitmap bm) throws IOException {
            String fileName = getFileName()+".jpeg";
            File dirFile = new File(CAPTRUE_PATH);
            if(!dirFile.exists()){
                dirFile.mkdir();
            }
            File myCaptureFile = new File(CAPTRUE_PATH + fileName);
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));
            bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);
            bos.flush();
            bos.close();
            bm.recycle();
            bm=null;
            Log.d("CameraHelper","new img:"+myCaptureFile.getAbsolutePath());
            EventBus.getDefault().post(myCaptureFile.getAbsolutePath());
        }

        private String getFileName() {
            long time = System.currentTimeMillis();
            sdf.applyPattern(TEMPLATE);
            return sdf.format(time);
        }
    }
复制代码

4、程序入口

4.1 开启相机

private CameraHelper myCamera;
    private ExecutorService executorService;
    private CameraRunnable cameraRunnable;
    
 executorService = new ThreadPoolExecutor(2,4,0, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(10));
        myCamera = new CameraHelper( Camera.CameraInfo.CAMERA_FACING_BACK);
        myCamera.setPictureRawCaptureListener(this);
        cameraRunnable = new CameraRunnable(myCamera);
        executorService.execute(cameraRunnable);
复制代码

4.2 拍照

myCamera.takePicture();
复制代码

4.2.1 保存图片

@Override
    public void onCapture(byte[] data) {
        Log.d("CameraHelper","onCapture "+data.length);
        Camera.Size previewSize = myCamera.getPreviewSize();
        executorService.execute(new PictureRunnable(data,previewSize));
    }
复制代码

4.3 关闭相机

executorService.shutdownNow();
myCamera.stopPreview();
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

用UML构建Web应用

用UML构建Web应用

科纳尔伦 (Conallen Jim) / 陈起 / 中国电力出版社 / 2003-11 / 39.0

用UML构建Web应用(第2版),ISBN:9787508315577,作者:(美)Jim Conallen著;陈起,英宇译;陈起译一起来看看 《用UML构建Web应用》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换