When using IP multicast it is expected that the send and recieve addresses will be the same. If multicast is not used, the send and recv addresses should be mirrored on the two machines being used. Ie, machine A should receive on the its own address and send to the address of machine B. The address to receive on is specified explicitly to allow for hosts with multiple IP addresses.
pyx_session() returns an integer handle. This handle is used to reference the newly created session.
The supplied integer send_port is for rtp. The rtcp port is calculated from this.
Errors: Incorrect address(es) specified.
Examples:
session = pyx_session("225.0.0.1", 8888, "225.0.0.1", 8887);
gethostname(my_name, 256);
session = pyx_session(send_address, port, my_name, port);
Example:
rc = pyx_end_session(session);
Example:
rc = pyx_halt();
An SSRC is a way of multiplexing a session. Multiple SSRCs can be made for a particular session. A session will not normally be used without at least one SSRC. The name that is given for the SSRC is global to all the participants in a session. The same name may be used in different sessions to refer to different devices; however, the SSRC number is unique across all sessions.
It is possible for pyx_make_ssrc() to be called more than once for the same device if it is used in different sessions.
Errors:
Example:
ssrc = pyx_make_ssrc(session, "my_camera");
This is not usually needed, as a call to pyx_end_session() will delete all ssrc's that are a part of the session.
Example:
rc = pyx_delete_ssrc(session, ssrc);
typedef int (*pyx_callback) (pyx_frame_t *pf, int session, int ssrc);A pyx_callback is a pointer to a function that takes these parameters: pointer to a pyx_frame_t, int session, int ssrc.
All callbacks that are registered in pyxis are of this type.
If an ssrc with the given name doesn't exist, the name and callback are put on a list of pending callback registrations. Whenever a packet does arrive for that named ssrc, the callback is registered. Names are used so that remote participants can refer to SSRCs without having access to their integer values.
pyx_bind_ssrc() can be called to register a callback for a named SSRC before that SSRC has been created with pyx_make_ssrc(). The callback will be placed in a pending state until notice of the creation of the SSRC is received. This allows frame handling callbacks to be set up before any frames arrive from their corresponding devices.
If an ssrc already has a callback associated with it, that callback will be replaced by the new one. Thus, there can only be one callback per ssrc.
If an ssrc already has a callback associated with it, and is replaced with a null function pointer, the callback will be removed.
The timeval structure will give the timeouts for pyx_timeout callbacks. It may also be used to give timeouts to the other types of callbacks, so that they do not wait indefinitely. If indefinite blocking is desired, the timeval structure may be specified as NULL. A timeval structure that is not NULL, but has a zero value, will result in continuous polling.
If the name is of the form "Wildcard #n", this will be a wildcard bind. When data arrives from an ssrc that does not have a callback pending, it will automatically be named "Wildcard #n". Thus, the first unknown data source can be bound to by specifying "Wildcard #1". This is useful for accepting connections from non-pyxis applications. It could also be used by Pyxis applications which could then negotiate a named ssrc after the inital connection has been made with the wildcard match.
Examples:
rc = pyx_bind_ssrc(session, "my_camera", frame_handler_function, timeout_s, PYX_CB_FRAME_IN); /* This one's for vic interop */ rc = pyx_bind_ssrc(session, "Wildcard #1", jv_frame_in, 0, PYX_CB_FRAME_IN);
An ssrc will last as long as the session that it is a part of. The packets describing the ssrc and its name will be continually broadcast. The broadcast frequency may slow down over time to prevent too much bandwith from being used for this control information.
Example:
rc = pyx_ssrc_isbound(session, ssrc);
Example:
rc = pyx_name_to_ssrc(session, "my_camera");
This structure is internal to pyxis and should not be modified in any way. The values in the structure will be updated as frames arrive from that ssrc.
??? Thus, after calling pyx_get_ssrc_stats once, the structure returned may be examined many times to see the current values of its member fields.
typedef struct pyx_ssrc_s{
unsigned int ssrc;
int session;
char name[NAME_LENGTH];
pyx_callback_t f;
pyx_callback_t bye_f;
/* int pending; not needed */
source_t s;
} pyx_ssrc_t;
#define MAX_SDES_ITEMS 10
/*
* Per-source state information
*/
typedef struct {
u_int32 max_seq; /* highest seq. number seen */
u_int32 cycles; /* count of seq. number cycles */
u_int32 base_seq; /* base seq number */
u_int32 bad_seq; /* last 'bad' seq number + 1 */
u_int32 received; /* packets received */
u_int32 expected_prior; /* packet expected at last interval */
u_int32 received_prior; /* packet received at last interval */
u_int32 transit; /* relative trans time for prev pkt */
u_int32 jitter; /* estimated jitter */
/* added by Stan */
int sd_count;
rtcp_sdes_item_t sd[MAX_SDES_ITEMS];
} source_t;
Errors: Incorrect ssrc name specified.
Example:
pyx_ssrc_t *sp; rc = pyx_get_ssrc_stats(session, "my_camera", &sp);
typedef struct pyx_frame_s{
int type; /* encoding type of frame, as in ietf-avt-profile */
int seq; /* frame sequence number (different from rtp sequence number) */
unsigned int tstamp; /* timestamp, generate automatically if NULL */
int full; /* is this frame complete? */
int seg_count; /* number of segments in this frame */
pyx_segment_t seg[MAX_SEGMENTS_PER_FRAME];
} pyx_frame_t;
typedef struct pyx_jpeg_frame_s{
pyx_frame_t frame;
int jpeg_type, width, height, q;
/*
char *header;
int header_len;
*/
} pyx_jpeg_frame_t;
The pyx_frame_t structure may be extended (as in the pyx_jpeg_frame_t struct) to add information needed for a particular encoding. If so, this extended structure must start with a pyx_frame_t struct. Currently, jpeg is the only extended structure.
The format of the time stamp is dependant on the RTP profile. It must be derived from a clock that increments monotonically and linearly in time. If RTP packets are generated periodically, the sampling clock should be used, not the system clock. For example, if 160 samples are sent per packet, the time stamp should increment by 160 every time a sample is taken, whether or not it is sent over the network. The initial value is random. Several packets may have the same timestamp if the are generated at once (ie, belong to the same video frame.)
/* A segment is a chunk of data. One or more segments can form a frame */
typedef struct pyx_segment_s{
int offset;
int len;
char *data;
} pyx_segment_t;
This specifies a buffer of data. There is a pointer to the region of memory,
*data, and a length, len. The memory will be copied as raw bytes.
offset indicates the offset of this segment into the whole frame.
Example:
rc = pyx_write(session, ssrc, &pf);
Example:
rc = pyx_setopt(session, PYX_OPT_TTL, 16);
Example:
rc = pyx_getopt(session, PYX_OPT_TTL);
Example:
perror("my_function");
If there was no memory left, this would output the following:
my_function: No memory left
typedef int (*pyx_err_handler) ();
Sets the error handler to the specified function. Note that there is no session specified. There is only one error handler per task. This is to allow the proper handling of errors that don't belong to any one session. (Such as invalid session handles).
Example:
my_error_handler(){
if(pyx_errno==PYX_ERR_NO_MEM) fprintf(stderr, "free some memory\n");
else perror("PYXIS ERROR: ");
}
rc = pyx_set_error_handler(my_error_handler);
Example:
rc = pyx_main();
When indefinite blocking is specified with a NULL timeval pointer arg to pyx_bind_ssrc, what actually happens is that a very large timeout is used by pyxis. This event is re-registered each time the timer expires, so the same effect is achieved.