Performance of the Client’s Part as Provided by Vidyo

Performance of the Client’s Part as Provided by Vidyo

Table of Contents

Introduction

What comes to your mind first when you need to arrange a video conference? Probably you would think about Skype as the best option for you. Nevertheless, modern technologies went even further suggesting wireless connection. It is high time to learn about Vidyo tecnhology and try it out with our tips.

1. Why Vidyo is better than its competitors

Vidyo is a company specialized in providing video conferencing services. It was established in 2005 by Osif Shapiro. To get the HD quality video, the Vidyo team first used the H.264 standard for video compression, SVC (Scalable Video Coding). The given approach ensures low latency and high error resilience (with adaptation to even 15-20% packet loss).

While many videoconferencing providers use Multipoint Control Unit (MCU), Vidyo has rejected this approach. They replaced MCU with much cheaper router (VidyoRouter), and arranged coding and decoding in endpoints.

One more Vidyo advantage over competitors is optimization video streams to the capabilities of each endpoint and to local network conditions. Vidyo team ensures data security through AES-128 bit media encryption.

2. How it works

Vidyo.png

Communication between users is ensured by the portals provided by Vidyo.

For portal creation, Vidyo provides Web Services API consisting of the four following parts:

  • Super APIs - a set of super administrative APIs to manage tenants, licenses and System components etc.
  • Admin APIs  - a set of administrative APIs to manage members, rooms, gateways, etc
  • Guest APIs - a set of APIs for developing guest user functionality via Web Services API.
  • User APIs - a set of APIs for developing third-party endpoints or applications targeted for end users, providing search, joining meeting rooms, making direct calls, etc.

At the left side of the picture, you may find the scheme of how the custom application works. Media translation is achieved via VidyoClient Library.

VidyoClient Library is a library Vidyo uses for writing the clients’ programs. Given library is written in C and has quite accessible and user-friendly interface. At the present, VidyoClient Library is supported in iOS, Android, MacOS, Windows і Linux.

3. Terms you should know when using Vidyo

Participants - authorized users who have accounts for using the portal. They always use login name and password for authorization. Participants can make/receive calls, schedule meetings and join the conferences. They can have a display name as well as set other parameters. Each participant is a member of a particular group.

Rooms - entitled conferences that other participants can join based on their status, accessibility, PIN, etc. There are three types of rooms, personal, public and scheduled meeting rooms. Each room has its owner. The owner can change room settings and control the conference during the session. Each participant has one room.

  • Groups - a group has a set of properties. All the members belonging to a group share these properties.
  • Guests - guests do not belong to the system; however, they are allowed to join the room without any authentication.

Portal - is a channel aimed at communication between the authorized users. Each channel has its address. You can grasp the idea of how the portal works from the right side of the picture. VidyoConferencing Server and VidyoRouter ensure portal activity.

VidyoRouter - is a router that uses video packet switching technology to achieve record performance without the need for time-consuming transcoding. VideoRouter manages all video traffic.

Video call

In this article, we will examine the performance of the client’s part as provided by Vidyo.

Related: Your business in your smartphone. Is it real?

As mentioned earlier, VidyoClient Library is used to build web client applications. The convenience of this library consists in its simplicity. It requires only six methods and one callback function. These methods include:

  • VidyoClientInitialize()
  • VidyoClientUninitialize()
  • VidyoClientStart()
  • VidyoClientStop()
  • VidyoClientSendRequest()
  • VidyoClientSendEvent()

Callback function looks like this:

  • VidyoClientOutEventCallback()
  • VidyoClientInitialize() is used for memory management and client initialization. This method should be used only once during running the program.  
  • VidyoClientUninitialize() is used for freeing memory and termination of all the current tasks. Similarly to VidyoClientInitialize(), this method should be used just once during running the program.  

VidyoClientStart() is used to configure the following:

  • Logging (location, levels, categories, size);
  • Location of the dump file in case of an abnormal exit.
  • Location of the window for video display (father object and “father frame”).
  • Localization table.
  • Callback function and corresponding content.

VidyoClientStop() stops library processes.

The performance of VidyoClient Library depends on the events. There are two types of events, In Events and Out Events.  

VidyoClientOutEventCallback()– is the callback function that is used for receiving out event API messages from the application. Below, you will find the examples of such events:

