ethand91 / mediasoup-ios-client

Mediasoup 3 iOS Client
ISC License
131 stars 65 forks source link

Simulcast support? #69

Closed Rockjan closed 4 years ago

Rockjan commented 4 years ago

Hi, I don't know if there has a method like "[producer setSimulcastEnable:YES]" ?

If no, how can we implement Simulcast?

I really need a demo :)

Thanks.

Rockjan commented 4 years ago

I don’t know if my code is right (actually the app crashed......)

       NSMutableArray *codecs = [[NSMutableArray alloc] initWithCapacity:3];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:400000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:0]];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:1000000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:0]];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:1500000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:0]];

        NSString *str = [weakSelf stringFromDict:@{@"videoGoogleStartBitrate": @(1000)}];

        RTCVideoTrack *videoTrack = [capturer createVideoTrackWithPresentView:videoView];

       //Crashed at this line
        Producer *producer = [weakSelf.sendTransport produce:nil track:videoTrack encodings:codecs codecOptions:str];

Crash info : *** Terminating app due to uncaught exception 'RuntimeException', reason: 'error creating transceiver'

Rockjan commented 4 years ago

I don’t know if my code is right (actually the app crashed......)

       NSMutableArray *codecs = [[NSMutableArray alloc] initWithCapacity:3];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:400000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:0]];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:1000000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:0]];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:1500000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:0]];

        NSString *str = [weakSelf stringFromDict:@{@"videoGoogleStartBitrate": @(1000)}];

        RTCVideoTrack *videoTrack = [capturer createVideoTrackWithPresentView:videoView];

       //Crashed at this line
        Producer *producer = [weakSelf.sendTransport produce:nil track:videoTrack encodings:codecs codecOptions:str];

Crash info : *** Terminating app due to uncaught exception 'RuntimeException', reason: 'error creating transceiver'

Finally, I found the reason:

it should be: [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:400000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:4]]; [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:1000000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:2]]; [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:1500000 minBitrateBps:0 maxFramerate:60 numTemporalLayers:0 scaleResolutionDownBy:1]];

sivakumaraketi commented 4 years ago

Hi is Simulcast available please share example code.

Rockjan commented 4 years ago

Hi is Simulcast available please share example code.

Hi, just use the code below to create a producer, then simulcast will be open (maybe you should use your own parameters):

if ENABLE_SIMULCAST

        NSMutableArray *codecs = [[NSMutableArray alloc] initWithCapacity:3];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:400000 minBitrateBps:0 maxFramerate:15 numTemporalLayers:2 scaleResolutionDownBy:3]];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:550000 minBitrateBps:0 maxFramerate:20 numTemporalLayers:2 scaleResolutionDownBy:2]];
        [codecs addObject:[RTCUtils genRtpEncodingParameters:YES maxBitrateBps:1300000 minBitrateBps:0 maxFramerate:25 numTemporalLayers:2 scaleResolutionDownBy:1]];

        @try
        {
            RTCVideoTrack *videoTrack = [capturer createVideoTrackWithPresentView:videoView];
            producer = [weakSelf.sendTransport produce:nil track:videoTrack encodings:codecs codecOptions:nil];
        }
        @catch (NSException * e)
        {
            NSLog(@" - genVideoProducerWithCapturer Exception: %@", e);
        }

else

        RTCVideoTrack *videoTrack = [capturer createVideoTrackWithPresentView:videoView];
        producer = [weakSelf.sendTransport produce:nil track:videoTrack encodings:nil codecOptions:nil];

endif

sivakumaraketi commented 4 years ago

Than you very much, let me try

sivakumaraketi commented 4 years ago

sorry for asking extended help, If possible please give full sample code.

Rockjan commented 4 years ago

sorry for asking extended help, If possible please give full sample code.

Sorry, I can't offer you my full code because they are owned by my company.

Maybe you can have a look at example code offered by ethand91 : https://github.com/ethand91/mediasoup-ios-client-sample.

