UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
blank.c
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2013-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 "lib_common.h"
46#include "libavcodec/utils.h"
47#include "messaging.h"
48#include "module.h"
49
50#include "video.h"
51#include "video_codec.h"
52
53#include <libswscale/swscale.h>
54
55#define FACTOR 6
56
57static int init(struct module *parent, const char *cfg, void **state);
58static void done(void *state);
59static struct video_frame *filter(void *state, struct video_frame *in);
60
75
76static bool parse(struct state_blank *s, char *cfg)
77{
78 int vals[4];
79 double vals_relative[4];
80 unsigned int counter = 0;
81 bool black = false;
82
83 memset(&s->saved_desc, 0, sizeof(s->saved_desc));
84
85 if (strchr(cfg, '%')) {
86 s->in_relative_units = true;
87 } else {
88 s->in_relative_units = false;
89 }
90
91 char *item, *save_ptr = NULL;
92 while ((item = strtok_r(cfg, ":", &save_ptr))) {
93 if (s->in_relative_units) {
94 vals_relative[counter] = atof(item) / 100.0;
95 if (vals_relative[counter] < 0.0)
96 vals_relative[counter] = 0.0;
97 } else {
98 vals[counter] = atoi(item);
99 if (vals[counter] < 0)
100 vals[counter] = 0;
101 }
102
103 cfg = NULL;
104 counter += 1;
105 if (counter == sizeof(vals) / sizeof(int))
106 break;
107 }
108 while ((item = strtok_r(cfg, ":", &save_ptr))) {
109 if (strcmp(item, "black") == 0) {
110 black = true;
111 } else {
112 fprintf(stderr, "[Blank] Unknown config value: %s\n",
113 item);
114 return false;
115 }
116 }
117
118 if(counter != sizeof(vals) / sizeof(int)) {
119 fprintf(stderr, "[Blank] Few config values.\n");
120 return false;
121 }
122
123 if (s->in_relative_units) {
124 s->x_relative = vals_relative[0];
125 s->y_relative = vals_relative[1];
126 s->width_relative = vals_relative[2];
127 s->height_relative = vals_relative[3];
128 } else {
129 s->x = vals[0];
130 s->y = vals[1];
131 s->width = (vals[2] + FACTOR - 1) / FACTOR * FACTOR;
132 s->height = vals[3];
133 }
134 s->black = black;
135
136 return true;
137}
138
139static int init(struct module *parent, const char *cfg, void **state)
140{
141 if (cfg && strcasecmp(cfg, "help") == 0) {
142 printf("Blanks specified rectangular area:\n\n");
143 printf("blank usage:\n");
144 printf("\tblank:x:y:widht:height[:black]\n");
145 printf("\t\tor\n");
146 printf("\tblank:x%%:y%%:widht%%:height%%[:black]\n");
147 printf("\t(all values in pixels)\n");
148 return 1;
149 }
150
151 struct state_blank *s = calloc(1, sizeof *s);
152 assert(s);
153
154 if (cfg) {
155 char *tmp = strdup(cfg);
156 bool ret = parse(s, tmp);
157 free(tmp);
158 if (!ret) {
159 free(s);
160 return -1;
161 }
162 }
163
167
168 *state = s;
169 return 0;
170}
171
172static void done(void *state)
173{
174 struct state_blank *s = state;
175 module_done(&s->mod);
176
177 sws_freeContext(s->ctx_downscale);
178 sws_freeContext(s->ctx_upscale);
179 free(s);
180}
181
182static struct response * process_message(struct state_blank *s, struct msg_universal *msg)
183{
184 if (parse(s, msg->text)) {
185 return new_response(RESPONSE_OK, NULL);
186 } else {
188 }
189}
190
194static struct video_frame *filter(void *state, struct video_frame *in)
195{
196 assert(in->tile_count == 1);
197
198 struct state_blank *s = state;
200 int bpp = get_bpp(codec);
201 enum AVPixelFormat av_pixfmt = AV_PIX_FMT_NONE;
202
203 if (get_ug_to_av_pixfmt(codec) != AV_PIX_FMT_NONE) {
205 }
206
207 if (s->in_relative_units) {
208 s->x = s->x_relative * in->tiles[0].width;
209 s->y = s->y_relative * in->tiles[0].height;
210 s->width = s->width_relative * in->tiles[0].width;
211 s->width = (s->width + FACTOR - 1) / FACTOR * FACTOR;
212 s->height = s->height_relative * in->tiles[0].height;
213 }
214
215 int width = s->width;
216 int height = s->height;
217 int x = s->x;
218 int y = s->y;
219
220 x = (x + bpp - 1) / bpp * bpp;
221
222 if (y + height > (int) in->tiles[0].height) {
223 height = in->tiles[0].height - y;
224 }
225
226 if (x + width > (int) in->tiles[0].width) {
227 width = in->tiles[0].width - x;
228 width = width / FACTOR * FACTOR;
229 }
230
231 // don't know why but when not done, it leaves black or grey border on the right side
232 // for BGR
233 if (codec == BGR) {
234 width = width / (FACTOR * 3) * (FACTOR * 3);
235 }
236
239
240 if (av_pixfmt == AV_PIX_FMT_NONE || !sws_isSupportedInput(av_pixfmt) ||
241 !sws_isSupportedOutput(av_pixfmt)) {
242 fprintf(stderr, "Unable to find suitable pixfmt!\n");
243 return in;
244 }
245
246 sws_freeContext(s->ctx_downscale);
247 sws_freeContext(s->ctx_upscale);
248
249 s->ctx_downscale = sws_getContext(width, height, av_pixfmt,
250 width / FACTOR, height / FACTOR, av_pixfmt, SWS_FAST_BILINEAR,0,0,0);
251 s->ctx_upscale = sws_getContext(width / FACTOR, height / FACTOR, av_pixfmt,
252 width, height, av_pixfmt, SWS_FAST_BILINEAR,0,0,0);
253
254 if (s->ctx_downscale == NULL || s->ctx_upscale == NULL) {
255 fprintf(stderr, "Unable to initialize scaling context!");
256 return in;
257 }
258
260 }
261
262 struct message *msg;
263 while ((msg = check_message(&s->mod))) {
264 struct response *r = process_message(s, (struct msg_universal *) msg);
265 free_message(msg, r);
266 }
267
268 if (width <= 0 || height <= 0)
269 return in;
270
271 int orig_stride = vc_get_linesize(in->tiles[0].width, in->color_spec);
272 char *orig = in->tiles[0].data + x * bpp + y * orig_stride;
273 int tmp_stride = vc_get_linesize(width / FACTOR, in->color_spec);
274 size_t tmp_len = tmp_stride * (height / FACTOR);
275 uint8_t *tmp = (uint8_t *) malloc(tmp_len);
276 if (s->black) {
277 if (codec == UYVY) {
278 unsigned char pattern[] = { 127, 0 };
279
280 for (size_t i = 0; i < tmp_len; i += get_bpp(codec)) {
281 memcpy(tmp + i, pattern, get_bpp(codec));
282 }
283 } else {
284 memset(tmp, 0, tmp_len);
285 }
286 } else {
287 sws_scale(s->ctx_downscale, (const uint8_t * const *) &orig, &orig_stride, 0, height, &tmp, &tmp_stride);
288 }
289 sws_scale(s->ctx_upscale, (const uint8_t * const *) &tmp, &tmp_stride, 0, height / FACTOR, (uint8_t **) &orig, &orig_stride);
290
291 free(tmp);
292
293 return in;
294}
295
297 .init = init,
298 .done = done,
299 .filter = filter,
300};
301
303
void ** state
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)
pattern
Definition testcard.c:94
static struct video_frame * filter(void *state, struct video_frame *in)
Definition blank.c:194
static struct response * process_message(struct state_blank *s, struct msg_universal *msg)
Definition blank.c:182
#define FACTOR
Definition blank.c:55
static const struct capture_filter_info capture_filter_blank
Definition blank.c:296
static bool parse(struct state_blank *s, char *cfg)
Definition blank.c:76
static void done(void *state)
Definition blank.c:172
static int init(struct module *parent, const char *cfg, void **state)
Definition blank.c:139
#define CAPTURE_FILTER_ABI_VERSION
void module_init_default(struct module *module_data)
Definition module.c:48
void module_register(struct module *module_data, struct module *parent)
Definition module.c:82
void module_done(struct module *module_data)
Definition module.c:93
@ MODULE_CLASS_DATA
Definition module.h:86
enum AVPixelFormat av_pixfmt
@ 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
void free_message(struct message *msg, struct response *r)
struct response * new_response(int status, const char *text)
struct message * check_message(struct module *mod)
#define RESPONSE_OK
Definition messaging.h:57
#define RESPONSE_BAD_REQUEST
Definition messaging.h:60
struct msghdr msg
const char * parent
Definition settings.cpp:198
Definition hd-rum.c:27
enum module_class cls
Definition module.h:115
int width
Definition blank.c:64
double x_relative
Definition blank.c:65
struct SwsContext * ctx_downscale
Definition blank.c:72
int x
Definition blank.c:64
int height
Definition blank.c:64
struct module mod
Definition blank.c:62
int y
Definition blank.c:64
double y_relative
Definition blank.c:65
double height_relative
Definition blank.c:65
bool black
Definition blank.c:70
struct video_desc saved_desc
Definition blank.c:67
bool in_relative_units
Definition blank.c:69
struct SwsContext * ctx_upscale
Definition blank.c:73
double width_relative
Definition blank.c:65
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
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
codec_t color_spec
Definition types.h:306
codec_t
Definition types.h:65
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
@ BGR
8-bit BGR
Definition types.h:88
enum AVPixelFormat get_ug_to_av_pixfmt(codec_t ug_codec)
Definition utils.c:84
This is an umbrella header for video functions.
double get_bpp(codec_t codec)
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.