diff options
author | Wim Taymans <wtaymans@redhat.com> | 2018-11-30 11:07:45 +0100 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2018-11-30 15:12:46 +0100 |
commit | ac5f0b851ded92ba2bbc001e58a5b8b50e940543 (patch) | |
tree | 9640fcdec72f7ad8b95ecc1338fe6cdff5eb59f8 /src/examples | |
parent | c982f7377991d4c3cb99e9d365d8c0df52f8f4f1 (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.build | 2 | ||||
-rw-r--r-- | src/examples/video-play.c | 79 | ||||
-rw-r--r-- | src/examples/video-src.c | 72 |
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 = { |