Skip to content
This repository was archived by the owner on May 13, 2024. It is now read-only.

Commit d860181

Browse files
authored
Karkakol - add simulcast data to tracks
1 parent b8a8d3d commit d860181

9 files changed

+109
-44
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ Debug.xcconfig
88
.swiftpm
99
/.build
1010
/Packages
11-
DerivedData/
11+
DerivedData/
12+
/.idea/

Sources/MembraneRTC/Events/Event.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ struct EndpointAddedEvent: ReceivableEvent, Codable {
305305
let id: String
306306
let type: String
307307
let metadata: Metadata?
308-
let trackIdToMetadata: [String: Metadata]?
308+
let tracks: [String: TrackData]?
309309
}
310310

311311
let type: ReceivableEventType
@@ -349,14 +349,14 @@ struct OfferDataEvent: ReceivableEvent, Codable {
349349
let data: Data
350350
}
351351

352-
struct TracksAddedEvent: ReceivableEvent, Codable {
353-
struct Data: Codable {
352+
public struct TracksAddedEvent: ReceivableEvent, Codable {
353+
public struct Data: Codable {
354354
let endpointId: String
355-
let trackIdToMetadata: [String: Metadata]
355+
let tracks: [String: TrackData]
356356
}
357357

358-
let type: ReceivableEventType
359-
let data: Data
358+
public let type: ReceivableEventType
359+
public let data: Data
360360
}
361361

362362
struct TracksRemovedEvent: ReceivableEvent, Codable {

Sources/MembraneRTC/MembraneRTC.swift

+32-16
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
5858

5959
private var localTracks: [LocalTrack] = []
6060

61-
private var localEndpoint = Endpoint(id: "", type: "webrtc", metadata: .init([:]), trackIdToMetadata: [:])
61+
private var localEndpoint = Endpoint(id: "", type: "webrtc", metadata: .init([:]), tracks: [:])
6262

6363
// mapping from peer's id to itself
6464
private var remoteEndpoints: [String: Endpoint] = [:]
@@ -173,7 +173,10 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
173173

174174
- Returns: `LocalCameraVideoTrack` instance that user then can use for things such as front / back camera switch.
175175
*/
176-
public func createVideoTrack(videoParameters: VideoParameters, metadata: Metadata, captureDeviceId: String? = nil)
176+
public func createVideoTrack(
177+
videoParameters: VideoParameters, metadata: Metadata, captureDeviceId: String? = nil,
178+
simulcastConfig: SimulcastConfig? = nil
179+
)
177180
-> LocalVideoTrack
178181
{
179182
DispatchQueue.webRTC.sync {
@@ -191,7 +194,8 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
191194

192195
localTracks.append(videoTrack)
193196

194-
localEndpoint = localEndpoint.withTrack(trackId: videoTrack.rtcTrack().trackId, metadata: metadata)
197+
localEndpoint = localEndpoint.withTrack(
198+
trackId: videoTrack.rtcTrack().trackId, metadata: metadata, simulcastConfig: simulcastConfig)
195199

196200
engineCommunication.renegotiateTracks()
197201

@@ -219,7 +223,8 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
219223

220224
localTracks.append(audioTrack)
221225

222-
localEndpoint = localEndpoint.withTrack(trackId: audioTrack.rtcTrack().trackId, metadata: metadata)
226+
localEndpoint = localEndpoint.withTrack(
227+
trackId: audioTrack.rtcTrack().trackId, metadata: metadata, simulcastConfig: nil)
223228

224229
engineCommunication.renegotiateTracks()
225230

@@ -252,6 +257,7 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
252257
appGroup: appGroup, videoParameters: videoParameters,
253258
peerConnectionFactoryWrapper: peerConnectionFactoryWrapper)
254259
localTracks.append(screensharingTrack)
260+
let simulcastConfig = videoParameters.simulcastConfig
255261

256262
broadcastScreenshareReceiver = ScreenBroadcastNotificationReceiver(
257263
onStart: { [weak self, weak screensharingTrack] in
@@ -260,7 +266,7 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
260266
}
261267

262268
DispatchQueue.main.async {
263-
self?.setupScreencastTrack(track: track, metadata: metadata)
269+
self?.setupScreencastTrack(track: track, metadata: metadata, simulcastConfig: simulcastConfig)
264270
onStart(track)
265271
}
266272
},
@@ -369,7 +375,7 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
369375
public func updateTrackMetadata(trackId: String, trackMetadata: Metadata) {
370376
DispatchQueue.webRTC.sync {
371377
engineCommunication.updateTrackMetadata(trackId: trackId, trackMetadata: trackMetadata)
372-
localEndpoint = localEndpoint.withTrack(trackId: trackId, metadata: trackMetadata)
378+
localEndpoint = localEndpoint.withTrack(trackId: trackId, metadata: trackMetadata, simulcastConfig: nil)
373379
}
374380
}
375381

@@ -403,12 +409,15 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
403409
}
404410

405411
/// Adds given broadcast track to the peer connection and forces track renegotiation.
406-
private func setupScreencastTrack(track: LocalScreenBroadcastTrack, metadata: Metadata) {
412+
private func setupScreencastTrack(
413+
track: LocalScreenBroadcastTrack, metadata: Metadata, simulcastConfig: SimulcastConfig?
414+
) {
407415
let screencastStreamId = UUID().uuidString
408416

409417
peerConnectionManager.addTrack(track: track, localStreamId: screencastStreamId)
410418

411-
localEndpoint = localEndpoint.withTrack(trackId: track.rtcTrack().trackId, metadata: metadata)
419+
localEndpoint = localEndpoint.withTrack(
420+
trackId: track.rtcTrack().trackId, metadata: metadata, simulcastConfig: simulcastConfig)
412421

413422
engineCommunication.renegotiateTracks()
414423
}
@@ -469,8 +478,10 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
469478
self.remoteEndpoints[endpoint.id] = endpoint
470479

471480
// initialize peer's track contexts
472-
endpoint.trackIdToMetadata?.forEach { trackId, metadata in
473-
let context = TrackContext(track: nil, enpoint: endpoint, trackId: trackId, metadata: metadata)
481+
endpoint.tracks?.forEach { trackId, trackData in
482+
let context = TrackContext(
483+
track: nil, enpoint: endpoint, trackId: trackId, metadata: trackData.metadata,
484+
simulcastConfig: trackData.simulcastConfig)
474485

475486
self.trackContexts[trackId] = context
476487

@@ -512,7 +523,7 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
512523
remoteEndpoints.removeValue(forKey: endpoint.id)
513524

514525
// for a leaving peer clear his track contexts
515-
if let trackIds = endpoint.trackIdToMetadata?.keys {
526+
if let trackIds = endpoint.tracks?.keys {
516527
let contexts = trackIds.compactMap { id in
517528
self.trackContexts[id]
518529
}
@@ -560,7 +571,10 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
560571

561572
if let sdp = sdp, let midToTrackId = midToTrackId {
562573
self.engineCommunication.sdpOffer(
563-
sdp: sdp, trackIdToTrackMetadata: self.localEndpoint.trackIdToMetadata ?? [:],
574+
sdp: sdp,
575+
trackIdToTrackMetadata: self.localEndpoint.tracks?.mapValues({ trackData in
576+
trackData.metadata
577+
}) ?? [:],
564578
midToTrackId: midToTrackId)
565579
}
566580

@@ -577,7 +591,7 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
577591
peerConnectionManager.onRemoteCandidate(candidate: candidate)
578592
}
579593

580-
func onTracksAdded(endpointId: String, trackIdToMetadata: [String: Metadata]) {
594+
func onTracksAdded(endpointId: String, tracks: [String: TrackData]) {
581595
// ignore local participant
582596
guard localEndpoint.id != endpointId else {
583597
return
@@ -589,12 +603,14 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
589603
}
590604

591605
// update tracks of the remote peer
592-
endpoint = endpoint.with(trackIdToMetadata: trackIdToMetadata)
606+
endpoint = endpoint.with(tracks: tracks)
593607
remoteEndpoints[endpoint.id] = endpoint
594608

595609
// for each track create a corresponding track context
596-
endpoint.trackIdToMetadata?.forEach { trackId, metadata in
597-
let context = TrackContext(track: nil, enpoint: endpoint, trackId: trackId, metadata: metadata)
610+
endpoint.tracks?.forEach { trackId, trackData in
611+
let context = TrackContext(
612+
track: nil, enpoint: endpoint, trackId: trackId, metadata: trackData.metadata,
613+
simulcastConfig: trackData.simulcastConfig)
598614

599615
self.trackContexts[trackId] = context
600616

Sources/MembraneRTC/RTCEngineCommunication.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ internal class RTCEngineCommunication {
6060
engineListener.onEndpointAdded(
6161
endpoint: Endpoint(
6262
id: endpointAdded.data.id, type: endpointAdded.data.type, metadata: endpointAdded.data.metadata,
63-
trackIdToMetadata: endpointAdded.data.trackIdToMetadata))
63+
tracks: endpointAdded.data.tracks)
64+
)
6465
case .EndpointRemoved:
6566
let endpointRemoved = event as! EndpointRemovedEvent
6667
engineListener.onEndpointRemoved(endpointId: endpointRemoved.data.id)
@@ -80,7 +81,7 @@ internal class RTCEngineCommunication {
8081
case .TracksAdded:
8182
let tracksAdded = event as! TracksAddedEvent
8283
engineListener.onTracksAdded(
83-
endpointId: tracksAdded.data.endpointId, trackIdToMetadata: tracksAdded.data.trackIdToMetadata)
84+
endpointId: tracksAdded.data.endpointId, tracks: tracksAdded.data.tracks)
8485
case .TracksRemoved:
8586
let tracksRemoved = event as! TracksRemovedEvent
8687
engineListener.onTracksRemoved(

Sources/MembraneRTC/RTCEngineListener.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal protocol RTCEngineListener {
88
func onOfferData(integratedTurnServers: [OfferDataEvent.TurnServer], tracksTypes: [String: Int])
99
func onSdpAnswer(type: String, sdp: String, midToTrackId: [String: String?])
1010
func onRemoteCandidate(candidate: String, sdpMLineIndex: Int32, sdpMid: String?)
11-
func onTracksAdded(endpointId: String, trackIdToMetadata: [String: Metadata])
11+
func onTracksAdded(endpointId: String, tracks: [String: TrackData])
1212
func onTracksRemoved(endpointId: String, trackIds: [String])
1313
func onTrackUpdated(endpointId: String, trackId: String, metadata: Metadata)
1414
func onTrackEncodingChanged(endpointId: String, trackId: String, encoding: String, encodingReason: String)

Sources/MembraneRTC/Types/Endpoint.swift

+16-15
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,51 @@ public struct Endpoint: Codable {
22
public let id: String
33
public let type: String
44
public let metadata: Metadata
5-
public let trackIdToMetadata: [String: Metadata]?
5+
public let tracks: [String: TrackData]?
66

7-
public init(id: String, type: String, metadata: Metadata?, trackIdToMetadata: [String: Metadata]?) {
7+
public init(id: String, type: String, metadata: Metadata?, tracks: [String: TrackData]? = nil) {
88
self.id = id
99
self.type = type
1010
self.metadata = metadata ?? Metadata()
11-
self.trackIdToMetadata = trackIdToMetadata
11+
self.tracks = tracks
1212
}
1313

1414
public func with(
15-
id: String? = nil, type: String? = nil, metadata: Metadata? = nil, trackIdToMetadata: [String: Metadata]? = nil
15+
id: String? = nil, type: String? = nil, metadata: Metadata? = nil, tracks: [String: TrackData]? = nil
1616
) -> Self {
1717
return Endpoint(
1818
id: id ?? self.id,
1919
type: type ?? self.type,
2020
metadata: metadata ?? self.metadata,
21-
trackIdToMetadata: trackIdToMetadata ?? self.trackIdToMetadata
21+
tracks: tracks ?? self.tracks
2222
)
2323
}
2424

25-
public func withTrack(trackId: String, metadata: Metadata?) -> Self {
26-
var newTrackIdToMetadata = self.trackIdToMetadata
27-
newTrackIdToMetadata?[trackId] = metadata ?? Metadata()
25+
public func withTrack(trackId: String, metadata: Metadata?, simulcastConfig: SimulcastConfig?) -> Self {
26+
var newTracks = self.tracks
27+
let oldSimulcastConfig = newTracks?[trackId]?.simulcastConfig
28+
newTracks?[trackId] = TrackData(
29+
metadata: metadata ?? Metadata(), simulcastConfig: simulcastConfig ?? oldSimulcastConfig)
2830

29-
return Endpoint(id: self.id, type: self.type, metadata: self.metadata, trackIdToMetadata: newTrackIdToMetadata)
31+
return Endpoint(id: self.id, type: self.type, metadata: self.metadata, tracks: newTracks)
3032
}
3133

3234
public func withoutTrack(trackId: String) -> Self {
33-
var newTrackIdToMetadata = self.trackIdToMetadata
34-
newTrackIdToMetadata?.removeValue(forKey: trackId)
35+
var newTracks = self.tracks
36+
newTracks?.removeValue(forKey: trackId)
3537

36-
return Endpoint(id: self.id, type: self.type, metadata: self.metadata, trackIdToMetadata: newTrackIdToMetadata)
38+
return Endpoint(id: self.id, type: self.type, metadata: self.metadata, tracks: newTracks)
3739
}
3840

3941
enum CodingKeys: String, CodingKey {
40-
case id, type, metadata, trackIdToMetadata
42+
case id, type, metadata, tracks
4143
}
4244

4345
public init(from decoder: Decoder) throws {
4446
let container = try decoder.container(keyedBy: CodingKeys.self)
4547
self.id = try container.decode(String.self, forKey: .id)
4648
self.type = try container.decode(String.self, forKey: .type)
4749
self.metadata = try container.decodeIfPresent(Metadata.self, forKey: .metadata) ?? Metadata()
48-
self.trackIdToMetadata = try container.decodeIfPresent(
49-
[String: Metadata].self, forKey: .trackIdToMetadata)
50+
self.tracks = try container.decodeIfPresent([String: TrackData].self, forKey: .tracks)
5051
}
5152
}

Sources/MembraneRTC/Types/SimulcastConfig.swift

+28-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/// `"h"` - original encoding
33
/// `"m"` - original encoding scaled down by 2
44
/// `"l"` - original encoding scaled down by 4
5-
public enum TrackEncoding: Int, CustomStringConvertible {
5+
public enum TrackEncoding: Int, CustomStringConvertible, Codable {
66
case l = 0
77
case m
88
case h
@@ -15,6 +15,10 @@ public enum TrackEncoding: Int, CustomStringConvertible {
1515
}
1616
}
1717

18+
enum TrackEncodingCodingError: Error {
19+
case decoding(String)
20+
}
21+
1822
static func fromString(_ s: String) -> TrackEncoding? {
1923
switch s {
2024
case "l":
@@ -27,14 +31,36 @@ public enum TrackEncoding: Int, CustomStringConvertible {
2731
return nil
2832
}
2933
}
34+
35+
public init(from decoder: Decoder) throws {
36+
let container = try decoder.singleValueContainer()
37+
let encodingString = try container.decode(String.self)
38+
39+
switch encodingString {
40+
case "l":
41+
self = .l
42+
case "m":
43+
self = .m
44+
case "h":
45+
self = .h
46+
default:
47+
throw TrackEncodingCodingError.decoding("\(encodingString) is not a valid encoding")
48+
}
49+
}
50+
51+
public func encode(to encoder: Swift.Encoder) throws {
52+
var container = encoder.singleValueContainer()
53+
let encodingString = description
54+
try container.encode(encodingString)
55+
}
3056
}
3157

3258
/// Simulcast configuration.
3359
///
3460
/// At the moment, simulcast track is initialized in three versions - low, medium and high.
3561
/// High resolution is the original track resolution, while medium and low resolutions
3662
/// are the original track resolution scaled down by 2 and 4 respectively.
37-
public struct SimulcastConfig {
63+
public struct SimulcastConfig: Codable {
3864
/**
3965
* Whether to simulcast track or not.
4066
*/

Sources/MembraneRTC/Types/TrackContext.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public class TrackContext {
2424

2525
/// The reason of currently selected encoding. Only present for remote tracks.
2626
public private(set) var encodingReason: EncodingReason? = nil
27+
28+
/// Possible encodings that can be requested. Only present for remote tracks.
29+
public internal(set) var simulcastConfig: SimulcastConfig? = nil
2730

2831
internal func setEncoding(encoding: TrackEncoding, encodingReason: EncodingReason) {
2932
self.encoding = encoding
@@ -33,11 +36,12 @@ public class TrackContext {
3336
}
3437
}
3538

36-
init(track: RemoteTrack? = nil, enpoint: Endpoint, trackId: String, metadata: Metadata) {
39+
init(track: RemoteTrack? = nil, enpoint: Endpoint, trackId: String, metadata: Metadata, simulcastConfig: SimulcastConfig?) {
3740
self.track = track
3841
self.endpoint = enpoint
3942
self.trackId = trackId
4043
self.metadata = metadata
44+
self.simulcastConfig = simulcastConfig
4145
}
4246

4347
private var onTrackEncodingChangedListener: ((_ trackContext: TrackContext) -> Void)?
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
public struct TrackData: Codable{
2+
public let metadata: Metadata
3+
public let simulcastConfig: SimulcastConfig?
4+
5+
public init (metadata : Metadata, simulcastConfig : SimulcastConfig? = nil) {
6+
self.metadata = metadata
7+
self.simulcastConfig = simulcastConfig
8+
}
9+
10+
func copyWith(metadata: Metadata? = nil, simulcastConfig: SimulcastConfig? = nil) -> TrackData {
11+
return TrackData(
12+
metadata: metadata ?? self.metadata,
13+
simulcastConfig: simulcastConfig ?? self.simulcastConfig
14+
)
15+
}
16+
}

0 commit comments

Comments
 (0)