[英]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.