![](/img/trans.png)
[英]How to get camera2 preview frames programmatically(without layout) in Android?
[英]What is the correct way to get Preview Frames using Android NDK Camera2
基於 NDK 相機示例texture-view ,我想創建一個ImageReader
來獲取預覽幀。
創建ImageReader
和相機 session:
yuvReader_ = new ImageReader(&compatibleCameraRes_, AIMAGE_FORMAT_YUV_420_888);
camera_->CreateSession(ANativeWindow_fromSurface(env_, surface), yuvReader_->GetNativeWindow());
void NDKCamera::CreateSession(ANativeWindow* previewWindow, ANativeWindow* yuvWindow) {
// Create output from this app's ANativeWindow, and add into output container
requests_[PREVIEW_REQUEST_IDX].outputNativeWindow_ = previewWindow;
requests_[PREVIEW_REQUEST_IDX].template_ = TEMPLATE_PREVIEW;
requests_[YUV_REQUEST_IDX].outputNativeWindow_ = yuvWindow;
requests_[YUV_REQUEST_IDX].template_ = TEMPLATE_PREVIEW;
CALL_CONTAINER(create(&outputContainer_));
for (auto& req : requests_) {
if (!req.outputNativeWindow_) continue;
ANativeWindow_acquire(req.outputNativeWindow_);
CALL_OUTPUT(create(req.outputNativeWindow_, &req.sessionOutput_));
CALL_CONTAINER(add(outputContainer_, req.sessionOutput_));
CALL_TARGET(create(req.outputNativeWindow_, &req.target_));
CALL_DEV(createCaptureRequest(cameras_[activeCameraId_].device_,
req.template_, &req.request_));
CALL_REQUEST(addTarget(req.request_, req.target_));
}
// Create a capture session for the given preview request
captureSessionState_ = CaptureSessionState::READY;
CALL_DEV(createCaptureSession(cameras_[activeCameraId_].device_,
outputContainer_, GetSessionListener(),
&captureSession_));
}
然后開始預覽:
void NDKCamera::StartPreview(bool start) {
if (start) {
ACaptureRequest* requests[] = { requests_[PREVIEW_REQUEST_IDX].request_, requests_[YUV_REQUEST_IDX].request_};
CALL_SESSION(setRepeatingRequest(captureSession_, nullptr, 2,
requests,
nullptr));
} else if (!start && captureSessionState_ == CaptureSessionState::ACTIVE) {
ACameraCaptureSession_stopRepeating(captureSession_);
}
}
我在setRepeatingRequest
中設置了兩個請求。 一個用於TextureView
顯示,另一個用於接收 C++ 中的預覽幀。
現在,問題是設置兩個輸出后,預覽性能下降(看起來像播放幻燈片),這在 Java 中不會出現:
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
// The camera is already closed
if (null == mCameraDevice) {
return;
}
mCaptureSession = cameraCaptureSession;
startPreview();
}
@Override
public void onConfigureFailed(
@NonNull CameraCaptureSession cameraCaptureSession) {
showToast("Failed");
}
}, null
);
有人知道為什么嗎? 謝謝!
相比之下,我不知道您是如何設置 Java 代碼的,但是您在 NDK 代碼中所做的事情會使您的幀速率降低一半。 如果您希望以 30fps 的速度將預覽幀和幀都發送到本機 ImageReader,則需要在單個捕獲請求中包含兩個目標,而不是在每個僅針對一個 output 的兩個捕獲請求之間交替。 后者最多可為每個 output 提供 15fps。
因此,只需創建一個請求,然后使用預覽和 YUV windows 在其上調用 addTarget 兩次。 單個請求可以添加多少個目標是有限制的,但通常等於單個 session 中可以配置的目標數量,這取決於設備的硬件能力,以及每個 output 的分辨率。
但是,2 個流,一個預覽和一個應用綁定的 YUV,應該始終有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.