mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05: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')
|
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')
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue