使用CameraX启动和停止相机的正确方法是什么?

时间:2019-05-09 11:33:41

标签: android android-camerax

我已经开始与sample app一起探索CameraX库,并且发现在管理生命周期方面存在一些不一致之处。

在此线程中,我将仅讨论预览用例,因为它与生命周期密切相关。

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

我还尝试遵循getting started教程,其中SurfaceTexture中的TextureView被替换了。在示例应用程序中,首先从父级中删除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

2 个答案:

答案 0 :(得分: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,了解更多详细信息。

答案 1 :(得分:1)

2020年10月10日-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));
}

从任何地方询问问题: @canerkaseler