如何在CameraX中绑定预览和纹理

时间:2019-05-16 07:54:42

标签: flutter textures androidx android-camerax

我最近尝试用cameraX开发一个flutter插件,但是我发现无法简单地将Preview绑定到flutter的Texture。

过去,我只需要使用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?

2 个答案:

答案 0 :(得分:3)

我认为您可以通过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()));

答案 1 :(得分:0)

由于使用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。

不幸的是,FlutterNativeView的getFlutterJni是包私有的。所以这才是真正的问题-您可以在同一包中创建一个类,该类以公开可访问的方法调用该package-private方法。这太丑陋了,您可能必须在Gradle上摆弄一下才能获得允许的编译安全设置,但这应该是可能的。

在那之后,创建一个SurfaceTextureRegistryEntry并向flni jni注册纹理应该足够简单。我不认为您想脱离opengl上下文,而且我真的不知道这是否会真正起作用。但是,如果您想尝试一下并报告您发现的问题,我将有兴趣听到结果!