Как связать предварительный просмотр и текстуру в CameraX
Недавно я попытался разработать плагин флаттера с cameraX, но обнаружил, что просто невозможно связать Preview с текстурой флаттера.
В прошлом мне нужно было только использовать camera.setPreviewTexture(surfaceTexture.surfaceTexture()) для привязки камеры и текстуры, теперь я не могу найти API.
camera.setPreviewTexture(surfaceTexture.surfaceTexture())
val previewConfig = PreviewConfig.Builder().apply {
setTargetAspectRatio(Rational(1, 1))
setTargetResolution(Size(640, 640))
}.build()
// Build the viewfinder use case
val preview = Preview(previewConfig).also{
}
preview.setOnPreviewOutputUpdateListener {
// it.surfaceTexture = this.surfaceTexture.surfaceTexture()
}
// how to bind the CameraX Preview surfaceTexture and flutter surfaceTexture?
1 ответ
Думаю, можно привязать текстуру с помощью Preview.SurfaceProvider.
final CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
final ListenableFuture<ProcessCameraProvider> listenableFuture = ProcessCameraProvider.getInstance(appCompatActivity.getBaseContext());
listenableFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = listenableFuture.get();
Preview preview = new Preview.Builder()
.setTargetResolution(new Size(720, 1280))
.build();
cameraProvider.unbindAll();
Camera camera = cameraProvider.bindToLifecycle(appCompatActivity, cameraSelector, preview);
Preview.SurfaceProvider surfaceProvider = request -> {
Size resolution = request.getResolution();
surfaceTexture.setDefaultBufferSize(resolution.getWidth(), resolution.getHeight());
Surface surface = new Surface(surfaceTexture);
request.provideSurface(surface, ContextCompat.getMainExecutor(appCompatActivity.getBaseContext()), result -> {
});
};
preview.setSurfaceProvider(surfaceProvider);
} catch (Exception e) {
e.printStackTrace();
}
}, ContextCompat.getMainExecutor(appCompatActivity.getBaseContext()));
Кажется, что использование CameraX трудно или невозможно из-за того, что оно абстрагирует более сложные вещи и, следовательно, не раскрывает то, что вам нужно, например, возможность передавать в вашей собственной SurfaceTexture (которая обычно создается Flutter).
Поэтому простой ответ заключается в том, что вы не можете использовать CameraX.
Тем не менее, с некоторой работой вы можете заставить это работать, но я понятия не имею, будет ли это работать наверняка. Это уродливо и непристойно, поэтому я бы не советовал. YMMV.
Если мы собираемся сделать это, давайте сначала посмотрим, как трепетание создает текстуру
@Override
public TextureRegistry.SurfaceTextureEntry createSurfaceTexture() {
final SurfaceTexture surfaceTexture = new SurfaceTexture(0);
surfaceTexture.detachFromGLContext();
final SurfaceTextureRegistryEntry entry = new SurfaceTextureRegistryEntry(nextTextureId.getAndIncrement(),
surfaceTexture);
mNativeView.getFlutterJNI().registerTexture(entry.id(), surfaceTexture);
return entry;
}
Большая часть этого является воспроизводимой, поэтому мы можем сделать это с текстурой поверхности, которую дает нам камера.
Вы можете получить текстуру, которую камера создает следующим образом:
preview.setOnPreviewOutputUpdateListener { previewOutput ->
SurfaceTexture texture = previewOutput.surfaceTexture
}
Теперь вам нужно будет передать ссылку на ваш FlutterView в ваш плагин (я оставлю это для вас, чтобы разобраться). Тогда позвони flutterView.getFlutterNativeView()
чтобы овладеть FlutterNativeView.
К сожалению, getFlutterJni FlutterNativeView является частным пакетом. Так что это то, где это становится действительно хакерским - вы можете создать класс в том же пакете, который вызывает этот закрытый для пакета метод в общедоступном методе. Это ужасно, и вам, возможно, придется возиться с Gradle, чтобы настройки безопасности компиляции позволили это сделать, но это должно быть возможно.
После этого должно быть достаточно просто создать SurfaceTextureRegistryEntry
и зарегистрировать текстуру с помощью флаттера jni. Я не думаю, что вы хотите отсоединиться от контекста opengl, и я действительно не знаю, сработает ли это на самом деле. Но если вы хотите попробовать и сообщить, что вы нашли, мне было бы интересно услышать результат!