Transferring images from eXcite to outside

TOC
Overview
Samples
Detail: Server port number is configurable
Application-level protocol
    Protocol overview
    Establishing the connection
    Transferring the image size information
    Organization of the image data transfer loop
    Transferring the image data
The server program
The client program
    The member functions of GxClient
    The member objects of GxClient

Overview

The eXcite library contains classes to build application programs for transferring images from an eXcite device to a PC, via Ethernet network connection.

Note: The "PC" that the image data is transferred to can be any computer, including another eXcite : The eXcite library classes described in this section are usable for transferring image data not only to a normal PC but also to another eXcite. After all, the eXcite is a camera combined with a full-fledged PC, except only for the fact that the eXcite doesn't have keyboard and monitor connections. (See Figure 5-2 in the "operation and Features" section of the User's Manual, which contains a Block Diagram of the eXcite.) However, this section refers to the computer that receives the image data by the name "PC", which strictly speaking is a too restrictive name, but which reflects the most typical application situation. 

The image transfer classes in the eXcite library are intended to be used as follows.

The eXcite and the receiving PC are connected by Ethernet network. The simplest case is with one single eXcite in the network:

                  ,-----.
                  | PC  | GxClient
                  `-----'
                     | 
                     | GigE network
                     +--------+
                              |         
                         ,--------.     
                         | eXcite |     
                         `--------'     
                         GxStreamServer   

