Unable to show Participant video on Host device

Dear Team,

I am able to display the host video on the participant’s device. But not able to display participant video on the host device. Could you please suggest how to handle participant videos?

I have implemented the below code in MobileRTCMeetingState.inMeeting: state for the local user video.

guard let localUserID = MobileRTC.shared().getMeetingService()?.myselfUserID() else { return }

**self** .showHostVideo(videoView: **self** .participantVideoView!, withUserId: localUserID)



 func showAttendeeVideo(videoView: MobileRTCVideoView, withUserId userID: UInt) {
           
        
            videoView.showAttendeeVideo(withUserID: userID)
    
        guard let ms = MobileRTC.shared().getMeetingService() else {return}
            let size: CGSize = (ms.getUserVideoSize(userID))

            if __CGSizeEqualToSize(size, .zero) {
                return
            }
        
            videoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
        }

================

func showActiveUserVideo(videoView: MobileRTCVideoView, withUserId userID: UInt) {
           
            videoView.showAttendeeVideo(withUserID: userID)
    
        guard let ms = MobileRTC.shared().getMeetingService() else {return}
            let size: CGSize = (ms.getUserVideoSize(userID))

            if __CGSizeEqualToSize(size, .zero) {
                return
            }
            videoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
        }


func onInitMeetingView() {
  self.participantVideoView = MobileRTCVideoView(frame: **self** .mySelfUserView.bounds)
  self.participantVideoView?.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
  self.mySelfUserView.addSubview( **self** .participantVideoView!)
  self.activevideoView = MobileRTCActiveVideoView(frame: **self** .baseView.bounds)
  self.activevideoView?.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
  self.baseView.addSubview( **self** .activevideoView!)
}
    
    func onDestroyMeetingView() {
        self.activevideoView?.removeFromSuperview()
        self.participantVideoView?.removeFromSuperview()
    }

func onSinkMeetingVideoStatusChange(_ userID: UInt) {
        
        self.showHostVideo(videoView: self.participantVideoView!, withUserId: userID)

    }

Hey @srikanth-chetu,

Thanks for using the dev forum!

Can you also provide your code for the showHostVideo method?

Thanks!
Michael

Hi Michael,

Here is the code. I have incorrectly mentioned the function name as showActiveUserVideo instead of showHostVideo. Sorry for this.

func showHostVideo(videoView: MobileRTCVideoView, withUserId userID: UInt)
{

            videoView.showAttendeeVideo(withUserID: userID)

        guard let ms = MobileRTC.shared().getMeetingService() else {return}
            let size: CGSize = (ms.getUserVideoSize(userID))

            if __CGSizeEqualToSize(size, .zero) {
                return
            }
            videoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
        }

Hey @srikanth-chetu,

I see that you are using MobileRTCActiveVideoView. This view is a MobileRTCVideoView, but is only used for showing the active speaker’s video, which is normally the person who is currently talking. If you wish to show a specific user’s video you should use MobileRTCVideoView instead.

The other thing that might be happening is some issue with the UIView layouts. I see that you add one view to myselfUserView and another view to baseView. If you switch these, does the situation change at all? If so, it is likely a problem with the layout of the views.

When you call showAttendeeVideo what is returned?

Thanks!
Michael

Hi Michael,

Thanks for the replay. Please find my implemented code below.

  • The person who is making a call(Host) will get the zoom meeting id, password, and zak details through our internal API.

  • The participant will get only zoom meeting id and password.

So I am maintaining the host status and added a condition to join the meeting for host and participants as per below.

if isHost == true {
self.joinMeeting(meetingNumber: String(meetingNum), meetingPassword: meetingPass, meetingZak: meetingZak)
}else {
self.joinMeeting(meetingNumber: String(meetingNum), meetingPassword: meetingPass)
}

  • With the below code, I am able to show the Host (who is joining with meeting id, password, and zak) video on the participant device. But we are unable to display the participant video (who is joining with meeting id and password) on the Host device.

  • Please find the screenshot below. The Host video is displaying on the participant’s screen, but the participant’s video is not displaying on the host device and as well as own device. By default, the participant video is not working.

  • Here I have used the below video views to display the videos.

var participantVideoView: MobileRTCVideoView? → Used for Collection view
var activevideoView: MobileRTCVideoView? → Used for Full screen view
var myVideoViw: MobileRTCVideoView? → Used for self video (Right side top)

  • Could you check and help us on this.

