Functions :
Data Structures :
This document introduces a stream based software interface used by the Cheops I1 Video Input module. The I1 Input Card is a daughter-card to the M1 Memory module, and it buffers the video data being input in the M1 core memory. This stream model allows simple access to both video data being digitized and video data stored previously on M1. The buffer memory for all streams is maintained using the M1 movie library, and may be accessed (i.e. loaded or stored to disk) through the M1 movie utilities.
Time is maintained using the Stream Time data structures.
An example application using this library is available.
It must be emphasized that this library must be used in
conjunction with the RMan library and
the Norman Resource
Manager. In particular, the RmanInit()
function must be called before calling any I1 Stream function that
returns a QueueElem *
, such as
RmanInputReadStream()
.
There may be up to four input modules in a system, each designated by
a unique card id (that of the M1 card to which it is mounted.) Each
card has from one to seventeen source devices, designated by a device
id. The input source struct provides a unique and simple name for
each source. It is defined as a struct (of 32 bits) containing both
the card ID and the device ID.
The principal datatype in the software interface, a video stream,
is a sequence of color image frames from a single source. This
sequence may be either finite or infinite in length, and usually
represents a regular temporal sampling. Thus a video stream may be
anything from a single frame, or set of key frames, to a continuous
(and possibly subsampled) stream of frames. Routines are provided for
opening, reading, indexing into, and closing video streams.
Video streams are represented in applications by a pointer to an
input_stream_hdr. This header is created by
RmanInputOpenStream() or
RmanInputConnectStream(),
and either destroyed by
RmanInputCloseStream()
or non-destructively detached by
RmanInputDetachStream().
When an application creates a video stream, the number of frames
of buffering to be provided is specified. If the application is not
going to be processing the data in real time (i.e. at the temporal
sampling rate) the number of frames of buffering should be equal or
greater than the length of the video stream. When the video stream is
"infinite", the stream buffers store the last N frames digitized,
where N + 1 is the number of frames in the stream buffers. If the
application will be attempting to process the video stream in real
time the number of frames of buffering may be as small as two or
three, although larger stream buffers will generally produce better
results.
The video stream may be accessed by using
RmanInputReadStream()
to generate an Input Stream Queue Element, a QueueElem
structure. An Input Stream Queue Element represents the transfer of
one frame in the input stream into local P2 memory when connected into
a Transfer Pipe for execution by the Norman resource manager.
Multiple Input Stream Queue Elements may be created accessing the same
stream. Which frame is selected for transfer may be changed. A frame
that hasn't been digitized at the time when the pipe is presented for
execution may be selected. The resource manager will wait until the
frame has been digitized into the stream buffer before being
scheduling that transfer for execution.
In many cases of "real time" processing, the input video data is
temporally decimated to provide a lower temporal rate stream for
processing. The temporal decimation to be applied is specified using
the decimation_factor structure, which contains an array of interframe
offsets, the size of the offset array and the current index into the
offset array. The array of offsets is used repeatedly as necessary,
the value of the last entry in the offset array indicating the delay
before digitizing a frame corresponding to the first entry in the
array. Regular decimations therefore require only a single entry in
the offset array, but complex sampling patterns may also be
implemented simply. The offsets are specified, in frames, using 16
bits, which allows delays up to 18 minutes (at 60 fps) between
samples.
The last of the pre-defined decimation_factors,
example_decimation, shows a temporal decimation where four frames are
grabbed consecutively out of every sixteen frames of input video.
The destination buffers in P2 for data from a particular frame are
specified using the input_stream_dest structure, which is an array of
pointers. The exact number of destination buffers required varies
with the input sources configuration type. The two currently defined
formats (NTSC_FORMAT and RGB_FORMAT) both use only three channels
(entries 0, 1, and 2 in the array.) The input_stream_size structure
is used to represent the spatial size of one stream channel. An array
of input_stream_sizes is returned by
RmanInputStreamSize().
The functions described here are part of the Rman library. Their
prototypes are provided in
cheops_rman.h.
All applications must
either open a stream or connect to a stream already stored in M1
memory, using
RmanInputOpenStream() or
RmanInputConnectStream().
This returns a pointer to an input_stream_hdr, which can be used to
determine the spatial size and other characteristics of the stream.
RmanInputReadStream( ) takes a pointer to an input_stream_hdr and
returns an Rman QueueElem that represents the transfer of a frame of
data from the stream into local memory.
When an application is finished with a stream, it may close the stream
using RmanInputCloseStream(),
destroying the associated memory buffer if no other applications are
currently connected to it. Or it may merely detach from the stream,
using
RmanInputDetachStream(), leaving
the memory buffer intact in memory for later applications.
An Input source may normally only be used by a single application
at a time. The exception are applications explictly designed to share
video data. The first of these applications to call RmanInputOpenStream() opens the input
stream, allocating memory for the buffer and making an entry in the
movie directory pointing to it. Later applications attempting to open
that input source will "transparently" connect to the stream buffer
though the movie directory.
The temporal sampling is specified when a stream is opened, but
may be modified using the RmanInputChangeSampling( ) function. The
spatial sampling rate, along with many other video input configuration
options, may be modified by using the cheops_i1 library. A
stand-alone application which provides a convenient user interface for
all such video configuration changes is available.
If the starting stream_time is an absolute time, this function
starts by querying the I1 Address Generator to see if it is possible
to access that input source for the selected time span (and reserving
it if it is.) If possible, it allocates memory on M1 for the stream
buffer, and makes an entry in the movie directory for the buffer using
the name provided. If a movie or movies with the requested name
already exists, the name is suffixed with a higher version number.
The function then informs the I1 Address Generator (AG) about the
location of the stream buffers and enables the transfer. Digitizing
into the stream buffer will occur when the indicated stream time is
reached by the input source.
If the starting stream_time is TIME_IMMEDIATE, this function starts
by querying the I1 Address Generator to see if it is possible to
access that input source. If possible, it allocates memory on M1 for
the stream buffer, and makes an entry in the movie directory for the
buffer using the name provided (same as absolute time case). A later
call to RmanInputEnable() is
required to start the Address Generator digitizing data into the
stream buffer. This allows applications to decouple the stream open
from the start of digitizing when using relative time.
If, in either case, it is not possible access the specified input
source (either because it is in use or doesn't exist) the movie
directory is checked to see if a buffer with the name provided has
already been created. If such a buffer exists, it is opened and used.
If multiple buffers with the name and a version suffix are present,
the one with the highest version number is used. It is assumed that
such a buffer was created by another instance of this application, and
the stream will be shared. This is referred to as a "transparent
connect".
The movie directory entry for the stream buffer being used is
modified to increment the "open_links" field, used by
RmanInputCloseStream().
Finally, this function builds an input_stream_hdr structure for the
stream. A pointer to this structure is returned to the application.
I suggest the following conventions for naming the stream buffers :
Checks the M1 movie directory to see if the indicated buffer
exists. If so, it is opened, and the frame in the buffer with the
earliest stream_time is selected for transfer. The "open_links"
attribute of the movie is incremented. An input_stream_hdr
This function is provided for use by applications that assume that
the video data they are procesing was previously digitized and stored.
Using this function ensures that a previously stored data is used.
Destructively closes a stream created with
RmanInputOpenStream(). The number of applications using
the stream is indicated by the open_links field of the associated
movie structure. If only one application is using the stream, the
memory used for the stream buffer is also deallocated. If more than
one application is using the stream, the open_links attribute is
decremented but the buffer memory will not be freed. If this function
is called with an Input Stream Queue Element that was created using
the RmanInputConnectStream() function, the action is
identical to that of RmanInputDetachStream().
Nicely detaches from a stream, deallocating the input_stream_hdr
but leaving the movie data stored in M1 memory. The open_links
attribute of the stream buffer movie will be decremented, but the
movie is not deleted even if no other applications are currently
connected to it.
These functions support the allowed manipulations on a stream.
These are : providing multiple frames at a time, changing the temporal
sampling rate, changing the local destination, enabling and disabling
the stream. One additional feature provided through the Rman
interface is the ability for an application to be notified if the
configuration of a particular input source is modified.
This function allocates space on the Rman heap and generates a
QueueElem representing the transfer of a frame of data from the stream
buffer of the indicated stream to the P2 local memory indicated.
There is no procedure for deallocating memory objects on the Rman
heap, hence this routine has no equivalent function for free'ing the
QueueElems. Don't keep generating new QueueElem in the application !
Modify existing ones instead.
Modifies an Input Stream Queue Element to transfer a particular
frame from the stream into a particular location P2 local memory. The
desired frame may be identified by providing either an absolute or
relative stream_time. If selected using absolute time, the frame
temporally closest to the stream_time desired is selected for
transfer. If two frames are equidistant, the earlier (in time) will
be selected.
If the same P2 destination buffers are to be used, a NULL pointer
may be passed either for the pointer to the input_stream_dest
structure (if all destination buffers remain the same) or for
individual pointers within the structure that remain the same.
The absolute stream_time of the frame actually transferred is
returned to the caller upon succesful modification of the queue
element. If, however, the desired frame has already been deleted from
the buffer of an infinite stream (i.e. too far in the past), or the
desired frame is outside of the range of an finite stream, an
TIME_INVALID value is returned.
This function modifies an input_stream_hdr to change the temporal
sampling rate of the stream. The spatial sampling rate, along with
many other video input configuration options, may be modified by using
the cheops_i1 library.
In implementation, this function checks to make sure that the
stream is associated with a digitizer, then passes a message to the
appropriate I1 Address Generator to restart the stream with the new
parameters. If not associated with a digitizer, no action is taken
and no error is returned.
This function enables the appropriate channels in the address
generator, allowing video to be digitized. It is only needed when the
stream was created by calling
RmanInputOpenStream()
with stream_time of TIME_IMMEDIATE. If the stream is not associated
with an input source (i.e. a "transparent connect" occured) this
function has no effect and returns without an error.
In implementation, this function sends a message to the
appropriate I1 address generator (AG) to query the status of the input
source and reserve it if available. If it is still available, the
information about the stream buffer is passed in a message and
digitizing is enabled to occur at the indicated stream time. It is
possible that the input source is no longer idle, and this function
will fail, returning an RMAN_RSRC_NOT_FREE error.
This function provides the requested information about the frame
and stream associated with the input_stream_hdr provided. Any of the
other arguments may be NULL, if the application doesn't require
that information.
If called with the INSTALL operation, this function installs a
callback function that will be called if any changes are made to the
configuration of the specified input source. If called with the
REMOVE operation, it removes the callback function.
The callback function is defined as returning void, and taking an
InputSource as its only argument.
Returns the current timecode of a Input source. Beware that this
function currently only works when the stream library is being used to
digitize video from the indicated source.
Modifies the timecode of a Input source. Note that this is not
effective if the Input source has a timecode type other than
TIMECODE_FREE_RUN.
The following routines are part of the I1 library. Their
prototypes and defines may be found in cheops_i1.h. The configuration
of each input source may be altered by several different applications.
The state of the current configuration for each input source is stored
in a global data structure. The contents of this table may be read
and written by any application. A number of the configuration
parameters are common across the different sources, and are defined in
the InputDescCommon structure (shown below.) A separate
structure is defined for each configuration type supported.
The current configuration of a particular input source may be
examined by means of the GetInputConfig() function, which
returns a pointer to the configuration structure for that input
source. The SetInputConfig() function copies a
configuration structure into the global table. In general,
applications should not modify the configuration of an input source.
They should, however, properly handle a change in the configuration of
an input source. The RmanInputConfigNotify() function
allows the installation of a routine to be executed after any changes
to the configuration of the specified input source.
Uses a Magic7 system call to get a pointer to the global input
configuration table, then indexes into it and returns a pointer to the
configuration structure for that source.
Uses a Magic7 system call to get a pointer to the global input
configuration table, indexes into the table and then copies the
InputCardDesc structure passed as an argument into the proper entry.
It then calls RmanInputReset(), which causes the Norman Resource
Manager to notify any applications which have requested notification
of input change, using RmanInputConfigNotify().
See an example application
using this library. A completely functional (?) example may be found at
${CHEOPS_BASE}/local/src/diag/rman/streams/show.c
typedef struct {
unsigned long device:16,
card:16;
} InputSource;
typedef struct {
unsigned long num_offsets;
unsigned long index;
unsigned short offset[ MAX_SAMPLING_OFFSETS ];
} decimation_factor;
decimation_factor input_no_decimation = { 1, 0, 1 };
decimation_factor input_half_rate_decimation = { 1, 0, 2 };
decimation_factor example_decimation = { 4, 0, 1, 1, 1, 13 };
typedef struct {
unsigned long *chan[ MAX_SOURCE_CHANNELS ];
} input_stream_dest;
typedef struct {
unsigned long hor; /* The horizontal size of a frame */
unsigned long ver; /* The vertical size of a frame */
} input_stream_size;
Stream Creation and Destruction
RmanInputOpenStream
Arguments
Returns input_stream_hdr *
RmanInputConnectStream
Arguments
Returns input_stream_hdr
RmanInputCloseStream
Arguments
Returns void
RmanInputDetachStream
Arguments
Returns void
Stream Manipulations
RmanInputReadStream
Arguments
Returns QueueElem *
RmanInputIndexStream
Arguments
Returns stream_time
RmanInputChangeSampling
Arguments
Returns int
RmanInputEnableStream
Arguments
Returns int
RmanInputStreamSize
Arguments
Returns int
RmanInputConfigNotify
Arguments
Returns int
RmanGetTimecode
Arguments
Returns stream_time
RmanSetTimecode
Arguments
Returns int
Input Source Configuration Library Routines
typedef struct {
short device_present; /* either TRUE or FALSE */
short config_type; /* NTSC_FORMAT, RGB_FORMAT, etc... */
short resolution_x; /* x dimension of resolution */
short resolution_y; /* y dimension of resolution */
long frame_rate; /* frame rate, in TIME_FRACTIONS */
float aspect_ratio; /* hor / ver ratio */
short timecode_type; /* type of timecode (VITC/LTC/Run) */
short interlaced; /* either TRUE or FALSE */
short median_filtered; /* either TRUE or FALSE */
short chroma_x; /* x dimension of chroma channels */
short chroma_y; /* y dimension of chroma channels */
short h_blank; /* offset from hor. sync to start of video */
short v_blank; /* offset from ver. sync to start of video */
} InputDescCommon;
typedef union {
InputDescCommon common;
InputDescNTSC ntsc;
InputDescRGB rgb;
long raw[ MAX_INPUT_DESC_SIZE ];
} InputCardDesc;
GetInputConfig
Arguments
Returns
SetInputConfig
Arguments
Returns
Return to Software Index
Return to Cheops Homepage
wad@media.mit.edu
This is a "fix it yourself" page,
located at ${CHEOPS_BASE}/WWW/software/i1streams.html