sivakumaraketi commented 4 years ago

Thanks bro for your quick response, I am already done with 1 to 1 it's working fine, I am facing issue only with multicast, If possible please help me how to handle multicast, I already added above code you mentioned it stoping display video.

Rockjan commented 4 years ago

No difference between 1v1 and 1vN, just join the same room. The code I show you is to enable simulcast, it's already supported by mediasoup. I dont know what happend to your code, maybe you can post you code to us and then we could help you.

sivakumaraketi commented 4 years ago

Thanks for your response, Here it is not possible to share full code, Please give me your mail id i will send you full code below provided roomclient and mainviewcontroller code please check Below code related to roomClient

import Foundation import SwiftyJSON

protocol SendTransportHandlerDelegate: class { func sendSocketConnectionStatus(connectionStatus: String) }

public enum RoomError : Error { case DEVICE_NOT_LOADED case SEND_TRANSPORT_NOT_CREATED case RECV_TRANSPORT_NOT_CREATED case DEVICE_CANNOT_PRODUCE_VIDEO case DEVICE_CANNOT_PRODUCE_AUDIO case PRODUCER_NOT_FOUND case CONSUMER_NOT_FOUND }

final internal class RoomClient : NSObject {

private static let STATS_INTERVAL_MS: NSInteger = 3000

private let socket: EchoSocket
private let roomId: String
private let mediaCapturer: MediaCapturer
private var producers: [String : Producer]
private var consumers: [String : Consumer]
private var consumersInfo: [JSON]
private let device: MediasoupDevice

private var joined: Bool
private var sendTransport: SendTransport?
private var recvTransport: RecvTransport?

private var sendTransportHandler: SendTransportHandler?
private var recvTransportHandler: RecvTransportHandler?
private var producerHandler: ProducerHandler?
private var consumerHandler: ConsumerHandler?

private var roomListener: RoomListener?

public init(socket: EchoSocket, device: MediasoupDevice, roomId: String, roomListener: RoomListener) {
    self.socket = socket
    self.device = device
    self.roomId = roomId
    self.roomListener = roomListener

    self.mediaCapturer = MediaCapturer.shared
    self.producers = [String : Producer]()
    self.consumers = [String : Consumer]()
    self.consumersInfo = [JSON]()
    self.joined = false

    super.init()
}

func join() throws {
    // Check if the device is loaded
    if !self.device.isLoaded() {
        throw RoomError.DEVICE_NOT_LOADED
    }

    // if the user is already joined do nothing
    if self.joined {
        return
    }

    _ = Request.shared.sendLoginRoomRequest(socket: self.socket, roomId: self.roomId, deviceRtpCapabilities: self.device.getRtpCapabilities())
    self.joined = true

    print("join() join success")
}

func createSendTransport() {
    // Do nothing if send transport is already created
    if (self.sendTransport != nil) {
        print("createSendTransport() send transport is already created...")
        return
    }

    self.createWebRtcTransport(direction: "send")
    print("createSendTransport() send transport created")
}

func createRecvTransport() {
    // Do nothing if recv transport is already created
    if (self.recvTransport != nil) {
        print("createRecvTransport() recv transport is already created...")
        return
    }

    self.createWebRtcTransport(direction: "recv")
    print("createRecvTransport() recv transport created")
}

func switchCamera() {
    self.mediaCapturer.switchCamera()
}

func produceVideo(videoView: RTCEAGLVideoView) throws -> RTCVideoTrack? {
    if self.sendTransport == nil {
        print("trasnport nil")
        throw RoomError.SEND_TRANSPORT_NOT_CREATED
    }

    if !self.device.canProduce("video") {
        print("cannot produce")
        throw RoomError.DEVICE_CANNOT_PRODUCE_VIDEO
    }

     let codecOptions: JSON = [
                   "videoGoogleStartBitrate": 1000
                ]

    var videoTrack: RTCVideoTrack
    var producer: Producer

    do {

        //  Converted to Swift 5.3 by Swiftify v5.3.29902 - https://swiftify.com/
        #if ENABLE_SIMULCAST

        var encodings = [AnyHashable](repeating: 0, count: 3)
        encodings.append(RTCUtils.genRtpEncodingParameters(true, maxBitrateBps: 400000, minBitrateBps: 0, maxFramerate: 15, numTemporalLayers: 2, scaleResolutionDownBy: 3))
        encodings.append(RTCUtils.genRtpEncodingParameters(true, maxBitrateBps: 550000, minBitrateBps: 0, maxFramerate: 20, numTemporalLayers: 2, scaleResolutionDownBy: 2))
        encodings.append(RTCUtils.genRtpEncodingParameters(true, maxBitrateBps: 1300000, minBitrateBps: 0, maxFramerate: 25, numTemporalLayers: 2, scaleResolutionDownBy: 1))

        do {
            videoTrack = try mediaCapturer.createVideoTrack(videoView: videoView)
            producer =  sendTransport?.produce(nil, track: videoTrack, encodings: encodings, codecOptions: nil)

        } catch {
            print(" - genVideoProducerWithCapturer Exception")
        }
        #else
        videoTrack = try mediaCapturer.createVideoTrack(videoView: videoView)
        producer = (sendTransport?.produce(nil, track: videoTrack, encodings: nil, codecOptions: nil))!
        //producer = self.createProducer(track: videoTrack, codecOptions: codecOptions.description, encodings: nil)

        #endif
}
     return videoTrack
}

func produceAudio() throws {
    if self.sendTransport == nil {
        throw RoomError.SEND_TRANSPORT_NOT_CREATED
    }

    if !self.device.canProduce("audio") {
        throw RoomError.DEVICE_CANNOT_PRODUCE_AUDIO
    }

    let audioTrack: RTCAudioTrack = self.mediaCapturer.createAudioTrack()
    self.createProducer(track: audioTrack, codecOptions: nil, encodings: nil)
}

func pauseLocalVideo() throws {
    print("pauseLocalVideo()")
    let producer: Producer = try self.getProducerByKind(kind: "video")
    print("producervideo:\(producer)")
    producer.pause()

}

func resumeLocalVideo() throws {
    print("resumeLocalVideo()")
    let producer: Producer = try self.getProducerByKind(kind: "video")
    print("resumeproducervideo:\(producer)")
    producer.resume()
    //Request.shared.sendResumeProducerRequest(socket: self.socket, roomId: self.roomId, producerId: producer.getId())
}

func pauseLocalAudio() throws {
    print("pauseLocalAudio()")
    let producer: Producer = try self.getProducerByKind(kind: "audio")
    Request.shared.sendPauseProducerRequest(socket: self.socket, roomId: self.roomId, producerId: producer.getId())
}

func resumeLocalAudio() throws {
    print("resumeLocalAudio()")
    let producer: Producer = try self.getProducerByKind(kind: "audio")
    Request.shared.sendResumeProducerRequest(socket: self.socket, roomId: self.roomId, producerId: producer.getId())
}
var countVideo = 0
var countAudio = 0

func consumeTrack(consumerInfo: JSON) {
    if (self.recvTransport == nil) {
        // User has not yet created a transport for receiving so temporarily store it
        // and play it when the recv transport is created
        self.consumersInfo.append(consumerInfo)
        return
    }

    let kind: String = consumerInfo["kind"].stringValue

    // if already consuming type of track remove it, TODO support multiple remotes?
    for consumer in self.consumers.values {
        if consumer.getKind() == kind {
            print("consumeTrack() removing consumer kind=" + kind)
            self.consumers.removeValue(forKey: consumer.getId())
        }
    }

    var producerId = ""
    print("ppp:\(consumerInfo)")

    let id: String = consumerInfo["id"].stringValue
    producerId = consumerInfo["producerId"].stringValue
    if producerId == "" {
              producerId = consumerInfo["data"]["id"].stringValue

          }
    print("producerIddd:\(producerId)")

    let rtpParameters: JSON = consumerInfo["rtpParameters"]
    print("consumeTrack() rtpParameters " + rtpParameters.description)

    self.consumerHandler = ConsumerHandler.init()
    self.consumerHandler!.delegate = self.consumerHandler

    let kindConsumer: Consumer = self.recvTransport!.consume(self.consumerHandler!.delegate!, id: id, producerId: producerId, kind: kind, rtpParameters: rtpParameters.description)
    self.consumers[kindConsumer.getId()] = kindConsumer

    print("consumeTrack() consuming id =" + kindConsumer.getId())

        let peers = consumerInfo["peers"]
 self.roomListener?.onNewConsumer(consumer: kindConsumer)

}
func consumeTrack1(consumerInfo: JSON) {
    if (self.recvTransport == nil) {
        // User has not yet created a transport for receiving so temporarily store it
        // and play it when the recv transport is created
        self.consumersInfo.append(consumerInfo)
        return
    }

    let kind: String = consumerInfo["kind"].stringValue

    // if already consuming type of track remove it, TODO support multiple remotes?
    for consumer in self.consumers.values {
        if consumer.getKind() == kind {
            print("consumeTrack() removing consumer kind=" + kind)
            self.consumers.removeValue(forKey: consumer.getId())
        }
    }

    var producerId = ""
    print("ppp:\(consumerInfo)")

    let id: String = consumerInfo["id"].stringValue
    producerId = consumerInfo["producerId"].stringValue
    if producerId == "" {
              producerId = consumerInfo["data"]["id"].stringValue

          }
    print("producerIddd:\(producerId)")
   /* if (countVideo > 0 && countAudio > 0) {
        return
    } else if (countVideo > 0 && countAudio == 0) {
        if (kind == "video") {
            return
        }
    } else if (countAudio > 0 && countVideo == 0) {
        if (kind == "audio") {
            return
        }
    }
    if (kind == "video") {
        countVideo = 1
    }
    if (kind == "audio") {
        countAudio = 1
    }*/

    let rtpParameters: JSON = consumerInfo["rtpParameters"]
    print("consumeTrack() rtpParameters " + rtpParameters.description)

    self.consumerHandler = ConsumerHandler.init()
    self.consumerHandler!.delegate = self.consumerHandler

    let kindConsumer: Consumer = self.recvTransport!.consume(self.consumerHandler!.delegate!, id: id, producerId: producerId, kind: kind, rtpParameters: rtpParameters.description)
    self.consumers[kindConsumer.getId()] = kindConsumer

    print("consumeTrack() consuming id =" + kindConsumer.getId())

    self.roomListener?.onNewConsumer1(consumer: kindConsumer)
}

func consumeCurrentLayers(consumerInfo: JSON) throws {
  self.consumerHandler = ConsumerHandler.init()
           self.consumerHandler!.delegate = self.consumerHandler

let consumerId = consumerInfo["data"]["consumerId"].stringValue
    let consumer: Consumer = try self.getConsumerByKind(kind: "video")
          self.consumers[consumerId] = consumer
    print("consumeTrack() consuming id1 =" + consumer.getId())
    self.roomListener?.onNewConsumer1(consumer: consumer)
}

func pauseRemoteVideo() throws {
    let consumer: Consumer = try self.getConsumerByKind(kind: "video")
    consumer.pause()

    //Request.shared.sendPauseConsumerRequest(socket: self.socket, roomId: self.roomId, consumerId: consumer.getId())
}
func removeRemoteVideo() throws {
    let consumer: Consumer = try self.getConsumerByKind(kind: "video")
    //consumer.remove()

    //Request.shared.sendPauseConsumerRequest(socket: self.socket, roomId: self.roomId, consumerId: consumer.getId())
}
func addRemoteVideo(json:  JSON) throws {
    let consumer: Consumer = try self.getConsumerByKind(kind: "video")

    let peerId = json["peerId"].stringValue
     self.consumers[peerId] = consumer
    self.roomListener?.onNewConsumer1(consumer: consumer)
     print("peerId:\(peerId)")

    //Request.shared.sendPauseConsumerRequest(socket: self.socket, roomId: self.roomId, consumerId: consumer.getId())
}

func resumeRemoteVideo() throws {
    let consumer: Consumer = try self.getConsumerByKind(kind: "video")
    consumer.resume()

    print("consumerId1:\(consumer.getId())")
    Request.shared.sendResumeConsumerRequest(socket: self.socket, roomId: self.roomId, consumerId: consumer.getId())
}
func resumeRemoteVideo1() throws {
    let consumer: Consumer = try self.getConsumerByKind(kind: "video")
    consumer.resume()
    print("consumerId2:\(consumer.getId())")
    Request.shared.sendResumeConsumerRequest(socket: self.socket, roomId: self.roomId, consumerId: consumer.getId())
}

func pauseRemoteAudio() throws {
    let consumer: Consumer = try self.getConsumerByKind(kind: "audio")
    Request.shared.sendPauseConsumerRequest(socket: self.socket, roomId: self.roomId, consumerId: consumer.getId())
}

func resumeRemoteAudio() throws {
    let consumer: Consumer = try self.getConsumerByKind(kind: "audio")
    Request.shared.sendResumeConsumerRequest(socket: self.socket, roomId: self.roomId, consumerId: consumer.getId())
}

private func createWebRtcTransport(direction: String) {
    let response: JSON = Request.shared.sendCreateWebRtcTransportRequest(socket: self.socket, roomId: self.roomId, direction: direction)
    print("createWebRtcTransport() response = " + response.description)

    let webRtcTransportData: JSON = response["data"]

    let id: String = webRtcTransportData["id"].stringValue
    let iceParameters: JSON = webRtcTransportData["iceParameters"]
    let iceCandidatesArray: JSON = webRtcTransportData["iceCandidates"]
    let dtlsParameters: JSON = webRtcTransportData["dtlsParameters"]

    switch direction {
    case "send":
        self.sendTransportHandler = SendTransportHandler.init(parent: self)
        self.sendTransportHandler!.delegate = self.sendTransportHandler!
        self.sendTransport = self.device.createSendTransport(self.sendTransportHandler!.delegate!, id: id, iceParameters: iceParameters.description, iceCandidates: iceCandidatesArray.description, dtlsParameters: dtlsParameters.description)
        break
    case "recv":
        self.recvTransportHandler = RecvTransportHandler.init(parent: self)
        self.recvTransportHandler!.delegate = self.recvTransportHandler!
        self.recvTransport = self.device.createRecvTransport(self.recvTransportHandler!.delegate!, id: id, iceParameters: iceParameters.description, iceCandidates: iceCandidatesArray.description, dtlsParameters: dtlsParameters.description)

        // Play consumers that have been stored
        for consumerInfo in self.consumersInfo {
            print("consumerInfofina:\(consumerInfo)")
            self.consumeTrack(consumerInfo: consumerInfo)
        }
        break
    default:
        print("createWebRtcTransport() invalid direction " + direction)
    }
}

private func createProducer(track: RTCMediaStreamTrack, codecOptions: String?, encodings: Array<RTCRtpEncodingParameters>?) {
    self.producerHandler = ProducerHandler.init()
    self.producerHandler!.delegate = self.producerHandler!

    let kindProducer: Producer = self.sendTransport!.produce(self.producerHandler!.delegate!, track: track, encodings: encodings, codecOptions: codecOptions)
    self.producers[kindProducer.getId()] = kindProducer

    print("createProducer() created id =" + kindProducer.getId() + " kind =" + kindProducer.getKind())
}

private func handleLocalTransportConnectEvent(transport: Transport, dtlsParameters: String) {
    print("handleLocalTransportConnectEvent() id =" + transport.getId())

    Request.shared.sendConnectWebRtcTransportRequest(socket: self.socket, roomId: self.roomId, transportId: transport.getId(), dtlsParameters: dtlsParameters)
}

private func handleLocalTransportProduceEvent(transport: Transport, kind: String, rtpParameters: String, appData: String) -> String {
    print("handleLocalTransportProduceEvent() id =" + transport.getId() + " kind = " + kind)
    var producerId: String = ""
    let transportProduceResponse: JSON = Request.shared.sendProduceWebRtcTransportRequest(socket: self.socket, roomId: self.roomId, transportId: transport.getId(), kind: kind, rtpParameters: rtpParameters)
    print("transportProduceResponse:\(transportProduceResponse)--data:\(transportProduceResponse["producerId"].stringValue)--data1:\(transportProduceResponse["data"]["id"].stringValue)")
    producerId = transportProduceResponse["producerId"].stringValue
    if producerId == "" {
        producerId = transportProduceResponse["data"]["id"].stringValue
    }

    print("producerId:\(producerId)")
    return producerId
}

private func getProducerByKind(kind: String) throws -> Producer {
    print("kind:\(producers.values)")

    for producer in self.producers.values {

        print("kindproducer:\(producer.getKind())--\(kind)")
        if producer.getKind() == kind {
            return producer
        }
    }

    throw RoomError.PRODUCER_NOT_FOUND
}

private func getConsumerByKind(kind: String) throws -> Consumer {
    for consumer in self.consumers.values {
        if consumer.getKind() == kind {
            return consumer
        }
    }

    throw RoomError.CONSUMER_NOT_FOUND
}

// Class to handle send transport listener events
private class SendTransportHandler : NSObject, SendTransportListener {
    fileprivate weak var delegate: SendTransportListener?
    private var parent: RoomClient
    weak var socketDelegate: SendTransportHandlerDelegate?

