Page 1 of 1

Feeding vlc with memory stored data : option imem

Posted: 28 Jun 2013 10:59
by asqz
Hi,

I am developing an application using libVLC in which I feed vlc with data stored in my memory for streaming it. The only way I found to do this is by configuring vlc with the option imem :
--imem-width
--imem-height
--imem-get
--imem-release
--imem-data
I know that imem-get and imem-release are pointer to callback function. But I don't know what is the definition that this functions must match with. Could you give me the definition of this callback functions and the description of their arguments/return ?

I know that defining a vlc instance (libvlc_instance_t) with arguments is a bad practice, so is it possible to execute the same process with functions instead of command options ?

Re: Feeding vlc with memory stored data : option imem

Posted: 28 Jun 2013 17:46
by RĂ©mi Denis-Courmont
Functions should be added to wrap custom input streams, just like for audio and video output. Nobody volunteered though.

Re: Feeding vlc with memory stored data : option imem

Posted: 08 Oct 2013 17:44
by marcov83
I have developed an application with imem/smem module with libvlc. I have read the source code of these modules to understand how them work, due to lack of documentation.
It works very good.

So, i can help you (if you have not solved yet).

the most important parameters are imem-get/imem-release/imem-data/imem-cat, the others are self-explenatory (imem-width, imem-height, imem-channels and so forth). The callback-function signature are:
imem-get ==> int VLCGetBuffers(void *data, const char *cookie, int64_t *dts, int64_t *pts, unsigned *flags, size_t * bufferSize, void ** buffer);
imem-release ==> void VLCReleaseBuffers (void *data, const char *cookie, size_t bufferSize, void * buffer);
For the imem-get:
-void *data: custom data passed to the callback (useful for "this" pointers). it is the "imem-data" value passed in the module arguments list;
-const char *cookie: custom string passed as module parameter;
-int64_t *dts, int64_t *pts: DTS, PTS for the stream (fundamental);
-unsigned *flags: flags, but reading the code seems to be not used;
-size_t *bufferSize: buffer size (expressed in bytes);
-void **buffer: the data you want to pass to vlc.

For the imem-release:
-void *data: same as imem-get;
-const char *cookie: as above;
-size_t bufferSize: size of buffer;
-void *buffer: buffer

The paradigm for the module is easy. You pass the data in the imem-get assign directy to *buffer and fill the other fields with the correct data (size, pts, dts); in the imem-release you will called to free that buffer (in order to not call new/malloc i use a static buffer between calls). Consider that VLC core will COPY the data in a internal block strutcure, so you should lock the buffer between the imem-get and the imem-release call (if you are in a multithreading scenario).
The first thing to do is to init the module...this is the worst aspect of this module. The callback function are passed as "long int" converted as strings.... to be more clear I show the code i used (stream PCM):
char *vlc_args[12];

vlc_args[0] = "-vvvvv";
vlc_args[1] = (char*)calloc(200,1);
sprintf(vlc_args[1], "--imem-get=%ld", my_get_cb);
vlc_args[2] = (char*)calloc(200,1);
sprintf(vlc_args[2], "--imem-release=%ld", my_release_cb);
vlc_args[3] = (char*)calloc(200,1);
sprintf(vlc_args[3], "--imem-cat=1"); //CAT 1 == AUDIO
vlc_args[4] = (char*)calloc(200,1);
sprintf(vlc_args[4], "--imem-data=%ld", /** my context custom data to be passed callbacks **/);
vlc_args[5] = "--imem-id=0";
vlc_args[6] = (char*)calloc(200,1);
sprintf(vlc_args[6], "--imem-codec=s16l"); //CODEC, format of the data passed to vlc in the buffers
vlc_args[7] = (char*)calloc(200,1);
sprintf(vlc_args[7], "--imem-channels=%d", mNumInputs); //number of channels
vlc_args[8] = (char *)calloc(200,1);
sprintf(vlc_args[8], "--imem-samplerate=%d", mSampleFreq); //sample frequency
vlc_args[9] = "--rtp-caching=100";

//create vlc
mVlcInstance = libvlc_new(sizeof(vlc_args)/sizeof(char *), vlc_args);

/***
other initializations...then start stream!
***/

//add instance to the VLM (but you can simply start play)
libvlc_vlm_add_broadcast(mVlcInstance, VLM_STREAM_NAME, "imem://", mSoutString, 0, 0, 1, 1);
libvlc_vlm_play_media(mVlcInstance, VLM_STREAM_NAME);
(the mSoutString is a string for the sout module, you can use if you want for on-the fly transcoding or network streaming).

One important aspect is the use of the imem-cat parameter. If you use AUDIO (imem-cat == 1) or VIDEO (imem-cat == 2), VLC will load the module as ACCESS-DEMUX so it will ask you for PTS and DTS. The calculation of correct PTS and DTS require you to parse the stream if is encoded (not always easy step...i use PCM so the calculation is very easy). Otherwise, if you don't want to use these category, you can use imem-cat == 4; with this option VLC will load the submodule ACCESS, and will not ask you for DTS and PTS, so you simply pass the raw data and the core will demux/decode the stream for you. with imem-cat == 4 you can pass directy piece of file (fread to be clear).

you can read this older post, that is clearer than mine!
https://forum.videolan.org/viewtopic.php?f=32&t=93842

hope this helps.