It's also possible to connect two or more eXcite devices to the PC via the Ethernet network, and to transfer image data from any of the eXcite devices, or from two or more of them simultaneously, to the PC:

                  ,-----.
                  | PC  | GxClient
                  `-----'
                     | 
                     |                        GigE network
            +--------+--------+-------------------+ 
            |                 |                   |
    ,----------.          ,----------.       ,----------. 
    | eXcite 1 |          | eXcite 2 |       | eXcite 3 |
    `----------'          `----------'       `----------' 
    GxStreamServer        GxStreamServer      GxStreamServer

The user image transfer built using the eXcite library classes is always client-server based, and is organized as follows:

On the PC, there runs an application program that gets (receives) the image data. On the eXcite, there runs an application program that acts as a data source for the image data, and that sends the image data.

The data-sourcing program on the eXcite is called the server, and the data-getting program on the PC is called the client.

The server program on the eXcite is the passive component. It is started first, then waits for incoming requests from a client, and starts sending image data when such a client request is received.

The client program is the active component. It looks around for an image-sourcing server in the network, then opens a connection to it, and requests the server to start sending it image data.

The image-transfer classes in the eXcite library provide full functionality for all these tasks. When using these classes, the application programmer doesn't have to deal with (or know of) the underlying network layers used for the communication over the Ethernet network.

The image-transfer classes provided by the eXcite library are the following:

Class For use in
[[GxClient]] the client program on the PC
[[GxStreamServer]] the server program on the eXcite

These two classes are intended to be used with each other. That is, a client program using the GxClient class will find, make contact with, and communicate with a server program using the GxStreamServer class.


Samples

We recommend that you have a look at the two sample programs illustrating image transfer from eXcite to PC. These two sample programs are located in the directory "streamingsample". Each of the two programs consists of only one source file. These are:

SampleServer.cpp
sample server program (to be compiled for running on the eXcite)
SampleClient.cpp
sample client program (to be compiled for running on the PC)



Detail: Server port number is configurable

As in many other examples of network communication, the GxClient/GxStreamServer communication makes use of a so-called "port number" for the server. This server port number is simply an ID number that identifies the type of server. The purpose of the server port number is to allow multiple different GxStreamServer-based servers to run simultaneously on the same eXcite. [ If you're using only one GxStreamServer-based server and run only that server on each eXcite, then you need not bother about the port number and you can simply skip this subsection. ]
    For example, each of the eXcite devices in the network might run one image-sourcing server for images of type "A", and another image-sourcing server for images of another type "B". Each type of server must have a different, distinct port number associated with it. That is: in our example, the type "A" servers might have, say, port number 3219, and the type "B" servers might have port number 7212.
    [ Note that, as is usual with port numbers in client/server systems, on one machine (= eXcite device) each server port number can only be in use by at most one server. As already discussed above, it is possible (and intended by design) that an instance of the same GxStreamServer-based image-sourcing server program runs simultaneously on each of the eXcite devices in the network; in this case, each instance of that same server program (each running on one of the eXcites) will, and should, use the same server port number. ] Each request sent from client to server incorporates, as a part of the message, the port number of the type of server with which the client wishes to communicate. At the server side, each server "listens" and responds only to incoming client requests targeted to "its" port number.
    In order for a (specific) client and server to be able to communicate, both the client and the server must therefore know this server port number. The server port number that a GxStreamServer-based server listens to, and the server port number that a GxClient-based client program connects to, both have a default value (which is fixed in the eXcite library). These server port number default values for GxStreamServer and GxClient are identical to each other.
    In case there is only one GxStreamServer-based server program running on the eXcite, the application programmer can simply use this default server port number; the server and client will then find each other and communicate with each other.
    The application programmer only needs to specify non-default server port numbers in the case that multiple GxStreamServer-based servers are run on the same eXcite.

The server port number can be set to another than the default value as follows:

  • To specify a non-default server port number to the GxStreamServer class, we pass this server port number as the last argument to the GxStreamServer::Open() method. This argument has as its default value the default server port number. The sample "streamingsample/SampleServer.cpp" illustrates this.
  • To specify a non-default server port number to the GxClient class, the application programmer must make use of a PropertySet object passed to the DeviceManager::EnumerateDevices() call. Before passing the PropertySet to the EnumerateDevices() function, the PropertySet object is initialized to contain the port number information. Passing the port number in this way via a PropertySet object into the EnumerateDevices() function will make that the function returns a list containing only the GxStreamServer (=server) objects that use that port number. The sample "streamingsample/SampleClient.cpp" illustrates this.


Application-level protocol

Every type of communication needs a what is called a "communication protocol": a set of conventions about how the communication is structured that is adhered to by both of the communicating parties.

Everything in the lower-level layers of the communication between GxStreamServer-based server and GxClient-based client is hidden from the application programmer by the eXcite library. Only the very highest level of the control and (time-)sequencing of the communication remains visible to the application programmer: this highest level consists of the calls to the member functions of GxStreamServer and GxClient in the application code.

Inherent in the design of the GxStreamServer/GxClient classes is that, for the image transfer to work properly, the server and client application programs must call the member functions of GxStreamServer and GxClient in a certain way, especially with regard to the order (in time) of the function calls. The way in which the client and server application programs, through calls to the member functions of GxStreamServer and GxClient, control the communication so that client and server program interact usefully, is called the "application-level protocol".


Protocol overview

First, we give a diagram that summarizes this application-level protocol. The diagram maps the flow, over time, of the communication process between server and client. (In the diagram, Time increases downward, from top to bottom.)

Below the diagram, we describe in more detail the application-level protocol that client and server program must follow. The desription, like the diagram, simply tracks over time the flow of the communication process between server and client, as seen by the client and server application programs.

In the diagram below, the vertical lines

                              (function starts executing)
                                      |
                                      |
                                      |
                              (function returns)
indicate the period of time during which a function call is executing.

               server                                  client
 ---------------------------------------   ----------------------------------  

 Initialize
  ( = GxStreamServer::Open() )


 Wait for incoming client connection
 and wait till client opens a
 "streaming channel" in that connection
  [ The two waits are one single function call
    =  GxStreamServer::WaitForStreamOpen() ]
                   |
                   |                       Open connection to server
                   |                             = GxClient::Open()      
                   |
                   |                       Open streaming channel
                   |                            = GxClient::PrepareGrab()
                   |
 Sees that client has opened streaming channel
 ( = the GxStreamServer::WaitForStreamOpen()
      call returns successfully )


                                           Get image size
                                               = GxClient::TotalBytes()
                                                          |                 
 Sends image size information                             |                 
                                                          |                 
                                           The GxClient::TotalBytes() call
                                             returns

                                           Get other image dimensions
                                               (width, height, depth)
                                                          |                 
 Sends image width, height, depth                         |                 
                                                          |                 
                                           The GxClient::Width(), Height(),
                                                DataDepth() calls return


                                           Initialize user buffers

                                           Enqueue all user buffers:
                                             call GxStreamServer::QueueBuffer()
                                             for each buffer


 Waits till client sets 
  streamingEnabled to "true"
   ( = GxStreamServer::WaitForStreamingEnabled() )
                  |
                  |                        Sets streamingEnabled := true
                  |
 Sees that client has set 
  streamingEnabled to "true"
  ( = the GxStreamServer::WaitForStreamOpen()
    call returns successfully )


 Starts sending first image
   = { GxStreamServer::QueueBuffer();
       GxStreamServer::WaitForBuffer() }
                   |
                   |                       Calls GxClient::WaitForBuffer() 
                   |                        for retrieving the buffer
                   |                        containing the 1st image
                   |                                      |                 
 Waits till send of first image complete                  |                 
   ( = the GxStreamServer::WaitForBuffer()                |                 
        call returns successfully )                       |                 
                                                          |                 
                                           Waits till receive of 1st image done
                                           and retrieves the buffer containing
                                           the received image
                                             ( = the GxClient::WaitForBuffer()
                                                call returns successfully )

                                           Re-queue the buffer 
                                           for receiving further image data
                                               = GxStreamServer::QueueBuffer();

 Checks if still streamingEnabled == true
  ( = GxStreamServer::IsStreamingEnabled() )

 YES, so ...
 
 Starts sending 2nd image
   = { GxStreamServer::QueueBuffer();
       GxStreamServer::WaitForBuffer() }
                   |
                   |                       Calls GxClient::WaitForBuffer() 
                   |                        for retrieving the buffer
                   |                        containing the 2nd image
                   |                                      |              
 Waits till send of 2nd image complete                    |              
   ( = the GxStreamServer::WaitForBuffer()                |              
        call returns successfully )                       |              
                                                          |              
                                           Waits till receive of 2nd image done
                                           and retrieves the buffer containing
                                           the received image
                                             = GxClient::WaitForBuffer()

                                           Re-queue the buffer 
                                           for receiving further image data
                                               = GxStreamServer::QueueBuffer();


                             ... REPEAT ...

                                 ... UNTIL :

                                           Sets streamingEnabled := false

 Completes sending of Nth image
      = GxStreamServer::WaitForBuffer()

 Checks if still streamingEnabled == true
  ( = GxStreamServer::IsStreamingEnabled() )

 NO, so ...

 Waits for client to close streaming channel
  = GxStreamServer::WaitForStreamClose()
                   |
                   |                       Closes streaming channel
                   |                           = GxClient::FinishGrab()
                   |
 Sees that client has closed streaming channel
    ( = the WaitForStreamClose() call
           returns successfully )


Establishing the connection

For ease of description, we assume (unless explicitly stated otherwise) that each server program instantiates only one GxStreamServer object, and that each client program instantiates only one GxClient object.

Since the server is the passive party and the client the active party, the server program must be "on line" first. Thus, the first act of the process is that the server program is started. As soon as it is started, the server program instantiates a GxStreamServer object, calls its Open() function (which initializes the object), and then calls its WaitForStreamOpen() function. This last function call puts the GxStreamServer object in the state of listening out for, and waiting for, a client that wants to establish a connection with the server.

We speak of a "connection" between a server (= GxSteamServer object) on an eXcite and a client (= GxClient object) on a PC if in some lower-level communication layer, the GxStreamServer and GxClient objects have "seen" each other, and have opened a communication channel between them via the network hardware.

After the "connection" between the GxStreamServer object on the eXcite and the GxClient object on the PC is established, the GxStreamServer and GxClient objects create an additional communication channel between them, which is called the "streaming channel". It is this streaming channel via which the actual image data is transferred from server to client. This streaming channel is best visualized as a higher-level communication channel built on top of the lower-level "connection".

Both the "connection" and the "streaming channel" are communication channels between exactly and only two parties: namely between (on the one side) one specific GxStreamServer object on one specific eXcite, and (on the other side) one specific GxClient object on the PC.


       eXcite 1                                   PC
   ,------------------------------------.      .---------------. 
   |                                    |      |               |
   |  ,--------------. ,--------------. |      | ,----------.  |
   |  |GxStreamServer| |GxStreamServer| |      | | GxClient |  |
   |  |object A      | |object B      | |      | | object   |  |
   |  `--------------'  `----| |------' |      | `---| |----'  |
   |                         | |        |      |     | |       |
   `-------------------------| |--------'      `-----| |-------'
                             | |                     | |
                             | `---------------------' |
                             `-------------------------'
                                connection
                                + streaming channel

