| acp_out_container.c File : acp_out_container.c
Description : ACPOUT Container Development Functions
Category : ACP Container
Author : Charles Yates
This source file and its header define the ACPOUT Container functions. These
functions allow a container to register callbacks and are distinct from the
ACPOUT Scripting functions which are for use in .acp scripts and in the containers
callback code.
Without a callback, the acpout structure will grow to accomodate the entirety of the
data written to it. Hence, to output a complete output structure to an open file, the
following type of function could be used:
void Output( FILE *file, ACPOUT out )
{
int index = 0;
int count = 0;
for ( index = 0; index < ACPOUT_Count( out ); index ++ )
{
count = ACPOUT_GetLength( out, index );
fwrite( ACPOUT_Get( out, index ), 1, count, file );
}
}
Obviously, if the amount of data is large the above approach is far from
efficient since the whole of the input must be in the output structure. This
causes large overhead when delivering graphic, audio or video content. An
alternative approach can be set up as follows:
1. A user defined structure can be associated to the output structure
using the SetUser and GetUser functions;
2. A call back function must be set up which receives an ACPOUT as it's
only argument and must be registered with the SetFlush function.
3. Optionally the amount of data to be buffered before the registered
function is called can be specified via SetMaxSize;
4. The registered function can write out and clear the data in the output
before returning.
An example which streams data from an audio file to an open socket (fd):
extern int Flusher( ACPOUT out );
void Transfer( int fd, char *file )
{
ACPOUT out = ACPOUT_Init( );
// For convenience, convert a socket file descriptor
FILE *user = fdreopen( fd );
// Set up input variables
FILE *in = fopen( file, "r" );
char buffer[ 1024 ];
int count = 0;
// Register info
ACPOUT_SetUser( out, user );
ACPOUT_SetFlush( out, Flusher );
// Start outputting
while ( ( count = fread( buffer, 1, 1024, in ) ) != 0 )
ACPOUT_Write( out, buffer, count );
fclose( in );
fclose( user );
ACPOUT_Close( out );
}
int Flusher( ACPOUT out )
{
FILE *file = ACPOUT_GetUser( out );
for ( index = 0; index < ACPOUT_Count( out ); index ++ )
{
count = ACPOUT_GetLength( out, index );
fwrite( ACPOUT_Get( out, index ), 1, count, file );
}
ACPOUT_Clear( out );
return 0;
}
Using the default max size (as in the above example), the out structure
will be flushed every time 10k is read from the file.
Note that the container should be responsible for dealing with the headers
on the first call. It can use the ACPOUT_SetStreaming function to track this.
It should not attempt to specify a Content-Length header in the flusher function,
though it is free to do so after the ACP_Run call (obviously, it won't take
effect if the ACP_GetStreaming call returns a non-zero).
ACPOUT_SetUser void DLLEXP ACPOUT_SetUser( ACPOUT out, void *user )
Function : ACPOUT_SetUser
Description : Sets the user defined structure
Input : ACPOUT out - output structure to use
void *user - pointer to user defined structure
Output : user defined structure is associated to out
Returns : void
ACPOUT_GetUser void * DLLEXP ACPOUT_GetUser( ACPOUT out )
Function : ACPOUT_GetUser
Description : Gets the user defined structure
Input : ACPOUT out - output structure to use
Output : void
Returns : void * - pointer of user defined structure
ACPOUT_SetFlush void DLLEXP ACPOUT_SetFlush( ACPOUT out, ACPOUT_FLUSHER flusher )
Function : ACPOUT_SetFlush
Description : Sets the flushing call back function
Input : ACPOUT out - output structure to use
ACPOUT_FLUSHER flusher - function to flush the output
Output : output structure is updated
Returns : void
|