diff options
author | Wim Taymans <wtaymans@redhat.com> | 2018-11-22 10:18:50 +0100 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2018-11-22 10:18:50 +0100 |
commit | 16b6a51b789b9d714418087f0797d29fb7b86c60 (patch) | |
tree | 7a36da88ba3513ae35d6761d275297a19f722f06 | |
parent | 1ea84b2869d5506851ee4f52c98e16d14333b46d (diff) |
examples: add video crop example
Add support for video crop metadata in video-play and draw only the
cropped areas.
Add support for video crop in video-src and make it generate cropping
regions that grow and shrink dynamically.
-rw-r--r-- | src/examples/meson.build | 2 | ||||
-rw-r--r-- | src/examples/video-play.c | 28 | ||||
-rw-r--r-- | src/examples/video-src.c | 33 |
3 files changed, 55 insertions, 8 deletions
diff --git a/src/examples/meson.build b/src/examples/meson.build index 4890f68e..37b3d4ff 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('export-source', 'export-source.c', diff --git a/src/examples/video-play.c b/src/examples/video-play.c index b259a86b..287c2c4d 100644 --- a/src/examples/video-play.c +++ b/src/examples/video-play.c @@ -73,6 +73,7 @@ struct data { int32_t stride; int counter; + SDL_Rect rect; }; static void handle_events(struct data *data) @@ -96,6 +97,7 @@ on_stream_process(void *_data) struct spa_buffer *b; void *sdata, *ddata; int sstride, dstride, ostride; + struct spa_meta_video_crop *mc; uint32_t i; uint8_t *src, *dst; @@ -114,6 +116,17 @@ on_stream_process(void *_data) fprintf(stderr, "Couldn't lock texture: %s\n", SDL_GetError()); goto done; } + if ((mc = spa_buffer_find_meta(b, data->t->meta.VideoCrop))) { + if (data->rect.x != mc->x || + data->rect.y != mc->y || + data->rect.w != mc->width || + data->rect.h != mc->height) { + data->rect.x = mc->x; + data->rect.y = mc->y; + data->rect.w = mc->width; + data->rect.h = mc->height; + } + } sstride = b->datas[0].chunk->stride; ostride = SPA_MIN(sstride, dstride); @@ -127,7 +140,7 @@ on_stream_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); SDL_RenderPresent(data->renderer); done: @@ -226,7 +239,7 @@ on_stream_format_changed(void *_data, const struct spa_pod *format) struct pw_type *t = data->t; 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[3]; Uint32 sdl_format; void *d; @@ -254,6 +267,11 @@ on_stream_format_changed(void *_data, const struct spa_pod *format) SDL_LockTexture(data->texture, NULL, &d, &data->stride); SDL_UnlockTexture(data->texture); + 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, t->param.idBuffers, t->param_buffers.Buffers, ":", t->param_buffers.size, "i", data->stride * data->format.size.height, @@ -266,8 +284,12 @@ on_stream_format_changed(void *_data, const struct spa_pod *format) t->param.idMeta, t->param_meta.Meta, ":", t->param_meta.type, "I", t->meta.Header, ":", t->param_meta.size, "i", sizeof(struct spa_meta_header)); + params[2] = spa_pod_builder_object(&b, + t->param.idMeta, t->param_meta.Meta, + ":", t->param_meta.type, "I", t->meta.VideoCrop, + ":", t->param_meta.size, "i", sizeof(struct spa_meta_video_crop)); - pw_stream_finish_format(stream, 0, params, 2); + pw_stream_finish_format(stream, 0, params, 3); } static const struct pw_stream_events stream_events = { diff --git a/src/examples/video-src.c b/src/examples/video-src.c index 5960bd88..db508a59 100644 --- a/src/examples/video-src.c +++ b/src/examples/video-src.c @@ -20,6 +20,7 @@ #include <stdio.h> #include <errno.h> #include <time.h> +#include <math.h> #include <sys/mman.h> #include <spa/support/type-map.h> @@ -44,7 +45,12 @@ static inline void init_type(struct type *type, struct spa_type_map *map) spa_type_video_format_map(map, &type->video_format); } -#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 type type; @@ -65,6 +71,8 @@ struct data { int counter; uint32_t seq; + double crop; + double accumulator; }; static void on_timeout(void *userdata, uint64_t expirations) @@ -73,6 +81,7 @@ static void on_timeout(void *userdata, uint64_t expirations) int i, j; uint8_t *p; struct spa_meta_header *h; + struct spa_meta_video_crop *mc; struct pw_buffer *buf; struct spa_buffer *b; @@ -97,6 +106,18 @@ static void on_timeout(void *userdata, uint64_t expirations) h->seq = data->seq++; h->dts_offset = 0; } + if ((mc = spa_buffer_find_meta(b, data->t->meta.VideoCrop))) { + mc->x = data->crop; + mc->y = data->crop; + mc->width = WIDTH - data->crop*2; + mc->height = HEIGHT - data->crop*2; + + data->accumulator += M_PI_M2 / 50.0; + if (data->accumulator >= M_PI_M2) + data->accumulator -= M_PI_M2; + + data->crop = (sin(data->accumulator) + 1.0) * 32.0; + } for (i = 0; i < data->format.size.height; i++) { for (j = 0; j < data->format.size.width * BPP; j++) { @@ -148,7 +169,7 @@ on_stream_format_changed(void *_data, const struct spa_pod *format) struct pw_type *t = data->t; 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[3]; if (format == NULL) { pw_stream_finish_format(stream, 0, NULL, 0); @@ -170,8 +191,12 @@ on_stream_format_changed(void *_data, const struct spa_pod *format) t->param.idMeta, t->param_meta.Meta, ":", t->param_meta.type, "I", t->meta.Header, ":", t->param_meta.size, "i", sizeof(struct spa_meta_header)); + params[2] = spa_pod_builder_object(&b, + t->param.idMeta, t->param_meta.Meta, + ":", t->param_meta.type, "I", t->meta.VideoCrop, + ":", t->param_meta.size, "i", sizeof(struct spa_meta_video_crop)); - pw_stream_finish_format(stream, 0, params, 2); + pw_stream_finish_format(stream, 0, params, 3); } static const struct pw_stream_events stream_events = { @@ -214,7 +239,7 @@ static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remo "I", data->type.media_type.video, "I", data->type.media_subtype.raw, ":", data->type.format_video.format, "I", data->type.video_format.RGB, - ":", data->type.format_video.size, "Rru", &SPA_RECTANGLE(320, 240), + ":", data->type.format_video.size, "Rru", &SPA_RECTANGLE(WIDTH, HEIGHT), SPA_POD_PROP_MIN_MAX(&SPA_RECTANGLE(1, 1), &SPA_RECTANGLE(4096, 4096)), ":", data->type.format_video.framerate, "F", &SPA_FRACTION(25, 1)); |