The function GxStreamServer::WaitForStreamOpen() blocks, and does not return until a GxClient object has connected to GxStreamSever object and has opened a streaming channnel to it.

Note: Actually, this is not the "whole truth". All the Wait... member functions of GxStreamServer and GxClient make use of a timeout. In all these functions, the timeout value is one of the function parameters. These functions return not only when the event they "wait" for occurs, but they also return when the timeout triggers, i.e. when after waiting for the "timeout" duration, the event still has not occurred. All of these functions have a return value that indicates whether the function ran successfully -- meaning that the function returned because the anticipated event occurred -- or whether the function has returned because the timeout was reached. 

The very act of the GxStreamServer::Wait... returning (with return value indicating success), passes information from client to server: namely, the information that the server has completed the action that the server is waiting for.
    This mechanism of a server function blocking and returning (successfully) only when some action is completed by the client, is used in many places in the high-level (application-level) coordination of the communication between GxStreamServer and GxClient, and constitutes an important ingredient in the application-level protocol.

Note: Every GxStreamServer::Wait...() call must be checked in the server program on its return value. When a return value indicating failure is returned on any of these calls, this means that the client has not properly followed the communiation protocol: e.g. the client may have simply hung up the connection. Whenever a GxStreamServer::Wait...() call returns unsuccessfully, the server can break off the protocol and can terminate the connection. The server program can terminate the connection at any point, irrespective of the state of the connection, by simply calling the GxStreamServer::Close() function. 

