1

最近尝试用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?

4

2 回答 2

4

我认为您可以通过 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()));
于 2020-06-18T09:57:22.817 回答
2

更新:CameraX 添加了功能,现在允许这样做,因为这个答案是写的,但这可能对某人仍然有用。有关详细信息,请参阅此答案


似乎使用 CameraX 似乎很难甚至不可能,因为它会将更复杂的东西抽象出来,因此不会暴露你需要的东西,比如能够传入你自己的 SurfaceTexture(通常由 Flutter 创建)。

所以简单的答案是你不能使用CameraX。

话虽这么说,通过一些工作你也许可以让它工作,但我不知道它是否会工作。这是丑陋和hacky,所以我不会推荐它。YMMV。


如果我们要这样做,我们先看看flutter view是如何创建纹理的

    @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是包私有的。所以这就是它变得非常棘手的地方 - 您可以在同一个包中创建一个类,该类在可公开访问的方法中调用该包私有方法。它超级难看,你可能不得不摆弄 Gradle 来获得允许它的编译安全设置,但它应该是可能的。

SurfaceTextureRegistryEntry之后,创建一个并使用颤振 jni 注册纹理应该足够简单。我不认为你想脱离 opengl 上下文,我真的不知道这是否真的有效。但是,如果您想尝试一下并报告您的发现,我将有兴趣听到结果!

于 2019-05-16T18:11:19.653 回答