Skip to content

Commit

Permalink
Merge pull request #179 from dolbyio-samples/bugfix/rts-viewer-tv-n-ios
Browse files Browse the repository at this point in the history
Update to use 1.7.0 Millicast SDK on iOS and tvOS apps
  • Loading branch information
aravind-raveendran authored Feb 13, 2024
2 parents a392fad + 7dba83b commit 7e5188b
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 60 deletions.
4 changes: 2 additions & 2 deletions rts-viewer-ios/LocalPackages/RTSComponentKit/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(url: "https://github.com/millicast/millicast-sdk-swift-package", from: "1.5.0"),
.package(url: "https://github.com/DolbyIO/rts-uikit-ios", from: "0.0.4")
.package(url: "https://github.com/millicast/millicast-sdk-swift-package", exact: "1.7.0"),
.package(url: "https://github.com/DolbyIO/rts-uikit-ios", exact: "0.0.4")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public protocol SubscriptionManagerDelegate: AnyObject {
func onStreamInactive()
func onStreamStopped()
func onConnectionError(reason: String)
func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [MCLayerData]?)
func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [String]?)
}

public protocol SubscriptionManagerProtocol: AnyObject {
Expand Down Expand Up @@ -176,32 +176,36 @@ private extension SubscriptionManager {

extension SubscriptionManager: MCSubscriberListener {

public func onDisconnected() {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onDisconnected()")
}

public func onSubscribed() {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onSubscribed()")
delegate?.onSubscribed()
}

public func onSubscribedError(_ reason: String!) {
public func onSubscribedError(_ reason: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onSubscribedError(_ reason:)")
delegate?.onSubscribedError(reason)
}

public func onVideoTrack(_ track: MCVideoTrack!, withMid mid: String!) {
public func onVideoTrack(_ track: MCVideoTrack, withMid mid: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onVideoTrack(_ mid:)")
delegate?.onVideoTrack(track, withMid: mid)
}

public func onAudioTrack(_ track: MCAudioTrack!, withMid mid: String!) {
public func onAudioTrack(_ track: MCAudioTrack, withMid mid: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onAudioTrack(_ mid:)")
delegate?.onAudioTrack(track, withMid: mid)
}

public func onActive(_ streamId: String!, tracks: [String]!, sourceId: String!) {
public func onActive(_ streamId: String, tracks: [String], sourceId: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onActive(_ streamId:tracks:sourceId:)")
delegate?.onStreamActive()
}

public func onInactive(_ streamId: String!, sourceId: String!) {
public func onInactive(_ streamId: String, sourceId: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onInactive(_ streamId:sourceId:)")
delegate?.onStreamInactive()
}
Expand All @@ -211,11 +215,11 @@ extension SubscriptionManager: MCSubscriberListener {
delegate?.onStreamStopped()
}

public func onVad(_ mid: String!, sourceId: String!) {
public func onVad(_ mid: String, sourceId: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onVad(_ mid:sourceId:)")
}

public func onLayers(_ mid: String!, activeLayers: [MCLayerData]!, inactiveLayers: [MCLayerData]!) {
public func onLayers(_ mid: String, activeLayers: [MCLayerData], inactiveLayers: [String]) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onLayers(_ mid:activeLayers:inactiveLayers:)")
delegate?.onStreamLayers(mid, activeLayers: activeLayers, inactiveLayers: inactiveLayers)
}
Expand All @@ -225,16 +229,16 @@ extension SubscriptionManager: MCSubscriberListener {
delegate?.onConnected()
}

public func onConnectionError(_ status: Int32, withReason reason: String!) {
public func onConnectionError(_ status: Int32, withReason reason: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onConnectionError(_ status:withReason:)")
delegate?.onConnectionError(reason: reason)
}

public func onSignalingError(_ message: String!) {
public func onSignalingError(_ message: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onSignalingError(_ message:)")
}

public func onStatsReport(_ report: MCStatsReport!) {
public func onStatsReport(_ report: MCStatsReport) {
delegate?.onStatsReport(report: report)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,35 @@ extension RTSDataStore: SubscriptionManagerDelegate {
updateState(to: .error(.connectError(reason: reason)))
}

public func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [MCLayerData]?) {
public func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [String]?) {
Task {
await MainActor.run {
layerActiveMap = activeLayers?.filter { layer in
// For H.264 there are no temporal layers and the id is set to 255. For VP8 use the first temporal layer.
return layer.temporalLayerId == 0 || layer.temporalLayerId == 255
var layersForSelection: [MCLayerData] = []

// Simulcast active layers
if let simulcastLayers = activeLayers?.filter({ !$0.encodingId.isEmpty }), !simulcastLayers.isEmpty {
// Select the max (best) temporal layer Id from a specific encodingId
let dictionaryOfLayersMatchingEncodingId = Dictionary(grouping: simulcastLayers, by: { $0.encodingId })
dictionaryOfLayersMatchingEncodingId.forEach { (_: String, layers: [MCLayerData]) in
// Picking the layer matching the max temporal layer id - represents the layer with the best FPS
if let layerWithBestFrameRate = layers.first(where: { $0.temporalLayerId == $0.maxTemporalLayerId }) ?? layers.last {
layersForSelection.append(layerWithBestFrameRate)
}
}
layersForSelection.sort(by: >)
}
// Using SVC layer selection logic
else if let simulcastLayers = activeLayers?.filter({ $0.spatialLayerId != nil }) {
let dictionaryOfLayersMatchingSpatialLayerId = Dictionary(grouping: simulcastLayers, by: { $0.spatialLayerId! })
dictionaryOfLayersMatchingSpatialLayerId.forEach { (_: NSNumber, layers: [MCLayerData]) in
// Picking the layer matching the max temporal layer id - represents the layer with the best FPS
if let layerWithBestFrameRate = layers.first(where: { $0.spatialLayerId == $0.maxSpatialLayerId }) ?? layers.last {
layersForSelection.append(layerWithBestFrameRate)
}
}
}

layerActiveMap = layersForSelection
activeStreamType.removeAll()

switch layerActiveMap?.count {
Expand Down Expand Up @@ -341,3 +362,14 @@ extension RTSDataStore: SubscriptionManagerDelegate {
return codecStats.mime_type as String
}
}

extension MCLayerData: Comparable {
public static func < (lhs: MCLayerData, rhs: MCLayerData) -> Bool {
switch (lhs.encodingId.lowercased(), rhs.encodingId.lowercased()) {
case ("h", "m"), ("l", "m"), ("h", "s"), ("l", "s"), ("m", "s"):
return false
default:
return true
}
}
}
9 changes: 0 additions & 9 deletions rts-viewer-ios/RTSViewer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,6 @@
);
mainGroup = 3FE90C0F26B2AF4200B206A3;
packageReferences = (
E8575E9729527B420070F53E /* XCRemoteSwiftPackageReference "millicast-sdk-swift-package" */,
B63736D32A3958BD0004C4EF /* XCRemoteSwiftPackageReference "rts-uikit-ios" */,
);
productRefGroup = 3FE90C1926B2AF4200B206A3 /* Products */;
Expand Down Expand Up @@ -862,14 +861,6 @@
version = 0.0.4;
};
};
E8575E9729527B420070F53E /* XCRemoteSwiftPackageReference "millicast-sdk-swift-package" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/millicast/millicast-sdk-swift-package";
requirement = {
kind = exactVersion;
version = 1.5.0;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/millicast/millicast-sdk-swift-package",
"state" : {
"revision" : "f5e0abd63564f591d4fef0ab82d9e0cdee858579",
"version" : "1.5.0"
"revision" : "001f8654ba31461ecf805ae8a15e4d92efa8064e",
"version" : "1.7.0"
}
},
{
Expand Down
4 changes: 2 additions & 2 deletions rts-viewer-tvos/LocalPackages/RTSComponentKit/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(url: "https://github.com/millicast/millicast-sdk-swift-package", from: "1.5.0"),
.package(url: "https://github.com/DolbyIO/rts-uikit-ios", branch: "0.0.4")
.package(url: "https://github.com/millicast/millicast-sdk-swift-package", from: "1.7.0"),
.package(url: "https://github.com/DolbyIO/rts-uikit-ios", exact: "0.0.4")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public protocol SubscriptionManagerDelegate: AnyObject {
func onStreamInactive()
func onStreamStopped()
func onConnectionError(reason: String)
func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [MCLayerData]?)
func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [String]?)
}

public protocol SubscriptionManagerProtocol: AnyObject {
Expand Down Expand Up @@ -175,33 +175,36 @@ private extension SubscriptionManager {
}

extension SubscriptionManager: MCSubscriberListener {
public func onDisconnected() {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onDisconnected()")
}

public func onSubscribed() {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onSubscribed()")
delegate?.onSubscribed()
}

public func onSubscribedError(_ reason: String!) {
public func onSubscribedError(_ reason: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onSubscribedError(_ reason:)")
delegate?.onSubscribedError(reason)
}

public func onVideoTrack(_ track: MCVideoTrack!, withMid mid: String!) {
public func onVideoTrack(_ track: MCVideoTrack, withMid mid: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onVideoTrack(_ mid:)")
delegate?.onVideoTrack(track, withMid: mid)
}

public func onAudioTrack(_ track: MCAudioTrack!, withMid mid: String!) {
public func onAudioTrack(_ track: MCAudioTrack, withMid mid: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onAudioTrack(_ mid:)")
delegate?.onAudioTrack(track, withMid: mid)
}

public func onActive(_ streamId: String!, tracks: [String]!, sourceId: String!) {
public func onActive(_ streamId: String, tracks: [String], sourceId: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onActive(_ streamId:tracks:sourceId:)")
delegate?.onStreamActive()
}

public func onInactive(_ streamId: String!, sourceId: String!) {
public func onInactive(_ streamId: String, sourceId: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onInactive(_ streamId:sourceId:)")
delegate?.onStreamInactive()
}
Expand All @@ -211,11 +214,11 @@ extension SubscriptionManager: MCSubscriberListener {
delegate?.onStreamStopped()
}

public func onVad(_ mid: String!, sourceId: String!) {
public func onVad(_ mid: String, sourceId: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onVad(_ mid:sourceId:)")
}

public func onLayers(_ mid: String!, activeLayers: [MCLayerData]!, inactiveLayers: [MCLayerData]!) {
public func onLayers(_ mid: String, activeLayers: [MCLayerData], inactiveLayers: [String]) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onLayers(_ mid:activeLayers:inactiveLayers:)")
delegate?.onStreamLayers(mid, activeLayers: activeLayers, inactiveLayers: inactiveLayers)
}
Expand All @@ -225,16 +228,16 @@ extension SubscriptionManager: MCSubscriberListener {
delegate?.onConnected()
}

public func onConnectionError(_ status: Int32, withReason reason: String!) {
public func onConnectionError(_ status: Int32, withReason reason: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onConnectionError(_ status:withReason:)")
delegate?.onConnectionError(reason: reason)
}

public func onSignalingError(_ message: String!) {
public func onSignalingError(_ message: String) {
Self.logger.debug("Delegate - \(MCSubscriberListener.self) - onSignalingError(_ message:)")
}

public func onStatsReport(_ report: MCStatsReport!) {
public func onStatsReport(_ report: MCStatsReport) {
delegate?.onStatsReport(report: report)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,35 @@ extension RTSDataStore: SubscriptionManagerDelegate {
updateState(to: .error(.connectError(reason: reason)))
}

public func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [MCLayerData]?) {
public func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [String]?) {
Task {
await MainActor.run {
layerActiveMap = activeLayers?.filter { layer in
// For H.264 there are no temporal layers and the id is set to 255. For VP8 use the first temporal layer.
return layer.temporalLayerId == 0 || layer.temporalLayerId == 255
var layersForSelection: [MCLayerData] = []

// Simulcast active layers
if let simulcastLayers = activeLayers?.filter({ !$0.encodingId.isEmpty }), !simulcastLayers.isEmpty {
// Select the max (best) temporal layer Id from a specific encodingId
let dictionaryOfLayersMatchingEncodingId = Dictionary(grouping: simulcastLayers, by: { $0.encodingId })
dictionaryOfLayersMatchingEncodingId.forEach { (_: String, layers: [MCLayerData]) in
// Picking the layer matching the max temporal layer id - represents the layer with the best FPS
if let layerWithBestFrameRate = layers.first(where: { $0.temporalLayerId == $0.maxTemporalLayerId }) ?? layers.last {
layersForSelection.append(layerWithBestFrameRate)
}
}
layersForSelection.sort(by: >)
}
// Using SVC layer selection logic
else if let simulcastLayers = activeLayers?.filter({ $0.spatialLayerId != nil }) {
let dictionaryOfLayersMatchingSpatialLayerId = Dictionary(grouping: simulcastLayers, by: { $0.spatialLayerId! })
dictionaryOfLayersMatchingSpatialLayerId.forEach { (_: NSNumber, layers: [MCLayerData]) in
// Picking the layer matching the max temporal layer id - represents the layer with the best FPS
if let layerWithBestFrameRate = layers.first(where: { $0.spatialLayerId == $0.maxSpatialLayerId }) ?? layers.last {
layersForSelection.append(layerWithBestFrameRate)
}
}
}

layerActiveMap = layersForSelection

activeStreamType.removeAll()

Expand Down Expand Up @@ -341,3 +363,14 @@ extension RTSDataStore: SubscriptionManagerDelegate {
return codecStats.mime_type as String
}
}

extension MCLayerData: Comparable {
public static func < (lhs: MCLayerData, rhs: MCLayerData) -> Bool {
switch (lhs.encodingId.lowercased(), rhs.encodingId.lowercased()) {
case ("h", "m"), ("l", "m"), ("h", "s"), ("l", "s"), ("m", "s"):
return false
default:
return true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Foundation
import MillicastSDK

final class MockSubscriptionManagerDelegate: SubscriptionManagerDelegate {

enum Event {
case onSubscribed
case onSubscribedError(reason: String)
Expand All @@ -19,7 +20,7 @@ final class MockSubscriptionManagerDelegate: SubscriptionManagerDelegate {
case onStreamInactive
case onStreamStopped
case onConnectionError(reason: String)
case onStreamLayers(mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [MCLayerData]?)
case onStreamLayers(mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [String]?)
}

private(set) var events: [Event] = []
Expand Down Expand Up @@ -64,7 +65,7 @@ final class MockSubscriptionManagerDelegate: SubscriptionManagerDelegate {
events.append(.onConnectionError(reason: reason))
}

func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [MCLayerData]?) {
func onStreamLayers(_ mid: String?, activeLayers: [MCLayerData]?, inactiveLayers: [String]?) {
events.append(.onStreamLayers(mid: mid, activeLayers: activeLayers, inactiveLayers: inactiveLayers))
}
}
9 changes: 0 additions & 9 deletions rts-viewer-tvos/RTSViewer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,6 @@
);
mainGroup = 3FE90C0F26B2AF4200B206A3;
packageReferences = (
E8575E9729527B420070F53E /* XCRemoteSwiftPackageReference "millicast-sdk-swift-package" */,
B63736D32A3958BD0004C4EF /* XCRemoteSwiftPackageReference "rts-uikit-ios" */,
);
productRefGroup = 3FE90C1926B2AF4200B206A3 /* Products */;
Expand Down Expand Up @@ -1216,14 +1215,6 @@
version = 0.0.4;
};
};
E8575E9729527B420070F53E /* XCRemoteSwiftPackageReference "millicast-sdk-swift-package" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/millicast/millicast-sdk-swift-package";
requirement = {
kind = exactVersion;
version = 1.5.0;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand Down
Loading

0 comments on commit 7e5188b

Please sign in to comment.