In the case of the GxStreamServer::WaitForStreamOpen() function, when this function returns successfully, the server program knows that a client has connected and has successfully established a streaming channel. That is, the server program knows that the streaming channel is up and running.

On the client side, there is no corresponding "wait" involved in the opening of the connection and streaming channel. In general, all over the application-level protocol, the waiting is done on the server side only. This organization means that for a client request to be successful, the server must be in a ready-and-waiting state, waiting for exactly that kind of client request.
    Accordingly, the client-side functions GxClient::Open() and GxClient::PrepareGrab(), which open a connection and a streaming channel respectively, simply carry out their task and then return immediately.


Transferring the image size information

Apart from the image data itself, there is another kind of information that must be transferred from server to client, namely information about the size of the images.

With respect to image size, it is important to note first of all that the GxStreamServer/GxClient-based communication is organized in such a way that:

The image dimensions (width, height, data depth per pixel) are specified by the server program to the GxStreamServer object by means of arguments to the GxStreamServer constructor.

The image size information must actually be transferred from server to client first, before the actual images are transferred. This is because the image size information is needed by the client program in order for it to be able to instantiate buffers into which the received image data can be written.
    The member functions of GxClient that receive images are organized in a way similar to the image-grabbing member functions of Camera (as discussed in the section \ref ssect5a). Specifically, the two sets of member functions are similar in that they write image data into buffers that are supplied by the application programmer.

