The Sender object is designed to interface with an application program to provide the facilities necessary to capture audio/video data from capture hardware and transport it across the network.
To use the Sender object, the application program needs to create the SOM environment, then instantiate the Sender object and initialize it via method calls with parameters that specify the following information to the object:
In addition to the above required parameters, the application program needs to provide a callback routine to be invoked when the Sender object needs to communicate back with the application program to indicate unexpected errors or events.
After the object is initialized and the callback routine is set up, the application program needs to issue the send method call to notify the Sender object to start capturing and transmitting the data. After issuing this method call, the application program needs to enter an event loop to wait for and process errors that may be returned from the Sender object.
While the Sender object is in the send mode (send method call issued), the application program can alter or add the following parameters:
When the application program has completed, the program needs to issue the terminate method call and free the instantiated Sender object before exiting.
The following sample code illustrates the preceding calling sequence:
#include <UMSNetSender.h> #include <X11/Intrinsic.h> #include <X11/StringDefs.h>
int main(int argc, char * argv[]) { int error_code; /* Returned error code */ int rc; /* Call return code */ long eventhandle; /* Event handle */ UMSH32xVideoSize size; /* Video size structure */ long bitrate=256000; /* Desired average bitrate */
/* Create the user interface and make available a display pointer, */ /* window ID to display local video and the window ID of the user */ /* interface toplevel window. In the following code these are called */ /* DisplayPtr, WindowID and TopWin. */ create_user_interface(&argc,argv);
XtRealizeWidget(TopLevel); XFlush(display); XSync(display,FALSE);
You must create the user interface first so that the window ID of the video window is available when needed later in the following code. The next nine method calls specify operating parameters for the Sender object. These include such things as compression formats, input connectors, etc.
/* Specify the video format */ if((rc=UMSNetSender_set_video_format(netsend, somEnv, H261)) != UMSNetSender_Success) { printf("Unable to set video format. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
/* Specify the audio format */ if((rc=UMSNetSender_set_audio_format(netsend, somEnv, PCMU)) != UMSNetSender_Success) { printf("Unable to set audio format. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
/* Specify the video connector */ if((rc=UMSNetSender_set_video_connector(netsend, somEnv,"INPUT_COMPOSITE"))) !=UMSNetSender_Success) printf("Unable to set video connector. RC:%d\n",rc);
/* Specify the audio connector */ if((rc=UMSNetSender_set_audio_connector(netsend, somEnv,"LINE_IN"))) !=UMSNetSender_Success) printf("Unable to set audio connector. RC:%d\n",rc);
/* Specify the video signal format */ if((rc=UMSNetSender_set_video_signal_format(netsend, somEnv,"NTSC")) != UMSNetSender_Success) printf("Unable to set video signal. RC:%d\n",rc);
/* Specify the audio volume */ if((rc=UMSNetSender_set_audio_volume(netsend, somEnv, 75)) != UMSNetSender_Success) printf("Unable to change the volume. RC:%d\n",rc);
/* Specify the video size */ size.width=176; size.height=144; if((rc=UMSNetSender_set_video_size(netsend, somEnv, size)) != UMSNetSender_Success) { printf("Unable to set video size. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
/* Specify the source name identifier */ if((rc=UMSNetSender_set_source_name(netsend, somEnv, "My Name")) != UMSNetSender_Success) printf("Unable to set the sender identifier. RC:%d\n",rc);
The following method call specifies the desired average bit rate to use when encoding and sending the audio and/or video data. Note the value is an average and not an upper or lower bound. Also note that the specified value is a desired value, meaning that the Sender object for various reasons might not achieve the desired value. This is most often the case if the specified value is to high for a given video content and size. The parameter value is specified as a long pointer, because the Sender object might change the value if one is specified outside of the encoder operating range. If this happens, the object alters the specified value to a valid one and returns UMSNetSender_ValueChanged.
/* Specify the desired average bitrate */ if((rc=UMSNetSender_set_average_bitrate(netsend, somEnv, &bitrate)) == UMSNetSender_Failure) { printf("Unable to set the desired average bitrate. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
The following method call specifies the TTL value to use when sending multicast data. This call needs to be specified only if a multicast address is specified in one of the add_h323 method calls.
/* Specify the desired multicast ttl */ if((rc=UMSNetSender_set_multicast_ttl(netsend, somEnv, 32)) != UMSNetSender_Success) { printf("Unable to set the multicast ttl. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
The following method call specifies the window and display information used to monitor the video being transmitted. This call uses the window ID information now available since the user interface was created first.
/* Specify the monitor window information */ if((rc=UMSNetSender_set_video_monitor(netsend, somEnv,UMSNetSender_On, WindowID,TopWin,DisplayPtr)))!=UMSNetSender_Success) { printf("Unable to set video monitoring on.RC:%d\n",rc); error_code = -1; goto ErrorExit; }
The following method call is used to specify the destination of the transmitted data. One or more destinations can be specified by using one or more of these calls.
/* Specify a network connection */ if((rc=UMSNetSender_add_h323(netsend,somEnv,"8.88.8.1","227.0,0,4",9005)) != UMSNetSender_Success) { printf("Unable to add connection. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
The remaining code registers the event/error handler and gets things going by issuing the send method call. Following that, the application program simply enters an X loop to wait for and process X and Sender object events.
/* Get the event handle and setup the callback routine */ if((rc=UMSNetSender_get_event_handle(netsend, somEnv, &eventhandle)) != UMSNetSender_Success) { printf("Unable to get event handle. RC:%d\n",rc); error_code = -1; goto ErrorExit; } XtInputID=XtAddInput(eventhandle,XtInputReadMask,SenderEvent,NULL);
/* Issue the send method call to start capturing and sending */ if((rc=UMSNetSender_send(netsend,somEnv)) != UMSNetSender_Success) { printf("Unable to start sender. RC:%d\n",rc); error_code = -1; goto ErrorExit; }
/* Process X events and Sender errors */ XtMainLoop();
ErrorExit: UMSNetSender_terminate(netsend,somEnv); if(netsend !=NULL) _somFree(netsend); exit(error_code); }
The following routine is an example of the event/error handler that is registered above.
void SenderEvent(Widget w, int *fid, XtInputId *id) { UMSNetSender_EventData event_data; int rc;
/* Get the event data */ if((rc = UMSNetSender_get_event(netsend, somEnv, &event_data)) != UMSNetSender_Success) { XtRemoveInput(XtInputID); printf("Unable to get the next event. RC:%d\n",rc); if(netsend !=NULL) _somFree(netsend); SOM_UninitEnvironment(somEnv); exit(-1);} /* Process the event */ switch(event_data.type) { case UMSNetSender_Error: printf("Network Sender returned an error %d",event_data.specific); break; default:;} }
For introductory information, see Programming with Collaboration Objects.