【问题标题】:Crash when using front camera ONLY on pre-iPhone 7 devices仅在 iPhone 7 之前的设备上使用前置摄像头时崩溃
【发布时间】:2019-04-12 06:36:23
【问题描述】:

我最近开始在我的基于相机的应用上运行测试版。除了 iPhone 6 设备外,一切都按预期工作。

会话从后置摄像头开始,每次 iPhone 6 用户切换到前置摄像头时,应用程序都会崩溃。 (并且要非常清楚:任何其他 iPhone 型号上都没有人遇到过这个问题。)我已经拿到了 6 进行测试,并且可以始终如一地重现错误,从而导致 libc++abi.dylib: terminating with uncaught exception of type NSException

我尝试在前置摄像头上启动会话,但它立即崩溃。

func initializeCamera() {
    self.captureSession.sessionPreset = .hd1920x1080

    let discovery = AVCaptureDevice.DiscoverySession.init(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera],
                                                          mediaType: .video,
                                                          position: .unspecified) as AVCaptureDevice.DiscoverySession

    for device in discovery.devices as [AVCaptureDevice] {
        if device.hasMediaType(.video) {
            if device.position == AVCaptureDevice.Position.front {
                videoCaptureDevice = device
                do {
                    try currentDeviceInput = AVCaptureDeviceInput(device: device)
                } catch {
                    print("error: \(error.localizedDescription)")
                }
            }
        }
    }

    if videoCaptureDevice != nil {
        do {
            let videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice!)
            captureSession.addInput(videoInput)

            if let audioInput = AVCaptureDevice.default(for: .audio) {
                try captureSession.addInput(AVCaptureDeviceInput(device: audioInput))
            }

            previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

            guard let previewLayer = previewLayer else { return }

            cameraPreviewView.frame = cameraContainer.frame

            cameraPreviewView.layer.addSublayer(previewLayer)
            previewLayer.frame = cameraPreviewView.frame

            previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

            setVideoOrientation()

            captureSession.addOutput(movieFileOutput)

            if let movieFileOutputConnection = movieFileOutput.connection(with: .video) {
                if movieFileOutputConnection.isVideoStabilizationSupported {
                    movieFileOutputConnection.preferredVideoStabilizationMode = .cinematic
                }
            }

            captureSession.startRunning()

            sessionIsReady(true)

        } catch {
            print("error: \(error.localizedDescription)")
        }
    }

}
func setVideoOrientation() {
    if let connection = self.previewLayer?.connection {
        if connection.isVideoOrientationSupported {
            connection.videoOrientation = .portrait
            previewLayer?.frame = cameraContainer.bounds
        }
    }
}

崩溃是在captureSession.addInput(videoInput) 触发的。 videoInput 不是 nil。相机的方向被锁定为纵向。

谁能提供任何见解?请让我知道是否有任何其他代码会有所帮助。提前致谢。

【问题讨论】:

  • 这是整个错误信息吗?你之前没有更多信息吗?
  • 不,就是这样。 Xcode 将我重定向到 AppDelegate 并显示 Thread 1: signal SIGABRT
  • 尝试启用异常断点。
  • 当控制台中没有更多消息时,这种情况很少见。它有时会发生。 addInput 的文档:This method throws an exception when invoked and canAddInput(_:) returns false.。你能事先检查一下let canAdd = catpureSession.canAddInput(videoInput)吗?它的价值是什么?另外,那个 iPhone 6 的 iOS 版本是什么?
  • 很久没玩AVCapure了,难道是因为sessionPreset对iPhone 6的前置摄像头来说太高了?还是 builtInWideAngleCamera 导致问题?

标签: ios swift avfoundation avcapturesession


【解决方案1】:

captureSession.addInput(videoInput) 导致崩溃。

所以你应该在之前使用canAddInput(_:) 以避免崩溃。

if captureSession.canAddInput(videoInput) {
    captureSession.addInput(videoInput)
}

在你的情况下,captureSession.canAddInput(videoInput) == false 与 iPhone 6。

现在,你也在做self.captureSession.sessionPreset = .hd1920x1080

但是according to WikiPedia,iPhone 6 前置摄像头硬件支持 相机 1.2 MP(最大 1280×960 像素),720p 视频录制(30 fps)。似乎不适合 1920*1080(“全高清”)。

您可以检查一下您可以使用的“最大”AVCaptureSession.Preset

func setSessionPreset(forDevice device: AVCaptureDevice) {
    let videoPresets: [AVCaptureSession.Preset] = [.hd4K3840x2160, .hd1920x1080, .hd1280x720] //etc. Put them in order to "preferred" to "last preferred"
    let preset = videoPresets.first(where: { device.supportsSessionPreset($0) }) ?? .hd1280x720
    captureSession.sessionPreset = preset
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    相关资源
    最近更新 更多