Information about the size of the images is therefore necessarily the first kind of information that is transferred from server to client, before the first actual image is transferred. For getting the image size information from the GxStreamServer object into the client program, the client program makes use of the following read-only member objects of the GxClient object:

- Width = image width (in pixels)
- Height = image height (in pixels)
- DataDepth = data depth (in bytes) of each pixel
- TotalBytes   = total size (in bytes) of one image

The API of these GxClient member objects is similar to that of the member objects of Camera as discussed in the section \ref sect5b. All the GxClient member objects are of IInteger data type.
    The methods of the GxClient member objects are however implemented differently than those of the Camera member objects. The method GetValue() (like its equivalent operator()) of the GxClient member objects is implemented as the action of getting the relevant value from the server.
    The effect of this is that the member objects of GxClient are not similar to variables (in which an actual value is stored), but are much more like references or pointers: a member object of GxClient is a "window" to a value stored in the connected GxStreamServer object. Each member object of GxClient has a corresponding variable in the connected GxStreamServer object, which is the place where the actual value is stored. When we access the GxClient member object (that is, when we are calling one of its methods), then what we are actually doing is that we are accessing the value of the corresponding variable in the connected GxStreamServer object is accessed. [ Note: The behaviour of (any of) the methods of (any of) the member objects of GxClient is only defined if there is a streaming channel established between the GxClient object and a GxStreamServer object. ]
    As far as the application programmer is concerned, the information transfer actions carried out when the client program calls a method of one of the member objects of GxClient is carried out fully "automatically", i.e. without any explicit coding in either of the server and the client application programs.
    To summarize:

The member objects of GxClient allow the client program to access
the corresponding values stored in the connected GxStreamServer object.

Once the streaming channel is up and running, the first thing that the client program does, therefore, is to call the GetValue() methods of the read-only member objects of GxClient listed above, in order to get the needed image dimension information. With this information, the client program then instantiates the user buffers it needs.
    Note: It is recommended that the client application program uses the TotalBytes value to determine the size of the buffers, instead of computing the buffer size from Width*Heigth*DataDepth.
    As soon as the client program has instantiated the used buffers, it "queues in" these buffers into the GxClient object, by means of calls to the GxClient::QueueBuffer() function. This makes the addresses of the user buffers known to the GxClient object. The GxClient object will start receiving image data, and writing the received data into the available user buffers, as soon as possible.
    The purpose of using multiple user buffers is the same as discussed at the and of the subsection \ref ssect5a for the use case of controlling the eXcite from a local program: namely, to speed up image transfer in the case that a longer sequence of image is to be transferred.


Organization of the image data transfer loop

At this point, we have the client in a state where it is trying to receive image data from the server. Therefore, at this point the server could in principle start sending image data.

That is, we could now make the server enter a loop like this:

	while ( some_criterion )
	{
		send the next chunk of image data
	}
This would work perfectly well: the client would then also enter a similar loop, and would retrieve the received chunks of image data one by one.

This is, in broad lines, indeed the way in which the sending of the actual image data is intended to be carried out by client and server programs that use the GxStreamServer and GxClient classes. That is, during the actual image transfer, both client and server iterate over a loop, where during each pass through the loop, one chunk of image data is sent or received.

The one thing that the organization of the image transfer process as outlined above can not do, is to stop the server on a command issued by the client. Such a "stop server" command fits well with the general kind of system organization of the server being the passive component and the client the active component.
    To allow application programmers to create client/server systems where the server can be stopped on command of the client, the eXcite library provides as way for the client to determine the value of the loop test criterion some_criterion in the image-transfer loop in the server as shown above. The feature that is provided for this is the member object EnableStreaming of GxClient.

