Camera - dump 预览帧数据处理(一)

        Camera中有很多check预览帧的需求,可以在应用层、HAL层通过不同的方法dump数据进而check某一时刻的Camera YUV数据、RGBA数据是否有异常,本节主要分析应用层dump 预览流YUV数据的方法,之后会继续check GPU框架下dump GLSurfaceView的RGBA数据的方法以及HAL层dump数据的节点和相关命令。

1.保存预览上来的YUV数据

配置YUV数据

 

配置预览回调数据

private static class CameraPreViewCallbackForward extends CameraPreViewCallbackAbstract {
        private final Handler mHandler;
        private final CameraPreviewDataCallback mCallback;
        private final CameraAgent.CameraProxy mCamera;

        public static CameraPreViewCallbackForward getNewInstance(Handler handler,
                CameraProxy camera, CameraPreviewDataCallback cb) {
            if (handler == null || camera == null || cb == null)
                return null;
            return new CameraPreViewCallbackForward(handler, camera, cb);
        }

        private CameraPreViewCallbackForward(Handler h, CameraProxy camera, CameraPreviewDataCallback cb) {
            mHandler = h;
            mCallback = cb;
            mCamera = camera;
        }

        @Override
        public void onImageAvailable(ImageReader reader) {
            try (Image image = reader.acquireNextImage()) {
                if(mAppMode == /*SettingsScopeNamespaces.PANORAMA*/37){
                    final Plane[] planeList = image.getPlanes();
                    if(planeList.length == 3){
                        ...

                        onPreviewFrameImage(byteBuffer, rowStride, pixelStride);
                    }
                }else{
                    //这边拿到绑定了mPreviewReader的YUV数据
                    onPreviewFrame(getNV21FromImage(image), mCamera);
                }
            }
        }

        @Override
        public void onPreviewFrame(byte[] data, CameraAgent.CameraProxy camera) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    //传给之前的callback回调
                    mCallback.onPreviewFrame(data, mCamera);
                }
            });
        }

        public void onPreviewFrameImage(ByteBuffer[] byteBuffer , int[] rowStride, int[] pixelStride){//add by cyy for 360 panorama request
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onPreviewFrameImage(byteBuffer , rowStride, pixelStride);
                }
            });
        }
    }

保存YUV数据

public static String saveYuvImage(byte[] data, String path, String name){
        if (data == null)
            return null;

        //File mediaStorageDir = mContext.getExternalFilesDir("megvii");
        //File dir = new File(mediaStorageDir, path);
        File dir = new File(path);
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                return null;
            }
        }
        String yuvFileName = name + ".yuv";
        // String bitmapFileName = System.currentTimeMillis() + "";
        File file = new File(dir, yuvFileName);
        FileOutputStream fos = null;
        String ret = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(data);
            ret = file.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null) fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ret;
}
    SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
        String date = sDateFormat.format(new java.util.Date());

        File mediaStorageDir = mActivity.getAndroidContext().getExternalFilesDir("DCIM");
        File d = new File(mediaStorageDir, path);

        //File d = new File("/storage/emulated/0/bitmap/");
        File f = new File(d, date + ".yuv");

        if (!d.exists()) {
            d.mkdirs();
        }

        if (f.exists()) {
            f.delete();
        }

        try {
            FileOutputStream out = new FileOutputStream(f);
            out.write(data);
            out.flush();
            out.close();
        } catch (IOException e) {
            Log.e(TAG, "CameraSaveBitmap saveBitmapToFileException:" + f.getAbsolutePath() + " Exception");
            e.printStackTrace();
        }
    }

 

dump出来的预览图

原始的:

旋转90度的:

旋转yuv数据:

        byte[] rotatedData = new byte[data.length];
        for (int y = 0; y < cameraHeight; y++) {
            for (int x = 0; x < cameraWidth; x++)
                rotatedData[x * cameraHeight + cameraHeight - y - 1] = data[x + y * cameraWidth];
        }
        int tmp = cameraWidth;
        cameraWidth = cameraHeight;
        cameraHeight = tmp;

 旋转时候没有去check stride,但是算法那边只读取y数据,所以没有造成太大影响

                    final Plane[] planeList = image.getPlanes();
                    if(planeList.length == 3){
                        final ByteBuffer[] byteBuffer = new ByteBuffer[3];
                        final int[] rowStride = new int[3];
                        final int[] pixelStride = new int[3];
                        byteBuffer[0] = planeList[0].getBuffer();
                        rowStride[0] = planeList[0].getRowStride();
                        pixelStride[0] = planeList[0].getPixelStride();

                        byteBuffer[1] = planeList[1].getBuffer();
                        rowStride[1] = planeList[1].getRowStride();
                        pixelStride[1] = planeList[1].getPixelStride();

                        byteBuffer[2] = planeList[2].getBuffer();
                        rowStride[2] = planeList[2].getRowStride();
                        pixelStride[2] = planeList[2].getPixelStride();
                        onPreviewFrameImage(byteBuffer, rowStride, pixelStride);
                    }

 

总结:

        今天正好遇到算法检测不到人脸数据的问题,流程上看不出一些问题,然后就疯狂dump各个节点的流数据进行分析,那酸爽不言而喻,然后就乘机把dump的一些流程进行一下总结,痛苦被记录下来以后再遇到就没那么痛苦了吧!

  • 1
    点赞
  • 6
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cmatrix204

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值