Android Camera2 获取预览数据

一、Camera2简介

Camera2是Google在Android 5.0后推出的一个全新的相机API,Camera2和Camera没有继承关系,是完全重新设计的,且Camera2支持的功能也更加丰富,但是提供了更丰富的功能的同时也增加了使用的难度。Google的官方Demo:

https://github.com/googlesamples/android-Camera2Basic

二、Camera2预览流程

Camera2 API使用流程如下

三、使用Camera2获取预览数据

1.获取预览数据

一般情况下,大多设备其实只支持ImageFormat.YUV_420_888ImageFormat.JPEG格式的预览数据,而ImageFormat.JPEG是压缩格式,一般适用于拍照的场景,而不适合直接用于算法检测,因此我们一般取ImageFormat.YUV_420_888作为我们获取预览数据的格式,对于YUV不太了解的同学可以戳这里

复制代码
mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(), mPreviewSize.getHeight(),
                ImageFormat.YUV_420_888, 2);
mImageReader.setOnImageAvailableListener(
               new OnImageAvailableListenerImpl(), mBackgroundHandler);

其中OnImageAvailableListenerImpl的实现如下

复制代码
private class OnImageAvailableListenerImpl implements ImageReader.OnImageAvailableListener {
        private byte[] y;
        private byte[] u;
        private byte[] v;
        private ReentrantLock lock = new ReentrantLock();

        @Override
        public void onImageAvailable(ImageReader reader) {
            runOnSubThread(new Runnable() {
                @Override
                public void run() {
                    Image image = reader.acquireNextImage();
                    // Y:U:V == 4:2:2
                    if (image.getFormat() == ImageFormat.YUV_420_888) {
                        Image.Plane[] planes = image.getPlanes();
                        // 加锁确保y、u、v来源于同一个Image
                        lock.lock();
                        // 重复使用同一批byte数组,减少gc频率
                        if (y == null) {
                            y = new byte[planes[0].getBuffer().limit() - planes[0].getBuffer().position()];
                            u = new byte[planes[1].getBuffer().limit() - planes[1].getBuffer().position()];
                            v = new byte[planes[2].getBuffer().limit() - planes[2].getBuffer().position()];
                        }
                        if (image.getPlanes()[0].getBuffer().remaining() == y.length) {
                            planes[0].getBuffer().get(y);
                            planes[1].getBuffer().get(u);
                            planes[2].getBuffer().get(v);
							//2.处理数据
                            byte[] nv21 = new byte[planes[0].getRowStride() * mPreviewSize.getHeight() * 3 / 2];
                            yuv422ToYuv420sp(y, u, v, nv21, planes[0].getRowStride(), mPreviewSize.getHeight());
                        }
                        lock.unlock();
                    }
                    image.close();
                }
            });
        }
    }
2.将YUV_420_888的数据转化成nv21
复制代码
	/**
     * 将Y:U:V == 4:2:2的数据转换为nv21
     *
     * @param y      Y 数据
     * @param u      U 数据
     * @param v      V 数据
     * @param nv21   生成的nv21,需要预先分配内存
     * @param stride 步长
     * @param height 图像高度
     */
    public void yuv422ToYuv420sp(byte[] y, byte[] u, byte[] v, byte[] nv21, int stride, int height) {
        System.arraycopy(y, 0, nv21, 0, y.length);
        // 注意,若length值为 y.length * 3 / 2 会有数组越界的风险,需使用真实数据长度计算
        int length = y.length + u.length / 2 + v.length / 2;
        int uIndex = 0, vIndex = 0;
        for (int i = stride * height; i < length; i += 2) {
            nv21[i] = v[vIndex];
            nv21[i + 1] = u[uIndex];
            vIndex += 2;
            uIndex += 2;
        }
        List<FacePreviewInfo> facePreviewInfos = HrHelper.getInstance().onPreviewFrame(nv21, true);
        HrHelper.getInstance().clearLeftFace(facePreviewInfos);
    }

四、参考

进击的丸子

Android Camera2入门系列2 - ImageReader获得预览数据

相关推荐
韩仔搭建4 小时前
第二章:安卓端启动流程详解与疑难杂症调试手册
android·ui·娱乐
A-花开堪折4 小时前
Android7 Input(七)App与input系统服务建立连接
android
冰糖葫芦三剑客4 小时前
Android 自定义悬浮拖动吸附按钮
android
吃汉堡吃到饱4 小时前
【Android】从Choreographer到UI渲染(二)
android·ui
微信公众号:AI创造财富4 小时前
显示的图标跟UI界面对应不上。
android·ui
aningxiaoxixi4 小时前
安卓 Audio Stream 类型
android
奔跑吧 android5 小时前
【android bluetooth 协议分析 01】【HCI 层介绍 3】【NUMBER_OF_COMPLETED_PACKETS 事件介绍】
android·bluetooth·hci·bt·gd·aosp13
_龙小鱼_7 小时前
Kotlin扩展简化Android动画开发
android·开发语言·kotlin
奔跑吧 android8 小时前
【android bluetooth 协议分析 01】【HCI 层介绍 6】【WriteLeHostSupport命令介绍】
android·bluetooth·bt·gd·aosp13·writelehostsup·hcicmd
uwvwko8 小时前
ctfshow——web入门254~258
android·前端·web·ctf·反序列化