@@ -18,63 +18,71 @@ import AVFoundation
18
18
@testable import LiveKit
19
19
import XCTest
20
20
21
+ @available ( iOS 15 . 0 , * )
21
22
class BufferCapturerTest : XCTestCase {
22
- @available ( iOS 15 . 0 , * )
23
- func testX( ) async throws {
23
+ // Creates a LocalVideoTrack with BufferCapturer, generates frames for approx 30 seconds
24
+ func createSampleVideoTrack( targetFps: Int = 30 , _ onCapture: @escaping ( CMSampleBuffer ) -> Void ) async throws -> ( Task < Void , any Error > ) {
25
+ // Sample video
24
26
let url = URL ( string: " https://storage.unxpected.co.jp/public/sample-videos/ocean-1080p.mp4 " ) !
25
27
26
- print ( " Downloading... " )
27
- let ( tempLocalURL, _) = try await URLSession . shared. download ( from: url)
28
+ print ( " Downloading sample video from \( url) ... " )
29
+ // TODO: Backport for iOS13
30
+ let ( downloadedLocalUrl, _) = try await URLSession . shared. download ( from: url)
28
31
29
32
// Move the file to a new temporary location with a more descriptive name, if desired
30
- let fileManager = FileManager . default
31
- let tempDirectory = fileManager. temporaryDirectory
32
- let targetURL = tempDirectory. appendingPathComponent ( UUID ( ) . uuidString) . appendingPathExtension ( " mp4 " )
33
-
34
- try fileManager. moveItem ( at: tempLocalURL, to: targetURL)
35
-
36
- print ( " Opening \( targetURL) ... " )
37
-
38
- let asset = AVAsset ( url: targetURL)
33
+ let tempLocalUrl = FileManager . default. temporaryDirectory. appendingPathComponent ( UUID ( ) . uuidString) . appendingPathExtension ( " mp4 " )
34
+ try FileManager . default. moveItem ( at: downloadedLocalUrl, to: tempLocalUrl)
39
35
36
+ print ( " Opening \( tempLocalUrl) with asset reader... " )
37
+ let asset = AVAsset ( url: tempLocalUrl)
40
38
let assetReader = try AVAssetReader ( asset: asset)
41
39
42
40
guard let track = asset. tracks ( withMediaType: . video) . first else {
43
- return
41
+ XCTFail ( " No video track found in sample video file " )
42
+ fatalError ( )
44
43
}
45
44
46
45
let outputSettings : [ String : Any ] = [
47
46
kCVPixelBufferPixelFormatTypeKey as String : Int ( kCVPixelFormatType_32BGRA) ,
48
47
]
49
48
50
- let trackOutput = AVAssetReaderTrackOutput ( track: track, outputSettings: outputSettings) // nil for outputSettings to get samples in their original format
49
+ let trackOutput = AVAssetReaderTrackOutput ( track: track, outputSettings: outputSettings)
51
50
assetReader. add ( trackOutput)
52
51
52
+ // Start reading...
53
+ guard assetReader. startReading ( ) else {
54
+ XCTFail ( " Could not start reading the asset. " )
55
+ fatalError ( )
56
+ }
57
+
58
+ // XCTAssert(assetReader.status == .reading)
59
+
60
+ let readBufferTask = Task . detached {
61
+ let frameDuration = UInt64 ( 1_000_000_000 / targetFps)
62
+ while !Task. isCancelled, assetReader. status == . reading, let sampleBuffer = trackOutput. copyNextSampleBuffer ( ) {
63
+ onCapture ( sampleBuffer)
64
+ // Sleep for the frame duration to regulate to ~30 fps
65
+ try await Task . sleep ( nanoseconds: frameDuration)
66
+ }
67
+ }
68
+
69
+ return readBufferTask
70
+ }
71
+
72
+ func testPublishBufferTrack( ) async throws {
53
73
try await with2Rooms { room1, _ in
54
74
55
75
let bufferTrack = LocalVideoTrack . createBufferTrack ( )
56
76
let bufferCapturer = bufferTrack. capturer as! BufferCapturer
57
77
58
- // Start reading...
59
- guard assetReader. startReading ( ) else {
60
- XCTFail ( " Could not start reading the asset. " )
61
- return
62
- }
63
-
64
- let readBufferTask = Task . detached {
65
- let frameDuration = UInt64 ( 1_000_000_000 / 30 ) // 30 fps
66
- while !Task. isCancelled, let sampleBuffer = trackOutput. copyNextSampleBuffer ( ) {
67
- // print("sampleBuffer: \(sampleBuffer)")
68
- bufferCapturer. capture ( sampleBuffer)
69
- // Sleep for the frame duration to regulate to ~30 fps
70
- try await Task . sleep ( nanoseconds: frameDuration)
71
- }
78
+ let captureTask = try await self . createSampleVideoTrack { buffer in
79
+ bufferCapturer. capture ( buffer)
72
80
}
73
81
74
82
try await room1. localParticipant. publish ( videoTrack: bufferTrack)
75
83
76
84
// Wait until finish reading buffer...
77
- try await readBufferTask . value
85
+ try await captureTask . value
78
86
}
79
87
}
80
88
}
0 commit comments