    init(parent: RoomClient) {
        self.parent = parent
    }

    func onConnect(_ transport: Transport!, dtlsParameters: String!) {
        print("SendTransport::onConnect dtlsParameters = " + dtlsParameters)
        self.parent.handleLocalTransportConnectEvent(transport: transport, dtlsParameters: dtlsParameters)
    }

    func onConnectionStateChange(_ transport: Transport!, connectionState: String!) {
        print("SendTransport::onConnectionStateChange connectionState = " + connectionState)
        if connectionState == "disconnected" {
            socketDelegate?.sendSocketConnectionStatus(connectionStatus: connectionState)
        }

    }

    func onProduce(_ transport: Transport!, kind: String!, rtpParameters: String!, appData: String!, callback: ((String?) -> Void)!) {
        let producerId = self.parent.handleLocalTransportProduceEvent(transport: transport, kind: kind, rtpParameters: rtpParameters, appData: appData)

        callback(producerId)
    }
}

// Class to handle recv transport listener events
private class RecvTransportHandler : NSObject, RecvTransportListener {
    fileprivate weak var delegate: RecvTransportListener?
    private var parent: RoomClient

    init(parent: RoomClient) {
        self.parent = parent
    }

    func onConnect(_ transport: Transport!, dtlsParameters: String!) {
        print("RecvTransport::onConnect")
        self.parent.handleLocalTransportConnectEvent(transport: transport, dtlsParameters: dtlsParameters)
    }

