v4l2: show v4l captured output in SDL window

This commit is contained in:
Wim Taymans 2016-07-07 11:31:52 +02:00
parent a31eb56663
commit cbde76f500
4 changed files with 73 additions and 4 deletions

View file

@ -3,6 +3,7 @@ project('spa', 'c')
alsa_dep = dependency('alsa') alsa_dep = dependency('alsa')
v4l2_dep = dependency('libv4l2') v4l2_dep = dependency('libv4l2')
xv_dep = dependency('x11') xv_dep = dependency('x11')
sdl_dep = dependency('sdl2')
dl_lib = find_library('dl', required : true) dl_lib = find_library('dl', required : true)
inc = include_directories('include') inc = include_directories('include')

View file

@ -493,13 +493,15 @@ mmap_init (SpaV4l2Source *this)
b->meta[0].size = sizeof (b->header); b->meta[0].size = sizeof (b->header);
b->data[0].type = SPA_DATA_TYPE_MEMPTR; b->data[0].type = SPA_DATA_TYPE_MEMPTR;
b->data[0].size = buf.length;
b->data[0].data = mmap (NULL, b->data[0].data = mmap (NULL,
buf.length, buf.length,
PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
MAP_SHARED, MAP_SHARED,
state->fd, state->fd,
buf.m.offset); buf.m.offset);
b->data[0].offset = 0;
b->data[0].size = buf.length;
b->data[0].stride = state->fmt.fmt.pix.bytesperline;
if (b->data[0].data == MAP_FAILED) { if (b->data[0].data == MAP_FAILED) {
perror ("mmap"); perror ("mmap");

View file

@ -5,5 +5,5 @@ executable('test-mixer', 'test-mixer.c',
executable('test-v4l2', 'test-v4l2.c', executable('test-v4l2', 'test-v4l2.c',
include_directories : inc, include_directories : inc,
dependencies : [dl_lib], dependencies : [dl_lib, sdl_dep],
install : false) install : false)

View file

@ -23,12 +23,17 @@
#include <unistd.h> #include <unistd.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <SDL2/SDL.h>
#include <spa/node.h> #include <spa/node.h>
#include <spa/video/format.h> #include <spa/video/format.h>
typedef struct { typedef struct {
SpaHandle *source; SpaHandle *source;
const SpaNode *source_node; const SpaNode *source_node;
SDL_Renderer *renderer;
SDL_Window *window;
SDL_Texture *texture;
} AppData; } AppData;
static SpaResult static SpaResult
@ -73,6 +78,7 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char
} }
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
} }
#define MIN(a,b) (a < b ? a : b)
static void static void
on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data) on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data)
@ -84,10 +90,32 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data)
{ {
SpaOutputInfo info[1] = { 0, }; SpaOutputInfo info[1] = { 0, };
SpaResult res; SpaResult res;
void *sdata, *ddata;
int sstride, dstride;
int i;
uint8_t *src, *dst;
if ((res = data->source_node->pull_port_output (data->source, 1, info)) < 0) if ((res = data->source_node->pull_port_output (data->source, 1, info)) < 0)
printf ("got pull error %d\n", res); printf ("got pull error %d\n", res);
if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) {
fprintf (stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return;
}
sdata = info[0].buffer->datas[0].data;
sstride = info[0].buffer->datas[0].stride;
for (i = 0; i < 240; i++) {
src = ((uint8_t*)sdata + i * sstride);
dst = ((uint8_t*)ddata + i * dstride);
memcpy (dst, src, MIN (sstride, dstride));
}
SDL_UnlockTexture(data->texture);
SDL_RenderClear (data->renderer);
SDL_RenderCopy (data->renderer, data->texture, NULL, NULL);
SDL_RenderPresent (data->renderer);
if (info[0].buffer) { if (info[0].buffer) {
spa_buffer_unref (info[0].buffer); spa_buffer_unref (info[0].buffer);
} }
@ -164,13 +192,30 @@ run_async_source (AppData *data)
{ {
SpaResult res; SpaResult res;
SpaCommand cmd; SpaCommand cmd;
bool done = false;
cmd.type = SPA_COMMAND_START; cmd.type = SPA_COMMAND_START;
if ((res = data->source_node->send_command (data->source, &cmd)) < 0) if ((res = data->source_node->send_command (data->source, &cmd)) < 0)
printf ("got error %d\n", res); printf ("got error %d\n", res);
printf ("sleeping for 10 seconds\n");
sleep (10); while (!done) {
SDL_Event event;
while (SDL_PollEvent (&event)) {
switch (event.type) {
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE) {
done = SDL_TRUE;
}
break;
case SDL_QUIT:
done = SDL_TRUE;
break;
}
}
}
cmd.type = SPA_COMMAND_STOP; cmd.type = SPA_COMMAND_STOP;
if ((res = data->source_node->send_command (data->source, &cmd)) < 0) if ((res = data->source_node->send_command (data->source, &cmd)) < 0)
@ -183,6 +228,25 @@ main (int argc, char *argv[])
AppData data; AppData data;
SpaResult res; SpaResult res;
if (SDL_Init (SDL_INIT_VIDEO) < 0) {
printf ("can't initialize SDL: %s\n", SDL_GetError ());
return -1;
}
if (SDL_CreateWindowAndRenderer (320, 240, SDL_WINDOW_RESIZABLE, &data.window, &data.renderer)) {
printf ("can't create window: %s\n", SDL_GetError ());
return -1;
}
data.texture = SDL_CreateTexture (data.renderer,
SDL_PIXELFORMAT_YUY2,
SDL_TEXTUREACCESS_STREAMING,
320, 240);
if (!data.texture) {
printf ("can't create texture: %s\n", SDL_GetError ());
return -1;
}
if ((res = make_nodes (&data)) < 0) { if ((res = make_nodes (&data)) < 0) {
printf ("can't make nodes: %d\n", res); printf ("can't make nodes: %d\n", res);
return -1; return -1;
@ -194,5 +258,7 @@ main (int argc, char *argv[])
run_async_source (&data); run_async_source (&data);
SDL_DestroyRenderer (data.renderer);
return 0; return 0;
} }