In addition to the GxClient member objects already described above, the GxClient class has one more member object, named StreamingEnabled. The function of this member object is to allow the client to tell the server to stop sending data and to terminate the connection.

The member object GxClient::StreamingEnabled is similar to the other member objects: it is a "window" to a variable stored in the connected GxStreamServer object. The only difference between StreamingEnabled and the other member objects is that StreamingEnables is read+write, and not read-only like the other member ojects. This means that for GxClient::StreamingEnabled, the method SetValue() (and its equivalent operator=) is defined. This method sets the value of the variable stored in the connected GxStreamServer object. Whereas the other member objects are used to pass information from server to client, the member object GxClient::StreamingEnabled is used to pass information the other way, from client to server.

The value of StreamingEnabled stored in the GxStreamServer object is intended to be used (by the client) to command the GxStreamServer object to stop or start the transfer of image data. The value false means stop, and the value true means start. Initially, the value (stored in the GxStreamServer object) of StreamingEnabled is false.

On the server side, there are two functions that inspect the value of SteamingEnabled, namely:

bool GxStreamServer::isStreamingEnabled()
Returns the current value of StreamingEnabled.

GxStreamServer::WaitForStreamingEnabled()
Blocks (waits) until StreamingEnabled is true.
Using these functions, the image-sending loop in the server can now be coded as:
	while ( pServer->isStreamingEnabled() )
	{
		send the next chunk of image data
	}
Now, the server can be stopped by the client program, namely simply by the client program setting GxClient::StreamingEnabled to true.

For this to work as intended, we need to add one last extra into the server application program. As mentioned, the initial value of StreamingEnabled is false. However, just before entering the image-sending loop as shown above, the value of StreamingEnabled must be true, otherwise the loop will never get executed even once.

This is the reason why, in the flow diagram, at the server side, we insert a call to the function GxStreamServer::WaitForStreamingEnabled() between the return of the function GxStreamServer::WaitForStreamingEnabled() and point where we enter the image-sending loop. The "wait" that this introduces at server side gives the client a chance (a "time slot") in which it can set StreamingEnabled to true.


Transferring the image data

The transfer of the actual image data, done by the GxStreamServer and GxClient objects, is based on sending individual images, one by one. That is, the image data transfer is organized in "chunks" that are sent sequentially in time, one by one; and the size of the chunks is identical to the image size.

This organization if the image data transfer is possible because both the client and the server know the "chunk" size: i.e., both know at which byte count from the start of the transmission of a new chunk, the end of the chunk is reached. As we already saw above, the image size information is transferred from server to client by the client calling the GetValue() method of the GxClient::TotalBytes member object.

The member functions of GxStreamServer and GxClient that carry out the transfer of images are QueueBuffer() and WaitForBuffer(). Each of these two functions is present in both the GxStreamServer and GxClient classes, and each has a similar function in both classes.

The QueueBuffer() function "enqueues" a user buffer into the GxStreamServer or GxClient object, meaning that the address of the buffer is passed to the GxStreamServer or GxClient object. In addition, for both classes, the QueueBuffer() call also starts the actual sending and receiving of the image data.
    For GxStreamServer::QueueBuffer(), the buffer passed to the function contains image data to be sent. For GxClient::QueueBuffer(), the buffer passed to the function is used by GxClient to write image data into for one of the images that it receives.