Host Screen

Participant Screen

import UIKit
import MobileRTC

class MultiCallVC: UIViewController {
    
    var participantVideoView: MobileRTCVideoView?
    var activevideoView: MobileRTCVideoView?
    var myVideoViw: MobileRTCVideoView?
    
    @IBOutlet var baseView:UIView!
    @IBOutlet var mySelfUserView:UIView!
    
    var memberUserIdList: [Any] = []
    var participantsUserIdList:[UInt] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.JointMeeting()
    }
}

extension MultiCallVC {
    
    
    func JointMeeting(){
        
        if let meetingInfo = startBCData?.payload["extra"] as? [String:Any] {
            let meetingNum = meetingInfo["meeting_id"] as? Int ?? 0
            let meetingPass = meetingInfo["password"] as? String ?? ""
            let meetingZak = meetingInfo["zak"] as? String ?? ""
            
            if isHost == true {
                self.joinMeeting(meetingNumber: String(meetingNum), meetingPassword: meetingPass, meetingZak: meetingZak)
            }else {
                self.joinMeeting(meetingNumber: String(meetingNum), meetingPassword: meetingPass)
            }
        }
    }
    
    func joinMeeting(meetingNumber: String, meetingPassword: String, meetingZak: String? = "") {
        MobileRTC.shared().getMeetingSettings()?.setMuteAudioWhenJoinMeeting(false)
        MobileRTC.shared().getMeetingSettings()?.enableCustomMeeting = true
        MobileRTC.shared().getMeetingSettings()?.meetingVideoHidden = false
        if let meetingService = MobileRTC.shared().getMeetingService() {
            
            meetingService.delegate = self
            meetingService.customizedUImeetingDelegate = self
            let joinMeetingParameters = MobileRTCMeetingJoinParam()
            joinMeetingParameters.meetingNumber = meetingNumber
            joinMeetingParameters.password = meetingPassword
            joinMeetingParameters.zak = meetingZak
            meetingService.joinMeeting(with: joinMeetingParameters)
            
        }
    }
    
}

extension MultiCallVC: MobileRTCMeetingServiceDelegate {
    
    func onMeetingStateChange(_ state: MobileRTCMeetingState) {
        
        print("Current meeting state: \(state)")
        
        switch state {
        case MobileRTCMeetingState.connecting:
            print("Meeting state: Connected")
            break
        case MobileRTCMeetingState.failed:
            print("Meeting state: Failed")
            break
        case MobileRTCMeetingState.inMeeting:
            print("Meeting state: inMeeting")
            
            guard let localUserID = MobileRTC.shared().getMeetingService()?.myselfUserID() else { return }
            self.showLocalVideo(videoView: self.myVideoViw!.self, withUserId: localUserID)
            
            break
        case MobileRTCMeetingState.inWaitingRoom:
            print("Meeting state: inWaitingRoom")
            break
        case MobileRTCMeetingState.unknow:
            print("Meeting state: unknow")
            break
        case MobileRTCMeetingState.locked:
            print("Meeting state: locked")
            break
        case MobileRTCMeetingState.idle:
            print("Meeting state: idle")
            break
        case MobileRTCMeetingState.ended:
            print("Meeting state: ended")
            self.mySelfUserView.isHidden = true
            break
        case MobileRTCMeetingState.waitingForHost:
            print("Meeting state: waitingForHost")
            break
        default:
            print("Meeting state: Other")
            break
        }
    }
    //Meeting Ended
    func onMeetingEndedReason(_ reason: MobileRTCMeetingEndReason) {
        
        navigationController?.popToViewController(ofClass: LandingVC.self)
    }
}

extension MultiCallVC: MobileRTCCustomizedUIMeetingDelegate {
    
    func showAttendeeVideo(videoView: MobileRTCVideoView, withUserId userID: UInt) {
        
        videoView.showAttendeeVideo(withUserID: userID)
        guard let ms = MobileRTC.shared().getMeetingService() else {return}
        let size: CGSize = (ms.getUserVideoSize(userID))
        
        if __CGSizeEqualToSize(size, .zero) {
            return
        }
        videoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
    }
    
