问题描述
我正在编写一个摄像机应用程序。当我打开我的捕获活动时,我想配置一个开始预览的相机捕获会话,当用户稍后按下录制按钮时,它应该开始使用 MediaCodec + Mediamuxer(不是 MediaRecorder,因为应用程序特定的原因)录制视频无需重新创建新的 CameraCaptureSession。我尝试使用 MediaCodec#createPersistentInputSurface 使这成为可能。
到目前为止,我已经让预览正常工作,并且 MediaCodec/Mediamuxer 位正在生成一个“有效”的输出视频文件(根据 ffprobe),但视频的内容是随机对角线颜色/加扰的闪烁。在另一台设备上,相同的代码根本无法创建捕获会话。我相信问题在于我在创建捕获会话之后创建 MediaCodec 实例,这意味着当相机配置有持久表面时,它不知道它应该使用什么输出大小和颜色格式.
我的问题:我需要遵循什么管道才能通过 MediaCodec 和持久输入表面实现我正在寻找的行为?
我的笔记:
-
据我测试/了解,您只能使用一次 MediaCodec 实例。对于下一个录音,您必须创建一个新录音。因此,如果只有一个允许多个视频录制的摄像头捕获会话,则需要在配置捕获会话之后创建一个 MediaCodec 实例。
-
必须为所有创建的 MediaCodec 使用相同的表面,因为它是在相机捕获会话中指定的(可以 deferred surfaces (second bullet point) 改变这一点吗?),因此为什么它需要持久化。
-
需要在摄像头捕获会话之前创建持久表面,并且 MediaCodec 需要在摄像头捕获会话开始之前配置持久表面...
有点鸡和蛋的问题。有没有办法打破这种循环依赖循环?
解决方法
通过执行以下操作,我最终获得了所需的行为(即使它看起来有点笨拙):
- 创建持久的输入表面
- 创建一个虚拟 MediaCodec,其配置/参数与您稍后将使用的完全相同,甚至调用
MediaCodec::configure
和MediaCodec::setInputSurface
(使用持久输入表面)。这会初始化持久表面的内部颜色/格式参数等,这是创建捕获会话成功所必需的。 - 使用持久输入表面创建所需的捕获会话
- 释放虚拟视频编码器,因为我们不再需要它
从那时起,您可以在每次想要录制某些内容时保持同一个相机捕获会话并创建新的 MediaCodec,但它们始终需要像虚拟的那样进行配置,否则可能会出现录制问题。
旁注:在这个问题中,我认为延迟曲面会有所帮助,但我现在完全理解它们,不,它们对解决特定问题没有帮助。