The SIH plugin API replaces the old SII plugin API. mtvp-sdk version 1.0.7.0 and later uses the SIH API for input plugins. Upcoming versions of mtvp-sdk will not support the old SII plugins (sorry). The new SIH plugin architecture is very similar to the old SII plugin architecture and migration should be easy.A SIH plugin is a dynamic library that the application can dynamically link to mtvp to add support to a new input type. An SIH plugin defines the set of routines that mtvp uses internally to open, read, seek and close a particular type of input stream.
SIH plugins are linked to mtvp with the COM_SIH_LINK command. It is possible to link several SIH plugins at the same time.
SIH plugins may be very useful if you want to play from a non standard input. The application could of course read the data a separate process and pipe the data into the the standard input player, but this involves several buffer copies and makes the stream always non-seekable. Using an SIH plugin is much more efficient and allows seeking (when possible).
Support for SIH plugins is currently available for all platforms for which mtvp-sdk version 1.0.7.0 (or later) is available, except HP.If you would like SIH plugin support for a platform for which it is not currently available, please send a request to info@mpegtv.com.
An SIH plugin is a dynamic library (.so file) that defines the following symbols:SIH_register is called by the Player to register the SIH plugin. SIH_register should initialize the SIH_EXPOSED structure with the adresses of the various routines of the SIH plugin. It should be defined as:[*] int _init(void); [*] int _fini(void); int SIH_register(SIH_EXPOSED *sih_exposed); [*] means that the routine is optional.
The SIH plugin should define the following static routines:int SIH_register(SIH_EXPOSED *sih_exposed) { sih_exposed->SIH_version = SIH_VERSION; sih_exposed->SIH_init = SIH_init; sih_exposed->SIH_free = SIH_free; sih_exposed->SIH_probe_url = SIH_probe_url; sih_exposed->SIH_open_url = SIH_open_url; sih_exposed->SIH_close = SIH_close; sih_exposed->SIH_read = SIH_read; sih_exposed->SIH_lseek = SIH_lseek; sih_exposed->SIH_cntl = SIH_cntl; sih_exposed->SIH_fd = SIH_fd; sih_exposed->SIH_size = SIH_size; sih_exposed->SIH_buffer = SIH_buffer; return 0; }
static void *SIH_init(const SIH_RESOURCES *sih_resources, const char *p); static int SIH_free(void *handler_data); static int SIH_probe_url(const SIH_RESOURCES *sih_resources, const char *url); static void *SIH_open_url(void *handler_data, const char *url); static int SIH_fd(void *stream_data); static int SIH_read(void *stream_data, char *buf, size_t count); [*] static off_t SIH_lseek(void *stream_data, off_t offset, int whence); [*] static off_t SIH_size(void *stream_data); static int SIH_close(void *stream_data); [*] static int SIH_cntl(void *handler_data, const void *data, u_int size); [*] static void SIH_buffer(void *handler_data, SIB_IPL_SIZES *sizes); [*] means that the routine is optional and can be set to NULL by SIH_register.
An SIH plugin must be fully reentrant, i.e. it should not have ANY global or static variables. SIH plugins should be compiled with the -DREENTRANT compiler flag.Any "global" variable should be implemented as an element of the HANDLER_DATA structure dynamically allocated and returned by SIH_init.
Unless otherwise specified, each routine returning an int should return 0 when successful, and -1 (with errno set) in case of error.
static int _init(void)
If defined, this routine is called right after the SIH plugin is linked.
static int _fini(void)
If defined, this routine is called right before the SIH plugin is unlinked.
static int SIH_probe_url(const SIH_RESOURCES *sih_resources,
const char *url)
Probe a URL.This routine is called to ask the SIH plugin if it can handle the specified URL. Note that this routine may be called before SIH_init, i.e. before the SIH plugin has been initialized.
- If the SIH plugin can handle the URL, it should return 0.
- If the SIH plugin cannot handle the URL, it should return -1 (errno doesn't need to be set).
static void *SIH_init(const SIH_RESOURCES *sih_resources,
const char *p)
Instanciate the SIH plugin.This routine instanciates the SIH plugin i.e. allocates a HANDLER_DATA structure for storing its "global" variables, initializes this structure and returns a pointer to this structure as an opaque handler_data pointer (void *handler_data). The HANDLER_DATA structure, defined and known only by the SIH plugin, should contain at least the sih_resources pointer passed to SIH_init:
You can initialize the SIH plugin by sending a COM_SIH_INIT message./* handler data */ typedef struct { const SIH_RESOURCES *sih_resources; ... anything you want ... } HANDLER_DATA;
The parameter of COM_SIH_INIT must be formed of an SIH_HANDLER_ID identifying the SIH plugin (SIH_HANDLER_ID is an int), followed by a string. A pointer to this string will be passed to SIH_init as its second parameter.
If you do not send a COM_SIH_INIT, SIH_init will be called automatically before the handler opens its first URL, and in that case the second parameter passed to SIH_init will be that URL.
In all the following routines, the "void *handler_data" parameter is the pointer that was returned by SIH_init.
static int SIH_free(void *handler_data)
Delete the SIH plugin instance.The routine can be called only when the SIH plugin has no opened streams.
SIH_free should release any resources allocated by SIH_init and free the memory referenced by the handler_data that was returned by SIH_init.
After a call to SIH_free, the "void *handler_data" pointer should be considered invalid.
SIH_free is called automatically before the player quits, but it can also be called explicitely by sending a COM_SIH_FREE message, with a "int handler_id" as parameter to identify the SIH handler.
static void *SIH_open_url(void *handler_data,
const char *url)
Open a URL.SIH_open_url allocates a STREAM_DATA structure to store all the resources associated with the stream. It should initialize this structure and return a pointer to it as an opaque pointer (void *stream_data). The STREAM_DATA structure, defined and known only by the SIH plugin, should contain at least the handler_data pointer:
If the specified URL cannot be opened, SIH_open returns NULL and sets errno./* stream data */ typedef struct { HANDLER_DATA *handler_data; /* should always be there */ ... } STREAM_DATA;
In all the following routines, the "void *stream_data" parameter is the pointer that was returned by SIH_open.
static int SIH_fd(const void *stream_data)
Get file descriptor associated with specified stream.This routine must return a real file descriptor. The Player calls select on this file descriptor and if there is something available for reading on it, calls SIH_read (provided that there is buffer space available to read some input data).
The file descriptor returned by SIH_fd does not have to be the actual fd used by SIH_read to read the stream. It may be one end of a control pipe.
static int SIH_read(void *stream_data,
char *buf,
size_t count)
Read stream data.SIH_read is normally called when data is available for reading on the fd returned by SIH_fd. However, it is possible that SIH_read be called if there is no data to be read on the fd returned by SIH_fd. If there is no data immediately available, SIH_read should return -1 with errno set to EAGAIN.
SIH_read must always behave like a non-blocking read (i.e. like read behaves when the flag O_NONBLOCK set). This means that SIH_read should never block, even if there is not enough data immediately available (or no data available at all, for some reason).
If there is less data available than requested, SIH_read should copy all the data available into the buffer and return the number of bytes copied, which should be > 0 and <= count.
SIH_read returning 0 means EOF.
All read errors (except EAGAIN) are considered like EOF.
IMPORTANT: SIH_read should NEVER block. If there is no data immediately available, SIH_read should return -1 with errno set to EAGAIN.
static off_t SIH_lseek(void *stream_data,
off_t offset,
int whence)
Seek in stream.SIH_lseek must behave exactly like the regular lseek routine. In particular SIH_lseek should return -1 with errno set to ESPIPE (regardless of the offset and whence parameters) if the stream does not support seeking.
If SIH_lseek is set to NULL by SIH_register, it is assumed that the stream does not support seeking.
static off_t SIH_size(void *stream_data)
Get stream size, in byte.SIH_size should return the size of the stream, in bytes, or -1 (and set errno) if the stream size cannot be known.
If SIH_size is set to NULL by SIH_register, appropriate calls to SIH_lseek are used to determine the size of the stream.
Note: It is possible to have streams that support SIH_size (i.e. size of stream is known), but yet do not support seeking.
static int SIH_close(void *stream_data)
Close specified stream.This routine must release every resource allocated by SIH_open and free the STREAM_DATA structure. All the resources allocated for the specified stream should be released.
After a call to SIH_close, that "void *stream_data" pointer should be considered invalid.
static int SIH_cntl(void *handler_data,
const void *data,
u_int size)
Handle private messages from application.SIH_cntl is called if and only if the application sends the message COM_SIH_CNTL. The SIH plugin must be already initialized.
Note that size is always <= sizeof(PMP_DATA_GENERIC) - sizeof(SIH_HANDLER_ID), as defined in pmp.h, i.e. <= 1020 bytes.
To call SIH_cntl, the application must send a COM_SIH_CNTL message with a parameter being this block of data starting with a SIH_HANDLER_ID identifying the SIH plugin (SIH_HANDLER_ID is an int). The block of data following the SIH_HANDLER_ID will be passed to SIH_cntl.
If SIH_cntl is set to NULL by SIH_register, COM_SIH_CNTL messages will do nothing and return an error status.
static void SIH_buffer(void *stream_data,
SIB_IPL_SIZES *sizes)
Set buffer specification.If SIH_buffer is defined, it is called after SIH_open_url (and before any call to SIH_read). SIH_buffer must initialize the SIB_IPL_SIZES structure. The values in the SIB_IPL_SIZES structure are used to allocate the buffer pool.
If SIH_buffer is set to NULL by SIH_register, the default buffer specification is used.
You should probably not define SIH_buffer unless you have a very good reason for not using the default buffer specification.
Sending a COM_SIH_LINK message causes the player to link an SIH plugin. The application can link several SIH plugins at the same time.The parameter of COM_SIH_LINK is the full pathname of the SIH plugin (.so file).
If you want to communicate with a particular handler (built-in or plugin), using the messages COM_SIH_INIT, COM_SIH_CNTL, A2G_COM_SIH_FEEDBACK or COM_SIH_FREE, you need to know the handler_id which is an integer identifying the handler.The built-in SIH handlers have the following ids:
To get the handler_id of an SIH plugin, you should ask for the return status of the COM_SIH_LINK message.SIH_HANDLER_ID_HTTP_FTP for the HTTP and FTP handler. SIH_HANDLER_ID_PORT for the raw TCP/UDP handler. SIH_HANDLER_ID_VCD for the VCD handler. SIH_HANDLER_ID_FD for the FD handler. SIH_HANDLER_ID_FILE for the FILE handler.
If the status indicates that no error occured (i.e. if you get a message of type A2G_COM_RETURN_SUCCESS in return), the handler_id is passed back in the data.data_return_success.value of the A2G_COM_RETURN_SUCCESS message.
To get the return status of a message, the application must pass the PMP_FLAG_RETURN_STATUS flag when sending the message. Note that passing also the flag PMP_FLAG_RETURN_ORIGINAL causes the original message to be sent right after the return status, which is can be used to identify the source of a return status message.
Sending a COM_SIH_UNLINK message causes the player to unlink the specified SIH plugin.The parameter of COM_SIH_UNLINK is the handler_id of the SIH plugin.
Is is not possible to unlink an SIH plugin that has a stream opened. If the current stream was opened by the SIH plugin that you want to detach, the stream must be closed first using the COM_CLOSE_STREAM message.
The COM_OPEN_STREAM_URL message causes the Player to open a stream using the first built-in handler or SIH plugin that recognizes the URL (i.e. with SIH_probe_URL returning 0). The SIH plugins are probed before the built-in handlers.The parameter of COM_OPEN_STREAM_URL is a URL (string).
The COM_CLOSE_STREAM message causes the Player to close the current stream.
The COM_SIH_CNTL message causes the SIH routine SIH_cntl of the specified SIH plaugin to be called with the specified parameter.The parameter of COM_SIH_CNTL is an SIH_HANDLER_ID identifying the plugin (SIH_HANDLER_ID is an int) followed by an arbitrary chunk of data.
Note: The size of the chunk of data must be <= sizeof(PMP_DATA_GENERIC) - sizeof(SIH_HANDLER_ID), as defined in pmp.h, i.e. <= 1020 bytes. If size is larger than the maximum value authorized, then the message will return the error status EINVAL.
Any of the routines in an SIH plugin (except SIH_register, _init and _fini) can send arbitrary feedback data to the application by calling:int (*sih_resources->feedback)( const SIH_RESOURCES *sih_resources, const void *data, u_int size );
Note: size must be <= sizeof(PMP_DATA_GENERIC) - sizeof(SIH_HANDLER_ID), as defined in pmp.h, i.e. <= 1020 bytes. If size is larger than the maximum value authorized, sih_resources->feedback returns -1 and sets errno to EINVAL.
- sih_resources is the pointer passed to SIH_init or SIH_probe_url.
- data is a pointer to an arbitrary chunk of data,
- size is the size of the chunk in bytes.
Calling sih_resources->feedback causes the application to receive a message A2G_COM_SIH_FEEDBACK with the data block specified by the data and size parameters.
The protocol used to communicate between the application and an SIH plugin using COM_SIH_CNTL / SIH_cntl() and sih_resources->feedback() / A2G_COM_SIH_FEEDBACK must be agreed privately between the application and the SIH plugin.
You can look at the example of SIH plugin provided with mtvp-sdk. SIH plugins should be compiled as dynamic (shared) libraries.Important: You should ALWAYS define the _REENTRANT macro in the compiler line (i.e. use the compilation flag -D_REENTRANT).
To test the SIH plugin API you can use sample_sih.so which is functionally equivalent to the built-in FILE handler (i.e. it recognizes URL of the form "file:filename").You can use the sample application simple_player as a test program to test this SIH handler.
If you define the macro TEST_SIH (in simple_player.c) to be the pathname of the sample SIH plugin (sample_sih.so), simple_player will link the sample SIH plugin and use it (instead of the buil-in handler) to access input files.
The routines in sample_sih.so print many messages so that you see what is happening.
You can use sample_sih.c as a template to develop your own SIH plugin.