99import UIKit
1010import AgoraRtcKit
1111import AGEVideoLayout
12- import SimpleAudioFilter
12+ import SimpleFilter
1313
14- class SimpleAudioFilterEntry : UIViewController
14+ class SimpleFilterEntry : UIViewController
1515{
1616 @IBOutlet weak var joinButton : AGButton !
1717 @IBOutlet weak var channelTextField : AGTextField !
18- let identifier = " SimpleAudioFilter "
18+ let identifier = " SimpleFilter "
1919
2020 override func viewDidLoad( ) {
2121 super. viewDidLoad ( )
@@ -36,12 +36,14 @@ class SimpleAudioFilterEntry : UIViewController
3636
3737}
3838
39- class SimpleAudioFilterMain : BaseViewController {
39+ class SimpleFilterMain : BaseViewController {
4040
4141 var agoraKit : AgoraRtcEngineKit !
4242 @IBOutlet weak var container : AGEVideoContainer !
43- var audioViews : [ UInt : VideoView ] = [ : ]
44- let FILTER_NAME = " VolumeChange "
43+ var localVideo = Bundle . loadVideoView ( type: . local, audioOnly: false )
44+ var remoteVideo = Bundle . loadVideoView ( type: . remote, audioOnly: false )
45+ let AUDIO_FILTER_NAME = " VolumeChange "
46+ let VIDEO_FILTER_NAME = " Watermark "
4547
4648 // indicate if current instance has joined channel
4749 var isJoined : Bool = false
@@ -51,6 +53,10 @@ class SimpleAudioFilterMain: BaseViewController {
5153
5254 guard let channelName = configs [ " channelName " ] as? String
5355 else { return }
56+ // layout render view
57+ localVideo. setPlaceholder ( text: " Local Host " . localized)
58+ remoteVideo. setPlaceholder ( text: " Remote Host " . localized)
59+ container. layoutStream ( views: [ localVideo, remoteVideo] )
5460
5561 // set up agora instance when view loaded
5662 let config = AgoraRtcEngineConfig ( )
@@ -61,38 +67,46 @@ class SimpleAudioFilterMain: BaseViewController {
6167 config. audioScenario = . default
6268
6369 // set audio filter extension
64- config. mediaFilterExtensions = [ SimpleAudioFilterManager ( ) ]
70+ config. mediaFilterExtensions = [ SimpleFilterManager ( ) ]
6571 config. eventDelegate = self
6672
6773 agoraKit = AgoraRtcEngineKit . sharedEngine ( with: config, delegate: self )
6874
69- agoraKit. enableExtension ( withVendor: SimpleAudioFilterManager . vendorName ( ) , extension: FILTER_NAME, enabled: true )
75+ agoraKit. enableExtension ( withVendor: SimpleFilterManager . vendorName ( ) , extension: VIDEO_FILTER_NAME, enabled: true )
76+ agoraKit. enableExtension ( withVendor: SimpleFilterManager . vendorName ( ) , extension: AUDIO_FILTER_NAME, enabled: true )
7077
7178 agoraKit. setLogFile ( LogUtils . sdkLogPath ( ) )
7279
7380 // make myself a broadcaster
7481 agoraKit. setClientRole ( . broadcaster)
7582
7683 // disable video module
77- agoraKit. disableVideo ( )
84+ agoraKit. enableVideo ( )
85+
86+ // set up local video to render your local camera preview
87+ let videoCanvas = AgoraRtcVideoCanvas ( )
88+ videoCanvas. uid = 0
89+ // the view to be binded
90+ videoCanvas. view = localVideo. videoView
91+ videoCanvas. renderMode = . hidden
92+ agoraKit. setupLocalVideo ( videoCanvas)
93+ // you have to call startPreview to see local video
94+ agoraKit. startPreview ( )
7895
7996 // set audio profile
8097 agoraKit. setAudioProfile ( . default)
8198
8299 // Set audio route to speaker
83100 agoraKit. setDefaultAudioRouteToSpeakerphone ( true )
84101
85- // enable volume indicator
86- // agoraKit.enableAudioVolumeIndication(200, smooth: 3)
87-
88102 // start joining channel
89103 // 1. Users can only see each other after they join the
90104 // same channel successfully using the same app id.
91105 // 2. If app certificate is turned on at dashboard, token is needed
92106 // when joining channel. The channel name and uid used to calculate
93107 // the token has to match the ones used for channel join
94108 let option = AgoraRtcChannelMediaOptions ( )
95- option. publishCameraTrack = . of( false )
109+ option. publishCameraTrack = . of( true )
96110 option. clientRoleType = . of( ( Int32) ( AgoraClientRole . broadcaster. rawValue) )
97111
98112 let result = agoraKit. joinChannel ( byToken: KeyCenter . Token, channelId: channelName, uid: 0 , mediaOptions: option)
@@ -116,19 +130,15 @@ class SimpleAudioFilterMain: BaseViewController {
116130 }
117131 }
118132
119- func sortedViews( ) -> [ VideoView ] {
120- return Array ( audioViews. values) . sorted ( by: { $0. uid < $1. uid } )
121- }
122-
123133 @IBAction func onChangeRecordingVolume( _ sender: UISlider ) {
124134 let value : Int = Int ( sender. value)
125135 print ( " adjustRecordingSignalVolume \( value) " )
126- agoraKit. setExtensionPropertyWithVendor ( SimpleAudioFilterManager . vendorName ( ) , extension: FILTER_NAME , key: " volume " , value: String ( value) )
136+ agoraKit. setExtensionPropertyWithVendor ( SimpleFilterManager . vendorName ( ) , extension: AUDIO_FILTER_NAME , key: " volume " , value: String ( value) )
127137 }
128138}
129139
130140/// agora rtc engine delegate events
131- extension SimpleAudioFilterMain : AgoraRtcEngineDelegate {
141+ extension SimpleFilterMain : AgoraRtcEngineDelegate {
132142 /// callback when warning occured for agora sdk, warning can usually be ignored, still it's nice to check out
133143 /// what is happening
134144 /// Warning code description can be found at:
@@ -153,27 +163,23 @@ extension SimpleAudioFilterMain: AgoraRtcEngineDelegate {
153163 func rtcEngine( _ engine: AgoraRtcEngineKit , didJoinChannel channel: String , withUid uid: UInt , elapsed: Int ) {
154164 self . isJoined = true
155165 LogUtils . log ( message: " Join \( channel) with uid \( uid) elapsed \( elapsed) ms " , level: . info)
156-
157- //set up local audio view, this view will not show video but just a placeholder
158- let view = Bundle . loadVideoView ( type: . local, audioOnly: true )
159- self . audioViews [ 0 ] = view
160- view. setPlaceholder ( text: self . getAudioLabel ( uid: uid, isLocal: true ) )
161- self . container. layoutStream3x2 ( views: self . sortedViews ( ) )
162166 }
163167
164168 /// callback when a remote user is joinning the channel, note audience in live broadcast mode will NOT trigger this event
165169 /// @param uid uid of remote joined user
166170 /// @param elapsed time elapse since current sdk instance join the channel in ms
167171 func rtcEngine( _ engine: AgoraRtcEngineKit , didJoinedOfUid uid: UInt , elapsed: Int ) {
168172 LogUtils . log ( message: " remote user join: \( uid) \( elapsed) ms " , level: . info)
169-
170- //set up remote audio view, this view will not show video but just a placeholder
171- let view = Bundle . loadVideoView ( type: . remote, audioOnly: true )
172- view. uid = uid
173- self . audioViews [ uid] = view
174- view. setPlaceholder ( text: self . getAudioLabel ( uid: uid, isLocal: false ) )
175- self . container. layoutStream3x2 ( views: sortedViews ( ) )
176- self . container. reload ( level: 0 , animated: true )
173+
174+ // Only one remote video view is available for this
175+ // tutorial. Here we check if there exists a surface
176+ // view tagged as this uid.
177+ let videoCanvas = AgoraRtcVideoCanvas ( )
178+ videoCanvas. uid = uid
179+ // the view to be binded
180+ videoCanvas. view = remoteVideo. videoView
181+ videoCanvas. renderMode = . hidden
182+ agoraKit. setupRemoteVideo ( videoCanvas)
177183 }
178184
179185 /// callback when a remote user is leaving the channel, note audience in live broadcast mode will NOT trigger this event
@@ -183,10 +189,15 @@ extension SimpleAudioFilterMain: AgoraRtcEngineDelegate {
183189 func rtcEngine( _ engine: AgoraRtcEngineKit , didOfflineOfUid uid: UInt , reason: AgoraUserOfflineReason ) {
184190 LogUtils . log ( message: " remote user left: \( uid) reason \( reason) " , level: . info)
185191
186- //remove remote audio view
187- self . audioViews. removeValue ( forKey: uid)
188- self . container. layoutStream3x2 ( views: sortedViews ( ) )
189- self . container. reload ( level: 0 , animated: true )
192+ // to unlink your view from sdk, so that your view reference will be released
193+ // note the video will stay at its last frame, to completely remove it
194+ // you will need to remove the EAGL sublayer from your binded view
195+ let videoCanvas = AgoraRtcVideoCanvas ( )
196+ videoCanvas. uid = uid
197+ // the view to be binded
198+ videoCanvas. view = nil
199+ videoCanvas. renderMode = . hidden
200+ agoraKit. setupRemoteVideo ( videoCanvas)
190201 }
191202
192203 /// Reports which users are speaking, the speakers' volumes, and whether the local user is speaking.
@@ -203,23 +214,35 @@ extension SimpleAudioFilterMain: AgoraRtcEngineDelegate {
203214 /// Reports the statistics of the current call. The SDK triggers this callback once every two seconds after the user joins the channel.
204215 /// @param stats stats struct
205216 func rtcEngine( _ engine: AgoraRtcEngineKit , reportRtcStats stats: AgoraChannelStats ) {
206- audioViews [ 0 ] ? . statsInfo? . updateChannelStats ( stats)
217+ localVideo. statsInfo? . updateChannelStats ( stats)
218+ }
219+
220+ /// Reports the statistics of the uploading local video streams once every two seconds.
221+ /// @param stats stats struct
222+ func rtcEngine( _ engine: AgoraRtcEngineKit , localVideoStats stats: AgoraRtcLocalVideoStats ) {
223+ localVideo. statsInfo? . updateLocalVideoStats ( stats)
207224 }
208225
209226 /// Reports the statistics of the uploading local audio streams once every two seconds.
210227 /// @param stats stats struct
211228 func rtcEngine( _ engine: AgoraRtcEngineKit , localAudioStats stats: AgoraRtcLocalAudioStats ) {
212- audioViews [ 0 ] ? . statsInfo? . updateLocalAudioStats ( stats)
229+ localVideo. statsInfo? . updateLocalAudioStats ( stats)
230+ }
231+
232+ /// Reports the statistics of the video stream from each remote user/host.
233+ /// @param stats stats struct
234+ func rtcEngine( _ engine: AgoraRtcEngineKit , remoteVideoStats stats: AgoraRtcRemoteVideoStats ) {
235+ remoteVideo. statsInfo? . updateVideoStats ( stats)
213236 }
214237
215238 /// Reports the statistics of the audio stream from each remote user/host.
216239 /// @param stats stats struct for current call statistics
217240 func rtcEngine( _ engine: AgoraRtcEngineKit , remoteAudioStats stats: AgoraRtcRemoteAudioStats ) {
218- audioViews [ stats . uid ] ? . statsInfo? . updateAudioStats ( stats)
241+ remoteVideo . statsInfo? . updateAudioStats ( stats)
219242 }
220243}
221244
222- extension SimpleAudioFilterMain : AgoraMediaFilterEventDelegate {
245+ extension SimpleFilterMain : AgoraMediaFilterEventDelegate {
223246 func onEvent( _ vendor: String ? , extension: String ? , key: String ? , json_value: String ? ) {
224247 LogUtils . log ( message: " onEvent: \( String ( describing: key) ) \( String ( describing: json_value) ) " , level: . info)
225248 }
0 commit comments