Почему 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()
        })
    }
}

Другие вопросы по тегам