…
VIDYO_CLIENT_OUT_EVENT_USER_MESSAGE,
VIDYO_CLIENT_OUT_EVENT_LOGIC_STARTED,
VIDYO_CLIENT_OUT_EVENT_SIGN_IN,
VIDYO_CLIENT_OUT_EVENT_SIGN_OUT,
VIDYO_CLIENT_OUT_EVENT_SUBSCRIBING,
VIDYO_CLIENT_OUT_EVENT_APP_EXIT,
VIDYO_CLIENT_OUT_EVENT_DEVICE_SELECT,
VIDYO_CLIENT_OUT_EVENT_DEVICES_CHANGED,
VIDYO_CLIENT_OUT_EVENT_DEVICE_SELECTION_CHANGED,
VIDYO_CLIENT_OUT_EVENT_SELECTED_DEVICE_ON_OS_CHANGED,
VIDYO_CLIENT_OUT_EVENT_RINGING,
VIDYO_CLIENT_OUT_EVENT_END_RINGING,
VIDYO_CLIENT_OUT_EVENT_CALLING
…

VidyoClientSendEvent() is used for sending event API messages to the library. Both out events and in events are asynchronous.

Examples of the events include:

…
VIDYO_CLIENT_IN_EVENT_SIGN_IN,
VIDYO_CLIENT_IN_EVENT_CANCEL,
VIDYO_CLIENT_IN_EVENT_LEAVE,
VIDYO_CLIENT_IN_EVENT_ANSWER,
VIDYO_CLIENT_IN_EVENT_DECLINE,
VIDYO_CLIENT_IN_EVENT_PREVIEW,
VIDYO_CLIENT_IN_EVENT_MUTE_AUDIO_IN,
VIDYO_CLIENT_IN_EVENT_MUTE_AUDIO_OUT,
VIDYO_CLIENT_IN_EVENT_MUTE_VIDEO,
VIDYO_CLIENT_IN_EVENT_SHARE,
VIDYO_CLIENT_IN_EVENT_UNSHARE,
VIDYO_CLIENT_IN_EVENT_SEND_FRAME,
VIDYO_CLIENT_IN_EVENT_SETUP_CAMERA,
VIDYO_CLIENT_IN_EVENT_RESIZE,
VIDYO_CLIENT_IN_EVENT_PARTICIPANTS_LIMIT,
VIDYO_CLIENT_IN_EVENT_LAYOUT,
…

VidyoClientSendRequest() is a synchronous server request.

Examples of the requests include:

...
IDYO_CLIENT_REQUEST_GET_CONFIGURATION,
VIDYO_CLIENT_REQUEST_SET_CONFIGURATION,
VIDYO_CLIENT_REQUEST_GET_EID,
VIDYO_CLIENT_REQUEST_GET_LID,   
VIDYO_CLIENT_REQUEST_GET_PID,
VIDYO_CLIENT_REQUEST_ACTIVATE_EID,
VIDYO_CLIENT_REQUEST_GET_CONNECTIVITY_INFO, 
VIDYO_CLIENT_REQUEST_GET_VOLUME_AUDIO_IN, 
VIDYO_CLIENT_REQUEST_SET_VOLUME_AUDIO_IN, 
VIDYO_CLIENT_REQUEST_GET_VOLUME_AUDIO_OUT, 
VIDYO_CLIENT_REQUEST_SET_VOLUME_AUDIO_OUT
... 

Next, we will demonstrate how to work with the library.

Initialization phase is the first phase of using the Vidyo library. We initialize the component using the following method:

