@@ -2,6 +2,7 @@ import AWSCore
22import AWSCognitoIdentityProvider
33import AWSKinesisVideo
44import AWSKinesisVideoSignaling
5+ import AWSKinesisVideoWebRTCStorage
56import AWSMobileClient
67import Foundation
78import WebRTC
@@ -32,6 +33,7 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
3233
3334 // variables controlled by UI
3435 var sendAudioEnabled : Bool = true
36+ var sendVideoEnabled : Bool = true
3537 var isMaster : Bool = false
3638 var signalingConnected : Bool = false
3739 var selectedResolution : VideoResolution = . resolution720p
@@ -52,6 +54,7 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
5254 @IBOutlet var clientID : UITextField !
5355 @IBOutlet var regionName : UITextField !
5456 @IBOutlet var isAudioEnabled : UISwitch !
57+ @IBOutlet var isVideoEnabled : UISwitch !
5558 @IBOutlet var resolutionButton : UIButton !
5659
5760 // Connect Buttons
@@ -118,6 +121,14 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
118121 }
119122 }
120123
124+ @IBAction func videoStateChanged( sender: UISwitch ! ) {
125+ if sender. isOn {
126+ self . sendVideoEnabled = true
127+ } else {
128+ self . sendVideoEnabled = false
129+ }
130+ }
131+
121132 @IBAction func resolutionButtonTapped( _ sender: UIButton ) {
122133 let alert = UIAlertController ( title: " Select Resolution " , message: nil , preferredStyle: . actionSheet)
123134
@@ -224,18 +235,24 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
224235 }
225236 }
226237 // check whether signalling channel will save its recording to a stream
227- // only applies for master
228- var usingMediaServer : Bool = false
229- if self . isMaster {
230- usingMediaServer = isUsingMediaServer ( channelARN: channelARN!, channelName: channelNameValue)
231- // Make sure that audio is enabled if ingesting webrtc connection
232- if ( usingMediaServer && !self . sendAudioEnabled) {
233- popUpError ( title: " Invalid Configuration " , message: " Audio must be enabled to use MediaServer " )
238+ var useStorageSession : Bool = isUsingStorageSession ( channelARN: channelARN!, channelName: channelNameValue)
239+ // Make sure that audio is enabled if ingesting webrtc connection
240+ if ( useStorageSession) {
241+ if ( self . isMaster && ( !self . isAudioEnabled. isOn || !self . isVideoEnabled. isOn) ) {
242+ // Master mode: Both audio and video required
243+ popUpError ( title: " Invalid Configuration " , message: " Video and audio must be enabled for WebRTC ingestion master " )
234244 return
245+ } else if ( !self . isMaster) {
246+ // Viewer mode: Video not allowed, audio optional
247+ if ( self . isVideoEnabled. isOn) {
248+ popUpError ( title: " Invalid Configuration " , message: " Video is not allowed for WebRTC ingestion viewer " )
249+ return
250+ }
235251 }
236252 }
253+
237254 // get signalling channel endpoints
238- let endpoints = getSignallingEndpoints ( channelARN: channelARN!, region: awsRegionValue, isMaster: self . isMaster, useMediaServer : usingMediaServer )
255+ let endpoints = getSignallingEndpoints ( channelARN: channelARN!, region: awsRegionValue, isMaster: self . isMaster, useStorageSession : useStorageSession )
239256 //// Ensure that the WebSocket (WSS) endpoint is available; WebRTC requires a valid signaling endpoint.
240257 if endpoints [ " WSS " ] == nil {
241258 popUpError ( title: " Invalid SignallingEndpoints " , message: " SignallingEndpoints is required for WebRTC connection " )
@@ -254,8 +271,20 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
254271 service: . KinesisVideo,
255272 url: URL ( string: endpoints [ " HTTPS " ] !! ) )
256273 let RTCIceServersList = getIceCandidates ( channelARN: channelARN!, endpoint: httpsEndpoint!, regionType: awsRegionType, clientId: localSenderId)
257- webRTCClient = WebRTCClient ( iceServers: RTCIceServersList, isAudioOn: sendAudioEnabled, resolution: selectedResolution)
274+ webRTCClient = WebRTCClient ( iceServers: RTCIceServersList, isAudioOn: sendAudioEnabled, isVideoOn : sendVideoEnabled , resolution: selectedResolution)
258275 webRTCClient!. delegate = self
276+
277+ guard !useStorageSession || endpoints [ " WEBRTC " ] != nil else {
278+ print ( " connectAsRole IllegalState! WEBRTC endpoint is required for WebRTC ingestion " )
279+ return
280+ }
281+ if useStorageSession {
282+ let webRTCEndpoint : String = endpoints [ " WEBRTC " ] !!
283+ let webRTCStorageConfiguration = AWSServiceConfiguration ( region: awsRegionType,
284+ endpoint: AWSEndpoint ( urlString: webRTCEndpoint) ,
285+ credentialsProvider: getCredentialsProvider ( ) )
286+ AWSKinesisVideoWebRTCStorage . register ( with: webRTCStorageConfiguration!, forKey: awsKinesisVideoKey)
287+ }
259288
260289 // Connect to signalling channel with wss endpoint
261290 print ( " Connecting to web socket from channel config " )
@@ -267,7 +296,7 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
267296 let seconds = 2.0
268297 DispatchQueue . main. asyncAfter ( deadline: . now( ) + seconds) {
269298 self . updateConnectionLabel ( )
270- self . vc = VideoViewController ( webRTCClient: self . webRTCClient!, signalingClient: self . signalingClient!, localSenderClientID: self . localSenderId, isMaster: self . isMaster, mediaServerEndPoint : endpoints [ " WEBRTC " ] ?? nil )
299+ self . vc = VideoViewController ( webRTCClient: self . webRTCClient!, signalingClient: self . signalingClient!, localSenderClientID: self . localSenderId, isMaster: self . isMaster, signalingChannelArn : useStorageSession ? channelARN : nil , isVideoEnabled : self . sendVideoEnabled )
271300 self . present ( self . vc!, animated: true , completion: nil )
272301 }
273302 }
@@ -327,8 +356,8 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
327356 return channelARN
328357 }
329358
330- // check media server is enabled for signalling channel
331- func isUsingMediaServer ( channelARN: String , channelName: String ) -> Bool {
359+ // check storage session (WebRTC ingestion) is enabled for signalling channel
360+ func isUsingStorageSession ( channelARN: String , channelName: String ) -> Bool {
332361 var usingMediaServer : Bool = false
333362 /*
334363 equivalent AWS CLI command:
@@ -348,6 +377,7 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
348377 }
349378 }
350379 } ) . waitUntilFinished ( )
380+ print ( " \( channelARN) configured for ingestion? \( usingMediaServer) " )
351381 return usingMediaServer
352382 }
353383
@@ -388,7 +418,7 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
388418 }
389419
390420 // Get signalling endpoints for the given signalling channel ARN
391- func getSignallingEndpoints( channelARN: String , region: String , isMaster: Bool , useMediaServer : Bool ) -> Dictionary < String , String ? > {
421+ func getSignallingEndpoints( channelARN: String , region: String , isMaster: Bool , useStorageSession : Bool ) -> Dictionary < String , String ? > {
392422
393423 var endpoints = Dictionary < String , String ? > ( )
394424 /*
@@ -400,7 +430,7 @@ class ChannelConfigurationViewController: UIViewController, UITextFieldDelegate
400430 singleMasterChannelEndpointConfiguration? . protocols = videoProtocols
401431 singleMasterChannelEndpointConfiguration? . role = getSingleMasterChannelEndpointRole ( isMaster: isMaster)
402432
403- if ( useMediaServer ) {
433+ if ( useStorageSession ) {
404434 singleMasterChannelEndpointConfiguration? . protocols? . append ( " WEBRTC " )
405435 }
406436
@@ -499,6 +529,12 @@ extension ChannelConfigurationViewController: SignalClientDelegate {
499529 remoteSenderClientId = senderClientId
500530 }
501531 setRemoteSenderClientId ( )
532+
533+ // Mark that offer was received to stop storage session retries
534+ if sdp. type == . offer {
535+ vc? . markOfferReceived ( )
536+ }
537+
502538 webRTCClient!. set ( remoteSdp: sdp, clientId: senderClientId) { _ in
503539 print ( " Setting remote sdp and sending answer. " )
504540 self . vc!. sendAnswer ( recipientClientID: self . remoteSenderClientId!)
@@ -529,14 +565,23 @@ extension ChannelConfigurationViewController: WebRTCClientDelegate {
529565 switch state {
530566 case . connected, . completed:
531567 print ( " WebRTC connected/completed state " )
568+ DispatchQueue . main. async {
569+ self . vc? . showToast ( message: " WebRTC Connected " , length: " short " )
570+ }
532571 case . disconnected:
533572 print ( " WebRTC disconnected state " )
573+ DispatchQueue . main. async {
574+ self . vc? . showToast ( message: " WebRTC Disconnected " , length: " short " )
575+ }
576+ case . failed:
577+ print ( " WebRTC failed state " )
578+ DispatchQueue . main. async {
579+ self . vc? . showToast ( message: " WebRTC Connection Failed " , length: " long " )
580+ }
534581 case . new:
535582 print ( " WebRTC new state " )
536583 case . checking:
537584 print ( " WebRTC checking state " )
538- case . failed:
539- print ( " WebRTC failed state " )
540585 case . closed:
541586 print ( " WebRTC closed state " )
542587 case . count:
0 commit comments