mirror of
https://github.com/samsonjs/SJSAssetExportSession.git
synced 2026-04-27 14:57:46 +00:00
Try to fix a possible retain cycle
This commit is contained in:
parent
f72a073b36
commit
2dac7d58dc
1 changed files with 49 additions and 31 deletions
|
|
@ -41,8 +41,8 @@ actor SampleWriter {
|
||||||
|
|
||||||
// MARK: Internal state
|
// MARK: Internal state
|
||||||
|
|
||||||
private let reader: AVAssetReader
|
private var reader: AVAssetReader?
|
||||||
private let writer: AVAssetWriter
|
private var writer: AVAssetWriter?
|
||||||
private var audioOutput: AVAssetReaderAudioMixOutput?
|
private var audioOutput: AVAssetReaderAudioMixOutput?
|
||||||
private var audioInput: AVAssetWriterInput?
|
private var audioInput: AVAssetWriterInput?
|
||||||
private var videoOutput: AVAssetReaderVideoCompositionOutput?
|
private var videoOutput: AVAssetReaderVideoCompositionOutput?
|
||||||
|
|
@ -111,15 +111,15 @@ actor SampleWriter {
|
||||||
|
|
||||||
progressContinuation.yield(0.0)
|
progressContinuation.yield(0.0)
|
||||||
|
|
||||||
writer.startWriting()
|
writer?.startWriting()
|
||||||
writer.startSession(atSourceTime: timeRange.start)
|
writer?.startSession(atSourceTime: timeRange.start)
|
||||||
reader.startReading()
|
reader?.startReading()
|
||||||
try Task.checkCancellation()
|
try Task.checkCancellation()
|
||||||
|
|
||||||
startEncodingAudioTracks()
|
startEncodingAudioTracks()
|
||||||
startEncodingVideoTracks()
|
startEncodingVideoTracks()
|
||||||
|
|
||||||
while reader.status == .reading, writer.status == .writing {
|
while reader?.status == .reading, writer?.status == .writing {
|
||||||
guard !Task.isCancelled else {
|
guard !Task.isCancelled else {
|
||||||
// Flag so that we stop writing samples
|
// Flag so that we stop writing samples
|
||||||
isCancelled = true
|
isCancelled = true
|
||||||
|
|
@ -129,26 +129,31 @@ actor SampleWriter {
|
||||||
try await Task.sleep(for: .milliseconds(10))
|
try await Task.sleep(for: .milliseconds(10))
|
||||||
}
|
}
|
||||||
|
|
||||||
guard !isCancelled, reader.status != .cancelled, writer.status != .cancelled else {
|
defer {
|
||||||
log.debug("Cancelled before writing samples")
|
cleanUp()
|
||||||
reader.cancelReading()
|
|
||||||
writer.cancelWriting()
|
|
||||||
throw CancellationError()
|
|
||||||
}
|
|
||||||
guard writer.status != .failed else {
|
|
||||||
reader.cancelReading()
|
|
||||||
throw Error.writeFailure(writer.error)
|
|
||||||
}
|
|
||||||
guard reader.status != .failed else {
|
|
||||||
writer.cancelWriting()
|
|
||||||
throw Error.readFailure(reader.error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guard !isCancelled, reader?.status != .cancelled, writer?.status != .cancelled else {
|
||||||
|
log.debug("Cancelled before writing samples")
|
||||||
|
cancelReaderAndWriter()
|
||||||
|
throw CancellationError()
|
||||||
|
}
|
||||||
|
guard writer?.status != .failed else {
|
||||||
|
reader?.cancelReading()
|
||||||
|
throw Error.writeFailure(writer?.error)
|
||||||
|
}
|
||||||
|
guard reader?.status != .failed else {
|
||||||
|
writer?.cancelWriting()
|
||||||
|
throw Error.readFailure(reader?.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let writer {
|
||||||
await withCheckedContinuation { continuation in
|
await withCheckedContinuation { continuation in
|
||||||
writer.finishWriting {
|
writer.finishWriting {
|
||||||
continuation.resume(returning: ())
|
continuation.resume(returning: ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
progressContinuation.yield(1.0)
|
progressContinuation.yield(1.0)
|
||||||
|
|
||||||
|
|
@ -169,7 +174,7 @@ actor SampleWriter {
|
||||||
let audioOutput = AVAssetReaderAudioMixOutput(audioTracks: audioTracks, audioSettings: nil)
|
let audioOutput = AVAssetReaderAudioMixOutput(audioTracks: audioTracks, audioSettings: nil)
|
||||||
audioOutput.alwaysCopiesSampleData = false
|
audioOutput.alwaysCopiesSampleData = false
|
||||||
audioOutput.audioMix = audioMix
|
audioOutput.audioMix = audioMix
|
||||||
guard reader.canAdd(audioOutput) else {
|
guard let reader, reader.canAdd(audioOutput) else {
|
||||||
throw Error.setupFailure(.cannotAddAudioOutput)
|
throw Error.setupFailure(.cannotAddAudioOutput)
|
||||||
}
|
}
|
||||||
reader.add(audioOutput)
|
reader.add(audioOutput)
|
||||||
|
|
@ -177,7 +182,7 @@ actor SampleWriter {
|
||||||
|
|
||||||
let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioOutputSettings)
|
let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioOutputSettings)
|
||||||
audioInput.expectsMediaDataInRealTime = false
|
audioInput.expectsMediaDataInRealTime = false
|
||||||
guard writer.canAdd(audioInput) else {
|
guard let writer, writer.canAdd(audioInput) else {
|
||||||
throw Error.setupFailure(.cannotAddAudioInput)
|
throw Error.setupFailure(.cannotAddAudioInput)
|
||||||
}
|
}
|
||||||
writer.add(audioInput)
|
writer.add(audioInput)
|
||||||
|
|
@ -193,7 +198,7 @@ actor SampleWriter {
|
||||||
)
|
)
|
||||||
videoOutput.alwaysCopiesSampleData = false
|
videoOutput.alwaysCopiesSampleData = false
|
||||||
videoOutput.videoComposition = videoComposition
|
videoOutput.videoComposition = videoComposition
|
||||||
guard reader.canAdd(videoOutput) else {
|
guard let reader, reader.canAdd(videoOutput) else {
|
||||||
throw Error.setupFailure(.cannotAddVideoOutput)
|
throw Error.setupFailure(.cannotAddVideoOutput)
|
||||||
}
|
}
|
||||||
reader.add(videoOutput)
|
reader.add(videoOutput)
|
||||||
|
|
@ -201,7 +206,7 @@ actor SampleWriter {
|
||||||
|
|
||||||
let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoOutputSettings)
|
let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoOutputSettings)
|
||||||
videoInput.expectsMediaDataInRealTime = false
|
videoInput.expectsMediaDataInRealTime = false
|
||||||
guard writer.canAdd(videoInput) else {
|
guard let writer, writer.canAdd(videoInput) else {
|
||||||
throw Error.setupFailure(.cannotAddVideoInput)
|
throw Error.setupFailure(.cannotAddVideoInput)
|
||||||
}
|
}
|
||||||
writer.add(videoInput)
|
writer.add(videoInput)
|
||||||
|
|
@ -233,11 +238,25 @@ actor SampleWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func cancelReaderAndWriter() {
|
||||||
|
reader?.cancelReading()
|
||||||
|
writer?.cancelWriting()
|
||||||
|
cleanUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cleanUp() {
|
||||||
|
reader = nil
|
||||||
|
writer = nil
|
||||||
|
audioInput = nil
|
||||||
|
audioOutput = nil
|
||||||
|
videoInput = nil
|
||||||
|
videoOutput = nil
|
||||||
|
}
|
||||||
|
|
||||||
private func writeAllReadySamples() {
|
private func writeAllReadySamples() {
|
||||||
guard !isCancelled else {
|
guard !isCancelled else {
|
||||||
log.debug("Cancelled while writing samples")
|
log.debug("Cancelled while writing samples")
|
||||||
reader.cancelReading()
|
cancelReaderAndWriter()
|
||||||
writer.cancelWriting()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,11 +273,10 @@ actor SampleWriter {
|
||||||
while input.isReadyForMoreMediaData {
|
while input.isReadyForMoreMediaData {
|
||||||
guard !isCancelled else {
|
guard !isCancelled else {
|
||||||
log.debug("Cancelled while writing samples")
|
log.debug("Cancelled while writing samples")
|
||||||
reader.cancelReading()
|
cancelReaderAndWriter()
|
||||||
writer.cancelWriting()
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
guard reader.status == .reading && writer.status == .writing,
|
guard reader?.status == .reading && writer?.status == .writing,
|
||||||
let sampleBuffer = output.copyNextSampleBuffer() else {
|
let sampleBuffer = output.copyNextSampleBuffer() else {
|
||||||
input.markAsFinished()
|
input.markAsFinished()
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue