Я столкнулся с любопытной проблемой с iOS видео приложением, которое использует AVFoundation. Приложение начинает показывать зависание своего предварительного просмотра камеры в реальном времени после рефакторинга своего взаимодействия AVAssetWriter
в отдельной очереди. Эта очередь используется только тогда, когда приложение активно записывает видео. Наблюдаемое поведение заключается в том, что при запуске записи через 1–15 секунд (точное время изменяется) приложение начнет зависать и сбрасывать кадры.
Это происходит при первой записи после загрузки приложения, в сборках отладки и выпуска, и что интересно, это происходит только тогда, когда приложение запускается вне отладчика. Когда прикреплены определенные инструменты, например, указатели, проблема также исчезает из поля зрения. Это делает его довольно сложным для отладки, но есть некоторые отведения.
Первое - это то, что, по-видимому, существует некоторое отношение к времени жизни пиксельных буферов, содержащихся в CMSampleBuffer
s, которые принимаются AVCaptureVideoDataOutputSampleBufferDelegate.captureOutput(_ captureOutput: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)
. Когда этот код обновляется, чтобы добавить содержащийся буфер пикселей в экземпляр AVAssetWriter
в качестве синхронного рабочего элемента в очереди, который взаимодействует с экземпляром AVAssetWriter
, а не в качестве асинхронного рабочего элемента c в этой очереди, возникает проблема исчезает. Однако попытка воспроизвести эту структуру в отдельном примере приложения не увенчалась успехом, и документы Apple указывают, что этот шаблон поддерживается до тех пор, пока очереди не задерживаются (что не так хорошо, как я могу сказать).
Кроме того, если базовый CVPixelBuffer
глубоко скопирован, а затем эта копия используется асинхронным рабочим элементом c, добавленным в очередь, проблема исчезает. Копирование буферов нежелательно.
Качество записи, похоже, не влияет на проблему. Я записываю 540p 24fps со скромными битрейтами, чтобы убедиться, что это не связано с высокими битрейтами или разрешениями. Я тестирую на iPhone XS, то есть на сравнительно недавнем оборудовании.
Другой интересный вывод заключается в том, что AVAssetWriterInput.isReadyForMoreMediaData
начинает возвращать false в тот момент, когда происходит замораживание. Я проверил, что AVAssetWriterInput.expectsMediaDataInRealTime
было установлено в true, и также увеличил приоритет очереди средства записи ресурсов, но это не имело никакого эффекта. Почему этот метод начинает возвращать false, неясно. Через некоторое время он снова начинает возвращать значение true, но причина этого опять-таки неясна.
Очередь для доступа к экземпляру AVAssetWriter
не является отставанием, рабочие элементы всегда обрабатываются своевременно .
Некоторые исходные вопросы, которые возникают:
- Каковы точные гарантии времени жизни данных пиксельного буфера, передаваемых
AVCaptureVideoDataOutputSampleBufferDelegate
методам? - Что бы заставить
AVAssetWriterInput.isReadyForMoreMediaData
начать возвращать false без всякой очевидной причины, а затем переключиться обратно на true? - Что может привести к тому, что проблема такого рода может наблюдаться только вне отладчика и только тогда, когда определенные инструменты не подключены?
Любое понимание, которое вы могли бы иметь, будет высоко ценится. Спасибо!