簡體   English   中英

獲取android camera2預覽幀而不會滯后屏幕預覽

[英]Getting android camera2 preview frames without lagging the screen preview

在原始(現已棄用)的相機API中,我們曾經能夠在Camera.PreviewCallback中獲取預覽幀並能夠處理它(可能需要很長時間)並釋放緩沖區以便能夠接收另一幀,而不會滯后屏幕預覽,包含以下代碼:

public void onPreviewFrame(final byte[] data, Camera camera) {
    new AsyncTask<Void, Void, Void>() {

        @Override
        protected Void doInBackground(Void... params) {
            (... do some slow processing ...)
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            mCamera.addCallbackBuffer(data); // free the buffer to be able
                                               // to process another frame
        }
    }.execute();
}

如果有另一個可用於接收它的緩沖區,API將僅使用新幀進行回調,而不會滯后屏幕預覽。

我試圖在新的Camera2 API上復制相同的行為,但我找不到一種方法來做到這一點而不會滯后於屏幕預覽。 如果我向預覽請求添加第二個目標(與屏幕1相同的分辨率,YUV_420_888):

mPreviewRequestBuilder.addTarget(surface);
mPreviewRequestBuilder.addTarget(previewImageReader.getSurface());
mCameraDevice.createCaptureSession(
    Arrays.asList(surface, previewImageReader.getSurface()), ...

屏幕預覽會滯后,即使我只是在我得到它時立即關閉圖像:

@Override
public void onImageAvailable(ImageReader reader) {
    reader.acquireNextImage().close();
}

使用Camera2模擬原始相機API行為的正確方法是什么(即,只要有一個空閑且沒有減慢屏幕預覽,就會有一個新的緩沖區)?

更新:如果有人想知道代碼的其余部分是什么樣的,它只是標准android-camera2Basic示例的修改版本, 這就是我改變的內容

如果有人仍然感興趣。

創建一個SurfaceTextureListener並從onSurfaceTextureUpdated方法調用您的異步函數。 在使用BarcodeDetection API和Camera 2 API檢查條形碼的幀時,我已成功使用此功能。

以下是從onSurfaceTextureUpdated方法啟動的異步函數示例。 如果您只想在后台運行一個異步任務,則可以使用標志來檢查上一個任務是否已完成。

private final TextureView.SurfaceTextureListener mSurfaceTextureListener
    = new TextureView.SurfaceTextureListener() {

    boolean processing;

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
        openCamera(width, height);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
        configureTransform(width, height);
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture texture) {
        if (processing) {
            return;
        }

        processing = true;

        Bitmap photo = mTextureView.getBitmap();

        new ImageTask(photo, new ImageResponse() {
                @Override
                public void processFinished() {
                    processing = false;
                }
            }).execute();
    }
};

private interface ImageResponse {
    void processFinished();
}

private class ImageTask extends AsyncTask<Void, Void, Exception> {
    private Bitmap photo;
    private ImageResponse imageResponse;
    ImageTask(Bitmap photo, ImageResponse imageResponse) {
        this.photo = photo;
        this.imageResponse = imageResponse;
    }

    @Override
    protected Exception doInBackground(Void... params) {
        // do background work here
        imageResponse.processFinished();
        return null;
    }

    @Override
    protected void onPostExecute(Exception result) {

    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM