UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
logo.c
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2013-2024 CESNET
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
39#include <assert.h> // for assert
40#include <stdbool.h> // for false, bool, true
41#include <stdio.h> // for printf, fprintf, stderr
42#include <stdlib.h> // for free, NULL, malloc, atoi, calloc
43#include <string.h> // for strlen, strtok_r, strdup
44
45#include "capture_filter.h"
46#include "compat/strings.h" // for strcasecmp
47#include "debug.h"
48#include "lib_common.h"
49#include "pixfmt_conv.h" // for get_decoder_from_to, decoder_t, vc_copyl...
50#include "types.h" // for video_frame, tile, RGB
51#include "utils/macros.h"
52#include "utils/pam.h"
53#include "video_codec.h"
54#include "video_frame.h" // for VIDEO_FRAME_DISPOSE
55
56struct module;
57
58#define MOD_NAME "[logo] "
59
61 unsigned char *logo;
62 unsigned int width;
63 unsigned int height;
64 int x;
65 int y;
66};
67
68static int init(struct module *parent, const char *cfg, void **state);
69static void done(void *state);
70static struct video_frame *filter(void *state, struct video_frame *in);
71
72static bool load_logo_data_from_file(struct state_capture_filter_logo *s, const char *filename) {
73 if (strcasecmp(filename + (MAX(strlen(filename), 4) - 4), ".pam") == 0) {
74 bool rgb;
75 unsigned char *data;
76 struct pam_metadata info;
77 if (!pam_read(filename, &info, &data, malloc)) {
78 return false;
79 }
80 s->width = info.width;
81 s->height = info.height;
82 if (info.depth != 3 && info.depth != 4) {
83 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unsupported depth %d in PAM file.\n", info.depth);
84 free(data);
85 return false;
86 }
87 rgb = info.depth == 3;
88 int datalen = info.depth * s->width * s->height;
89 if (rgb) {
90 datalen = 4 * s->width * s->height;
91 unsigned char * tmp = malloc(datalen);
92 vc_copylineRGBtoRGBA(tmp, data, datalen, 0, 8, 16);
93 s->logo = tmp;
94 free(data);
95 } else {
96 s->logo = data;
97 }
98 } else {
99 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Only logo in PAM format is currently supported.\n");
100 return false;
101 }
102
103 return true;
104}
105
106static int init(struct module *parent, const char *cfg, void **state)
107{
108 UNUSED(parent);
109 struct state_capture_filter_logo *s = calloc(1, sizeof *s);
110
111 s->x = s->y = -1;
112
113 if (strlen(cfg) == 0 || strcasecmp(cfg, "help") == 0) {
114 printf("Draws overlay logo over video:\n\n");
115 printf("'logo' usage:\n");
116 printf("\tlogo:<file>[:<x>[:<y>]]\n");
117 printf("\t\t<file> - is path to logo to be added in PAM format with alpha\n");
118 free(s);
119 return 1;
120 }
121 char *tmp = strdup(cfg);
122 char *save_ptr = NULL;
123 char *item;
124 if ((item = strtok_r(tmp, ":", &save_ptr)) == NULL) {
125 fprintf(stderr, "File name with logo required!\n");
126 goto error;
127 }
128
130 goto error;
131 }
132
133 if ((item = strtok_r(NULL, ":", &save_ptr))) {
134 s->x = atoi(item);
135 if ((item = strtok_r(NULL, ":", &save_ptr))) {
136 s->y = atoi(item);
137 }
138 }
139 free(tmp);
140 tmp = NULL;
141
142 *state = s;
143 return 0;
144error:
145 free(tmp);
146 free(s->logo);
147 free(s);
148 return -1;
149}
150
151static void done(void *state)
152{
154 state;
155 free(s->logo);
156 free(s);
157}
158
159static struct video_frame *filter(void *state, struct video_frame *in)
160{
162 state;
163 decoder_t decoder, coder;
164 decoder = get_decoder_from_to(in->color_spec, RGB);
165 if (decoder == NULL) {
166 MSG(ERROR, "Cannot find decoder from %s to RGB!\n",
168 }
169 coder = get_decoder_from_to(RGB, in->color_spec);
170 if (coder == NULL) {
171 MSG(ERROR, "Cannot find encoder from %s to RGB!\n",
173 }
174 if (decoder == NULL || coder == NULL)
175 return in;
176
177 int rect_x = s->x;
178 int rect_y = s->y;
179
180 if (rect_x < 0 || rect_x + s->width > in->tiles[0].width) {
181 rect_x = in->tiles[0].width - s->width;
182 }
183 assert(get_pf_block_bytes(in->color_spec) > 0);
184 rect_x = (rect_x / get_pf_block_bytes(in->color_spec)) * get_pf_block_bytes(in->color_spec);
185
186 if (rect_y < 0 || rect_y + s->height > in->tiles[0].height) {
187 rect_y = in->tiles[0].height - s->height;
188 }
189
190 if (rect_x < 0 || rect_y < 0)
191 return in;
192
193 int dec_width = s->width;
194 dec_width = (dec_width + 1) / get_pf_block_bytes(in->color_spec) * get_pf_block_bytes(in->color_spec);
195 int linesize = dec_width * 3;
196
197 unsigned char *segment = (unsigned char *) malloc(linesize * s->height);
198
199 for (unsigned int y = 0; y < s->height; ++y) {
200 decoder(segment + y * linesize, (unsigned char *) in->tiles[0].data + (y + rect_y) *
202 vc_get_linesize(rect_x, in->color_spec), linesize,
203 0, 8, 16);
204 }
205
206 const unsigned char *overlay_data = s->logo;
207 for (unsigned int y = 0; y < s->height; ++y) {
208 unsigned char *image_data = segment + y * linesize;
209 for (unsigned int x = 0; x < s->width; ++x) {
210 int alpha = overlay_data[3];
211 for (int i = 0; i < 3; ++i) {
212 *image_data = (*image_data * (255 - alpha) + *overlay_data++ * alpha) / 255;
213 image_data++;
214 }
215 overlay_data++; // skip alpha
216 }
217 }
218
219 for (unsigned int y = 0; y < s->height; ++y) {
220 coder((unsigned char *) in->tiles[0].data + (rect_y + y) *
222 vc_get_linesize(rect_x, in->color_spec),
223 segment + y * linesize,
224 vc_get_linesize(s->width, in->color_spec), 0, 8, 16);
225 }
226
227 free(segment);
228
229 return in;
230}
231
233 init,
234 done,
235 filter,
236};
237
239
#define UNUSED(x)
void ** state
int vc_get_linesize(unsigned int width, codec_t codec)
const char * get_codec_name(codec_t codec)
#define CAPTURE_FILTER_ABI_VERSION
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MSG(l, fmt,...)
Definition debug.h:96
@ 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
static struct video_frame * filter(void *state, struct video_frame *in)
Definition logo.c:159
static const struct capture_filter_info capture_filter_logo
Definition logo.c:232
static bool load_logo_data_from_file(struct state_capture_filter_logo *s, const char *filename)
Definition logo.c:72
#define MOD_NAME
Definition logo.c:58
static void done(void *state)
Definition logo.c:151
static int init(struct module *parent, const char *cfg, void **state)
Definition logo.c:106
#define MAX(a, b)
Definition macros.h:65
bool pam_read(const char *filename, struct pam_metadata *info, unsigned char **data, void *(*allocator)(size_t))
Definition pam.c:141
decoder_t get_decoder_from_to(codec_t in, codec_t out)
decoder_func_t vc_copylineRGBtoRGBA
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
const char * parent
Definition settings.cpp:198
Definition hd-rum.c:27
unsigned int width
Definition logo.c:62
unsigned int height
Definition logo.c:63
unsigned char * logo
Definition logo.c:61
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
codec_t color_spec
Definition types.h:306
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
int get_pf_block_bytes(codec_t codec)
returns codec_info_t::block_size_bytes