- (VidyoBool)initVidyoClient {
  VidyoBool lInitState = VIDYO_FALSE;    
  //1.1
  if ((lInitState = VidyoClientIsStarted()) == VIDYO_FALSE) {
    //1.2
    VidyoClientConsoleLogConfigure( VIDYO_CLIENT_CONSOLE_LOG_CONFIGURATION_ALL );
    //1.3        
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,    
      NSUserDomainMask, YES);
      
      NSString *documentsDirectory = [paths objectAtIndex:0];
      documentsDirectory = [documentsDirectory stringByAppendingString:@"/"];
      const char *pathToLogDir = [documentsDirectory cStringUsingEncoding:NSUTF8StringEncoding];
      
      VidyoClientLogParams logParams = {0};
      
      logParams.logBaseFileName = "TMCentre";
      logParams.pathToLogDir = pathToLogDir;
      logParams.logLevelsAndCategories = "fatal error warning info@AppGui info@App info@AppEmcpClient info@LmiApp debug@App debug@AppEvents info@LmiH264SvcPace info@AppWebProxy";
      //1.4       
      AppDelegate* lAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
      lInitState = VidyoClientInitialize(vidyoClientSampleOnVidyoClientEvent, (__bridge           
        VidyoVoidPtr)(lAppDelegate), &logParams);
        //1.5                
        CGRect lScreenFrame = [UIScreen mainScreen].bounds;
        lAppDelegate.windowCall = [[UIWindow alloc] initWithFrame:lScreenFrame];
        [lAppDelegate.windowCall setWindowLevel:UIWindowLevelAlert];
        [lAppDelegate.windowCall setScreen:[UIScreen mainScreen]];
        [lAppDelegate.windowCall setBackgroundColor:[UIColor clearColor]];   
        //1.6     
        VidyoClientProfileParams profileParams = {0};
        //1.7
        VidyoRect videoRect = {(VidyoInt)(0), 
          (VidyoInt)(0),
          (VidyoUint)(lScreenFrame.size.width),
          (VidyoUint)(lScreenFrame.size.height)};
          
          if (lInitState == VIDYO_TRUE) {
            //1.8
            lInitState = VidyoClientStart(vidyoClientEvents,
              (__bridge VidyoVoidPtr)(_appDelegate),
              &logParams,
              (__bridge VidyoWindowId)_appDelegate.windowCall,
              &videoRect,
              NULL,
              &profileParams,
              VIDYO_FALSE);
              
              if (lInitState == VIDYO_FALSE){
                NSLog(@"VidyoClientStart() returned failure!\n");
              } else {
                NSLog(@"VidyoClientStart() returned success!\n");
                //1.9
                lInitState = [self bootstrap];            }
              }
              
            }
            return lInitState;
          }

Video confernce

4. Let’s examine the initialization process step-by-step

1.1. At first, we check if the Vidyo library is initialized and working. For that, we use calling the method VidyoClientIsStarted().This method returns value of VidyoBool type, especially VIDYO_TRUE (in case Vidyo client is ready to work), or VIDYO_FALSE (if library initialization is needed).

1.2. Method VidyoClientConsoleLogConfigure() is used to configure library logging. You can pass the following parameters:

VIDYO_CLIENT_CONSOLE_LOG_CONFIGURATION_NONE,   /*!< no console logging (default) */
VIDYO_CLIENT_CONSOLE_LOG_CONFIGURATION_DIRECT,  /*!< only logs that are specified to be printed in console */
VIDYO_CLIENT_CONSOLE_LOG_CONFIGURATION_ALL,       /*!< all logs go to console */
VIDYO_CLIENT_CONSOLE_LOG_CONFIGURATION_RESERVED /*!< reserved range for private use */

1.3. Next, we set log parameters. For that, we indicate the file name for logging, its path, log levels and categories in the VidyoClientLogParams structure.

1.4. Phase of library initialization. VidyoClientInitialize() – method used for initialization of Vidyo client. In-parameters include:

  • Function pointer - callback responding to out events.
  • Parameters used for setting logs (passing NULL is possible).
  • Object pointer with which a callback (or context) will be associated.

This method returns VIDYO_TRUE in a case of successful initialization or VIDYO_FALSE, if library initialization failed.

1.5. Vidyo uses separate window (UIWindow) for starting the conference. It means you have to create one more UIWindow object apart from the main window in AppDelegate class. We will call it windowCall.

1.6. VidyoClientProfileParams – the structure containing parameters for application profile configuration. This structure will remain empty, meanwhile, its initialization will look as follows:

VidyoClientProfileParams profileParams = {0};
profileParams.PROGFILES_DIR   = "\\CompanyName\\Product Name\\";
profileParams.CONFIG_KEY_PATH = "SOFTWARE\\CompanyName\\Product Name\\";
profileParams.PRODUCT_NAME    = "ProductName";
profileParams.MYDOCS_DIR      = "\\Product Name\\";
profileParams.VIDYO_DIR       = "\\CompanyName";
profileParams.portNumber      = 63457;

