2015-05-11 2 views
10

One of the official Google samples for the Camera2 API страдает от the same BufferQueue has been abandoned problem как видно на:Когда «Потребительская сторона» TextureView закрыта?

В частности, пример приложения называет closeCamera() метод из onPause() фрагмента, где closeCamera() вызовы close() на CameraCaptureSession , затем close() на CameraDevice, затем close() на ImageReader (используется для фактической съемки). После close() на CameraDevice, когда в LogCat появляется несколько вхождений вышеупомянутого сообщения BufferQueue has been abandoned, хотя я получаю сообщение только на некоторых устройствах Android 5.1 (Nexus 4 и Nexus 7 2013), а не на других (Nexus 5 и Nexus 6). Комментарий

Фадден на это:

Если сторона потребитель закрыли перед входом OnPause(), сообщения можно было бы ожидать.

Когда TextureView «потребительская сторона» будет закрыта, и почему тогда?

Образец кода Google не проактивно ничего не делает, чтобы закрыть TextureView, что я вижу. И, поскольку TextureView все еще может быть видимым при паузе, я бы ожидал, что «потребительская сторона» не будет затронута во время onPause(), но, возможно, позже в onStop().

Хотя я понимаю, что это сообщение (несмотря на то, что оно является ошибкой) является доброкачественным, я пытаюсь выяснить, как избавиться от него, если не по какой-либо другой причине, кроме как предотвратить мое время от времени и снова, почему код моя регистрирует эту ошибку. Я надеюсь, что, понимая больше об этой «стороне потребителя», я могу понять, как лучше убирать вещи, когда пользователь выходит из действия или фрагмента, использующего Camera2, и избегает этой ошибки.

+0

может быть подклассификация TextureView и вызов close() onDetachFromWindow - опция? – Blackbelt

+1

@Blackbelt: Возможно. Я бы не ожидал, что он будет вызываться до 'onPause()' фрагмента. Я дам ему шанс и посмотрю, что такое время. Спасибо за предложение! – CommonsWare

ответ

3

Вы ожидаете вызова метода обратного вызова onClosed для камеры, прежде чем выйти из функции Pause?

До тех пор, пока этот обратный вызов не загорится, камера все еще может выполнять незавершенную работу, а определение close() - завершить все ожидающие запросы на захват перед выключением устройства. Это можно ускорить, вызвав abortCapture() перед вызовом функции close().

Некоторые устройства (например, N5 и N6) в настоящее время блокируют вызов close(), поэтому, когда он возвращается, выполняется все незавершенные работы, но это детализация реализации, которые, как я думаю, наш пример неосторожно полагается на сегодняшний день.

Однако мы обычно хотим разрешить приложениям называть close() и немедленно оставить onPause(), чтобы избежать зависания потока пользовательского интерфейса при ожидании закрытия аппаратного обеспечения камеры. Но сегодня это еще не реальность.

Другими словами, close() должен быть асинхронным и не на всех устройствах. Но мы хотели бы, чтобы вы могли стрелять и забывать об этом, поэтому эти сообщения об ошибках должны быть адресованы на стороне устройства камеры (не спам журнала, когда цель повторного запроса уходит в середине операции).

Другой причиной, по которой вызов close() и выхода на onPause() не рекомендуется сегодня, заключается в том, что он не позволит другим приложениям открыть камеру в своих вызовах onResume(), что вызовет ложные ошибки при переключении между камерой Программы.

Итак, подведем итог:

Сейчас: Подождите CameraDevice.StateCallback#onClosed будет вызываться до выхода из OnPause() после вызова CameraDevice # близко().

В какой-то будущий момент: будет безопасно просто вызвать close() и выйти onPause; структура будет правильно разрешать подключению следующего приложения, а не спаму вашего журнала. Извините, сегодня это не состояние!

+0

«Ожидаете ли вы вызов метода обратного вызова onClosed для камеры, прежде чем выйти из режима« Пауза? »? - um, no. Я придерживаюсь подхода, установленного Camera2Basic, который не имеет 'onClosed()'. «Подождите, пока CameraDevice.StateCallback # onClosed будет вызываться перед выходом из onPause() после вызова CameraDevice # close()." - Хорошо, я буду экспериментировать с «CountDownLatch» и вернуться завтра. Благодаря! – CommonsWare

+1

Я могу подтвердить, что использование 'CountDownLatch' для блокировки в' onPause() 'пока' onClosed() 'не работает. Это не идеально, поскольку мы блокируем основной поток приложений, но если это то, что нужно, c'est la vie. Технически этот ответ не отвечает на вопрос («Когда« Потребительская сторона TextureView »закрыта?»), Хотя он определенно решает мою основную проблему. Поэтому я собираюсь взять довольно нетрадиционный подход к предоставлению щедрости, но не согласен с ответом, так как для кого-то еще может быть значение в других ответах, относящихся к вопросу «TextureView». Несмотря ни на что, большое спасибо! – CommonsWare

+0

Да, извините, что образец здесь немного неверен. Обратите внимание, что, поскольку N5/N6/N9/любой блок устройства камеры без камеры LEGACY закрывается до тех пор, пока это не будет выполнено, вы не добавляете никаких реальных задержек для этих устройств. –

1

Что касается актуального вопроса - «когда« Потребительская сторона TextureView »закрыта, я не знаю точного времени, но, безусловно, после возвращения onPause.

Грубо, TextureView содержит поверхность GL, и после того, как пользовательский интерфейс для активности больше не виден, эти ресурсы срываются. Как только это произойдет, SurfaceTexture, выданный TextureView, уже недействителен, и все существующие пользователи этой SurfaceTexture (или Surfaces, сделанные из него) начнут получать эти ошибки. Метод TextureView.SurfaceTextureListener.onSurfaceTextureDestroyed должен быть вызван TextureView прямо перед этим.

Так как вы можете возвратить false из onSurfaceTextureDestroyed, чтобы избежать его освобождения во время разрыва пользовательского интерфейса, а вместо этого ждать onClosed для запуска, а затем в onClosed освободить SurfaceTexture TextureView самостоятельно. Тем не менее, я недостаточно хорошо знаком с интерфейсом UI/View, чтобы точно знать, что это сработает, и поскольку некоторые из лежащих в основе нативных поверхностей выпущены в любом случае, вы все равно можете увидеть заброшенные ошибки с этим подходом.

Если вам интересно, верхние уровни соответствующего кода находятся в TextureView, особенно метод destroySurface, хотя вам нужно будет понять все, что касается всей системы Android UI, чтобы разобраться, когда именно метод destroySurface вызывается и каковы его эффекты.

+1

Мое утверждение, цитируемое в вопросе, было основано на предположении, что камера 'close()' заблокирована. Если он еще может отправлять кадры после 'onPause()', тогда сообщения имеют смысл - TextureView выключается вскоре после того, как 'onPause()' возвращает, освобождая SurfaceTexture, и каждый кадр, отправленный камерой закрывания-закрытия сообщение журнала.Таким образом, ответ на исходный вопрос: «именно тогда, когда вы ожидаете этого». Удержание при выпуске SurfaceTexture должно работать, чтобы избежать (безобидных) сообщений, но не затрагивает другие проблемы, перечисленные в первом ответе. – fadden

Смежные вопросы