Make SampleWriter.init nonisolated so it can load tracks

This commit is contained in:
Sami Samhuri 2024-08-12 19:01:21 -07:00
parent 996251cfde
commit 8f049aed95
No known key found for this signature in database
5 changed files with 19 additions and 19 deletions

View file

@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
7B7AE3092C36615700DB7391 /* SampleWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7AE3082C36615700DB7391 /* SampleWriter.swift */; };
7B9867982C6AF57C001353BC /* AVAsset+sending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */; };
7B9BC00E2C305D2C00C160C2 /* SJSAssetExportSession.docc in Sources */ = {isa = PBXBuildFile; fileRef = 7B9BC00D2C305D2C00C160C2 /* SJSAssetExportSession.docc */; };
7B9BC0142C305D2C00C160C2 /* SJSAssetExportSession.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B9BC0092C305D2C00C160C2 /* SJSAssetExportSession.framework */; };
7B9BC0192C305D2C00C160C2 /* SJSAssetExportSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9BC0182C305D2C00C160C2 /* SJSAssetExportSessionTests.swift */; };
@ -16,7 +17,6 @@
7BC5FC772C3B8C5A0090B757 /* SendableWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC762C3B8C5A0090B757 /* SendableWrapper.swift */; };
7BC5FC792C3B90F70090B757 /* AutoDestructingURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC782C3B90F70090B757 /* AutoDestructingURL.swift */; };
7BC5FC8A2C3BAA150090B757 /* ExportSession+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC892C3BAA150090B757 /* ExportSession+Error.swift */; };
7BC5FC8C2C3BB0180090B757 /* AVAsset+sending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */; };
7BC5FC902C3BB2030090B757 /* AudioOutputSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC8F2C3BB2030090B757 /* AudioOutputSettings.swift */; };
7BC5FC922C3BB4BD0090B757 /* VideoOutputSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC912C3BB4BD0090B757 /* VideoOutputSettings.swift */; };
7BC5FC942C3BC3AD0090B757 /* CMTime+seconds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC5FC932C3BC3AD0090B757 /* CMTime+seconds.swift */; };
@ -95,7 +95,6 @@
children = (
7BC5FC8F2C3BB2030090B757 /* AudioOutputSettings.swift */,
7BC5FC912C3BB4BD0090B757 /* VideoOutputSettings.swift */,
7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */,
7BC5FC932C3BC3AD0090B757 /* CMTime+seconds.swift */,
7B9BC0272C30612C00C160C2 /* ExportSession.swift */,
7BC5FC892C3BAA150090B757 /* ExportSession+Error.swift */,
@ -110,6 +109,7 @@
isa = PBXGroup;
children = (
7BC5FC782C3B90F70090B757 /* AutoDestructingURL.swift */,
7BC5FC8B2C3BB0180090B757 /* AVAsset+sending.swift */,
7BC5FC812C3B9E3D0090B757 /* Resources */,
7BC5FC762C3B8C5A0090B757 /* SendableWrapper.swift */,
7B9BC0182C305D2C00C160C2 /* SJSAssetExportSessionTests.swift */,
@ -233,7 +233,6 @@
7B7AE3092C36615700DB7391 /* SampleWriter.swift in Sources */,
7BC5FC902C3BB2030090B757 /* AudioOutputSettings.swift in Sources */,
7B9BC0282C30612C00C160C2 /* ExportSession.swift in Sources */,
7BC5FC8C2C3BB0180090B757 /* AVAsset+sending.swift in Sources */,
7BC5FC922C3BB4BD0090B757 /* VideoOutputSettings.swift in Sources */,
7B9BC00E2C305D2C00C160C2 /* SJSAssetExportSession.docc in Sources */,
7BC5FC8A2C3BAA150090B757 /* ExportSession+Error.swift in Sources */,
@ -246,6 +245,7 @@
files = (
7B9BC0192C305D2C00C160C2 /* SJSAssetExportSessionTests.swift in Sources */,
7BC5FC792C3B90F70090B757 /* AutoDestructingURL.swift in Sources */,
7B9867982C6AF57C001353BC /* AVAsset+sending.swift in Sources */,
7BC5FC772C3B8C5A0090B757 /* SendableWrapper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View file

@ -45,12 +45,12 @@ actor SampleWriter {
private var videoInput: AVAssetWriterInput?
private var isCancelled = false
init(
nonisolated init(
asset: sending AVAsset,
audioOutputSettings: sending [String: (any Sendable)],
audioMix: AVAudioMix?,
audioMix: sending AVAudioMix?,
videoOutputSettings: sending [String: (any Sendable)],
videoComposition: AVVideoComposition,
videoComposition: sending AVVideoComposition,
timeRange: CMTimeRange? = nil,
optimizeForNetworkUse: Bool = false,
outputURL: URL,
@ -67,10 +67,14 @@ actor SampleWriter {
let writer = try AVAssetWriter(outputURL: outputURL, fileType: fileType)
writer.shouldOptimizeForNetworkUse = optimizeForNetworkUse
let audioTracks = try await asset.sendTracks(withMediaType: .audio)
try Self.validateAudio(tracks: audioTracks, outputSettings: audioOutputSettings, writer: writer)
let videoTracks = try await asset.sendTracks(withMediaType: .video)
try Self.validateVideo(tracks: videoTracks, outputSettings: videoOutputSettings, writer: writer)
let audioTracks = try await asset.loadTracks(withMediaType: .audio)
// Audio is optional so only validate output settings when it's applicable.
if !audioTracks.isEmpty {
try Self.validateAudio(outputSettings: audioOutputSettings, writer: writer)
}
let videoTracks = try await asset.loadTracks(withMediaType: .video)
guard !videoTracks.isEmpty else { throw Error.setupFailure(.videoTracksEmpty) }
try Self.validateVideo(outputSettings: videoOutputSettings, writer: writer)
Self.warnAboutMismatchedVideoSize(
renderSize: videoComposition.renderSize,
settings: videoOutputSettings
@ -85,8 +89,8 @@ actor SampleWriter {
self.duration = duration
self.timeRange = timeRange ?? CMTimeRange(start: .zero, duration: duration)
try setUpAudio(audioTracks: audioTracks)
try setUpVideo(videoTracks: videoTracks)
try await setUpAudio(audioTracks: audioTracks)
try await setUpVideo(videoTracks: videoTracks)
}
func writeSamples() async throws {
@ -281,11 +285,9 @@ actor SampleWriter {
// MARK: Input validation
private static func validateAudio(
tracks: [AVAssetTrack],
outputSettings: [String: any Sendable],
writer: AVAssetWriter
) throws {
guard !tracks.isEmpty else { return } // Audio is optional so this isn't a failure.
guard !outputSettings.isEmpty else { throw Error.setupFailure(.audioSettingsEmpty) }
guard writer.canApply(outputSettings: outputSettings, forMediaType: .audio) else {
throw Error.setupFailure(.audioSettingsInvalid)
@ -293,11 +295,9 @@ actor SampleWriter {
}
private static func validateVideo(
tracks: [AVAssetTrack],
outputSettings: [String: any Sendable],
writer: AVAssetWriter
) throws {
guard !tracks.isEmpty else { throw Error.setupFailure(.videoTracksEmpty) }
guard writer.canApply(outputSettings: outputSettings, forMediaType: .video) else {
throw Error.setupFailure(.videoSettingsInvalid)
}

View file

@ -5,7 +5,7 @@
// Created by Sami Samhuri on 2024-07-07.
//
public import AVFoundation
import AVFoundation
public struct VideoOutputSettings {
public enum H264Profile {

View file

@ -1,6 +1,6 @@
//
// AVAsset+sending.swift
// SJSAssetExportSession
// SJSAssetExportSessionTests
//
// Created by Sami Samhuri on 2024-07-07.
//

View file

@ -5,7 +5,7 @@
// Created by Sami Samhuri on 2024-06-29.
//
import AVFoundation
internal import AVFoundation
@testable import SJSAssetExportSession
import Testing