Avaya Client SDK

< Back to Package Overview

Answering a Video Call

Using the Avaya Client SDK, you can easily integrate the ability for users of your application to make and receive audio or video calls.

To receive and answer an incoming video call, you must complete the following activities.

  • Implement the call service listener to monitor for call service events
  • Implement the call delegate to monitor for call events
  • Detect the presence of offered video
  • Obtain resources for answering a video call
  • Accept the incoming video call
  • Activate video resources
  • End the call

Implement the call service listener to monitor for call service events

In order to get notifications for any incoming calls, your application can define an object that implements the <CSCallServiceDelegate> protocol and add this delegate to the CSCallService object to receive call service notifications.

@interface AppCallServiceHandler() 
...
@end

@implementation AppCallServiceHandler
    - (void)callService:(CSCallService *)callService 
    didReceiveIncomingCall:(CSCall *)call {
        // Called to report that there is an incoming call. 
        // Add code here to handle this incoming call, eg, 
        // update UI to alert user, provide options for handling
        // the call, ... etc.
    }

    - (void)callService:(CSCallService *)callService 
          didRemoveCall:(CSCall *)call {
        // Called to report that the call has been removed before
        // answer.
        // Add code here to handle the removed call, eg,
        // update UI to remove the call... etc.
    }
    ...
@end

You can instantiate a call service handler (AppCallServiceHandler) and add it as a delegate to the call service.

AppCallServiceHandler* callServiceHandler = 
    [[AppCallServiceHandler alloc] init];
CSCallService* callService = user.callService;
callService.delegate = callServiceHandler;

When there is an incoming call, the callService:didReceiveIncomingCall: method is called with a CSCall object in the arguments. You can instantiate a call handler and add that as a delegate to this call object for handling subsequent call events.

Implement the call delegate to monitor for call events

To monitor call events, the <CSCallDelegate> protocol provided by the CSCall object can be used. This protocol provides notification as the call state changes.

Your application can define an object that implements the <CSCallDelegate> methods and can add it to the CSCall object to receive callback notifications.

@interface AppCallHandler() 
...
@end

@implementation AppCallHandler
    - (void)callDidStart:(CSCall *)call {
        // Called to report that call has started (ie, call is in progress).
        // Add code here to update the UI as appropriate.
    }

    - (void)callDidBeginRemoteAlerting:(CSCall *)call 
                        withEarlyMedia:(BOOL)hasEarlyMedia {
        // Called to report that an outgoing call is ringing at the far end.
        // Add code here to update the UI as appropriate.
    }

    - (void)callDidEstablish:(CSCall *)call {
        // Called to report that an outgoing call has been established 
        // (ie, far end has answered and speechpath has been established).
        // Add code here to update the UI as appropriate.
    }

    - (void)callDidEnd:(CSCall *)call reason:(CSCallEndReason)reason {
        // Called to report that call has ended.
        // Add code here to update the UI as appropriate.
    }

    - (void)call:(CSCall *)call didFailWithError:(NSError *)error {
        // Called to report that call has failed and the failure reason
        // is described in the error parameter.
        // Add code here to update the UI as appropriate.
    }

    - (void)updateVideoChannels:(NSArray *)videoChannels {
        // Called to report that video channels of the call updated
        // Add code here to update the UI as appropriate.
    }
    ...
@end

You can instantiate an application call handler (AppCallHandler) and add that as a delegate to the call.

AppCallHandler *callHandler = [[AppCallHandler alloc] init];
call.delegate = callHandler;

Detect the presence of offered video

Any incoming call may include video, and the App needs to use the CSIncomingVideoStatus API on the Call to determine the call's offer status. The API returns one of three values which the application must handle

  • SUPPORTED. The calling party included video when making the call. If desired, the application can answer with bi-directional or reception-only video.
  • INDEFINITE. The calling party may or may not have included video when making the call. Due to requirements of some calling endpoints, it's highly recommended that the application answer with reception-only video. If this is not done, some endpoints will never be able to establish a video session with the application.
  • OFF. The calling party did not include video when making the call. The application should not answer the call with video.
CSIncomingVideoStatus videoStatus = call.incomingVideoStatus;

Obtain resources for answering a video call

The application needs to obtain one or two resources when answering a call with video. If the application wishes to transmit video, it should find a video camera. Camera availability is verified through the CSVideoCapturerIOS class. This class manages most aspects of camera operation, including verification of available hardware. Regardless of camera need, a video interface is required.

VideoInterface* videoInterface = user.mediaServices.videoInterface;
CSVideoCapturerIOS* videoCapturer = [[CSVideoCapturerIOS alloc] init];

Answer the incoming call with video

To answer the incoming call with video, you should call setVideoMode with CSVideoModeSendReceive and then call the accept method on the incoming call object.

[call setVideoMode:CSVideoModeSendReceive 
                   completionHandler:^(NSError *handler)];
[call accept];

Activate video resources

Video transmission/rendering could be updated as follows:

- (void)updateVideoChannels:(NSArray *)videoChannels {

    CSVideoChannel *videoChannel = videoChannels[0];

    if (videoChannel.enabled == YES) {
        // Start video rendering
        if (videoChannel.negotiatedDirection == CSMediaDirectionSendReceive
        || videoChannel.negotiatedDirection == CSMediaDirectionReceiveOnly) {
            // An object on the view that is responsible for video rendering
            CSVideoCapturerIOS* remoteSink = [[CSVideoRendereIOS alloc] init];
            [[videoInterface getRemoteVideoSource:videoChannel.channelId]
                                                  setVideoSink:remoteSink];
            }
        }

        // Start video transmission
        if (videoChannel.negotiatedDirection == CSMediaDirectionSendReceive
        || videoChannel.negotiatedDirection == CSMediaDirectionSendOnly) {
            // Use frontal camera - CSVideoCameraPositionFront 
            // or rear camera - CSVideoCameraPositionBack
            [videoCapturer useVideoCameraAtPosition:CSVideoCameraPositionFront
                                                        completion:nil];
            }
        }
    }
    else {
        [[videoInterface getRemoteVideoSource:videoChannel.channelId]
                                                            setVideoSink:nil];
        [videoCapturer setVideoSink: nil];
        }
    }
}

End the call

To terminate the call from the application, you can use the end() function on the call object.

[call end];

The onCallEnded callback event is sent to the call listener when the call has been ended. Use this event to update the UI of your application. Ending the call will deallocate the video channel and release the video camera automatically, but any render surface allocated by the application will need to be released by it. Again, see SdkSampleApp for the steps.