【问题标题】:When Is a TextureView's "Consumer Side" Closed?TextureView 的“消费者端”何时关闭?
【发布时间】:2015-07-22 05:51:46
【问题描述】:

One of the official Google samples for the Camera2 API 遭受the same BufferQueue has been abandoned problem 的影响,如下所示:

具体来说,示例应用程序从片段的onPause() 调用closeCamera() 方法,其中closeCamera()CameraCaptureSession 上调用close(),然后在CameraDevice 上调用close(),然后是close()ImageReader 上(用于实际拍照)。在CameraDevice 上的close() 之后,LogCat 中出现了几次上述BufferQueue has been abandoned 消息,尽管我只在某些 Android 5.1 硬件(Nexus 4 和 Nexus 7 2013)而不是其他硬件(Nexus 5)上收到消息和 Nexus 6)。

fadden 对此的评论是:

如果消费者端在进入 onPause() 之前关闭,则消息是预期的。

TextureView 的“消费者端”何时会被关闭,为什么?

Google 的示例代码并没有主动做任何事情来关闭我可以看到的TextureView。而且,由于TextureView 在暂停时仍然可见,我预计“消费者端”在onPause() 时不会受到影响,但可能会在onStop() 之后受到影响。

虽然我意识到这条消息(尽管是一个错误)是良性的,但我正试图弄清楚如何摆脱它,如果没有其他原因,只是为了防止我一次又一次地被问到为什么我的代码正在记录此错误。我希望通过更多地了解这个“消费者方面”,我可以弄清楚当用户退出使用 Camera2 的活动或片段时如何更好地整理并避免此错误。

【问题讨论】:

  • 可以子类化 TextureView 并调用 close() onDetachFromWindow 吗?
  • @Blackbelt:可能。我也不希望它在片段的onPause() 之前被调用。我会试一试,看看时机如何。感谢您的建议!

标签: android android-camera textureview


【解决方案1】:

在退出onPause之前,您是否等待调用相机的onClosed状态回调方法?

在回调触发之前,相机可能仍有待处理的工作,close() 的定义是在关闭设备之前完成所有待处理的捕获请求。这可以通过在调用 close() 之前调用 abortCapture() 来加速。

某些设备(如 N5 和 N6)当前会阻止 close() 调用,因此当它返回时,所有待处理的工作都已完成,但这是我认为我们的示例今天无意中依赖的实现细节。

但是,我们通常希望允许应用立即调用 close() 并离开 onPause(),以避免在等待相机硬件关闭时挂起 UI 线程。但这在今天还不是现实。

换句话说,close() 应该是异步的,并且不是在所有设备上。但是我们希望您可以触发并忘记它,因此需要在相机设备端解决这些错误消息(当重复请求目标在操作中途消失时不要向日志发送垃圾邮件)。

今天不推荐只调用 close() 并退出 onPause() 的另一个原因是它会阻止其他应用程序打开 相机在他们的 onResume() 调用中,这将在相机应用程序之间切换时导致虚假错误。

总结一下:

现在:在调用 CameraDevice#close() 后退出 onPause() 之前等待调用 CameraDevice.StateCallback#onClosed

在未来的某个时刻:调用 close() 并退出 onPause 是安全的;该框架将正确地允许下一个应用程序连接并且不会向您的日志发送垃圾邮件。抱歉,这不是今天的状态!

【讨论】:

  • "是否等待相机的onClosed状态回调方法被调用,才退出onPause?" - 不。我正在遵循 Camera2Basic 建立的方法,它没有onClosed()。 “在调用 CameraDevice#close() 后退出 onPause() 之前,等待调用 CameraDevice.StateCallback#onClosed。” -- 好的,我将尝试使用CountDownLatch 并在明天回帖。谢谢!
  • 我可以确认使用CountDownLatch 阻止onPause() 直到onClosed() 有效。这并不理想,因为我们阻塞了主应用程序线程,但如果它是需要的,c'est la vie。从技术上讲,这个答案并没有回答这个问题(“TextureView 的“消费者端”何时关闭?”),尽管它确实解决了我的潜在问题。因此,我将采取相当非常规的方法来授予赏金但不接受答案,至于其他人,与TextureView 问题有关的其他答案可能有价值。无论如何,非常感谢!
  • 是的,很抱歉这里的示例有点不正确。请注意,由于 N5/N6/N9/任何非 LEGACY camera2 设备在完成之前都会关闭,因此您不会为这些设备添加任何真正的延迟。
【解决方案2】:

至于实际问题——“TextureView 的‘消费者端’何时关闭”,我不知道确切的时间,但肯定是在 onPause 返回之后。

大致来说,TextureView 包含一个 GL 表面,一旦 Activity 的 UI 不再可见,这些资源就会被拆除。一旦发生这种情况,TextureView 给出的 SurfaceTexture 将不再有效,并且该 SurfaceTexture(或由它制成的 Surface)的任何现有用户将开始收到这些错误。方法TextureView.SurfaceTextureListener.onSurfaceTextureDestroyed 应该在这发生之前由TextureView 调用。

因此,作为替代方案,您可以从 onSurfaceTextureDestroyed 返回 false 以避免在 UI 拆卸期间释放它,而是等待 onClosed 触发,然后在 onClosed 中自己释放 TextureView 的 SurfaceTexture。但是,我对 UI/View 方面不太熟悉,无法确定这会起作用,而且由于某些底层原生表面是通过任何一种方式发布的,因此您可能仍然会看到这种方法的废弃错误。

如果你很好奇,相关代码的顶层在 TextureView 中,尤其是 destroySurface 方法,尽管你需要了解整个 Android UI 系统的很多内容才能弄清楚何时确切地使用 destroySurface方法被调用,它的效果是什么。

【讨论】:

  • 我在问题中引用的陈述是基于摄像头close() 被挡住的假设。如果它仍然可以在onPause() 之后发送帧,那么这些消息是有意义的——TextureView 在onPause() 返回后不久关闭,释放 SurfaceTexture,并且静止关闭的相机发送的每一帧都会导致一条日志消息。所以原始问题的答案是,“正是你期望的时候”。推迟发布 SurfaceTexture 应该可以避免(无害)消息,但不能解决您在第一个答案中列出的其他问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-21
  • 2019-03-10
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多