Soy un yonki. No me he podido aguantar hasta mañana. ¡Pero ya funciona!.
El problema era que estaba poniendo la altura y anchura de la SDL_Surface a 0 y se quejaba.
[code language="c"]/* libSDL and libVLC sample code
* Copyright © 2008 Sam Hocevar <sam@zoy.org>
* license: [http://en.wikipedia.org/wiki/WTFPL WTFPL] */
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_mutex.h>
#include <vlc/vlc.h>
/* BennuGD stuff */
#include <bgddl.h>
#include <xstrings.h>
#include <libgrbase.h>
#include <g_video.h>
#define WIDTH 640
#define HEIGHT 480
#define VIDEOWIDTH 320
#define VIDEOHEIGHT 240
struct ctx
{
SDL_Surface *surf;
SDL_mutex *mutex;
};
static char clock[64], cunlock[64], cdata[64];
static char width[32], height[32], pitch[32];
static libvlc_exception_t ex;
static libvlc_instance_t *libvlc;
static libvlc_media_t *m;
static libvlc_media_player_t *mp;
static struct ctx video;
static char const *vlc_argv[] =
{
"-q",
// "-vvvvv",
"--ignore-config", /* Don't use VLC's config files */
"--vout", "vmem",
"--vmem-width", width,
"--vmem-height", height,
"--vmem-pitch", pitch,
"--vmem-chroma", "RV16",
"--vmem-lock", clock,
"--vmem-unlock", cunlock,
"--vmem-data", cdata,
};
static int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
static void catch (libvlc_exception_t *ex)
{
if(libvlc_exception_raised(ex))
{
fprintf(stderr, "Exception: %s\n", libvlc_exception_get_message(ex));
exit(1);
}
libvlc_exception_clear(ex);
}
#ifdef VLC09X
static void * lock(struct ctx *ctx)
{
SDL_LockMutex(ctx->mutex);
SDL_LockSurface(ctx->surf);
return ctx->surf->pixels;
}
#else
static void lock(struct ctx *ctx, void **pp_ret)
{
SDL_LockMutex(ctx->mutex);
SDL_LockSurface(ctx->surf);
*pp_ret = ctx->surf->pixels;
}
#endif
static void unlock(struct ctx *ctx)
{
/* VLC just rendered the video, but we can also render stuff */
SDL_UnlockSurface(ctx->surf);
SDL_UnlockMutex(ctx->mutex);
}
/* Init VLC stuff */
static void vlc_init()
{
printf("Initializing\n");
fflush(stdout);
if(! scr_initialized) gr_init(320, 240);
/* Create the 16bpp surface that will hold the video */
video.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT, 16,
(((Uint32)0xff) >> 3) << 11, (((Uint32)0xff) >> 2) << 5 ,
((Uint32)0xff) >> 3, 0);
video.mutex = SDL_CreateMutex();
sprintf(clock, "%lld", (long long int)(intptr_t)lock);
sprintf(cunlock, "%lld", (long long int)(intptr_t)unlock);
sprintf(cdata, "%lld", (long long int)(intptr_t)&video);
sprintf(width, "%i", VIDEOWIDTH);
sprintf(height, "%i", VIDEOHEIGHT);
sprintf(pitch, "%i", VIDEOWIDTH * 2);
printf("Done initializing\n");
fflush(stdout);
}
/* Stop the VLC lib */
static void vlc_finalize()
{
/*
* Stop stream and clean up libVLC
*/
libvlc_media_player_stop(mp, &ex);
catch(&ex);
libvlc_media_player_release(mp);
libvlc_release(libvlc);
/*
* Close window and clean up libSDL
*/
SDL_DestroyMutex(video.mutex);
SDL_FreeSurface(video.surf);
}
static int play_video(INSTANCE *my, int * params)
{
/* The name of the file to play */
GRAPH *gr = NULL;
libvlc_exception_init(&ex);
libvlc = libvlc_new(vlc_argc, vlc_argv, &ex);
catch(&ex);
m = libvlc_media_new(libvlc, string_get(params[0]), &ex);
catch(&ex);
mp = libvlc_media_player_new_from_media(m, &ex);
catch(&ex);
libvlc_media_release(m);
libvlc_media_player_play(mp, &ex);
catch(&ex);
string_discard(params[0]);
// Create the graphic that will hold the video surface data
gr = bitmap_new_ex(0, video.surf->w, video.surf->h,
video.surf->format->BitsPerPixel, video.surf->pixels,
video.surf->pitch);
gr->code = bitmap_next_code();
grlib_add_map(0, gr);
return gr->code;
}
DLSYSFUNCS __bgdexport( mod_vlc, functions_exports )[] =
{
{"PLAY_VIDEO", "S" , TYPE_DWORD , play_video },
{ NULL , NULL , 0 , NULL }
};
char * __bgdexport( mod_vlc, modules_dependency )[] =
{
"libgrbase",
"libvideo",
NULL
};
void __bgdexport( mod_vlc, module_initialize )()
{
vlc_init();
}
void __bgdexport( mod_vlc, module_finalize )()
{
vlc_finalize();
}[/code]El código de ejemplo que he usado es:[code language="bennu"]import "mod_key"
import "mod_vlc"
import "mod_video"
import "mod_mouse"
import "mod_say"
import "mod_map"
Process main()
Begin
dump_type=complete_dump; restore_type=complete_restore;
set_mode(640, 480, 16);
mouse.graph = play_video("big_buck_bunny_480p_stereo.ogg");
graph = mouse.graph;
flags = B_HMIRROR;
x = 320;
y = 240;
while(! key(_esc))
// Uncomment to take screenshots
//save_png(0, mouse.graph, "shot.png");
angle += 50;
FRAME;
end;
End;[/code]Lo que más mola es que además de para vídeos vale para webcams, DVDs y en general cualquier cosa que VLC pueda reproducir...
Splinter, si te mola esto y quisieras convertirlo en un módulo oficial, yo más contento que unas pascuas. Si no, con tiempo lo intentaré limpiar y mejorar (pero seguro que tú eres capaz de hacerlo mucho mejor y dejarlo muy limpito).
¡Ah! ¡y el rendimiento parece bastante bueno!.
[Edito] He cambiado el código de ejemplo por uno un poquito más complejo que muestra que realmente funciona.
¡Screenshot!.