    func onConnectionStateChange(_ transport: Transport!, connectionState: String!) {
        print("RecvTransport::onConnectionStateChange newState = " + connectionState)
    }
}

// Class to handle producer listener events
private class ProducerHandler : NSObject, ProducerListener {
    fileprivate weak var delegate: ProducerListener?

    func onTransportClose(_ producer: Producer!) {
        print("Producer::onTransportClose")
    }
}

// Class to handle consumer listener events
private class ConsumerHandler : NSObject, ConsumerListener {
    fileprivate weak var delegate: ConsumerListener?

    func onTransportClose(_ consumer: Consumer!) {
        print("Consumer::onTransportClose")
    }
}

}

videoVC controller code

extension VideoCallVC : MessageObserver { func on(event: String, data: JSON?) {

    switch event {

    case ActionEvent.OPEN:
        print("socket connected")
        self.handleWebSocketConnected()
        break
    case ActionEvent.NEW_USER:
        print("NEW_USER id =" + data!["userId"]["userId"].stringValue)
        break
    case ActionEvent.NEW_DATA_CONSUMER:
        print("NEW_CONSUMER1 data=" + data!.description)
       // self.handleNewConsumerEvent(consumerInfo: data!["data"])

        break
    case ActionEvent.NEW_CONSUMER:
       // isRemoteVideo = true
        print("NEW_CONSUMER data=" + data!.description)
       // self.handleNewConsumerEvent(consumerInfo: data!["data"])
        isRemoteVideo = true
                   self.handleNewConsumerEvent(consumerInfo: data!["data"])

        break
        case "newPeer":
               print("NEW_Peer data=" + data!.description)
            addRemoteVideo(json: data!["data"])
              // pauseLocalStream()
               break
        case "peerClosed":
          print("NEW_Peer data=" + data!.description)
       let peerId  =  data!["id"]

         // pauseLocalStream()
          break

    case ActionEvent.CLOSED_CONSUMER:
        print("CLOSED_CONSUMER data=" + data!.description)
       // isRemoteVideoPaused = true
        pauseRemoteVideo()
        /*DispatchQueue.main.async {
            self.viewRemoteCamera.isHidden = true
            self.viewRemoteCamera.backgroundColor = .black
            self.labelWaitingParticipants.isHidden = false
            self.labelWaitingParticipants.text = "Remote video paused..."
        }*/
    case ActionEvent.CONSUMER_LAYER_CHANGED:
        print("CONSUMER_LAYER_CHANGED data=" + data!.description)

// if data!["data"]["spatialLayer"] > 1 { // addRemoteVideo(json: data!["data"]) // }

// print(data!["data"]["spatialLayer"]) // if data!["data"]["spatialLayer"] >= 1 { // let consumer = Consumer() // let videoTrack = RTCVideoTrack.self as! RTCVideoTrack // videoTrack.isEnabled = true // videoTrack.add(self.videoRemoteCamera1) // }

// do { // try self.handleVideoConsumerEvent(consumerInfo: data!["data"]) // // } // catch { // print("failed to create video track") // }

    case ActionEvent.PAUSE_CONSUMER:
         print("PAUSE_CONSUMER data=" + data!.description)
    case ActionEvent.PAUSE_PRODUCER:
        print("PAUSE_PRODUCER data=" + data!.description)
    case ActionEvent.RESUME_PRODUCER:
        print("RESUME_PRODUCER data=" + data!.description)
    case ActionEvent.RESUME_CONSUMER:
        print("RESUME_CONSUMER data=" + data!.description)
        DispatchQueue.main.async {
                     //  self.viewRemoteCamera.isHidden = false
                       self.resumeRemoteVideo()
                   }
    case "activeSpeaker":
        break
    default:
        print("Unknown event " + event)
    }
}

private func handleNewConsumerEvent(consumerInfo: JSON) {
    print("handleNewConsumerEvent info = " + consumerInfo.description)
    // Start consuming
    self.client!.consumeTrack(consumerInfo: consumerInfo)
}
private func handleVideoConsumerEvent(consumerInfo: JSON) throws {
       print("handleVideoConsumerEvent info = " + consumerInfo.description)
       // Start consuming
   try! self.client!.consumeTrack1(consumerInfo: consumerInfo)
   }

}