    func showLocalVideo(videoView: MobileRTCVideoView, withUserId userID: UInt) {
        
        videoView.showAttendeeVideo(withUserID: userID)
        
        guard let ms = MobileRTC.shared().getMeetingService() else {return}
        let size: CGSize = (ms.getUserVideoSize(userID))
        
        if __CGSizeEqualToSize(size, .zero) {
            return
        }
        videoView.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
    }
    
    func onInitMeetingView() {
        
        self.myVideoViw = MobileRTCVideoView(frame: self.mySelfUserView.bounds)
        self.myVideoViw?.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
        self.mySelfUserView.addSubview(self.myVideoViw!)
        
        self.activevideoView = MobileRTCVideoView(frame: self.baseView.bounds)
        self.activevideoView?.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
        self.baseView.addSubview(self.activevideoView!)
    }
    
    func onDestroyMeetingView() {
        self.activevideoView?.removeFromSuperview()
        self.participantVideoView?.removeFromSuperview()
        self.myVideoViw?.removeFromSuperview()
    }
}

extension MultiCallVC: MobileRTCVideoServiceDelegate {
    
    func onSinkMeetingActiveVideo(_ userID: UInt) {
        
        showAttendeeVideo(videoView: self.activevideoView!, withUserId: userID)
        
    }
    
    func onSinkMeetingVideoStatusChange(_ userID: UInt, videoStatus: MobileRTC_VideoStatus) {
        
        memberUserIdList = MobileRTC.shared().getMeetingService()?.getInMeetingUserList()! as! [Any]
        memberUserIdList.forEach { (id) in
            
            participantsUserIdList.append(id as! UInt)
        }
        multiCallCollectionView.superview?.bringSubviewToFront(multiCallCollectionView)
        
        multiCallCollectionView.reloadData()
    }

}

extension MultiCallVC: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        let uniqueValues = unique(source: participantsUserIdList)
        return uniqueValues.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MultiCallCell.identifierForPhone, for: indexPath) as? MultiCallCell else {fatalError()}
            
            self.participantVideoView = MobileRTCVideoView(frame: cell.baseView.bounds)
            self.participantVideoView?.setVideoAspect(MobileRTCVideoAspect_PanAndScan)
            cell.baseView.addSubview(self.participantVideoView!)
            
            let uniqueValues = unique(source: participantsUserIdList)
            
            self.showAttendeeVideo(videoView: self.participantVideoView!, withUserId: uniqueValues[indexPath.row] as! UInt)

            return cell
    
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if UIDevice.current.userInterfaceIdiom == .phone {
            return CGSize(width: 120, height: 140)
        }else {
            return CGSize(width: 150, height: 230)
        }
    }
    
    func unique<S : Sequence, T : Hashable>(source: S) -> [T] where S.Iterator.Element == T {
        var buffer = [T]()
        var added = Set<T>()
        for elem in source {
            if !added.contains(elem) {
                buffer.append(elem)
                added.insert(elem)
            }
        }
        return buffer
    }
}

Hi @Michael_Condon

Could you please update me on this?

Regards,
Srikanth

Hey @srikanth-chetu,

Sorry for the delay, I will run through this today.

Thanks!
Michael

@srikanth-chetu, on the participant device when you call showAttendeeVideo for the user that is the host, what does the method return?

@Michael_Condon It is returning participantVideoView and activevideoView.

Hey @srikanth-chetu,

Sorry I mean the SDK interface showAttendeeVideo, it should return a Bool.

Thanks!
Michael

Hi @Michael_Condon ,

Sorry for the delay in response. It is returning Bool value as true.

Please suggest.

Hey @srikanth-chetu,

I see. So that means that the sdk is reporting that all went well. I would double check to make sure that the videoview in question is fitting into the correct spot in your view hierarchy by using the viewDebugger.

Thanks!
Michael

Noted @Michael_Condon , if possible prioritize it.

@srikanth-chetu, sounds good. Let us know how else we can assist.

Thanks!
Michael

Hi @Michael_Condon ,

How to unmute participant video by default?

And how to handle the video on/off functionality in custom UI, could you please share the code snippet in swift language.

Thanks,
Srikanth

Hey @srikanth-chetu,

You would use the iOS API: MobileRTCMeetingSettings Class Reference interface:

MobileRTC.shared()?.getMeetingSettings.muteVideoWhenJoinMeeting = false

Thanks!
Michael

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.