@@ -53,19 +53,37 @@ class LiveStreamingEntry : UIViewController
53
53
}
54
54
55
55
class LiveStreamingMain : BaseViewController {
56
- var localVideo = Bundle . loadView ( fromNib: " VideoView " , withType: VideoView . self)
57
- var remoteVideo = Bundle . loadView ( fromNib: " VideoView " , withType: VideoView . self)
58
- @IBOutlet weak var localVideoContainer : UIView !
59
- @IBOutlet weak var remoteVideoContainer : UIView !
56
+ var foregroundVideo = Bundle . loadView ( fromNib: " VideoView " , withType: VideoView . self)
57
+ var backgroundVideo = Bundle . loadView ( fromNib: " VideoView " , withType: VideoView . self)
58
+ @IBOutlet weak var foregroundVideoContainer : UIView !
59
+ @IBOutlet weak var backgroundVideoContainer : UIView !
60
+ @IBOutlet weak var clientRoleToggleView : UIView !
61
+ @IBOutlet weak var ultraLowLatencyToggleView : UIView !
60
62
@IBOutlet weak var clientRoleToggle : UISwitch !
61
63
@IBOutlet weak var ultraLowLatencyToggle : UISwitch !
64
+ var remoteUid : UInt ? {
65
+ didSet {
66
+ foregroundVideoContainer. isHidden = !( role == . broadcaster && remoteUid != nil )
67
+ }
68
+ }
62
69
var agoraKit : AgoraRtcEngineKit !
63
70
var role : AgoraClientRole = . broadcaster {
64
71
didSet {
65
- localVideoContainer . isHidden = role != . broadcaster
72
+ foregroundVideoContainer . isHidden = ! ( role == . broadcaster && remoteUid != nil )
66
73
ultraLowLatencyToggle. isEnabled = role == . audience
67
74
}
68
75
}
76
+ var isLocalVideoForeground = false {
77
+ didSet {
78
+ if isLocalVideoForeground {
79
+ foregroundVideo. setPlaceholder ( text: " Local Host " . localized)
80
+ backgroundVideo. setPlaceholder ( text: " Remote Host " . localized)
81
+ } else {
82
+ foregroundVideo. setPlaceholder ( text: " Remote Host " . localized)
83
+ backgroundVideo. setPlaceholder ( text: " Local Host " . localized)
84
+ }
85
+ }
86
+ }
69
87
var isUltraLowLatencyOn : Bool = false
70
88
71
89
// indicate if current instance has joined channel
@@ -75,12 +93,10 @@ class LiveStreamingMain: BaseViewController {
75
93
super. viewDidLoad ( )
76
94
77
95
// layout render view
78
- localVideoContainer. addSubview ( localVideo)
79
- remoteVideoContainer. addSubview ( remoteVideo)
80
- localVideo. setPlaceholder ( text: " Local Host " . localized)
81
- localVideo. bindFrameToSuperviewBounds ( )
82
- remoteVideo. setPlaceholder ( text: " Remote Host " . localized)
83
- remoteVideo. bindFrameToSuperviewBounds ( )
96
+ foregroundVideoContainer. addSubview ( foregroundVideo)
97
+ backgroundVideoContainer. addSubview ( backgroundVideo)
98
+ foregroundVideo. bindFrameToSuperviewBounds ( )
99
+ backgroundVideo. bindFrameToSuperviewBounds ( )
84
100
85
101
// set up agora instance when view loadedlet config = AgoraRtcEngineConfig()
86
102
let config = AgoraRtcEngineConfig ( )
@@ -92,6 +108,12 @@ class LiveStreamingMain: BaseViewController {
92
108
guard let channelName = configs [ " channelName " ] as? String ,
93
109
let role = configs [ " role " ] as? AgoraClientRole else { return }
94
110
111
+ // for audience put local video in foreground
112
+ isLocalVideoForeground = role == . audience
113
+ // if inital role is broadcaster, do not show audience options
114
+ clientRoleToggleView. isHidden = role == . broadcaster
115
+ ultraLowLatencyToggleView. isHidden = role == . broadcaster
116
+
95
117
// make this room live broadcasting room
96
118
agoraKit. setChannelProfile ( . liveBroadcasting)
97
119
updateClientRole ( role)
@@ -108,7 +130,7 @@ class LiveStreamingMain: BaseViewController {
108
130
// 2. If app certificate is turned on at dashboard, token is needed
109
131
// when joining channel. The channel name and uid used to calculate
110
132
// the token has to match the ones used for channel join
111
- let result = agoraKit. joinChannel ( byToken: nil , channelId: channelName, info: nil , uid: SCREEN_SHARE_BROADCASTER_UID ) { [ unowned self] ( channel, uid, elapsed) -> Void in
133
+ let result = agoraKit. joinChannel ( byToken: nil , channelId: channelName, info: nil , uid: 0 ) { [ unowned self] ( channel, uid, elapsed) -> Void in
112
134
self . isJoined = true
113
135
LogUtils . log ( message: " Join \( channel) with uid \( uid) elapsed \( elapsed) ms " , level: . info)
114
136
}
@@ -138,7 +160,7 @@ class LiveStreamingMain: BaseViewController {
138
160
let videoCanvas = AgoraRtcVideoCanvas ( )
139
161
videoCanvas. uid = 0
140
162
// the view to be binded
141
- videoCanvas. view = localVideo . videoView
163
+ videoCanvas. view = localVideoCanvas ( )
142
164
videoCanvas. renderMode = . hidden
143
165
agoraKit. setupLocalVideo ( videoCanvas)
144
166
@@ -159,6 +181,33 @@ class LiveStreamingMain: BaseViewController {
159
181
agoraKit. setClientRole ( . audience, options: options)
160
182
}
161
183
184
+ func localVideoCanvas( ) -> UIView {
185
+ return isLocalVideoForeground ? foregroundVideo. videoView : backgroundVideo. videoView
186
+ }
187
+
188
+ func remoteVideoCanvas( ) -> UIView {
189
+ return isLocalVideoForeground ? backgroundVideo. videoView : foregroundVideo. videoView
190
+ }
191
+
192
+ @IBAction func onTapForegroundVideo( _ sender: UIGestureRecognizer ) {
193
+ isLocalVideoForeground = !isLocalVideoForeground
194
+
195
+ let localVideoCanvas = AgoraRtcVideoCanvas ( )
196
+ localVideoCanvas. uid = 0
197
+ localVideoCanvas. renderMode = . hidden
198
+ localVideoCanvas. view = self . localVideoCanvas ( )
199
+
200
+ let remoteVideoCanvas = AgoraRtcVideoCanvas ( )
201
+ remoteVideoCanvas. renderMode = . hidden
202
+ remoteVideoCanvas. view = self . remoteVideoCanvas ( )
203
+
204
+ agoraKit. setupLocalVideo ( localVideoCanvas)
205
+ if let uid = remoteUid {
206
+ remoteVideoCanvas. uid = uid
207
+ agoraKit. setupRemoteVideo ( remoteVideoCanvas)
208
+ }
209
+ }
210
+
162
211
@IBAction func onToggleClientRole( _ sender: UISwitch ) {
163
212
let role : AgoraClientRole = sender. isOn ? . broadcaster : . audience
164
213
updateClientRole ( role)
@@ -227,13 +276,16 @@ extension LiveStreamingMain: AgoraRtcEngineDelegate {
227
276
func rtcEngine( _ engine: AgoraRtcEngineKit , didJoinedOfUid uid: UInt , elapsed: Int ) {
228
277
LogUtils . log ( message: " remote user join: \( uid) \( elapsed) ms " , level: . info)
229
278
279
+ //record remote uid
280
+ remoteUid = uid
281
+
230
282
// Only one remote video view is available for this
231
283
// tutorial. Here we check if there exists a surface
232
284
// view tagged as this uid.
233
285
let videoCanvas = AgoraRtcVideoCanvas ( )
234
286
videoCanvas. uid = uid
235
287
// the view to be binded
236
- videoCanvas. view = remoteVideo . videoView
288
+ videoCanvas. view = remoteVideoCanvas ( )
237
289
videoCanvas. renderMode = . hidden
238
290
agoraKit. setupRemoteVideo ( videoCanvas)
239
291
}
@@ -245,6 +297,11 @@ extension LiveStreamingMain: AgoraRtcEngineDelegate {
245
297
func rtcEngine( _ engine: AgoraRtcEngineKit , didOfflineOfUid uid: UInt , reason: AgoraUserOfflineReason ) {
246
298
LogUtils . log ( message: " remote user left: \( uid) reason \( reason) " , level: . info)
247
299
300
+ //clear remote uid
301
+ if ( remoteUid == uid) {
302
+ remoteUid = nil
303
+ }
304
+
248
305
// to unlink your view from sdk, so that your view reference will be released
249
306
// note the video will stay at its last frame, to completely remove it
250
307
// you will need to remove the EAGL sublayer from your binded view
0 commit comments