mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-12 13:30:15 -05:00
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.
This commit is contained in:
parent
1ea84b2869
commit
16b6a51b78
3 changed files with 55 additions and 8 deletions
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue