一种基于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();
复制代码

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

查看所有标签

猜你喜欢:

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

重新定义公司

重新定义公司

[美]埃里克·施密特 / 靳婷婷、陈序、何晔 / 中信出版社 / 2015-8 / 49.00

谷歌高管手绘风漫画视频: http://v.youku.com/v_show/id_XMTMxMzQ3NjMyMA==.html?from=y1.7-1.2 Google掌门人第一本国内引进作品 首次公开谷歌内部的管理与运营方法 全面解密执掌谷歌10余年的内幕故事 谷歌 创始人拉里•佩奇作序推荐 今日的谷歌是全球最具标志性的企业,在各个领域都有创新突破,并向技术......一起来看看 《重新定义公司》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具