// Extension for RoomListener extension VideoCallVC : RoomListener { func onNewConsumer1(consumer: Consumer) { print("RoomListener::onNewConsumer kind1=" + consumer.getKind()) print(consumer.getTrack())

    if consumer.getKind() == "video" {
        let videoTrack: RTCVideoTrack = consumer.getTrack() as! RTCVideoTrack
        videoTrack.isEnabled = true
        if isRemoteVideo == true {
          /*  DispatchQueue.main.async {
                videoTrack.remove(self.imageViewOwnCamera)
                self.imageViewOwnCamera.isHidden = false
                self.labelWaitingParticipants.isHidden = true
                _ = try! self.client!.produceVideo(videoView: self.imageViewOwnCamera)
            }*/

        }

        videoTrack.add(self.videoRemoteCamera1)

    }

    do {

        consumer.getKind() == "video"
            ? try self.client!.resumeRemoteVideo1()
            : try self.client!.resumeRemoteAudio()
    } catch {
        print("onNewConsumer() failed to resume remote track")
    }
}

func onNewConsumer(consumer: Consumer) {
    print("RoomListener::onNewConsumer kind=" + consumer.getKind())
    print(consumer.getTrack())

    if consumer.getKind() == "video" {
        let videoTrack: RTCVideoTrack = consumer.getTrack() as! RTCVideoTrack
        videoTrack.isEnabled = true
        if isRemoteVideo == true {
          /*  DispatchQueue.main.async {
                videoTrack.remove(self.imageViewOwnCamera)
                self.imageViewOwnCamera.isHidden = false
                self.labelWaitingParticipants.isHidden = true
                _ = try! self.client!.produceVideo(videoView: self.imageViewOwnCamera)
            }*/

        }
        print("consId:\(consumer.getId())")

        videoTrack.add(self.viewRemoteCamera)

    }

    do {

        consumer.getKind() == "video"
            ? try self.client!.resumeRemoteVideo()
            : try self.client!.resumeRemoteAudio()
    } catch {
        print("onNewConsumer() failed to resume remote track")
    }
}

}

