UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
testcard_common.c
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2020-2022 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#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 "pixfmt_conv.h"
45#include "utils/color_out.h"
46#include "video.h"
48
49const uint32_t rect_colors[] = {
50 0xff0000ffLU,
51 0xff00ff00LU,
52 0xffff0000LU,
53 0xff00ffffLU,
54 0xffffff00LU,
55 0xffff00ffLU
56};
57
58void testcard_fillRect(struct testcard_pixmap *s, struct testcard_rect *r, uint32_t color)
59{
60 uint32_t *data = s->data;
61
62 for (int cur_x = r->x; cur_x < r->x + r->w; ++cur_x) {
63 for (int cur_y = r->y; cur_y < r->y + r->h; ++cur_y) {
64 if (cur_x < s->w) {
65 *(data + (long) s->w * cur_y + cur_x) = color;
66 }
67 }
68 }
69}
70
77static void toI420(unsigned char *out, const unsigned char *input, int width, int height)
78{
79 const unsigned char *in = (const unsigned char *) input;
80 int w_ch = (width + 1) / 2;
81 int h_ch = (height + 1) / 2;
82 unsigned char *y = out;
83 unsigned char *u0 = out + width * height;
84 unsigned char *v0 = out + width * height + w_ch * h_ch;
85 unsigned char *u1 = u0, *v1 = v0;
86
87 for (int i = 0; i < height; i += 1) {
88 for (int j = 0; j < ((width + 1) & ~1); j += 2) {
89 // U
90 if (i % 2 == 0) {
91 *u0++ = *in++;
92 } else { // average with every 2nd row
93 *u1 = (*u1 + *in++) / 2;
94 u1++;
95 }
96 // Y
97 *y++ = *in++;
98 // V
99 if (i % 2 == 0) {
100 *v0++ = *in++;
101 } else { // average with every 2nd row
102 *v1 = (*v1 + *in++) / 2;
103 v1++;
104 }
105 // Y
106 if (j + 1 == width) {
107 in++;
108 } else {
109 *y++ = *in++;
110 }
111 }
112 }
113}
114
115void testcard_convert_buffer(codec_t in_c, codec_t out_c, unsigned char *out, unsigned const char *in, int width, int height)
116{
117 unsigned char *tmp_buffer = NULL;
118 if (out_c == I420 || out_c == YUYV || (in_c == RGBA && out_c == v210)) {
119 decoder_t decoder = get_decoder_from_to(in_c, UYVY);
120 tmp_buffer = malloc(2L * ((width + 1U) ^ 1U) * height);
121 long in_linesize = vc_get_size(width, in_c);
122 long out_linesize = vc_get_size(width, UYVY);
123 for (int i = 0; i < height; ++i) {
124 decoder(tmp_buffer + i * out_linesize, in + i * in_linesize, vc_get_size(width, UYVY), DEFAULT_R_SHIFT, DEFAULT_G_SHIFT, DEFAULT_B_SHIFT);
125 }
126 in = tmp_buffer;
127 in_c = UYVY;
128 }
129 if (out_c == I420) {
130 toI420(out, in, width, height);
131 free(tmp_buffer);
132 return;
133 }
134 decoder_t decoder = get_decoder_from_to(in_c, out_c);
135 assert(decoder != NULL);
136 long out_linesize = vc_get_linesize(width, out_c);
137 long in_linesize = vc_get_linesize(width, in_c);
138 for (int i = 0; i < height; ++i) {
139 decoder(out + i * out_linesize, in + i * in_linesize, vc_get_size(width, out_c), DEFAULT_R_SHIFT, DEFAULT_G_SHIFT, DEFAULT_B_SHIFT);
140 }
141 free(tmp_buffer);
142}
143
145{
146 return c == I420 || c == YUYV || c == v210;
147}
148
149void testcard_show_codec_help(const char *name, bool src_8b_only)
150{
151 bool print_i420 = !src_8b_only; // testcard2 cannot handle planar format, anyway
152 printf("Supported codecs (%s):\n", name);
153
154 color_printf(TERM_FG_RED "\t8 bits\n" TERM_RESET);
155 for (codec_t c = VIDEO_CODEC_FIRST; c != VIDEO_CODEC_COUNT; c = (int) c + 1) {
158 continue;
159 }
160 if (c == I420 && !print_i420) {
161 continue;
162 }
164 }
165
166 color_printf(TERM_FG_RED "\t10+ bits\n" TERM_RESET);
167 for (codec_t c = VIDEO_CODEC_FIRST; c != VIDEO_CODEC_COUNT; c = (int) c + 1) {
168 if (is_codec_opaque(c) || get_bits_per_component(c) == 8) {
169 continue;
170 }
172 ((src_8b_only && c != v210) || get_decoder_from_to(RG48, c) == VIDEO_CODEC_NONE)) {
173 continue;
174 }
176 }
177}
178
180{
181 return get_decoder_from_to(RG48, c) != NULL ||
182 get_decoder_from_to(RGBA, c) != NULL ||
184}
185
int vc_get_linesize(unsigned int width, codec_t codec)
const char * get_codec_name(codec_t codec)
int color_printf(const char *format,...)
#define TERM_BOLD
Definition color_out.h:48
#define TERM_FG_RED
Definition color_out.h:50
#define TERM_RESET
Definition color_out.h:47
decoder_t get_decoder_from_to(codec_t in, codec_t out)
#define DEFAULT_B_SHIFT
Definition pixfmt_conv.h:72
#define DEFAULT_R_SHIFT
Definition pixfmt_conv.h:70
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
#define DEFAULT_G_SHIFT
Definition pixfmt_conv.h:71
const char * name
Definition settings.cpp:193
const uint32_t rect_colors[]
static bool testcard_conv_handled_internally(codec_t c)
void testcard_show_codec_help(const char *name, bool src_8b_only)
void testcard_fillRect(struct testcard_pixmap *s, struct testcard_rect *r, uint32_t color)
static void toI420(unsigned char *out, const unsigned char *input, int width, int height)
bool testcard_has_conversion(codec_t c)
void testcard_convert_buffer(codec_t in_c, codec_t out_c, unsigned char *out, unsigned const char *in, int width, int height)
codec_t
Definition types.h:65
@ YUYV
YCbCr 422 8-bit - Y0 Cb Y1 Cr.
Definition types.h:72
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66
@ VIDEO_CODEC_FIRST
Definition types.h:68
@ RG48
16-bit RGB little-endian (RlRhGl...)
Definition types.h:95
@ VIDEO_CODEC_COUNT
count of known video codecs (including VIDEO_CODEC_NONE)
Definition types.h:108
@ I420
planar YCbCr 4:2:0
Definition types.h:97
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70
@ v210
YCbCr 422 10-bit - xVY0U|xY2UY1|xUY3V|xY5VY4, little-endian (2 bit padding /'x'/),...
Definition types.h:75
This is an umbrella header for video functions.
bool is_codec_opaque(codec_t codec)
int vc_get_size(unsigned int width, codec_t codec)
const char * get_codec_name_long(codec_t codec)
int get_bits_per_component(codec_t codec)