I am currently writing some class libraries to get the individiual frames from MJPEG and H.264 streams, but I noticed that I am getting around triple the framerate expected.
My current setup is using Ubuntu 12.04 x86 and libVLC 5.3.2. I am getting an MJPEG feed from an encoding server set at 5 FPS. Here is an image showing the issue with VLC on verbose mode:
http://i.imgur.com/hpBf2EY.png
Note that on each display callback (OnNewFrame in my code below), I print the hash to show the duplication.
Code: Select all
using namespace std;
struct ctx {
SDL_mutex *mutex;
unsigned char *pixels;
int height, width;
};
static void* lock(void *data, void** p_pixels)
{
struct ctx *ctx = (struct ctx*)data;
//Allocate buffer to fill in image, assuming 24bpp
ctx->pixels = (unsigned char *)calloc(ctx->height * ctx->width, 24);
*p_pixels = ctx->pixels;
return NULL;
}
static void unlock(void *data, void *id, void *const *p_pixels)
{
//Not needed
}
static void OnNewFrame(void *data, void *id)
{
struct ctx *ctx = (struct ctx *) data;
SDL_LockMutex(ctx->mutex);
MD5 md5;
cout << "NewFrame - " << md5(ctx->pixels, ctx->height * ctx->width * 24/8)<< endl;
SDL_UnlockMutex(ctx->mutex);
}
VideoWrapper::VideoWrapper(string stream_uri, int height, int width){
this->stream_uri = stream_uri;
this->height = height;
this->width = width;
Initialize();
}
// Initialize VLC and its dependencies
bool VideoWrapper::Initialize() {
char const *vlc_argv[] = {
"-I", "dummy", // Don't use any interface
"--ignore-config", // Don't use VLC's config
"--extraintf=logger", // Log anything
"--no-audio", // Don't play audio.
"--no-video-title-show", /* nor the filename displayed */
"--no-stats", /* no stats */
"--no-sub-autodetect-file", /* we don't want subtitles */
"--no-inhibit", /* we don't want interfaces */
"--no-disable-screensaver", /* we don't want interfaces */
"--no-snapshot-preview", /* no blending in dummy vout */
"--ffmpeg-hw",
"--no-xlib", // Don't use Xlib.
"--verbose=2"//, // Be much more verbose then normal for debugging purpose
//"--sout"//, smem_options // Stream to memory
};
int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
struct ctx *ctx = (struct ctx*)malloc( sizeof( *ctx ) );
if(SDL_Init(SDL_INIT_VIDEO ) == -1)
{
//TODO: Error callback here
return EXIT_FAILURE;
}
ctx->mutex = SDL_CreateMutex();
ctx->height = this->height;
ctx->width = this->width;
libvlc = libvlc_new(vlc_argc, vlc_argv);
libvlc_media_t *m = libvlc_media_new_path(libvlc, stream_uri.c_str());
mp = libvlc_media_player_new_from_media(m);
libvlc_media_release(m);
libvlc_video_set_callbacks(mp, lock, unlock, OnNewFrame, ctx);
libvlc_video_set_format(mp, "RV24", this->height, this->width, this->width * 24 / 8);
return true;
}
bool VideoWrapper::StartStream()
{
libvlc_media_player_play(mp);
return true;
}