The WaitForBuffer() function completes the sending or receiving of one image. The function blocks (waits) until the next image has been fully sent (for GxStreamServer) or received (for GxClient).
    The function GxClient::WaitForBuffer() completes the receiving of one image, and has as one of its output parameters the address of the buffer into which the image has been written. As regards the user buffers, the functions GxClient::QueueBuffer() and GxClient::WaitForBuffer() operate identically to the functions of the same names of the Camera class, used in the use case \ref sectMain2. In case multiple user buffers are used, the way in which the application programmer should go about with respect to these buffers and the GxClient::QueueBuffer() and GxClient::WaitForBuffer() calls, is the same as explained for the use case \ref sectMain2 in the sample MultiGrab (see the Samples Overview in the User's Manual).
    The function GxStreamServer::WaitForBuffer() completes the sending of one image.

For both the GxStreamServer and GxClient objects, whenever a WaitForBuffer() call returns successfully, this means that the GxStreamServer or GxClient object is done with the buffer; that is, the successful return from a WaitForBuffer() call "de-queues" one user buffer (removes one user buffer from the set of buffers known to and being operated on by the GxStreamServer or GxClient object). After a successful return from WaitForBuffer(), the application program can therefore re-queue the buffer (by means of a new QueueBuffer() call).

On the client side, as already explained, it makes sense to use multiple user buffers with one GxClient object. The sense of this is that this may speed up the image transfer. As discussed, a client program will normally enqueue all its user buffers immediately as soon as the buffers are instantiated, i.e. before the first WaitForBuffer() call.
    As soon as one or more user buffers are enqueued in the GxClient object, the GxClient object will start trying to receive image data. If a number of user buffers are enqueued in the GxClient object, then the GxClient object will immediately fill these buffers as soon as image data becomes available. The GxClient object will keep on receiving image data and writing to the image buffers as long as not all enqueued image buffers have been filled.

The GxClient::WaitForBuffer() call can come at any point relative to the image-sending actions carried out by the server: the GxClient::WaitForBuffer() call may (and is allowed to) come before the server starts sending an image, during the time that an image is transferred, or after the transfer of an image is already complete.


The server program

To make all the necessary features from the API of the eXcite library visible to it, the application programmer need only include the following line at the head of the source file(s) for the server program:
	#include <gxdevice/GxStreamServer.h>
It is not necessary in addition to set any #define.

The server functionality provided by the eXcite library sits all in one class: GxStreamServer.

The API of this class has nothing in common with the class(es) used by the client, and/or with the classes used in the use case \ref sectMain1.
    The GxStreamServer class does have the two member functions QueueBuffer() and WaitForBuffer(), which are roughly similar to the mamber functions of the same name of the classes Camera and GxClient. The main difference is, of course, that in the GxStreamServer class, these functions send data, whereas the Camera and GxClient member functions receive. A more minor difference is that the API (the function prototype) of these two functions in GxStreamServer is similar but not identical to that of the corresponding functions of Camera and GxClient.

A server program will normally instantiate just one instance of GxStreamServer. This GxStreamServer instance incarnates the server process.

Overview of the Member functions of GxStreamServer:

1) Methods to initialize and de-initialize GxStreamServer object
2) Methods to for the detect-that-stream-opened part of the communication
3) Methods to for the StreamingEnable part of the communication
4) methods for the send-individual-images part of the communication

For more info on each of these funcs, see the page for [[GxStreamServer]] in the API Reference, which documents all of its member functions.

For an example of all these functions in context in a realistic full server program, Please have a look at the sample streamingsample/SampleServer.cpp. Note that all the classes in the eXcite library may throw exceptions (see \ref sect3), so that most application programs would want to put every use (or instantiation) of any of the classes from the eXcite library inside try ... catch constructs.


The client program

To make all the necessary features from the API of the eXcite library visible to it, include the following lines at the head of the source file(s) for the client program:
	#include <device/DeviceManager.h>
	#include <gxdevice/GxClient.h>
It is not necessary in addition to set any #define.

The purpose of the client program is to download (to "get") images. The eXcite library, in its API design, has made use of the parallel between this and the grabbing of images done by the part of the eXcite library described in the section \ref sectMain1. Where in the section \ref sectMain1 the application program running on the eXcite is grabbing images from the camera portion of the eXcite, in the present case the client program running on the PC is "grabbing" images from a remote eXcite device, over the network.

