Skip to content

Commit 2dac7d5

Browse files
committed
Try to fix a possible retain cycle
1 parent f72a073 commit 2dac7d5

1 file changed

Lines changed: 45 additions & 27 deletions

File tree

Sources/SJSAssetExportSession/SampleWriter.swift

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ actor SampleWriter {
4141

4242
// MARK: Internal state
4343

44-
private let reader: AVAssetReader
45-
private let writer: AVAssetWriter
44+
private var reader: AVAssetReader?
45+
private var writer: AVAssetWriter?
4646
private var audioOutput: AVAssetReaderAudioMixOutput?
4747
private var audioInput: AVAssetWriterInput?
4848
private var videoOutput: AVAssetReaderVideoCompositionOutput?
@@ -111,15 +111,15 @@ actor SampleWriter {
111111

112112
progressContinuation.yield(0.0)
113113

114-
writer.startWriting()
115-
writer.startSession(atSourceTime: timeRange.start)
116-
reader.startReading()
114+
writer?.startWriting()
115+
writer?.startSession(atSourceTime: timeRange.start)
116+
reader?.startReading()
117117
try Task.checkCancellation()
118118

119119
startEncodingAudioTracks()
120120
startEncodingVideoTracks()
121121

122-
while reader.status == .reading, writer.status == .writing {
122+
while reader?.status == .reading, writer?.status == .writing {
123123
guard !Task.isCancelled else {
124124
// Flag so that we stop writing samples
125125
isCancelled = true
@@ -129,24 +129,29 @@ actor SampleWriter {
129129
try await Task.sleep(for: .milliseconds(10))
130130
}
131131

132-
guard !isCancelled, reader.status != .cancelled, writer.status != .cancelled else {
132+
defer {
133+
cleanUp()
134+
}
135+
136+
guard !isCancelled, reader?.status != .cancelled, writer?.status != .cancelled else {
133137
log.debug("Cancelled before writing samples")
134-
reader.cancelReading()
135-
writer.cancelWriting()
138+
cancelReaderAndWriter()
136139
throw CancellationError()
137140
}
138-
guard writer.status != .failed else {
139-
reader.cancelReading()
140-
throw Error.writeFailure(writer.error)
141+
guard writer?.status != .failed else {
142+
reader?.cancelReading()
143+
throw Error.writeFailure(writer?.error)
141144
}
142-
guard reader.status != .failed else {
143-
writer.cancelWriting()
144-
throw Error.readFailure(reader.error)
145+
guard reader?.status != .failed else {
146+
writer?.cancelWriting()
147+
throw Error.readFailure(reader?.error)
145148
}
146149

147-
await withCheckedContinuation { continuation in
148-
writer.finishWriting {
149-
continuation.resume(returning: ())
150+
if let writer {
151+
await withCheckedContinuation { continuation in
152+
writer.finishWriting {
153+
continuation.resume(returning: ())
154+
}
150155
}
151156
}
152157

@@ -169,15 +174,15 @@ actor SampleWriter {
169174
let audioOutput = AVAssetReaderAudioMixOutput(audioTracks: audioTracks, audioSettings: nil)
170175
audioOutput.alwaysCopiesSampleData = false
171176
audioOutput.audioMix = audioMix
172-
guard reader.canAdd(audioOutput) else {
177+
guard let reader, reader.canAdd(audioOutput) else {
173178
throw Error.setupFailure(.cannotAddAudioOutput)
174179
}
175180
reader.add(audioOutput)
176181
self.audioOutput = audioOutput
177182

178183
let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioOutputSettings)
179184
audioInput.expectsMediaDataInRealTime = false
180-
guard writer.canAdd(audioInput) else {
185+
guard let writer, writer.canAdd(audioInput) else {
181186
throw Error.setupFailure(.cannotAddAudioInput)
182187
}
183188
writer.add(audioInput)
@@ -193,15 +198,15 @@ actor SampleWriter {
193198
)
194199
videoOutput.alwaysCopiesSampleData = false
195200
videoOutput.videoComposition = videoComposition
196-
guard reader.canAdd(videoOutput) else {
201+
guard let reader, reader.canAdd(videoOutput) else {
197202
throw Error.setupFailure(.cannotAddVideoOutput)
198203
}
199204
reader.add(videoOutput)
200205
self.videoOutput = videoOutput
201206

202207
let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoOutputSettings)
203208
videoInput.expectsMediaDataInRealTime = false
204-
guard writer.canAdd(videoInput) else {
209+
guard let writer, writer.canAdd(videoInput) else {
205210
throw Error.setupFailure(.cannotAddVideoInput)
206211
}
207212
writer.add(videoInput)
@@ -233,11 +238,25 @@ actor SampleWriter {
233238
}
234239
}
235240

241+
private func cancelReaderAndWriter() {
242+
reader?.cancelReading()
243+
writer?.cancelWriting()
244+
cleanUp()
245+
}
246+
247+
private func cleanUp() {
248+
reader = nil
249+
writer = nil
250+
audioInput = nil
251+
audioOutput = nil
252+
videoInput = nil
253+
videoOutput = nil
254+
}
255+
236256
private func writeAllReadySamples() {
237257
guard !isCancelled else {
238258
log.debug("Cancelled while writing samples")
239-
reader.cancelReading()
240-
writer.cancelWriting()
259+
cancelReaderAndWriter()
241260
return
242261
}
243262

@@ -254,11 +273,10 @@ actor SampleWriter {
254273
while input.isReadyForMoreMediaData {
255274
guard !isCancelled else {
256275
log.debug("Cancelled while writing samples")
257-
reader.cancelReading()
258-
writer.cancelWriting()
276+
cancelReaderAndWriter()
259277
return false
260278
}
261-
guard reader.status == .reading && writer.status == .writing,
279+
guard reader?.status == .reading && writer?.status == .writing,
262280
let sampleBuffer = output.copyNextSampleBuffer() else {
263281
input.markAsFinished()
264282
return false

0 commit comments

Comments
 (0)