UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
crop.c
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2019-2023 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#include "config_unix.h"
41#include "config_win32.h"
42#endif /* HAVE_CONFIG_H */
43
44#include "capture_filter.h"
45#include "debug.h"
46#include "lib_common.h"
47#include "utils/color_out.h"
48#include "utils/macros.h"
49#include "video.h"
50#include "video_display.h"
51#include "vo_postprocess.h"
52
53#define MOD_NAME "[crop] "
54
55struct state_crop {
56 int width;
57 int height;
58 int xoff;
59 int yoff;
62 struct video_frame *in;
63};
64
65static bool crop_get_property(void *state, int property, void *val, size_t *len)
66{
68 return false;
69}
70
71static void usage(_Bool capture_filter) {
72 color_printf("This filter spatially crops video to given dimensions. If the video is smaller than the crop, no cropping is performed.\n\n");
73 color_printf("crop filter takes optional parameters: " TBOLD("width") ", "
74 TBOLD("height") ", "
75 TBOLD("xoff") " and "
76 TBOLD("yoff") ". Example:\n"
77 "\t" TBOLD(TRED("%s crop") "[:size=<w>x<h>][:xoff=<x>][:yoff=<y>]") "\n\n",
78 capture_filter ? "--capture-filter" : "-p");
79}
80
81static void * crop_init(const char *config) {
82
83 if (strcmp(config, "help") == 0) {
84 usage(0);
85 return NULL;
86 }
87
88 struct state_crop *s = calloc(1, sizeof *s);
89
90 char *tmp = strdup(config);
91 char *config_copy = tmp;
92 char *item, *save_ptr;
93 while ((item = strtok_r(config_copy, ":", &save_ptr))) {
94 if (strstr(item, "size=") == item) {
95 if (strchr(item, 'x') == NULL) {
96 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Missing height!\n");
97 }
98 s->width = atoi(strchr(item, '=') + 1);
99 s->height = atoi(strchr(item, 'x') + 1);
100 } else if (strncasecmp(item, "width=", strlen("width=")) == 0) {
101 s->width = atoi(item + strlen("width="));
102 } else if (strncasecmp(item, "height=", strlen("height=")) == 0) {
103 s->height = atoi(item + strlen("height="));
104 } else if (strncasecmp(item, "xoff=", strlen("xoff=")) == 0) {
105 s->xoff = atoi(item + strlen("xoff="));
106 } else if (strncasecmp(item, "yoff=", strlen("yoff=")) == 0) {
107 s->yoff = atoi(item + strlen("yoff="));
108 } else {
109 log_msg(LOG_LEVEL_ERROR, "Wrong config: %s!\n", item);
110 free(tmp);
111 free(s);
112 return NULL;
113 }
114
115 config_copy = NULL;
116 }
117
118 free(tmp);
119
120 return s;
121}
122
123static bool
125{
126 struct state_crop *s = state;
127 vf_free(s->in);
128
129 s->in_desc = desc;
131
132 s->out_desc = desc;
133 s->out_desc.width = s->width ? MIN(s->width, (int) desc.width) : (int) desc.width;
134 s->out_desc.height = s->height ? MIN(s->height, (int) desc.height) : (int) desc.height;
135
136 // make sure that width is divisible by pixel block size
137 assert(get_pf_block_bytes(desc.color_spec) != 0);
138 int linesize = (int) (s->out_desc.width * get_bpp(desc.color_spec)) / get_pf_block_bytes(desc.color_spec)
140 s->out_desc.width = linesize / get_bpp(desc.color_spec);
141
142 return true;
143}
144
145static struct video_frame * crop_getf(void *state)
146{
147 struct state_crop *s = state;
148 return s->in;
149}
150
151static bool crop_postprocess(void *state, struct video_frame *in, struct video_frame *out, int req_pitch)
152{
153 assert(in->tile_count == 1);
154 assert(get_pf_block_bytes(in->color_spec) != 0);
155
156 struct state_crop *s = state;
157 int src_linesize = vc_get_linesize(in->tiles[0].width, in->color_spec);
158 int xoff = s->xoff + out->tiles[0].width > in->tiles[0].width ? in->tiles[0].width - out->tiles[0].width : (unsigned) s->xoff;
159 int xoff_bytes = (int) (xoff * get_bpp(in->color_spec)) / get_pf_block_bytes(in->color_spec)
161 int yoff = s->yoff + out->tiles[0].height > in->tiles[0].height ? in->tiles[0].height - out->tiles[0].height : (unsigned) s->yoff;
162
163 for (int y = 0 ; y < (int) out->tiles[0].height; y++) {
164 memcpy(out->tiles[0].data + y * req_pitch,
165 in->tiles[0].data + (yoff + y) * src_linesize + xoff_bytes,
166 req_pitch);
167 }
168
169 return true;
170}
171
172static void crop_done(void *state)
173{
174 struct state_crop *s = state;
175
176 vf_free(s->in);
177 free(s);
178}
179
180static void crop_get_out_desc(void *state, struct video_desc *out, int *in_display_mode, int *out_frames)
181{
182 *out = ((struct state_crop *) state)->out_desc;
183
184 *in_display_mode = DISPLAY_PROPERTY_VIDEO_MERGED;
185 *out_frames = 1;
186}
187
188static int cf_crop_init(struct module *parent, const char *cfg, void **state)
189{
190 UNUSED(parent);
191 if (strcmp(cfg, "help") == 0) {
192 usage(1);
193 return 1;
194 }
195 void *s = crop_init(cfg);
196 if (!s) {
197 return -1;
198 }
199 *state = s;
200 return 0;
201}
202
203static struct video_frame *cf_crop_filter(void *state, struct video_frame *f)
204{
205 struct state_crop *s = state;
206
209 abort(); // cannot fail now
210 }
211 }
212
213 struct video_frame *out = vf_alloc_desc_data(s->out_desc);
217 vf_free(out);
218 return NULL;
219 }
221 return out;
222}
223
233
239
242
#define UNUSED(x)
void ** state
int void * val
struct video_desc desc
int void size_t * len
int property
void vf_free(struct video_frame *buf)
Frees video_frame structure.
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
int vc_get_linesize(unsigned int width, codec_t codec)
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
#define CAPTURE_FILTER_ABI_VERSION
int color_printf(const char *format,...)
#define TRED(x)
Definition color_out.h:75
#define TBOLD(x)
Definition color_out.h:70
static bool crop_postprocess_reconfigure(void *state, struct video_desc desc)
Definition crop.c:124
static struct video_frame * crop_getf(void *state)
Definition crop.c:145
static void crop_get_out_desc(void *state, struct video_desc *out, int *in_display_mode, int *out_frames)
Definition crop.c:180
static void * crop_init(const char *config)
Definition crop.c:81
static void crop_done(void *state)
Definition crop.c:172
static const struct capture_filter_info capture_filter_crop_info
Definition crop.c:234
static int cf_crop_init(struct module *parent, const char *cfg, void **state)
Definition crop.c:188
static bool crop_postprocess(void *state, struct video_frame *in, struct video_frame *out, int req_pitch)
Definition crop.c:151
#define MOD_NAME
Definition crop.c:53
static struct video_frame * cf_crop_filter(void *state, struct video_frame *f)
Definition crop.c:203
static bool crop_get_property(void *state, int property, void *val, size_t *len)
Definition crop.c:65
static const struct vo_postprocess_info vo_pp_crop_info
Definition crop.c:224
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
@ DISPLAY_PROPERTY_VIDEO_MERGED
monolithic framebuffer
void usage()
Definition main.cpp:28
@ LIBRARY_CLASS_VIDEO_POSTPROCESS
Definition lib_common.h:83
@ LIBRARY_CLASS_CAPTURE_FILTER
Definition lib_common.h:75
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
#define MIN(a, b)
Definition macros.h:63
const char * parent
Definition settings.cpp:198
Definition hd-rum.c:27
struct video_desc out_desc
Definition crop.c:61
int width
Definition crop.c:56
struct video_frame * in
Definition crop.c:62
int height
Definition crop.c:57
int yoff
Definition crop.c:59
struct video_desc in_desc
Definition crop.c:60
int xoff
Definition crop.c:58
unsigned int width
Definition types.h:280
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int height
Definition types.h:281
codec_t color_spec
Definition types.h:182
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
void(* dispose)(struct video_frame *)
Definition types.h:245
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
unsigned int tile_count
Definition types.h:344
struct video_frame_callbacks callbacks
Definition types.h:324
codec_t color_spec
Definition types.h:306
This is an umbrella header for video functions.
int get_pf_block_bytes(codec_t codec)
returns codec_info_t::block_size_bytes
double get_bpp(codec_t codec)
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.
#define VIDEO_FRAME_DISPOSE(frame)
Definition video_frame.h:76
#define VO_PP_ABI_VERSION