CaptureOutput(_:didOutput:from:) метод делегата не вызывается на одном конкретном iPhone XR ⇐ IOS
-
Гость
CaptureOutput(_:didOutput:from:) метод делегата не вызывается на одном конкретном iPhone XR
Я пытаюсь захватить кадры камеры (CVPixelBuffers), используя метод делегата captureOutput(:didOutput:from:). Для актуальности я затем отправляю эти кадры в CoreML для классификации изображения.
Проблема: Работает на всех устройствах iOS, которые мне удалось достать, за исключением iPhone XR. Под работой я подразумеваю, что буферы захватываются на всех устройствах, за исключением одного конкретного XR.
Характеристики:
[*]iPhone XR [*]Проблема отмечена в iOS 16.3 и 16.7 (другие версии iOS не пробовали)
Что я пробовал и блокировщики:
[*]Купил отремонтированный XR на Amazon, и он работал на этом устройстве. Это также сработало на XR коллеги. [*]К сожалению, у меня нет постоянного доступа к XR, где метод делегата не был запущен, поскольку это личный телефон и принадлежит клиенту. [*]Похоже, что Xcode также не выдает ошибки - я ожидал бы ошибку, сообщающую, что буферы не могут быть захвачены, но, к сожалению, в документации Apple указаны только два метода делегата (один из которых - captureOutput и другой связан с пропущенными кадрами)
Вот код, в котором я определяю контроллер представления:
импортировать фундамент импортировать UIKit импортировать AVFoundation импортировать видение класс TestCameraViewController: UIViewController { варufferSize: CGSize = .ноль частный предварительный просмотр var: UIView = UIView() частная переменная предварительного просмотра Layer: AVCaptureVideoPreviewLayer! = ноль частный сеанс Let = AVCaptureSession() частный let videoDataOutput = AVCaptureVideoDataOutput() частная переменная currentVideoDevice: AVCaptureDevice? переопределить функцию viewDidLoad() { супер.viewDidLoad() настройкаView() настройкаAVCapture() НачатьCaptureSession() } функция setupView() { viewView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(previewView) предварительный просмотрView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true предварительный просмотрView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true предварительный просмотрView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true предварительный просмотрView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true } функция setupAVCapture() { вар deviceInput: AVCaptureDeviceInput! // Выбираем видеоустройство, делаем ввод let videoDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, позиция: .back).devices.first если видеоDevice == ноль { print("Устройство не существует, свойства: ноль, уровень: .error, SkipAnalytics: true") возвращаться } делать { deviceInput = попробуйте AVCaptureDeviceInput(device: videoDevice!) } ловить { print("Не удалось создать вход для видеоустройства") возвращаться } сеанс.beginConfiguration() session.sessionPreset = .vga640x480 // Размер изображения модели меньше. // Добавляем видеовход Guard session.canAddInput(deviceInput) еще { сеанс.commitConfiguration() print("Не удалось добавить вход видеоустройства") возвращаться } session.addInput(deviceInput) если session.canAddOutput(videoDataOutput) { session.addOutput(videoDataOutput) videoDataOutput.alwaysDiscardsLateVideoFrames = true videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int (kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)] videoDataOutput.setSampleBufferDelegate(self, очередь: .global()) } еще { сеанс.commitConfiguration() print("Не удалось добавить вывод видеоданных.") возвращаться } пусть captureConnection = videoDataOutput.connection(с: .video) captureConnection?.isEnabled = true делать { попробуйте videoDevice!.lockForConfiguration() пусть размеры = CMVideoFormatDescriptionGetDimensions((videoDevice?.activeFormat.formatDescription))!) ufferSize.width = CGFloat(dimensions.width) ufferSize.height = CGFloat(dimensions.height) видеоДевице!.unlockForConfiguration() } ловить { print("Не удалось заблокировать конфигурацию видеоустройства.") возвращаться } сеанс.commitConfiguration() PreviewLayer = AVCaptureVideoPreviewLayer (сеанс: сеанс) предварительный просмотрLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill self.currentVideoDevice = видеоустройство } переопределить функцию viewDidLayoutSubviews() { супер.viewDidLayoutSubviews() если просмотр слоя != ноль { предварительный просмотрLayer.frame = предварительный просмотрView.bounds предварительный просмотрView.layer.addSublayer(previewLayer) } } функция startCaptureSession() { DispatchQueue.global(qos:.background).async { self.session.startRunning() } } // Очистка настроек захвата функция срыва AVCapture () { сеанс.stopRunning() предварительный просмотрLayer.removeFromSuperlayer() Предварительный просмотрСлой = ноль } } А вот код, в котором я соответствую делегату (который не запускается в XR)
расширение TestCameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate { func captureOutput (_ вывод: AVCaptureOutput, DidOutput sampleBuffer: CMSampleBuffer, из соединения: AVCaptureConnection) { //НЕ ВЫЗЫВАЕТСЯ на одном конкретном физическом устройстве iPhone XR Guard let PixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { возвращаться } } } Будем признательны за предложения и дальнейшие действия, а также потенциальные ошибки в коде, которые могут привести к такому поведению.
Я пытаюсь захватить кадры камеры (CVPixelBuffers), используя метод делегата captureOutput(:didOutput:from:). Для актуальности я затем отправляю эти кадры в CoreML для классификации изображения.
Проблема: Работает на всех устройствах iOS, которые мне удалось достать, за исключением iPhone XR. Под работой я подразумеваю, что буферы захватываются на всех устройствах, за исключением одного конкретного XR.
Характеристики:
[*]iPhone XR [*]Проблема отмечена в iOS 16.3 и 16.7 (другие версии iOS не пробовали)
Что я пробовал и блокировщики:
[*]Купил отремонтированный XR на Amazon, и он работал на этом устройстве. Это также сработало на XR коллеги. [*]К сожалению, у меня нет постоянного доступа к XR, где метод делегата не был запущен, поскольку это личный телефон и принадлежит клиенту. [*]Похоже, что Xcode также не выдает ошибки - я ожидал бы ошибку, сообщающую, что буферы не могут быть захвачены, но, к сожалению, в документации Apple указаны только два метода делегата (один из которых - captureOutput и другой связан с пропущенными кадрами)
Вот код, в котором я определяю контроллер представления:
импортировать фундамент импортировать UIKit импортировать AVFoundation импортировать видение класс TestCameraViewController: UIViewController { варufferSize: CGSize = .ноль частный предварительный просмотр var: UIView = UIView() частная переменная предварительного просмотра Layer: AVCaptureVideoPreviewLayer! = ноль частный сеанс Let = AVCaptureSession() частный let videoDataOutput = AVCaptureVideoDataOutput() частная переменная currentVideoDevice: AVCaptureDevice? переопределить функцию viewDidLoad() { супер.viewDidLoad() настройкаView() настройкаAVCapture() НачатьCaptureSession() } функция setupView() { viewView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(previewView) предварительный просмотрView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true предварительный просмотрView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true предварительный просмотрView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true предварительный просмотрView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true } функция setupAVCapture() { вар deviceInput: AVCaptureDeviceInput! // Выбираем видеоустройство, делаем ввод let videoDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, позиция: .back).devices.first если видеоDevice == ноль { print("Устройство не существует, свойства: ноль, уровень: .error, SkipAnalytics: true") возвращаться } делать { deviceInput = попробуйте AVCaptureDeviceInput(device: videoDevice!) } ловить { print("Не удалось создать вход для видеоустройства") возвращаться } сеанс.beginConfiguration() session.sessionPreset = .vga640x480 // Размер изображения модели меньше. // Добавляем видеовход Guard session.canAddInput(deviceInput) еще { сеанс.commitConfiguration() print("Не удалось добавить вход видеоустройства") возвращаться } session.addInput(deviceInput) если session.canAddOutput(videoDataOutput) { session.addOutput(videoDataOutput) videoDataOutput.alwaysDiscardsLateVideoFrames = true videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int (kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)] videoDataOutput.setSampleBufferDelegate(self, очередь: .global()) } еще { сеанс.commitConfiguration() print("Не удалось добавить вывод видеоданных.") возвращаться } пусть captureConnection = videoDataOutput.connection(с: .video) captureConnection?.isEnabled = true делать { попробуйте videoDevice!.lockForConfiguration() пусть размеры = CMVideoFormatDescriptionGetDimensions((videoDevice?.activeFormat.formatDescription))!) ufferSize.width = CGFloat(dimensions.width) ufferSize.height = CGFloat(dimensions.height) видеоДевице!.unlockForConfiguration() } ловить { print("Не удалось заблокировать конфигурацию видеоустройства.") возвращаться } сеанс.commitConfiguration() PreviewLayer = AVCaptureVideoPreviewLayer (сеанс: сеанс) предварительный просмотрLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill self.currentVideoDevice = видеоустройство } переопределить функцию viewDidLayoutSubviews() { супер.viewDidLayoutSubviews() если просмотр слоя != ноль { предварительный просмотрLayer.frame = предварительный просмотрView.bounds предварительный просмотрView.layer.addSublayer(previewLayer) } } функция startCaptureSession() { DispatchQueue.global(qos:.background).async { self.session.startRunning() } } // Очистка настроек захвата функция срыва AVCapture () { сеанс.stopRunning() предварительный просмотрLayer.removeFromSuperlayer() Предварительный просмотрСлой = ноль } } А вот код, в котором я соответствую делегату (который не запускается в XR)
расширение TestCameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate { func captureOutput (_ вывод: AVCaptureOutput, DidOutput sampleBuffer: CMSampleBuffer, из соединения: AVCaptureConnection) { //НЕ ВЫЗЫВАЕТСЯ на одном конкретном физическом устройстве iPhone XR Guard let PixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { возвращаться } } } Будем признательны за предложения и дальнейшие действия, а также потенциальные ошибки в коде, которые могут привести к такому поведению.
Мобильная версия