The most important object in the client program is the GxClient object. The API of this GxClient object is similar to the Camera object described in the section \ref sectMain1.


The member functions of GxClient

The GxClient object has the exact same set of member functions as the Camera object (these member functions of Camera were described in the section \ref ssect5a). In the case of GxClient, the member functions now execute the following actions:

1) Functions to open/close connection to GxStreamServer object
2) Functions to open/close "streaming channel" to GxStreamServer object
3) Functions for the part of the application-level communication protocol in which individual images are transferred

The EnableStreaming part of the appl~ level protocol is done on the client side by means of the EnableStreaming member object of GxClient.


The member objects of GxClient

The GxClient and Camera objects are further similar in that, apart from member function, they each have a set of member objects. In both, these member objects constitute an important part of the API.

Both classes use the same GenApi types for the member objects. (However, the GxClient class, at present, doesn't use any xxxEnums types). Since the data type of the member object determines the set of methods available for that member object, the application program accesses the member objects of GxClient in the same way as the application program accessed the member objects of Camera.
    Therefore, the discussion in the section \ref ssect5b in on the IInteger/IBoolean/IFloat/IString types of the member objects, and on how to use the set of methods for each of these types access the member object, is valid also for the member objects of GxClient.

What is very different between the Camera and GxClient classes however, is the sets of actual member objects of the two classes. The set of The set of member objects of a Camera-like class is referred to as the "control interface" of that class. Thus, we can say that the API of the Camera and GxClient classes is identical, except for the control interface of the two classes.

The complete set of member objects of GxClient is the folllowing:

- EnableStreaming    
- Width = Width of frame in pixels
- Height = Height of frame in pixels
- DataDepth = Number of bytes per pixel
- TotalBytes = Number of bytes in one frame
EnableStreaming is a read-write parameter; the other parameters are read-only.

EnableStreaming is provided as a facility for the client program to pass a command to the server to start or stop the sending of image data. Setting

	pClient->EnableStreaming = true;

passes to the server (that the GxClient object is connected to) the message that it should start sending image data. Setting

	pClient->EnableStreaming = false;

passes to the server (that the GxClient object is connected to) the message that the server should stop sending image data. How EnableStreaming is intended to be used is discussed in some detail in the section \ref sect2_apProt above.

Note, however, that the only thing that the eXcite library does is provide the read+write EnableStreaming member object to the application programmer, together with functions in the GxStreamServer class to query the value of EnableStreaming at the server side. That is, what is provided by the eXcite library in the EnableStreaming member object, is a way to pass one bit of information from client to server.

The client and server programs are free not to use this facility, and are free to use it in any way they want. The EnableStreaming feature is thought to be most useful for transferring "start/stop" commands from client to server, but application programs need not use it for that purpose.

The member objects

- Width = Width of frame in pixels
- Height = Height of frame in pixels
- DataDepth = Number of bytes per pixel
- TotalBytes = Number of bytes in one frame

are all read-only. The purpose of these member objects, as was already discussed in the section \ref sect2_apProt above, is to transfer image size and image dimension data from server to client. Recall that, as explained in that section, the server is the party that determines the values of these quanties.

After the streaming channel between GxClient and GxStreamServer objects is established, the client application program can query these member objects to the image dimensions. This image dimension information is, obviously, needed on the client side for the client to be able to interpret the received image data. In addition to that, the image size information is needed by the client program so that the client program can initialize buffer(s) into which to receive the image data.

The member object TotalBytes is provided specifically for the purpose of informing the client what is the size of the buffer (in bytes) needed for one image. The client program should use

	buffersize =   pClient->TotalBytes()

in preference to calculating the buffer size from the values of Width, Height, and DataDepth.


For more information on how to use the member functions and member objects of the GxClient object to receive ("download") image data from an eXcite running a GxStreamServer-based server program, see the page [[GxClient]] in the API Reference.