我是Camera2框架的新手,我想了解创建捕捉会话的逻辑。
我需要一个简单的东西--预览和录制视频。我还想设置正确的方向提示。在我开始录制视频的时候. 但我遇到了一个鸡肋问题。
这是我的逻辑。
为了开始录音,我这样做。
val recordRequest = session.device.createCaptureRequest(CameraDevice.TEMPLATE_RECORD).apply {
// Add the preview and recording surface targets
addTarget(viewFinder.holder.surface)
addTarget(recorder.surface)
}.build()
session.setRepeatingRequest(recordRequest, null, cameraHandler)
recorder.setOrientationHint(it) // NOT allowed after getSurface()!
recorder.prepare() // NOT allowed after getSurface()!
recorder.start()
但是,我已经调用了 recorder.surface
(或 getSurface()
)时,我在上面添加目标。可以认为我可以先准备好,然后再添加目标,然而。文件 对于 addTarget()
说,表面 添加的曲面必须是最近一次调用的曲面之一。CameraDevice#createCaptureSession
这就导致了一个有趣的问题。每当我打开应用程序时,我需要创建捕捉会话来开始预览相机图像。然而,在创建的时候 createCaptureSession() 需要包括 遍地 后会有期 捕捉请求. 这意味着,我也需要包括记录面,即使我只是打开相机,还没有记录。我如何得到这个 Surface
录音用的?嗯,这个 文件 说我可以从 MediaRecorder
或者我可以从 MediaCodec
. 我想从 MediaRecorder
因为我想用 CamcorderProfiles
. 然而,正如我在上面的代码中所显示的那样,一旦我从记录器中得到了曲面 在创建会话时 - 我不能在那里做任何改变 在开始录制时,比如设置方向提示。
官方 Camera2Video 样板应用做了一个技巧--它使用 创建持久性输入表面 然而在他们的例子中,摄像头是固定的,这使得他们可以为其分配足够的内存,并在整个应用生命周期中使用该表面。
如何解决这个问题?我是否误解了这里的概念?我如何能在稍后的时间点,当我开始录制时,创建记录器,但当我打开相机进行预览时,仍然有早期创建的表面?
使用一个持久化的输入面是正确的方法。一旦你知道了录制的方向,就创建一个新的MediaRecorder,并使用持久性输入表面设置它的Surface。
这正是Camera2Video示例所做的。也:
// React to user touching the capture button
capture_button.setOnTouchListener { view, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> lifecycleScope.launch(Dispatchers.IO) {
// Prevents screen rotation during the video recording
requireActivity().requestedOrientation =
ActivityInfo.SCREEN_ORIENTATION_LOCKED
// Start recording repeating requests, which will stop the ongoing preview
// repeating requests without having to explicitly call `session.stopRepeating`
session.setRepeatingRequest(recordRequest, null, cameraHandler)
// Finalizes recorder setup and starts recording
recorder.apply {
// Sets output orientation based on current sensor value at start time
relativeOrientation.value?.let { setOrientationHint(it) }
prepare()
start()
}
和 recorder
是用早期创建的持久化曲面创建的。
/** Saves the video recording */
private val recorder: MediaRecorder by lazy { createRecorder(recorderSurface)
}
当你说相机是固定的,你是指应用程序的方向是固定的,还是说样本不支持切换前后摄像头? 对于持久化曲面来说,这些应该都不是特别重要,如果需要的话,你可以在切换摄像头或改变方向时创建一个新的曲面。