fix: Fix RecordingSession nil crash by keeping it local (#938)

* fix: Fix RecordingSession nil crash by keeping it local

* fix: Fix error init

* Update CameraView+RecordVideo.swift
This commit is contained in:
Marc Rousavy 2022-04-15 09:48:32 +02:00 committed by GitHub
parent 2ccce3587d
commit 971b824914
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 18 deletions

View File

@ -64,9 +64,8 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
let enableAudio = self.audio?.boolValue == true let enableAudio = self.audio?.boolValue == true
let onFinish = { (status: AVAssetWriter.Status, error: Error?) in let onFinish = { (recordingSession: RecordingSession, status: AVAssetWriter.Status, error: Error?) in
defer { defer {
self.recordingSession = nil
if enableAudio { if enableAudio {
self.audioQueue.async { self.audioQueue.async {
self.deactivateAudioSession() self.deactivateAudioSession()
@ -78,6 +77,7 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
} }
} }
self.recordingSession = nil
self.isRecording = false self.isRecording = false
ReactLogger.log(level: .info, message: "RecordingSession finished with status \(status.descriptor).") ReactLogger.log(level: .info, message: "RecordingSession finished with status \(status.descriptor).")
@ -90,8 +90,8 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
} else { } else {
if status == .completed { if status == .completed {
callback.resolve([ callback.resolve([
"path": self.recordingSession!.url.absoluteString, "path": recordingSession.url.absoluteString,
"duration": self.recordingSession!.duration, "duration": recordingSession.duration,
]) ])
} else { } else {
callback.reject(error: .unknown(message: "AVAssetWriter completed with status: \(status.descriptor)")) callback.reject(error: .unknown(message: "AVAssetWriter completed with status: \(status.descriptor)"))
@ -99,14 +99,16 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
} }
} }
let recordingSession: RecordingSession
do { do {
self.recordingSession = try RecordingSession(url: tempURL, recordingSession = try RecordingSession(url: tempURL,
fileType: fileType, fileType: fileType,
completion: onFinish) completion: onFinish)
} catch let error as NSError { } catch let error as NSError {
callback.reject(error: .capture(.createRecorderError(message: nil)), cause: error) callback.reject(error: .capture(.createRecorderError(message: nil)), cause: error)
return return
} }
self.recordingSession = recordingSession
var videoCodec: AVVideoCodecType? var videoCodec: AVVideoCodecType?
if let codecString = options["videoCodec"] as? String { if let codecString = options["videoCodec"] as? String {
@ -122,8 +124,8 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
// get pixel format (420f, 420v, x420) // get pixel format (420f, 420v, x420)
let pixelFormat = CMFormatDescriptionGetMediaSubType(videoInput.device.activeFormat.formatDescription) let pixelFormat = CMFormatDescriptionGetMediaSubType(videoInput.device.activeFormat.formatDescription)
self.recordingSession!.initializeVideoWriter(withSettings: videoSettings, recordingSession.initializeVideoWriter(withSettings: videoSettings,
pixelFormat: pixelFormat) pixelFormat: pixelFormat)
// Init Audio (optional, async) // Init Audio (optional, async)
if enableAudio { if enableAudio {
@ -132,15 +134,15 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud
if let audioOutput = self.audioOutput, if let audioOutput = self.audioOutput,
let audioSettings = audioOutput.recommendedAudioSettingsForAssetWriter(writingTo: fileType) { let audioSettings = audioOutput.recommendedAudioSettingsForAssetWriter(writingTo: fileType) {
self.recordingSession!.initializeAudioWriter(withSettings: audioSettings) recordingSession.initializeAudioWriter(withSettings: audioSettings)
} }
} }
// start recording session with or without audio. // start recording session with or without audio.
do { do {
try self.recordingSession!.start() try recordingSession.start()
} catch { } catch let error as NSError {
callback.reject(error: .capture(.createRecorderError(message: "RecordingSession failed to start writing."))) callback.reject(error: .capture(.createRecorderError(message: "RecordingSession failed to start writing.")), cause: error)
return return
} }
self.isRecording = true self.isRecording = true

View File

@ -28,7 +28,7 @@ class RecordingSession {
private let assetWriter: AVAssetWriter private let assetWriter: AVAssetWriter
private var audioWriter: AVAssetWriterInput? private var audioWriter: AVAssetWriterInput?
private var bufferAdaptor: AVAssetWriterInputPixelBufferAdaptor? private var bufferAdaptor: AVAssetWriterInputPixelBufferAdaptor?
private let completionHandler: (AVAssetWriter.Status, Error?) -> Void private let completionHandler: (RecordingSession, AVAssetWriter.Status, Error?) -> Void
private var initialTimestamp: CMTime? private var initialTimestamp: CMTime?
private var latestTimestamp: CMTime? private var latestTimestamp: CMTime?
@ -48,7 +48,7 @@ class RecordingSession {
init(url: URL, init(url: URL,
fileType: AVFileType, fileType: AVFileType,
completion: @escaping (AVAssetWriter.Status, Error?) -> Void) throws { completion: @escaping (RecordingSession, AVAssetWriter.Status, Error?) -> Void) throws {
completionHandler = completion completionHandler = completion
do { do {
@ -197,15 +197,15 @@ class RecordingSession {
let error = NSError(domain: "capture/aborted", let error = NSError(domain: "capture/aborted",
code: 1, code: 1,
userInfo: [NSLocalizedDescriptionKey: "Stopped Recording Session too early, no frames have been recorded!"]) userInfo: [NSLocalizedDescriptionKey: "Stopped Recording Session too early, no frames have been recorded!"])
completionHandler(.failed, error) completionHandler(self, .failed, error)
} else if assetWriter.status == .writing { } else if assetWriter.status == .writing {
assetWriter.finishWriting { assetWriter.finishWriting {
self.bufferAdaptor?.assetWriterInput.markAsFinished() self.bufferAdaptor?.assetWriterInput.markAsFinished()
self.audioWriter?.markAsFinished() self.audioWriter?.markAsFinished()
self.completionHandler(self.assetWriter.status, self.assetWriter.error) self.completionHandler(self, self.assetWriter.status, self.assetWriter.error)
} }
} else { } else {
completionHandler(assetWriter.status, assetWriter.error) completionHandler(self, assetWriter.status, assetWriter.error)
} }
} }
} }