UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
border.c
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2016-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 "video.h"
48#include "video_display.h"
49#include "vo_postprocess.h"
50
53 uint8_t color[4];
54 unsigned int width;
55 unsigned int height;
56 struct video_frame *in;
57};
58
59static bool border_get_property(void *state, int property, void *val, size_t *len)
60{
62 return false;
63}
64
65static void * border_init(const char *config) {
66 struct state_border *s = calloc(1, sizeof *s);
67 memcpy(s->color, ((uint8_t []){ 0xff, 0xff, 0x00, 0xff }), sizeof s->color);
68 s->width = 10;
69 s->height = 10;
70
71 if (strcmp(config, "help") == 0) {
72 printf("border video postprocess takes optional parameters: color to be the border drawn with and border width. Example:\n");
73 printf("\t-p border[:color=rrggbb][:width=<x>][:height=<y>]\n");
74 printf("\n");
75 free(s);
76 return NULL;
77 }
78 char *tmp = strdup(config);
79 char *config_copy = tmp;
80 char *item, *save_ptr;
81 while ((item = strtok_r(config_copy, ":", &save_ptr))) {
82 if (strncasecmp(item, "color=", strlen("color=")) == 0) {
83 const char *color = item + strlen("color=");
84 if (color[0] == '#') {
85 color += 1; //skip #
86 }
87 if (strlen(color) == 6) {
88 char color_str[3] = "";
89 color += 1; //skip #
90
91 for (int i = 0; i < 3; ++i) {
92 color_str[0] = color[0];
93 color_str[1] = color[1];
94
95 s->color[i] = strtol(color_str, NULL, 16);
96
97 color += 2;
98 }
99 } else {
100 log_msg(LOG_LEVEL_ERROR, "Wrong color format!\"");
101 free(tmp);
102 free(s);
103 return NULL;
104 }
105 } else if (strncasecmp(item, "width=", strlen("width=")) == 0) {
106 s->width = atoi(item + strlen("width="));
107 s->width = (s->width + 1) / 2 * 2;
108 } else if (strncasecmp(item, "height=", strlen("height=")) == 0) {
109 s->height = atoi(item + strlen("height="));
110 s->height = (s->height + 1) / 2 * 2;
111 } else {
112 log_msg(LOG_LEVEL_ERROR, "Wrong config!\"");
113 free(tmp);
114 free(s);
115 return NULL;
116 }
117
118 config_copy = NULL;
119 }
120
121 free(tmp);
122
123 return s;
124}
125
126static bool
128{
129 struct state_border *s = (struct state_border *) state;
130 s->saved_desc = desc;
131 vf_free(s->in);
133 return true;
134}
135
136static struct video_frame * border_getf(void *state)
137{
138 struct state_border *s = (struct state_border *) state;
139 return s->in;
140}
141
142static bool border_postprocess(void *state, struct video_frame *in, struct video_frame *out, int req_pitch)
143{
144 assert(req_pitch == vc_get_linesize(in->tiles[0].width, in->color_spec));
145 assert(in->tile_count == 1);
146
147 struct state_border *s = (struct state_border *) state;
148
149 memcpy(out->tiles[0].data + s->height * req_pitch, in->tiles[0].data + s->height * req_pitch, in->tiles[0].data_len - 2 * s->height * req_pitch);
150
151 if (in->color_spec == UYVY) {
152 uint32_t rgba[2] = {0, 0};
153 uint32_t uyvy = 0;
154 memcpy(&rgba[0], s->color, 4);
155 memcpy(&rgba[1], s->color, 4);
157 vc_copylineRGBAtoUYVY((unsigned char *) &uyvy, (unsigned char *) rgba, 4, 0, 0, 0);
158 // up and down
159 for (unsigned int i = 0; i < s->height; ++i) {
160 char *line1 = out->tiles[0].data + i * req_pitch;
161 char *line2 = out->tiles[0].data + (out->tiles[0].height - 1 - i) * req_pitch;
162 for (unsigned int x = 0; x < out->tiles[0].width; x += 2) {
163 memcpy(line1 + x * 2, &uyvy, 4);
164 memcpy(line2 + x * 2, &uyvy, 4);
165 }
166 }
167 // sides
168 for (unsigned int i = 0; i < s->width; ++i) {
169 if (i % 2 == 0) {
170 for (unsigned int y = 0; y < out->tiles[0].height; y += 1) {
171 char *line = out->tiles[0].data + y * req_pitch;
172 char *line_end = out->tiles[0].data + y * req_pitch +
173 vc_get_linesize(out->tiles[0].width, UYVY) - 4;
174 memcpy(line + i / 2 * 4, &uyvy, 4);
175 memcpy(line_end - i / 2 * 4, &uyvy, 4);
176 }
177 }
178 }
179 } else if (in->color_spec == RGB || in->color_spec == RGBA) {
180 int bpp = get_bpp(in->color_spec);
181 for (unsigned int i = 0; i < s->height; ++i) {
182 char *line1 = out->tiles[0].data + i * req_pitch;
183 char *line2 = out->tiles[0].data + (out->tiles[0].height - 1 - i) * req_pitch;
184 for (unsigned int x = 0; x < out->tiles[0].width; x += 1) {
185 memcpy(line1 + x * bpp, s->color, bpp);
186 memcpy(line2 + x * bpp, s->color, bpp);
187 }
188 }
189
190 // sides
191 for (unsigned int i = 0; i < s->width; ++i) {
192 for (unsigned int y = 0; y < out->tiles[0].height; y += 1) {
193 char *line = out->tiles[0].data + y * req_pitch;
194 char *line_end = out->tiles[0].data + y * req_pitch +
195 (out->tiles[0].width - 1) * bpp;
196 memcpy(line + i * bpp, s->color, bpp);
197 memcpy(line_end - i * bpp, s->color, bpp);
198 }
199 }
200 } else {
201 log_msg(LOG_LEVEL_WARNING, "Unsupported pixel format!\n");
202 return false;
203 }
204
205 return true;
206}
207
208static void border_done(void *state)
209{
210 struct state_border *s = (struct state_border *) state;
211
212 vf_free(s->in);
213
214 free(s);
215}
216
217static void border_get_out_desc(void *state, struct video_desc *out, int *in_display_mode, int *out_frames)
218{
219 struct state_border *s = (struct state_border *) state;
220
221 *out = s->saved_desc;
222
223 *in_display_mode = DISPLAY_PROPERTY_VIDEO_MERGED;
224 *out_frames = 1;
225}
226
236
238
#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.
int vc_get_linesize(unsigned int width, codec_t codec)
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
static struct video_frame * border_getf(void *state)
Definition border.c:136
static void * border_init(const char *config)
Definition border.c:65
static bool border_postprocess_reconfigure(void *state, struct video_desc desc)
Definition border.c:127
static void border_get_out_desc(void *state, struct video_desc *out, int *in_display_mode, int *out_frames)
Definition border.c:217
static void border_done(void *state)
Definition border.c:208
static bool border_postprocess(void *state, struct video_frame *in, struct video_frame *out, int req_pitch)
Definition border.c:142
static bool border_get_property(void *state, int property, void *val, size_t *len)
Definition border.c:59
static const struct vo_postprocess_info vo_pp_border_info
Definition border.c:227
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
@ DISPLAY_PROPERTY_VIDEO_MERGED
monolithic framebuffer
@ LIBRARY_CLASS_VIDEO_POSTPROCESS
Definition lib_common.h:83
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
static void vc_copylineRGBAtoUYVY(unsigned char *__restrict dst, const unsigned char *__restrict src, int dst_len, int rshift, int gshift, int bshift)
Converts RGBA to UYVY.
decoder_t get_decoder_from_to(codec_t in, codec_t out)
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
Definition hd-rum.c:27
unsigned int width
border width in pixels (must be even)
Definition border.c:54
struct video_desc saved_desc
Definition border.c:52
uint8_t color[4]
border color in RGBA
Definition border.c:53
struct video_frame * in
Definition border.c:56
unsigned int height
border height in pixels (must be even)
Definition border.c:55
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 data_len
length of the data
Definition types.h:288
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
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70
This is an umbrella header for video functions.
double get_bpp(codec_t codec)
#define VO_PP_ABI_VERSION