summaryrefslogtreecommitdiff
path: root/src/examples
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2018-11-30 11:07:45 +0100
committerWim Taymans <wtaymans@redhat.com>2018-11-30 15:12:46 +0100
commitac5f0b851ded92ba2bbc001e58a5b8b50e940543 (patch)
tree9640fcdec72f7ad8b95ecc1338fe6cdff5eb59f8 /src/examples
parentc982f7377991d4c3cb99e9d365d8c0df52f8f4f1 (diff)
meta: add cursor metadata and examples
Add a moving and flashing circle cursor to video-src Render the cursor in video-play Alsa add VideoCrop metadata
Diffstat (limited to 'src/examples')
-rw-r--r--src/examples/meson.build2
-rw-r--r--src/examples/video-play.c79
-rw-r--r--src/examples/video-src.c72
3 files changed, 143 insertions, 10 deletions
diff --git a/src/examples/meson.build b/src/examples/meson.build
index 828e2d42..44907d0f 100644
--- a/src/examples/meson.build
+++ b/src/examples/meson.build
@@ -1,7 +1,7 @@
executable('video-src',
'video-src.c',
install: false,
- dependencies : [pipewire_dep],
+ dependencies : [pipewire_dep, mathlib],
)
executable('audio-src',
'audio-src.c',
diff --git a/src/examples/video-play.c b/src/examples/video-play.c
index 78f61794..d34c4981 100644
--- a/src/examples/video-play.c
+++ b/src/examples/video-play.c
@@ -46,6 +46,7 @@ struct data {
SDL_Renderer *renderer;
SDL_Window *window;
SDL_Texture *texture;
+ SDL_Texture *cursor;
struct pw_main_loop *loop;
@@ -60,6 +61,8 @@ struct data {
int32_t stride;
int counter;
+ SDL_Rect rect;
+ SDL_Rect cursor_rect;
};
static void handle_events(struct data *data)
@@ -83,8 +86,11 @@ on_process(void *_data)
struct spa_buffer *buf;
void *sdata, *ddata;
int sstride, dstride, ostride;
+ struct spa_meta_region *mc;
+ struct spa_meta_cursor *mcs;
uint32_t i;
uint8_t *src, *dst;
+ bool render_cursor = false;
b = pw_stream_dequeue_buffer(stream);
if (b == NULL)
@@ -103,6 +109,44 @@ on_process(void *_data)
fprintf(stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return;
}
+
+ if ((mc = spa_buffer_find_meta_data(buf, SPA_META_VideoCrop, sizeof(*mc)))) {
+ data->rect.x = mc->region.position.x;
+ data->rect.y = mc->region.position.y;
+ data->rect.w = mc->region.size.width;
+ data->rect.h = mc->region.size.height;
+ }
+ if ((mcs = spa_buffer_find_meta_data(buf, SPA_META_Cursor, sizeof(*mcs)))) {
+ struct spa_meta_bitmap *mb;
+ void *cdata;
+ int cstride;
+
+ data->cursor_rect.x = mcs->position.x;
+ data->cursor_rect.y = mcs->position.y;
+
+ mb = SPA_MEMBER(mcs, mcs->bitmap_offset, struct spa_meta_bitmap);
+ data->cursor_rect.w = mb->size.width;
+ data->cursor_rect.h = mb->size.height;
+
+ if (SDL_LockTexture(data->cursor, NULL, &cdata, &cstride) < 0) {
+ fprintf(stderr, "Couldn't lock cursor texture: %s\n", SDL_GetError());
+ goto done;
+ }
+
+ src = SPA_MEMBER(mb, mb->offset, uint8_t);
+ dst = cdata;
+ ostride = SPA_MIN(cstride, mb->stride);
+
+ for (i = 0; i < mb->size.height; i++) {
+ memcpy(dst, src, ostride);
+ dst += cstride;
+ src += mb->stride;
+ }
+ SDL_UnlockTexture(data->cursor);
+
+ render_cursor = true;
+ }
+
sstride = buf->datas[0].chunk->stride;
ostride = SPA_MIN(sstride, dstride);
@@ -116,10 +160,13 @@ on_process(void *_data)
SDL_UnlockTexture(data->texture);
SDL_RenderClear(data->renderer);
- SDL_RenderCopy(data->renderer, data->texture, NULL, NULL);
+ SDL_RenderCopy(data->renderer, data->texture, &data->rect, NULL);
+ if (render_cursor) {
+ SDL_RenderCopy(data->renderer, data->cursor, NULL, &data->cursor_rect);
+ }
SDL_RenderPresent(data->renderer);
-
+ done:
pw_stream_queue_buffer(stream, b);
}
@@ -147,7 +194,7 @@ on_stream_format_changed(void *_data, const struct spa_pod *format)
struct pw_stream *stream = data->stream;
uint8_t params_buffer[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer));
- const struct spa_pod *params[2];
+ const struct spa_pod *params[5];
Uint32 sdl_format;
void *d;
@@ -175,6 +222,17 @@ on_stream_format_changed(void *_data, const struct spa_pod *format)
SDL_LockTexture(data->texture, NULL, &d, &data->stride);
SDL_UnlockTexture(data->texture);
+ data->cursor = SDL_CreateTexture(data->renderer,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_STREAMING,
+ 64, 64);
+ SDL_SetTextureBlendMode(data->cursor, SDL_BLENDMODE_BLEND);
+
+ data->rect.x = 0;
+ data->rect.y = 0;
+ data->rect.w = data->format.size.width;
+ data->rect.h = data->format.size.height;
+
params[0] = spa_pod_builder_object(&b,
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
SPA_PARAM_BUFFERS_buffers, &SPA_POD_CHOICE_RANGE_Int(8, 2, MAX_BUFFERS),
@@ -189,8 +247,20 @@ on_stream_format_changed(void *_data, const struct spa_pod *format)
SPA_PARAM_META_type, &SPA_POD_Id(SPA_META_Header),
SPA_PARAM_META_size, &SPA_POD_Int(sizeof(struct spa_meta_header)),
0);
+ params[2] = spa_pod_builder_object(&b,
+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
+ SPA_PARAM_META_type, &SPA_POD_Id(SPA_META_VideoCrop),
+ SPA_PARAM_META_size, &SPA_POD_Int(sizeof(struct spa_meta_region)),
+ 0);
+ params[3] = spa_pod_builder_object(&b,
+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
+ SPA_PARAM_META_type, &SPA_POD_Id(SPA_META_Cursor),
+ SPA_PARAM_META_size, &SPA_POD_Int(sizeof(struct spa_meta_cursor) +
+ sizeof(struct spa_meta_bitmap) +
+ 64 * 64 * 4),
+ 0);
- pw_stream_finish_format(stream, 0, params, 2);
+ pw_stream_finish_format(stream, 0, params, 4);
}
static const struct pw_stream_events stream_events = {
@@ -267,6 +337,7 @@ int main(int argc, char *argv[])
pw_main_loop_destroy(data.loop);
SDL_DestroyTexture(data.texture);
+ SDL_DestroyTexture(data.cursor);
SDL_DestroyRenderer(data.renderer);
SDL_DestroyWindow(data.window);
diff --git a/src/examples/video-src.c b/src/examples/video-src.c
index f68c2de0..4220e4dc 100644
--- a/src/examples/video-src.c
+++ b/src/examples/video-src.c
@@ -25,14 +25,19 @@
#include <stdio.h>
#include <errno.h>
#include <time.h>
-#include <sys/mman.h>
+#include <math.h>
#include <spa/param/video/format-utils.h>
#include <spa/param/props.h>
#include <pipewire/pipewire.h>
-#define BPP 3
+#define BPP 3
+#define WIDTH 320
+#define HEIGHT 200
+#define CROP 8
+
+#define M_PI_M2 ( M_PI + M_PI )
struct data {
struct pw_main_loop *loop;
@@ -50,6 +55,9 @@ struct data {
int counter;
uint32_t seq;
+
+ double crop;
+ double accumulator;
};
static void on_timeout(void *userdata, uint64_t expirations)
@@ -59,8 +67,10 @@ static void on_timeout(void *userdata, uint64_t expirations)
struct spa_buffer *buf;
int i, j;
uint8_t *p;
- struct spa_meta_header *h;
struct spa_meta *m;
+ struct spa_meta_header *h;
+ struct spa_meta_region *mc;
+ struct spa_meta_cursor *mcs;
pw_log_trace("timeout");
@@ -96,6 +106,42 @@ static void on_timeout(void *userdata, uint64_t expirations)
if (spa_meta_check(r, m))
r->region = SPA_REGION(0,0,0,0);
}
+ if ((mc = spa_buffer_find_meta_data(buf, SPA_META_VideoCrop, sizeof(*mc)))) {
+ data->crop = (sin(data->accumulator) + 1.0) * 32.0;
+ mc->region.position.x = data->crop;
+ mc->region.position.y = data->crop;
+ mc->region.size.width = WIDTH - data->crop*2;
+ mc->region.size.height = HEIGHT - data->crop*2;
+ }
+ if ((mcs = spa_buffer_find_meta_data(buf, SPA_META_Cursor, sizeof(*mcs)))) {
+ struct spa_meta_bitmap *mb;
+ uint32_t *bitmap, color;
+
+ mcs->id = 1;
+ mcs->position.x = (sin(data->accumulator) + 1.0) * 160.0 + 80;
+ mcs->position.y = (cos(data->accumulator) + 1.0) * 100.0 + 50;
+ mcs->hotspot.x = 0;
+ mcs->hotspot.y = 0;
+ mcs->bitmap_offset = sizeof(struct spa_meta_cursor);
+
+ mb = SPA_MEMBER(mcs, mcs->bitmap_offset, struct spa_meta_bitmap);
+ mb->format = SPA_VIDEO_FORMAT_ARGB;
+ mb->size.width = 64;
+ mb->size.height = 64;
+ mb->stride = 64 * 4;
+ mb->offset = sizeof(struct spa_meta_bitmap);
+
+ bitmap = SPA_MEMBER(mb, mb->offset, uint32_t);
+ color = (cos(data->accumulator) + 1.0) * (1 << 23);
+ color |= 0xff000000;
+
+ for (i = 0; i < mb->size.height; i++) {
+ for (j = 0; j < mb->size.width; j++) {
+ int v = (i - 32) * (i - 32) + (j - 32) * (j - 32);
+ bitmap[i*64+j] = (v <= 32*32) ? color : 0x00000000;
+ }
+ }
+ }
for (i = 0; i < data->format.size.height; i++) {
for (j = 0; j < data->format.size.width * BPP; j++) {
@@ -105,6 +151,10 @@ static void on_timeout(void *userdata, uint64_t expirations)
data->counter += 13;
}
+ data->accumulator += M_PI_M2 / 50.0;
+ if (data->accumulator >= M_PI_M2)
+ data->accumulator -= M_PI_M2;
+
buf->datas[0].chunk->size = buf->datas[0].maxsize;
pw_stream_queue_buffer(data->stream, b);
@@ -148,7 +198,7 @@ on_stream_format_changed(void *_data, const struct spa_pod *format)
struct pw_stream *stream = data->stream;
uint8_t params_buffer[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer));
- const struct spa_pod *params[3];
+ const struct spa_pod *params[5];
if (format == NULL) {
pw_stream_finish_format(stream, 0, NULL, 0);
@@ -181,8 +231,20 @@ on_stream_format_changed(void *_data, const struct spa_pod *format)
sizeof(struct spa_meta_region) * 1,
sizeof(struct spa_meta_region) * 16),
0);
+ params[3] = spa_pod_builder_object(&b,
+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
+ SPA_PARAM_META_type, &SPA_POD_Id(SPA_META_VideoCrop),
+ SPA_PARAM_META_size, &SPA_POD_Int(sizeof(struct spa_meta_region)),
+ 0);
+ params[4] = spa_pod_builder_object(&b,
+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
+ SPA_PARAM_META_type, &SPA_POD_Id(SPA_META_Cursor),
+ SPA_PARAM_META_size, &SPA_POD_Int(sizeof(struct spa_meta_cursor) +
+ sizeof(struct spa_meta_bitmap) +
+ 64 * 64 * 4),
+ 0);
- pw_stream_finish_format(stream, 0, params, 3);
+ pw_stream_finish_format(stream, 0, params, 5);
}
static const struct pw_stream_events stream_events = {