sivakumaraketi commented 4 years ago

I am taking from this https://github.com/ethand91/mediasoup-ios-client-sample for new peer added case "newPeer": isRemoteVideo = true self.handleNewConsumerEvent(consumerInfo: data!["data"])

          break

and added for video added like below extension VideoCallVC : RoomListener { func onNewConsumer1(consumer: Consumer) { print("RoomListener::onNewConsumer kind1=" + consumer.getKind()) print(consumer.getTrack())
if consumer.getKind() == "video" { let videoTrack: RTCVideoTrack = consumer.getTrack() as! RTCVideoTrack videoTrack.isEnabled = true

        videoTrack.add(self.videoRemoteCamera1)

    }

    do {

        consumer.getKind() == "video"
            ? try self.client!.resumeRemoteVideo1()
            : try self.client!.resumeRemoteAudio()
    } catch {
        print("onNewConsumer() failed to resume remote track")
    }
}

func onNewConsumer(consumer: Consumer) {
    print("RoomListener::onNewConsumer kind=" + consumer.getKind())
    print(consumer.getTrack())

    if consumer.getKind() == "video" {
        let videoTrack: RTCVideoTrack = consumer.getTrack() as! RTCVideoTrack
        videoTrack.isEnabled = true

        print("consId:\(consumer.getId())")

        videoTrack.add(self.viewRemoteCamera)

    }

    do {

        consumer.getKind() == "video"
            ? try self.client!.resumeRemoteVideo()
            : try self.client!.resumeRemoteAudio()
    } catch {
        print("onNewConsumer() failed to resume remote track")
    }
}

}

   for remotevideo1 videoRemoteCamera and remotevideo2 videoRemoteCamera1
sivakumaraketi commented 4 years ago

any updates bro

sivakumaraketi commented 4 years ago

Please tell me my mistake bro for simulcast, thanks in advance