Skip to content

Commit 62be2bd

Browse files
committed
Add more error handling
1 parent b929062 commit 62be2bd

File tree

2 files changed

+83
-30
lines changed

2 files changed

+83
-30
lines changed

Sources/Upscaling/UpscalingCompositor.swift

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,29 @@ public final class UpscalingCompositor: NSObject, AVVideoCompositing {
2424
public func renderContextChanged(_: AVVideoCompositionRenderContext) {}
2525

2626
public func startRequest(_ asyncVideoCompositionRequest: AVAsynchronousVideoCompositionRequest) {
27-
let sourceFrame = asyncVideoCompositionRequest.sourceFrame(
28-
byTrackID: CMPersistentTrackID(truncating: asyncVideoCompositionRequest.sourceTrackIDs[0])
29-
)!
27+
guard let trackID = asyncVideoCompositionRequest.sourceTrackIDs.first else {
28+
asyncVideoCompositionRequest.finish(with: Error.couldNotGetSourceTrackID)
29+
return
30+
}
31+
guard let sourceFrame = asyncVideoCompositionRequest.sourceFrame(
32+
byTrackID: CMPersistentTrackID(truncating: trackID)
33+
) else {
34+
asyncVideoCompositionRequest.finish(with: Error.couldNotGetSourceFrame)
35+
return
36+
}
3037
#if canImport(MetalFX)
31-
let destinationFrame = asyncVideoCompositionRequest.renderContext.newPixelBuffer()!
32-
33-
let commandBuffer = commandQueue.makeCommandBuffer()!
34-
35-
var colorTexture: CVMetalTexture?
36-
CVMetalTextureCacheCreateTextureFromImage(
38+
guard let destinationFrame = asyncVideoCompositionRequest.renderContext.newPixelBuffer() else {
39+
asyncVideoCompositionRequest.finish(with: Error.couldNotCreateDestinationPixelBuffer)
40+
return
41+
}
42+
43+
guard let commandBuffer = commandQueue.makeCommandBuffer() else {
44+
asyncVideoCompositionRequest.finish(with: Error.couldNotMakeCommandBuffer)
45+
return
46+
}
47+
48+
var colorTexture: CVMetalTexture!
49+
var status = CVMetalTextureCacheCreateTextureFromImage(
3750
nil,
3851
cvTextureCache,
3952
sourceFrame,
@@ -44,9 +57,13 @@ public final class UpscalingCompositor: NSObject, AVVideoCompositing {
4457
0,
4558
&colorTexture
4659
)
60+
guard status == kCVReturnSuccess else {
61+
asyncVideoCompositionRequest.finish(with: Error.couldNotCreateMetalTextureFromSourceFrame(status))
62+
return
63+
}
4764

48-
var outputTexture: CVMetalTexture?
49-
CVMetalTextureCacheCreateTextureFromImage(
65+
var outputTexture: CVMetalTexture!
66+
status = CVMetalTextureCacheCreateTextureFromImage(
5067
nil,
5168
cvTextureCache,
5269
destinationFrame,
@@ -57,18 +74,32 @@ public final class UpscalingCompositor: NSObject, AVVideoCompositing {
5774
0,
5875
&outputTexture
5976
)
60-
61-
let intermediateOutputTexture = device.makeTexture(descriptor: intermediateOutputTextureDescriptor)!
62-
spatialScaler.colorTexture = CVMetalTextureGetTexture(colorTexture!)
77+
guard status == kCVReturnSuccess else {
78+
asyncVideoCompositionRequest.finish(with: Error.couldNotCreateMetalTextureFromDestinationFrame(status))
79+
return
80+
}
81+
82+
guard let intermediateOutputTexture = device.makeTexture(descriptor: intermediateOutputTextureDescriptor) else {
83+
asyncVideoCompositionRequest.finish(with: Error.couldNotMakeIntermediateOutputTexture)
84+
return
85+
}
86+
spatialScaler.colorTexture = CVMetalTextureGetTexture(colorTexture)
6387
spatialScaler.outputTexture = intermediateOutputTexture
6488

6589
spatialScaler.encode(commandBuffer: commandBuffer)
66-
let blitCommandEncoder = commandBuffer.makeBlitCommandEncoder()!
67-
blitCommandEncoder.copy(from: intermediateOutputTexture, to: CVMetalTextureGetTexture(outputTexture!)!)
90+
guard let blitCommandEncoder = commandBuffer.makeBlitCommandEncoder() else {
91+
asyncVideoCompositionRequest.finish(with: Error.couldNotMakeBlitCommandEncoder)
92+
return
93+
}
94+
blitCommandEncoder.copy(from: intermediateOutputTexture, to: CVMetalTextureGetTexture(outputTexture)!)
6895
blitCommandEncoder.endEncoding()
6996

7097
commandBuffer.commit()
7198
commandBuffer.waitUntilCompleted()
99+
if let error = commandBuffer.error {
100+
asyncVideoCompositionRequest.finish(with: error)
101+
return
102+
}
72103

73104
asyncVideoCompositionRequest.finish(withComposedVideoFrame: destinationFrame)
74105
#else
@@ -110,3 +141,18 @@ public final class UpscalingCompositor: NSObject, AVVideoCompositing {
110141
return textureDescriptor
111142
}()
112143
}
144+
145+
// MARK: UpscalingCompositor.Error
146+
147+
extension UpscalingCompositor {
148+
enum Error: Swift.Error {
149+
case couldNotGetSourceTrackID
150+
case couldNotGetSourceFrame
151+
case couldNotCreateDestinationPixelBuffer
152+
case couldNotMakeCommandBuffer
153+
case couldNotCreateMetalTextureFromSourceFrame(CVReturn)
154+
case couldNotCreateMetalTextureFromDestinationFrame(CVReturn)
155+
case couldNotMakeIntermediateOutputTexture
156+
case couldNotMakeBlitCommandEncoder
157+
}
158+
}

Sources/Upscaling/UpscalingExportSession.swift

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public class UpscalingExportSession {
154154
assetReader.startReading()
155155
assetWriter.startSession(atSourceTime: .zero)
156156

157-
await withCheckedContinuation { continuation in
157+
try await withCheckedThrowingContinuation { continuation in
158158
// - Returns: Whether or not the input has read all available media data
159159
@Sendable func copyReadySamples(from output: AVAssetReaderOutput, to input: AVAssetWriterInput) -> Bool {
160160
while input.isReadyForMoreMediaData {
@@ -173,20 +173,24 @@ public class UpscalingExportSession {
173173
@Sendable func finish() {
174174
if assetWriter.status == .failed {
175175
try? FileManager.default.removeItem(at: outputURL)
176+
continuation.resume(throwing: Error.assetWriterFailed(assetWriter.error))
177+
return
178+
}
179+
180+
if assetReader.status == .failed {
181+
try? FileManager.default.removeItem(at: outputURL)
182+
continuation.resume(throwing: Error.assetReaderFailed(assetReader.error))
183+
return
184+
}
185+
186+
if assetWriter.status == .cancelled {
187+
try? FileManager.default.removeItem(at: self.outputURL)
188+
continuation.resume(throwing: Error.cancelled)
189+
return
190+
}
191+
192+
assetWriter.finishWriting {
176193
continuation.resume()
177-
} else if assetReader.status == .failed {
178-
assetWriter.cancelWriting()
179-
if [.cancelled, .failed].contains(assetWriter.status) {
180-
try? FileManager.default.removeItem(at: outputURL)
181-
}
182-
continuation.resume()
183-
} else {
184-
assetWriter.finishWriting {
185-
if [.cancelled, .failed].contains(assetWriter.status) {
186-
try? FileManager.default.removeItem(at: self.outputURL)
187-
}
188-
continuation.resume()
189-
}
190194
}
191195
}
192196

@@ -228,5 +232,8 @@ extension UpscalingExportSession {
228232
case couldNotAddAssetWriterVideoInput
229233
case couldNotAddAssetReaderAudioOutput
230234
case couldNotAddAssetWriterAudioInput
235+
case assetReaderFailed(Swift.Error?)
236+
case assetWriterFailed(Swift.Error?)
237+
case cancelled
231238
}
232239
}

0 commit comments

Comments
 (0)