mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
v4l2: show v4l captured output in SDL window
This commit is contained in:
parent
a31eb56663
commit
cbde76f500
4 changed files with 73 additions and 4 deletions
|
|
@ -3,6 +3,7 @@ project('spa', 'c')
|
|||
alsa_dep = dependency('alsa')
|
||||
v4l2_dep = dependency('libv4l2')
|
||||
xv_dep = dependency('x11')
|
||||
sdl_dep = dependency('sdl2')
|
||||
dl_lib = find_library('dl', required : true)
|
||||
|
||||
inc = include_directories('include')
|
||||
|
|
|
|||
|
|
@ -493,13 +493,15 @@ mmap_init (SpaV4l2Source *this)
|
|||
b->meta[0].size = sizeof (b->header);
|
||||
|
||||
b->data[0].type = SPA_DATA_TYPE_MEMPTR;
|
||||
b->data[0].size = buf.length;
|
||||
b->data[0].data = mmap (NULL,
|
||||
buf.length,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
state->fd,
|
||||
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) {
|
||||
perror ("mmap");
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ executable('test-mixer', 'test-mixer.c',
|
|||
|
||||
executable('test-v4l2', 'test-v4l2.c',
|
||||
include_directories : inc,
|
||||
dependencies : [dl_lib],
|
||||
dependencies : [dl_lib, sdl_dep],
|
||||
install : false)
|
||||
|
|
|
|||
|
|
@ -23,12 +23,17 @@
|
|||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <spa/node.h>
|
||||
#include <spa/video/format.h>
|
||||
|
||||
typedef struct {
|
||||
SpaHandle *source;
|
||||
const SpaNode *source_node;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Window *window;
|
||||
SDL_Texture *texture;
|
||||
} AppData;
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -73,6 +78,7 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char
|
|||
}
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
#define MIN(a,b) (a < b ? a : b)
|
||||
|
||||
static void
|
||||
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, };
|
||||
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)
|
||||
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) {
|
||||
spa_buffer_unref (info[0].buffer);
|
||||
}
|
||||
|
|
@ -164,13 +192,30 @@ run_async_source (AppData *data)
|
|||
{
|
||||
SpaResult res;
|
||||
SpaCommand cmd;
|
||||
bool done = false;
|
||||
|
||||
cmd.type = SPA_COMMAND_START;
|
||||
if ((res = data->source_node->send_command (data->source, &cmd)) < 0)
|
||||
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;
|
||||
if ((res = data->source_node->send_command (data->source, &cmd)) < 0)
|
||||
|
|
@ -183,6 +228,25 @@ main (int argc, char *argv[])
|
|||
AppData data;
|
||||
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) {
|
||||
printf ("can't make nodes: %d\n", res);
|
||||
return -1;
|
||||
|
|
@ -194,5 +258,7 @@ main (int argc, char *argv[])
|
|||
|
||||
run_async_source (&data);
|
||||
|
||||
SDL_DestroyRenderer (data.renderer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue