【问题标题】:What is the correct way of starting and stopping camera using CameraX?使用 CameraX 启动和停止相机的正确方法是什么?
【发布时间】:2019-05-09 11:33:41
【问题描述】:

我已经开始与 sample app 一起探索 CameraX 库,我注意到在管理生命周期方面有些不一致。

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

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

我也尝试过遵循getting started 教程,其中TextureViewSurfaceTexture 刚刚被替换。在示例应用程序中,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

【问题讨论】:

  • CameraX 还是很新的。由于代码在过去一年中发生了很大变化,因此这些问题中的许多似乎已被弃用。我很想看到关于“新”代码的后续行动。 (我很好奇它会持续多久!)

标签: android android-camerax


【解决方案1】:

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

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

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

    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));
    }
    

    【讨论】:

    • 我们如何在 unbindAll 之前检查它是否正确绑定?如果我们检查 mCameraProvider 是否为空,它就不起作用。
    • 你应该在 onCreate 中绑定它。之后,您无需检查它。如果需要,可以直接unbindAll。
    猜你喜欢
    • 2016-02-27
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2016-11-01
    • 2016-11-08
    • 1970-01-01
    相关资源
    最近更新 更多