5

我已经开始探索 CameraX 库以及示例应用程序,并且我注意到在管理生命周期方面存在一些不一致之处。

在这个线程中,我将只讨论预览用例,因为它主要与生命周期有关。

在示例应用程序中CameraFragment,用例绑定到CameraXinonViewCreated和未绑定 in onDestroyView。第一个问题是,unbind如果我们传递LifecycleOwnerbind方法,我们是否必须使用用例?我们可以将它们绑定在一起onCreate并将生命周期管理留给CameraX?

我也尝试按照入门教程进行操作,其中SurfaceTextureTextureView刚刚被替换。在示例应用程序中,TextureView首先从父级中删除,然后添加,然后SurfaceTexture替换。我们必须这样做吗?是什么原因?

另一件事是,在示例应用程序中,用例是从view.post { }方法绑定的。我在使用这种方法时遇到了很多问题,因为在将片段放入后台堆栈后,用另一个片段替换而不是重新创建,CameraX 记录了许多消息:

E/CamX: [ERROR][STATS_AEC] aec_led_calibration.cpp:560: aec_led_cal_apply_calibration Invalid pointer 0x7921174000 0x0
E/CamX: [ERROR][STATS_AEC] aec_set.cpp:1346: aec_set_fps_range Aec_Error invalid input 414  E/CamX: [ERROR][STATS_AEC] camxcaecstatsprocessor.cpp:1671 SetAlgoBayerHistValue() Unsupported bayer hist channel! 
E/CamX: [ERROR][STATS  ] camxcaecstatsprocessor.cpp:3194 ProcessRequestFastAE() [FastAE] Failed to apply gain to the stats! E/CamX: [ERROR][STATS_AEC] aec_process.cpp:1229: aec_process_stats_parsing aec is null or invalid 
E/CamX: [ERROR][STATS_AEC] aec_process.cpp:7983: aec_process_preview_and_video Error: invalid stats

可以只设置OnPreviewOutputUpdateListener而不是绑定所有用例吗?

编辑

为了显示确切的问题,我创建了简单的项目Camera Playground

这是CameraFragment整个逻辑。

class CameraFragment : Fragment() {

    private val preview by lazy {
        val configuration = PreviewConfig.Builder().build()
        Preview(configuration)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        CameraX.bindToLifecycle(this, preview)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_camera, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        button_gallery.setOnClickListener {
            requireActivity().supportFragmentManager
                .beginTransaction()
                .replace(R.id.container, GalleryFragment())
                .addToBackStack("GalleryFragment")
                .commit()
        }

        preview.setOnPreviewOutputUpdateListener { texture_view.surfaceTexture = it.surfaceTexture }
    }
}

现在单击图库按钮后,CameraFragment将替换为GalleryFragment. 按下后退按钮并返回 后CameraFragment,CameraX 会记录以下消息:

2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS  ] gcamfastaeutil.cpp:1170 SetTuningData() [FastAE] ERROR! Failed to get the tuning data

2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][HAL    ] camxmetadatapool.cpp:1447 GetMetadataByTag() Invalid Slot to get a metadata from

2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][HAL    ] camxmetadatapool.cpp:1447 GetMetadataByTag() Invalid Slot to get a metadata from

2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS_AEC] aec_led_calibration.cpp:560: aec_led_cal_apply_calibration Invalid pointer 0x7920f1d000 0x0

2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS_AEC] aec_set.cpp:1346: aec_set_fps_range Aec_Error invalid input 0 

2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS  ] camxae.cpp:2203 AECSetSensorInfo() Wrong initial sequence from HAL!

2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][STATS_AEC] aec_get.cpp:777: aec_get_param GET_EXP_PARAMS ERROR, Uninitialized exposure settings requested

2019-05-09 14:12:20.969 778-1363/? E/CamX: [ERROR][HAL    ] camxmetadatapool.cpp:1447 GetMetadataByTag() Invalid Slot to get a metadata from
4

2 回答 2

3

第一个问题是,如果我们将 LifecycleOwner 传递给 bind 方法,我们是否必须取消绑定用例?我们可以将它们绑定在 onCreate 中并将生命周期管理留给 CameraX 吗?

你是对的。我认为示例应用程序可以安全地删除CameraX.unbindAll()呼叫。

TextureView 首先从父级中删除,然后添加,然后替换 SurfaceTexture。我们必须这样做吗?是什么原因?

需要从父视图中删除并重新添加 TextureView 才能附加 SurfaceTexture。这是因为 TextureView 一旦附加到视图层次结构,就会在内部创建自己的 SurfaceTexture,并且只有在从视图层次结构中删除父 TextureView 时,内部 SurfaceTexture 才会正确分离。入门 codelab已更新,包括重新附件。

另一件事是,在示例应用程序中,用例是从 view.post { } 方法绑定的。这种方法我遇到了很多问题,因为在将片段放入后台堆栈后,用另一个片段替换而不是重新创建,CameraX 记录了很多消息

在里面绑定用例 viewFinder.post { ... }是为了确保在正确布局 TextureView 之后绑定用例。您开始看到的错误E/CamX实际上与 CameraX 库无关,并且似乎来自您设备的本机相机堆栈(即相机驱动程序)。如果您在应用程序本身中没有看到任何问题,则可能会忽略错误消息。

只设置 OnPreviewOutputUpdateListener 而不是绑定所有用例可以吗?

我不确定我是否理解这一点。您必须为 CameraX 绑定所有用例,才能将它们作为相机会话的一部分实际启动。查看文档以获取更多详细信息。

于 2019-05-14T00:15:20.250 回答
1

CameraX 库使用 JAVA 启动和停止相机

要打开相机,我们没有特定的代码。只有您可以使用bindToLifecycle()。另外,不要忘记,实现LifecycleObserver。这是在 CameraX 中启动相机的镜头代码示例。

private void mStartCamera(){
    Camera camera = mCameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis);
}

要关闭相机,您应该使用cameraProvider。您不需要使用相机对象。短代码示例。

private void mStopCamera(){
    mCameraProvider.unbindAll();
}
  • 奖金

如果你想问“我如何定义 cameraProvider?” 您需要在cameraProviderFuture上添加监听器。短代码示例。

private void mDefineCameraProvider() {
    final ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);

    cameraProviderFuture.addListener(() -> {
        try {
            ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
            mCameraProvider = cameraProvider;
        } 
        catch (ExecutionException | InterruptedException e) {
            // No errors need to be handled for this Future.
            // This should never be reached.
            Log.e("CANER", "Camera provider error: " +e);
        }
    }, ContextCompat.getMainExecutor(this));
}
于 2020-10-28T22:20:01.097 回答