android Camera api1 및 api2 ZSL 간략한 설명

19684 단어 Camera
ZSL의 개념
ZSL(zero shutter lag)의 중국어 이름은 제로 타임 사진으로 사진 촬영 지연을 줄이고 사진 & 리셋을 순간적으로 완성하기 위한 기술이다.
Single Shot은 미리 보기를 시작하면sensor와 VFE에서 preview와 snapshot 프레임을 생성하고 최신 snapshot 프레임 데이터는 버퍼에 저장됩니다.사진이 터치되면 시스템은 실제 촬영 시간을 계산하여 버퍼에 있는 상응하는 프레임을 찾아내고 프레임을 사용자에게 되돌려주는 것이 이른바'ZERO'다.
시스템은 shutter lag의 시간을 계산한 다음에 어떤 프레임을 사진의 실시간 데이터로 인식한다.
ZSL의 실현 메커니즘
ZSL 구현을 위해서는 다음과 같은 몇 가지 사항이 필요합니다.
  • 미리 보기용surfaceView
  • 대기열 캐시 snapshot 데이터
  • 사진 동작 획득 대열의 모 정 데이터를 사진 데이터로 출력
  • 출력된 사진은 YUV->JPEG 데이터의 부호화 필요
  • 먼저 ZSL 기능이 android 4에 있다고 말씀드리겠습니다.4 와android 5.0에서 이루어진 차이.
    Android4.4의 실현은 2)보와 3)보가 모두HAL층에서 이루어지고,HAL층은 캐시 대기열을 유지하고 있으며,take를 거꾸로 받으면picture 명령을 내릴 때 특정 캐시 데이터를 직접 가져와 코드를 바꾼 다음 정상적으로 사진을 찍는 절차로 @link android를 사용합니다.hardware.Camera.PictureCallback 은 애플리케이션 계층의 사진 촬영 데이터를 알려줍니다.
    Android5.0의 실현은 2)보와 3)보에 모두 응용층에서 이루어진다. 응용층은 미리보기를 시작할 때HAL층에 2개의surface를HAL층에 전달하고HAL층은그 중의surface를 이용하여 미리보기 데이터 충전에 사용하며,한surface는snapshot의 데이터 충전에 사용한다.응용층은surface에서 snapshot의 데이터를 끊임없이 읽어서 캐시 대기열을 유지합니다.takepicture, 캐시 대기열의 데이터를 사진 데이터로 읽습니다.Android5.0의 애플리케이션 레이어에는 이미 ZSL 클래스가 있습니다.
    src/com/android/camera/one/v2/OneCameraZslImpl.java
    기본적으로 이 방법은 호출되지 않았습니다. 왜냐하면 HAL층은 기본적으로 지원하지 않기 때문입니다. 왜냐하면 HAL층은 실현 코드가 없기 때문에 각 제조업체가 실현한 후에 서로 다른 설정을 설정해야 지원합니다.
    당분간 응용층이 OneCameraZslImpl을 어떻게 호출하는지 고려하지 않겠습니다.java, One Camera Zsl Impl이 Camera API를 어떻게 활용하는지 직접 알려드립니다.0 ZSL 사진 촬영 기능을 구현합니다.
    Camera API2.0의 ZSL 미리 보기
    파일 OneCameraZslImpl.java 파일에서 startpreview를 시작하는 코드를 찾을 수 있습니다. 코드는 다음과 같습니다.
    @Override
    
        public void startPreview(Surface previewSurface, CaptureReadyCallback listener) {
    
            mPreviewSurface = previewSurface;
    
            setupAsync(mPreviewSurface, listener);
    
        }
    

    SetupAsync에서 두 개의 매개 변수를 전달하는데 첫 번째 매개 변수 mPreviewSurface는 미리보기의surface이고 두 번째 매개 변수는 하나의 리셋이다. 이름에서 알 수 있듯이 사진을 찍기 위해 준비한 리셋이다.
    *android 5.0의camera 응용 프로그램,camera 프레임워크 사방에 이런 유사한 실현 메커니즘이 있는데 일부러 코드를 이해하지 못하게 하는 것 같다.
    SetupAsync 메서드에서 setup을 비동기적으로 호출하여 미리 보기를 시작합니다.
    private void setupAsync(final Surface previewSurface, 
    
                                   final CaptureReadyCallback listener) {
    
            mCameraHandler.post(new Runnable() {
    
                    @Override
    
                public void run() {
    
                    setup(previewSurface, listener);
    
                }
    
            });
    
            }
    

    이제 setup 방법을 볼 수 있다. 이것이야말로HAL층과 상호작용하는 관건이자 응용층이 사진 대기열 데이터를 캐시하기 시작하는 관건이다.
      private void setup(Surface previewSurface, final CaptureReadyCallback listener) {
    
            .......
    
                List<Surface> outputSurfaces = new ArrayList<Surface>(2);
    
                outputSurfaces.add(previewSurface);//     surface
    
                outputSurfaces.add(mCaptureImageReader.getSurface()); //     surface
    
                //mDevice Framework CameraDeviceImpl.java  ,
    
                //  app  HAL      
    
                mDevice.createCaptureSession(outputSurfaces,
    
                                   new CameraCaptureSession.StateCallback() {
    
                        @Override
    
                    public void onConfigureFailed(CameraCaptureSession session) {
    
                        ......
    
                    }
    
                        @Override
    
                    public void onConfigured(CameraCaptureSession session) {
    
                        .......//       
    
                    }
    

    framework에 직접 가서createCaptureSession 방법을 보십시오. 이 방법에서 새로운 CapureSession을 만들 것입니다. 이 방법이 만들어진 후에 lister의 onConfigured 방법을 리셋합니다. 이렇게 하면 새로운 Session을 얻을 수 있습니다. 다음은createCaptureSession이CapureSession을 만드는 방법입니다.
    frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
    
     
    
     @Override
    
        public void createCaptureSession(List<Surface> outputs,
    
                CameraCaptureSession.StateCallback callback, Handler handler)
    
                throws CameraAccessException {
    
           .........
    
    //    Session
    
                CameraCaptureSessionImpl newSession =
    
                        new CameraCaptureSessionImpl(mNextSessionId++,
    
                                outputs, callback, handler, this, mDeviceHandler,
    
                                configureSuccess);
    
    ......
    
            }
    
        }
    

    sendRepeatingCaptureRequest를 호출하여 적용되는 onConfigured 메서드를 보려면 다음과 같이 하십시오.
     mCaptureSession = session;
    
                        .......
    
                        //         
    
                        boolean success = sendRepeatingCaptureRequest();
    
                        if (success) {
    
                            mReadyStateManager.setInput(ReadyStateRequirement
    
                                       .CAPTURE_NOT_IN_PROGRESS,
    
                                    true);
    
                            mReadyStateManager.notifyListeners();
    
                            listener.onReadyForCapture();
    
                        } else {
    
                            listener.onSetupFailed();
    
                        }
    

    sendRepeatingCaptureRequest 방법에서Camera Device Impl을 이용하여 사진 요청을 만들고 중복된 사진 명령을 설정하여 캐시 업데이트를 시작합니다.
    private boolean sendRepeatingCaptureRequest() {
    
                builder = mDevice.
    
                 createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
    
                 //TEMPLATE_ZERO_SHUTTER_LAG       HAL      
    
                 //        ZSL    
    
     
    
                builder.addTarget(mPreviewSurface);
    
                builder.addTarget(mCaptureImageReader.getSurface());
    
                //   HAL       
    
                mCaptureSession.setRepeatingRequest(builder.build(), mCaptureManager,
    
                        mCameraHandler);
    
                return true;
    
       }
    

    Camera API2.0의 ZSL 사진
    앞에서 설명한 대로 사진 명령을 실행하면 캐시 대기열의 데이터를 얻을 수 있습니다. ZSL의 캐시 데이터는 프레임워크가 제공하는 도구 종류인 ImageReader를 이용합니다.
    ImageReader의 인스턴스를 보려면 다음과 같이 하십시오.
    mCaptureImageReader = ImageReader.newInstance(pictureSize.getWidth(),
    
                    pictureSize.getHeight(),
    
                    sCaptureImageFormat, MAX_CAPTURE_IMAGES);
    
     
    
      sCaptureImageFormat     :
    
     
    
        /**
    
         * Set to ImageFormat.JPEG to use the hardware encoder, or
    
         * ImageFormat.YUV_420_888 to use the software encoder. No other image
    
         * formats are supported.
    
         */
    
        private static final int sCaptureImageFormat = ImageFormat.YUV_420_888;
    
     
    

    여기서 sCaptureImageFormat는 JPEG 또는 YUV 로 정의할 수 있습니다.420_888, 그 중에서 JEPG는 HAL 코드가 필요합니다. 코드는 효율 문제와 관련됩니다. YUV 로 설정됩니다.420_888은 응용층 디코딩이 필요하다. 만약에 응용 분배 자원이 적으면 응용 오버를 직접 초래할 수도 있다.
    MAX_CAPTURE_IMAGES는 정의된 캐시 수입니다.
      /**
    
         * The maximum number of images to store in the full-size ZSL ring buffer.
    
         * <br>
    
         * TODO: Determine this number dynamically based on available memory and the
    
         * size of frames.
    
         */
    
        private static final int MAX_CAPTURE_IMAGES = 10;
    
     
    
     
    
      OneCameraZslImpl.java   takePicture  ,      :
    
     @Override
    
        public void takePicture(final PhotoCaptureParameters params, 
    
                            final CaptureSession session) {
    
            //       
    
            mReadyStateManager.setInput(
    
                    ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, false);
    
     
    
    //        
    
     boolean capturedPreviousFrame = mCaptureManager.tryCaptureExistingImage(
    
                        new ImageCaptureTask(params, session), zslConstraints);
    
    }
    
     
    
    ImageCaptureTask   ImageCaptureListener   ,   onImageCaptured  :
    
     @Override
    
            public void onImageCaptured(Image image, TotalCaptureResult
    
                    captureResult) {
    
    ......
    
                  mReadyStateManager.setInput(
    
                        ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, true);
    
                mSession.startEmpty();
    
                savePicture(image, mParams, mSession);
    
    ......
    
                mParams.callback.onPictureTaken(mSession);
    
            }
    
     
    
     
    
                 ImageCaptureManager      :
    
     
    
        public boolean tryCaptureExistingImage(final ImageCaptureListener onImageCaptured,
    
                final List<CapturedImageConstraint> constraints) {
    
    ......
    
                 //     image  
    
                 selector = new Selector<ImageCaptureManager.CapturedImage>() {
    
                        @Override
    
                    public boolean select(CapturedImage e) {
    
                       ......
    
                };
    
            //            
    
            final Pair<Long, CapturedImage> toCapture =
    
     mCapturedImageBuffer.tryPinGreatestSelected(selector);
    
            return tryExecuteCaptureOrRelease(toCapture, onImageCaptured);
    
    }
    
     
    
     
    
     tryExecuteCaptureOrRelease     ImageCaptureTask onImageCaptured  ,   onImageCaptured     savePicture      ,  savePicture  :
    
     
    
    private void savePicture(Image image, final PhotoCaptureParameters captureParams,
    
                CaptureSession session) {
    
           
    
            // TODO: Add more exif tags here.
    
            //
    
            session.saveAndFinish(acquireJpegBytes(image), width, height, rotation, exif,
    
                    new OnMediaSavedListener() {
    
                    @Override
    
                        public void onMediaSaved(Uri uri) {
    
                            captureParams.callback.onPictureSaved(uri);
    
                        }
    
                    });
    
        }
    

    그림은 앱으로 생성되기 때문에 앱은 파일 헤더와 태그 정보를 책임지고 이 savePicture 방법에 그림의 GSP, 각도, 높이와 너비 정보를 채워야 한다.
    데이터를 저장할 때 YUV를 jpeg으로 전환해야 합니다. 구글은 이 문제를 위해 so 라이브러리를 만들었습니다. 이 코드는 Camera의 jni 디렉터리에 있습니다. Camera의 안드로이드에 있습니다.mk 파일
    LOCAL_JNI_SHARED_LIBRARIES := libjni_tinyplanet libjni_jpegutil
    그리고 제니의 안드로이드를 보세요.mk 파일
    # JpegUtil
    
    include $(CLEAR_VARS)
    
     
    
    LOCAL_CFLAGS := -std=c++11
    
    LOCAL_NDK_STL_VARIANT := c++_static
    
    LOCAL_LDFLAGS   := -llog -ldl
    
    LOCAL_SDK_VERSION := 9
    
    LOCAL_MODULE    := libjni_jpegutil
    
    LOCAL_SRC_FILES := jpegutil.cpp jpegutilnative.cpp
    

    Camera API2.0의 ZSL 문제점
    Camera API2.0은 앞으로 실시간 렌더링에 더 많은 조작성을 적용할 수 있는 더 큰 조작 공간을 제공한다.하지만 다음과 같은 문제가 발생합니다.
    1. 응용층의 메모리를 너무 많이 차지하기 때문에 ZSL은 응용층에 10개의 버퍼를 저장하여 그림을 저장해야 하기 때문에 자원 문제를 일으키기 쉽다. 그래서 구글은 코드에 ZSL에 사용할 그림의 크기를 1080P보다 강제로 추가했다.
    YUV가 JPEG를 거꾸로 돌리는 코드는 CPU 계산 능력에 대한 요구가 있기 때문에 CPU 계산 능력이 강하지 않으면 느린 문제를 초래할 수 있다.Google에서 캐시 데이터를 추가했습니다. JPEG 처리입니다.

    좋은 웹페이지 즐겨찾기