我正在编写一个简单的 NDK 应用程序,它应该使用相机拍照,而无需通过 JNI。
我已经使用ACameraManager_openCamera成功打开相机并获取了相机特征(ACameraManager_getCameraCharacteristics),但我不知道如何拍照。
我发现的所有示例都需要从 Java 层传递 surface。我不想这样做,想要一个仅使用 NDK 的 100% C++ 应用程序。
该应用程序将在专用的 root 设备上运行。
嗨,我不确定你所说的 100% 仅 C++ 到底是什么意思,但你最好的选择是使用 Native Activity 构建应用程序。 https://developer.android.com/ndk/reference/group/native-activity github 示例位于 https://github.com/android/ndk-samples,称为本机活动。
关于跳过 Java/Kotlin 的表面,最好的选择是使用 AImageReader https://developer.android.com/reference/android/media/ImageReader (该文档适用于 Java 版本,应该与功能(如果与 AImageReader 不同)。据我了解,AImageReader可以让你在CPU端高效地传输图像。
基于这个demo https://github.com/sixo/native-camera/blob/master/app/src/main/cpp/native-lib.cpp,可以看到可以从图像阅读器。
#ifdef WITH_IMAGE_READER
static void imageCallback(void* context, AImageReader* reader)
{
AImage *image = nullptr;
auto status = AImageReader_acquireNextImage(reader, &image);
LOGD("imageCallback()");
// Check status here ...
// Try to process data without blocking the callback
std::thread processor([=](){
uint8_t *data = nullptr;
int len = 0;
AImage_getPlaneData(image, 0, &data, &len);
// Process data here
// ...
AImage_delete(image);
});
processor.detach();
}
AImageReader* createJpegReader()
{
AImageReader* reader = nullptr;
media_status_t status = AImageReader_new(640, 480, AIMAGE_FORMAT_JPEG,
4, &reader);
//if (status != AMEDIA_OK)
// Handle errors here
AImageReader_ImageListener listener{
.context = nullptr,
.onImageAvailable = imageCallback,
};
AImageReader_setImageListener(reader, &listener);
return reader;
}
ANativeWindow* createSurface(AImageReader* reader)
{
ANativeWindow *nativeWindow;
AImageReader_getWindow(reader, &nativeWindow);
return nativeWindow;
}
#endif
和
ACaptureSessionOutputContainer_create(&outputs);
#ifdef WITH_IMAGE_READER
imageReader = createJpegReader();
imageWindow = createSurface(imageReader);
ANativeWindow_acquire(imageWindow);
ACameraOutputTarget_create(imageWindow, &imageTarget);
ACaptureRequest_addTarget(request, imageTarget);
ACaptureSessionOutput_create(imageWindow, &imageOutput);
ACaptureSessionOutputContainer_add(outputs, imageOutput);
#endif
// Create the session
ACameraDevice_createCaptureSession(cameraDevice, outputs, &sessionStateCallbacks, &textureSession);
// Start capturing continuously
ACameraCaptureSession_setRepeatingRequest(textureSession, &captureCallbacks, 1, &request, nullptr);
如您所见,您可以在没有任何 openGL 界面的情况下进行完整的会话,大多数示例都使用它,因为在屏幕上查看预览很有用,但我想这不是必需的。
好吧,说实话我还没有尝试过,所以让我们知道效果如何:)