LiveKitBridge.swift

  1import Foundation
  2import LiveKit
  3import WebRTC
  4
  5class LKRoomDelegate: RoomDelegate {
  6    var data: UnsafeRawPointer
  7    var onDidSubscribeToRemoteVideoTrack: @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void
  8    
  9    init(data: UnsafeRawPointer, onDidSubscribeToRemoteVideoTrack: @escaping @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void) {
 10        self.data = data
 11        self.onDidSubscribeToRemoteVideoTrack = onDidSubscribeToRemoteVideoTrack
 12    }
 13
 14    func room(_ room: Room, participant: RemoteParticipant, didSubscribe publication: RemoteTrackPublication, track: Track) {
 15        if track.kind == .video {
 16            self.onDidSubscribeToRemoteVideoTrack(self.data, Unmanaged.passRetained(track).toOpaque())
 17        }
 18    }
 19}
 20
 21class LKVideoRenderer: NSObject, VideoRenderer {
 22    var data: UnsafeRawPointer
 23    var onFrame: @convention(c) (UnsafeRawPointer, CVPixelBuffer) -> Void
 24    var onDrop: @convention(c) (UnsafeRawPointer) -> Void
 25    var adaptiveStreamIsEnabled: Bool = false
 26    var adaptiveStreamSize: CGSize = .zero
 27
 28    init(data: UnsafeRawPointer, onFrame: @escaping @convention(c) (UnsafeRawPointer, CVPixelBuffer) -> Void, onDrop: @escaping @convention(c) (UnsafeRawPointer) -> Void) {
 29        self.data = data
 30        self.onFrame = onFrame
 31        self.onDrop = onDrop
 32    }
 33
 34    deinit {
 35        self.onDrop(self.data)
 36    }
 37
 38    func setSize(_ size: CGSize) {
 39        print("Called setSize", size);
 40    }
 41
 42    func renderFrame(_ frame: RTCVideoFrame?) {
 43        let buffer = frame?.buffer as? RTCCVPixelBuffer
 44        if let pixelBuffer = buffer?.pixelBuffer {
 45            self.onFrame(self.data, pixelBuffer)
 46        }
 47    }
 48}
 49
 50@_cdecl("LKRelease")
 51public func LKRelease(ptr: UnsafeRawPointer)  {
 52    let _ = Unmanaged<AnyObject>.fromOpaque(ptr).takeRetainedValue()
 53}
 54
 55@_cdecl("LKRoomDelegateCreate")
 56public func LKRoomDelegateCreate(data: UnsafeRawPointer, onDidSubscribeToRemoteVideoTrack: @escaping @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void) -> UnsafeMutableRawPointer {
 57    let delegate = LKRoomDelegate(data: data, onDidSubscribeToRemoteVideoTrack: onDidSubscribeToRemoteVideoTrack)
 58    return Unmanaged.passRetained(delegate).toOpaque()
 59}
 60
 61@_cdecl("LKRoomCreate")
 62public func LKRoomCreate(delegate: UnsafeRawPointer) -> UnsafeMutableRawPointer  {
 63    let delegate = Unmanaged<LKRoomDelegate>.fromOpaque(delegate).takeUnretainedValue()
 64    return Unmanaged.passRetained(Room(delegate: delegate)).toOpaque()
 65}
 66
 67@_cdecl("LKRoomConnect")
 68public func LKRoomConnect(room: UnsafeRawPointer, url: CFString, token: CFString, callback: @escaping @convention(c) (UnsafeRawPointer, CFString?) -> Void, callback_data: UnsafeRawPointer) {
 69    let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
 70
 71    room.connect(url as String, token as String).then { _ in
 72        callback(callback_data, UnsafeRawPointer(nil) as! CFString?)
 73    }.catch { error in
 74        callback(callback_data, error.localizedDescription as CFString)
 75    }
 76}
 77
 78@_cdecl("LKRoomPublishVideoTrack")
 79public func LKRoomPublishVideoTrack(room: UnsafeRawPointer, track: UnsafeRawPointer, callback: @escaping @convention(c) (UnsafeRawPointer, CFString?) -> Void, callback_data: UnsafeRawPointer) {
 80    let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
 81    let track = Unmanaged<LocalVideoTrack>.fromOpaque(track).takeUnretainedValue()
 82    room.localParticipant?.publishVideoTrack(track: track).then { _ in
 83        callback(callback_data, UnsafeRawPointer(nil) as! CFString?)
 84    }.catch { error in
 85        callback(callback_data, error.localizedDescription as CFString)
 86    }
 87}
 88
 89@_cdecl("LKCreateScreenShareTrackForWindow")
 90public func LKCreateScreenShareTrackForWindow(windowId: uint32) -> UnsafeMutableRawPointer {
 91    let track = LocalVideoTrack.createMacOSScreenShareTrack(source: .window(id: windowId))
 92    return Unmanaged.passRetained(track).toOpaque()
 93}
 94
 95@_cdecl("LKVideoRendererCreate")
 96public func LKVideoRendererCreate(data: UnsafeRawPointer, onFrame: @escaping @convention(c) (UnsafeRawPointer, CVPixelBuffer) -> Void, onDrop: @escaping @convention(c) (UnsafeRawPointer) -> Void) -> UnsafeMutableRawPointer {
 97    Unmanaged.passRetained(LKVideoRenderer(data: data, onFrame: onFrame, onDrop: onDrop)).toOpaque()
 98}
 99
100@_cdecl("LKVideoTrackAddRenderer")
101public func LKVideoTrackAddRenderer(track: UnsafeRawPointer, renderer: UnsafeRawPointer) {
102    let track = Unmanaged<Track>.fromOpaque(track).takeUnretainedValue() as! VideoTrack
103    let renderer = Unmanaged<LKVideoRenderer>.fromOpaque(renderer).takeRetainedValue()
104    track.add(videoRenderer: renderer)
105}