diff options
Diffstat (limited to 'pipewire-jack/examples/video-dsp-play.c')
-rw-r--r-- | pipewire-jack/examples/video-dsp-play.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/pipewire-jack/examples/video-dsp-play.c b/pipewire-jack/examples/video-dsp-play.c new file mode 100644 index 0000000..be4c94c --- /dev/null +++ b/pipewire-jack/examples/video-dsp-play.c @@ -0,0 +1,203 @@ +/* PipeWire + * + * Copyright © 2019 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <unistd.h> +#include <sys/mman.h> + +#include <SDL2/SDL.h> + +#include <jack/jack.h> +#include <pipewire-jack-extensions.h> + +#define MAX_BUFFERS 64 + +#define JACK_DEFAULT_VIDEO_TYPE "32 bit float RGBA video" + +#define CLAMP(v,low,high) \ +({ \ + __typeof__(v) _v = (v); \ + __typeof__(low) _low = (low); \ + __typeof__(high) _high = (high); \ + (_v < _low) ? _low : (_v > _high) ? _high : _v; \ +}) + +struct pixel { + float r, g, b, a; +}; + +struct data { + const char *path; + + SDL_Renderer *renderer; + SDL_Window *window; + SDL_Texture *texture; + SDL_Texture *cursor; + + jack_client_t *client; + const char *client_name; + jack_port_t *in_port; + + jack_image_size_t size; + + int counter; + SDL_Rect rect; + SDL_Rect cursor_rect; +}; + +static void handle_events(struct data *data) +{ + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + exit(0); + break; + } + } +} + +static int +process (jack_nframes_t nframes, void *arg) +{ + struct data *data = (struct data*)arg; + void *sdata, *ddata; + int sstride, dstride; + uint32_t i, j; + uint8_t *src, *dst; + + sdata = jack_port_get_buffer (data->in_port, nframes); + + handle_events(data); + + if (SDL_LockTexture(data->texture, NULL, &ddata, &dstride) < 0) { + fprintf(stderr, "Couldn't lock texture: %s\n", SDL_GetError()); + goto done; + } + + /* copy video image in texture */ + sstride = data->size.stride; + + src = sdata; + dst = ddata; + + for (i = 0; i < data->size.height; i++) { + struct pixel *p = (struct pixel *) src; + for (j = 0; j < data->size.width; j++) { + dst[j * 4 + 0] = CLAMP(lrintf(p[j].r * 255.0f), 0, 255); + dst[j * 4 + 1] = CLAMP(lrintf(p[j].g * 255.0f), 0, 255); + dst[j * 4 + 2] = CLAMP(lrintf(p[j].b * 255.0f), 0, 255); + dst[j * 4 + 3] = CLAMP(lrintf(p[j].a * 255.0f), 0, 255); + } + src += sstride; + dst += dstride; + } + SDL_UnlockTexture(data->texture); + + SDL_RenderClear(data->renderer); + SDL_RenderCopy(data->renderer, data->texture, &data->rect, NULL); + SDL_RenderPresent(data->renderer); + + done: + return 0; +} + +int main(int argc, char *argv[]) +{ + struct data data = { 0, }; + jack_options_t options = JackNullOption; + jack_status_t status; + int res; + + data.client = jack_client_open ("video-dsp-play", options, &status); + if (data.client == NULL) { + fprintf (stderr, "jack_client_open() failed, " + "status = 0x%2.0x\n", status); + if (status & JackServerFailed) { + fprintf (stderr, "Unable to connect to JACK server\n"); + } + exit (1); + } + if (status & JackServerStarted) { + fprintf (stderr, "JACK server started\n"); + } + if (status & JackNameNotUnique) { + data.client_name = jack_get_client_name(data.client); + fprintf (stderr, "unique name `%s' assigned\n", data.client_name); + } + + jack_set_process_callback (data.client, process, &data); + + if ((res = jack_get_video_image_size(data.client, &data.size)) < 0) { + fprintf(stderr, "can't get video size: %d %s\n", res, strerror(-res)); + return -1; + } + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "can't initialize SDL: %s\n", SDL_GetError()); + return -1; + } + + if (SDL_CreateWindowAndRenderer + (data.size.width, data.size.height, SDL_WINDOW_RESIZABLE, &data.window, &data.renderer)) { + fprintf(stderr, "can't create window: %s\n", SDL_GetError()); + return -1; + } + + data.texture = SDL_CreateTexture(data.renderer, + SDL_PIXELFORMAT_RGBA32, + SDL_TEXTUREACCESS_STREAMING, + data.size.width, + data.size.height); + data.rect.x = 0; + data.rect.y = 0; + data.rect.w = data.size.width; + data.rect.h = data.size.height; + + data.in_port = jack_port_register (data.client, "input", + JACK_DEFAULT_VIDEO_TYPE, + JackPortIsInput, 0); + + if (data.in_port == NULL) { + fprintf(stderr, "no more JACK ports available\n"); + exit (1); + } + + if (jack_activate (data.client)) { + fprintf (stderr, "cannot activate client"); + exit (1); + } + + while (1) { + sleep (1); + } + + jack_client_close (data.client); + + SDL_DestroyTexture(data.texture); + SDL_DestroyRenderer(data.renderer); + SDL_DestroyWindow(data.window); + + return 0; +} |