1.7. In this phase, we have to determine the size of the window where the conference will take place. Therefore, we create VidyoRect, the structure containing intended size and display position.

1.8. Next phase is the “start” of Vidyo. We use VidyoClientStart() method for that. Here, we pass the following in-parameters:

  • Function pointer - callback, responding to out events.
  • Object pointer with which a callback (or context) will be associated.
  • Parameters used for setting logs (passing NULL is possible).
  • The window where the conference will take place.
  • The position of UIView within entire UIWindow.
  • VidyoClientAppStringsInfo structure.

1.9. Out next step is Vidyo system configuration. You will find the description below.

Vidyo video conference

For system configuration, we use the following method:

/* Startup configuration code. */
- (void)bootstrap {
  //2.1
  VidyoClientRequestConfiguration conf = {0};
  VidyoUint error;
  //2.2
  if ((error = VidyoClientSendRequest(VIDYO_CLIENT_REQUEST_GET_CONFIGURATION, &conf, sizeof(VidyoClientRequestConfiguration))) != VIDYO_CLIENT_ERROR_OK) {
    NSLog(@"Failed to request configuration with error %u", error);
  } else {
    //2.3
    /* Default configuration */
    conf.enableShowConfParticipantName = VIDYO_TRUE;
    conf.enableHideCameraOnJoin = VIDYO_FALSE;
    conf.enableBackgrounding = VIDYO_TRUE;
    
    /* Disable autologin */
    conf.userID[0] = '\0';
    conf.portalAddress[0] = '\0';
    conf.serverAddress[0] = '\0';
    conf.password[0] = '\0';
    conf.selfViewLoopbackPolicy = 2;
    
    //2.4
    if (VidyoClientSendRequest(VIDYO_CLIENT_REQUEST_SET_CONFIGURATION, &conf, sizeof(VidyoClientRequestConfiguration)) != VIDYO_CLIENT_ERROR_OK) {
      NSLog(@"Failed to set configuration");
    }
  }
}

2. Step-by-step system configuration process:

2.1. At first, we create an empty structure VidyoClientRequestConfiguration. Given structure is to be used in VidyoClientSendRequest method for receiving the current system status.

2.2. At this point, we send request VIDYO_CLIENT_REQUEST_GET_CONFIGURATION to the library.

2.3. If the request succeeds we get the current Vidyo status in the passed structure and can set more parameters if needed. Here, we set parameters responsible for library processing in background mode, camera settings, visibility of the script in which the names of conference participants are written, and parameters responsible for userId, portal address, user’s password and others.

2.4. After all the parameters have been successfully set during system configuration we send the parameter request VIDYO_CLIENT_REQUEST_SET_CONFIGURATION.

3. Now, the callback function will look as following:

