从Android相机快速访问原始帧

时间:2019-03-13 10:01:13

标签: java android android-camera low-latency

我正在研究延迟至关重要的实时视频流应用程序。我使用的设备是搭载Android 7.1.2的相机。现在,我正在尝试从应该访问30fps的摄像机访问原始帧,因此我希望使用摄像机预览在不到50ms的时间内获取帧。问题是我得到的延迟太高(超过200毫秒)。我不确定这是否是获取原始帧的正确方法,还是有一种更有效的方法来更快地读取它们。

我正在使用的获取框架的代码如下。我正在传递一个回调缓冲区,以避免发生enter link description here中所述的GC调用,任何帮助或提示都非常受欢迎。

    public void start(SurfaceTexture surfaceTexture) {

    thread = new Thread() {
        @Override
        public void run() {
            try {
                startCamera(surfaceTexture);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    thread.start();
}

private void startCamera(SurfaceTexture surfaceTexture){
    if (mCamera == null) {
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                mCameraId = i;
            }
            try {
                mCamera = Camera.open(mCameraId);
            } catch (Exception e) {
                Timber.d(e.getMessage());
            }
        }
        mCamera.setErrorCallback(mErrorCallback);
        mParameters = mCamera.getParameters();
        mParameters.setPreviewSize(1920, 960);
        mCamera.setParameters(mParameters);
        mCamera.setDisplayOrientation(0);
        try {
            mCamera.setPreviewTexture(surfaceTexture);
            int numBytes = 300000;
            mCamera.addCallbackBuffer(new byte[numBytes]);

            mCamera.setPreviewCallback(new android.hardware.Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    long ntpTimestamp = SntpClock.getInstance().getCurrentMilliseconds();
                    Camera.Parameters parameters = camera.getParameters();
                    Camera.Size size = parameters.getPreviewSize();
                    YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
                    Rect rectangle = new Rect();
                    rectangle.bottom = size.height;
                    rectangle.top = 0;
                    rectangle.left = 0;
                    rectangle.right = size.width;
                    try{
                        File sdCard = Environment.getExternalStorageDirectory();
                        File dir = new File (sdCard.getAbsolutePath() + "/images/");
                        File file = new File(dir, "preview-"+ntpTimestamp+".jpg");
                        FileOutputStream output = new FileOutputStream(file);
                        image.compressToJpeg(rectangle, 100, output);
                        output.flush();
                        output.close();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });

        } catch (IOException e) {
            Timber.d(e.getMessage());
        }
        mCamera.startPreview();
    }
}

0 个答案:

没有答案