Почему AVSampleBufferDisplayLayer завершается с ошибкой "Операция прервана" (-11847)?
Я использую AVSampleBufferDisplayLayer
декодировать и отображать видео H.264, передаваемое с сервера. Когда мое приложение переходит в фоновый режим, а затем возвращается на передний план, процесс декодирования облажается и AVSampleBufferDisplayLayer
выходит из строя. Я вижу ошибку:
H.264 decoding layer has failed: Error Domain=AVFoundationErrorDomain
Code=-11847 "Operation Interrupted" UserInfo=0x17426c500
{NSUnderlyingError=0x17805fe90 "The operation couldn’t be completed.
(OSStatus error -12084.)",
NSLocalizedRecoverySuggestion=Stop other operations and try again.,
NSLocalizedDescription=Operation Interrupted}
Кто-нибудь еще сталкивался с такими проблемами AVSampleBufferDisplayLayer
? Что это значит?
Я пытался уничтожить AVSampleBufferDisplayLayer
и создание нового, когда я получаю ошибку, но затем я начинаю получать другие ошибки от декодера H.264:
Error Domain=AVFoundationErrorDomain Code=-11821 "Cannot Decode"
UserInfo=0x1740e9700 {AVErrorMediaSubTypeKey=(1635148593),
NSLocalizedFailureReason=The media data could not be decoded. It may be damaged.,
NSUnderlyingError=0x174247680 "The operation couldn’t be completed. (OSStatus error -12909.)",
AVErrorMediaTypeKey=vide,
AVErrorPresentationTimeStampKey=CMTime: {7/30 = 0.233},
NSLocalizedDescription=Cannot Decode}
Я не получал ни одной из этих ошибок до AVSampleBufferDisplayLayer
не удалось.
3 ответа
После перестройки нового AVSampleBufferDisplayLayer вы должны поставить в очередь его последним ближайшим кадром IDR, за исключением того, что текущим кадром является IDR, что означает, что вы должны сохранять налус в одной GOP при декодировании и удалять их при появлении следующего IDR.
Я решил это
// create renderer
let renderingLayer = AVSampleBufferDisplayLayer()
// when enqueue data
if renderingLayer.status == .failed {
// this way
renderingLayer.flushAndRemoveImage()
}
Я столкнулся с той же проблемой и смог решить с помощью следующего кода. Мне нужно было использовать событие pubDidBecomeActive вместо события willEnterForeground, чтобы иметь дело со случаем, когда также была активирована Siri.
class RoomState: NSObject, ObservableObject {
private var subs = [AnyCancellable]()
@Published var displayLayer = AVSampleBufferDisplayLayer()
override init() {
super.init()
let pubDidBecomeActive = NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
subs.append(pubDidBecomeActive.sink { [weak self] _ in
self?.displayLayer = AVSampleBufferDisplayLayer()
})
}
}