void vidyoClientEvents(VidyoClientOutEvent event, VidyoVoidPtr param, VidyoUint  
  paramSize, VidyoVoidPtr data)
  {
    
    if (event >= VIDYO_CLIENT_OUT_EVENT_MIN && event <= VIDYO_CLIENT_OUT_EVENT_MAX)
    {
      switch (event) {
        
        case VIDYO_CLIENT_OUT_EVENT_CALL_PROGRESS: {
          break;
        }
        
        case VIDYO_CLIENT_OUT_EVENT_MUTED_VIDEO: {
          break;
        }
        case VIDYO_CLIENT_OUT_EVENT_PARTICIPANTS_CHANGED: {
          break;
        }
        case VIDYO_CLIENT_OUT_EVENT_DEVICE_SELECTION_CHANGED: {
          break;
        }
        case VIDYO_CLIENT_OUT_EVENT_USER_MESSAGE: {
          break;
        }
        …
        
        default:
        break;
        
      }

We should determine how the application should respond to certain events. To define the function outside of the class you may use NSNotificationCenter to notify the application about library out events (So, you need to make a post with the information received from the library).

4. Create a class both subscribed to events and containing block handlers for these events. It will ensure responding to events coming from the library.  For instance, we create the class EEVidyoManager. We get the following:

// EEVidyoOutEventManager.h

@interface EEVidyoManager : NSObject
…
@property(nonatomic, copy)void (^vidyoClientOutEventSignedIn)();
@property(nonatomic, copy)void (^vidyoClientOutEventSigneOut)(NSNumber *error);
@property(nonatomic, copy)void (^vidyoClientOutEventLicense)(NSNumber *error);
@property(nonatomic, copy)void (^vidyoClientOutEventIncomingCall)(NSString* user);
@property(nonatomic, copy)void (^vidyoClientOutEventEndCalling)();
....
@end

   We code the following in class implementation file:
   
       //  EEVidyoOutEventManager.m
   
       @implementation EEVidyoOutEventManager

- (id)init {
        self = [super init];
    if (self) {
               __weak EEVidyoOutEventManager *wself = self;

       [[NSNotificationCenter defaultCenter]

       addObserverForName:@"NotificationVidyoClientOutEventSignedIn" object:nil    

       queue:[NSOperationQueue new] usingBlock:^(NSNotification *note) {
           if ([wself vidyoClientOutEventSignedIn]) {
               [wself vidyoClientOutEventSignedIn]();
           }
       }];

       [[NSNotificationCenter defaultCenter]  
       addObserverForName:@"NotificationVidyoClientOutEventSignedOut" object:nil   

       queue:[NSOperationQueue new] usingBlock:^(NSNotification *note) {
           if ([wself vidyoClientOutEventSignedOut]) {
               [wself vidyoClientOutEventSignedOut](note.object);
           }
       }];

       [[NSNotificationCenter defaultCenter]
       addObserverForName:NOTIFICATION_VIDYO_CLIENT_OUT_EVENT_LICENSE object:nil
       queue:[NSOperationQueue new] usingBlock:^(NSNotification *note) {
           if ([wself vidyoClientOutEventLicense]) {
               [wself vidyoClientOutEventLicense](note.object);
           }
       }];
   
       [[NSNotificationCenter defaultCenter]
       addObserverForName:@"NotificationVidyoClientOutEventIncomingCall" object:nil
       queue:[NSOperationQueue new] usingBlock:^(NSNotification *note) {
           if ([wself vidyoClientOutEventIncomingCall]) {
               [wself vidyoClientOutEventIncomingCall](note.object);
           }
       }];

       [[NSNotificationCenter defaultCenter]
       addObserverForName:@"NotificationVidyoClientOutEventEndCalling" object:nil
       queue:[NSOperationQueue new] usingBlock:^(NSNotification *note) {
           if ([wself vidyoClientOutEventEndCall]) {
               [wself vidyoClientOutEventEndCall]();
           }
         }];

        …
      }

       @end

As a result, we got the class subscribed to certain events, and its properties act as block handlers for events. You can also add library initialization to the given class (meaning methods initVidyoClient, bootstrap).

5. You might choose to implement a separate class for sending events. For example,

//  VidyoClientInEventManager.h
@interface  EEVidyoInEventManager : NSObject

+ (BOOL)cancelLogin; 
+ (BOOL)cancelEnteringAConference; 
+ (BOOL)leaveConference; 
+ (BOOL)acceptAnIncomingCall; 

@end

Implementation file will look as following:

// EEVidyoInEventManager.m

@implementation EEVidyoInEventManager



+ (BOOL)cancelLogin {
  return (VidyoClientSendEvent(VIDYO_CLIENT_IN_EVENT_LOGIN_CANCEL, NULL, 0) == VIDYO_TRUE);
}

+ (BOOL)cancelEnteringAConference {
  return (VidyoClientSendEvent(VIDYO_CLIENT_IN_EVENT_CANCEL, NULL, 0) == VIDYO_TRUE);
}

+ (BOOL)leaveConference {
  return (VidyoClientSendEvent(VIDYO_CLIENT_IN_EVENT_LEAVE, NULL, 0) == VIDYO_TRUE);
}

+ (BOOL)acceptAnIncomingCall {
  return (VidyoClientSendEvent(VIDYO_CLIENT_IN_EVENT_ANSWER, NULL, 0) == VIDYO_TRUE);
}


@end

Conclusion

As you may have noticed, it is easy to deploy and manage Vidyo with the help of our tips. Try this technology in your business and you will soon get the results of better relationships with the partners, suppliers, and customers.  

Yevhen Fedoriuk

Written by

Yevhen Fedoriuk

VP of Delivery at Indeema Software Inc.

In his role as VP of Delivery, Yevhen Fedoriuk places a strong emphasis on prioritizing client needs, drawing upon his extensive experience of over a decade in both technology and management.