UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
cuda_dxt.cpp
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2012-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 "cuda_dxt/cuda_dxt.h"
45#include "cuda_wrapper.h"
46#include "debug.h"
47
48#include "host.h"
49#include "lib_common.h"
50#include "module.h"
52#include "video.h"
53#include "video_compress.h"
54
55using namespace std;
56
57namespace {
58
59struct cuda_buffer_data_allocator : public video_frame_pool_allocator {
60 void *allocate(size_t size) override {
61 void *ptr;
63 size)) {
64 return NULL;
65 }
66 return ptr;
67 }
68 void deallocate(void *ptr) override {
70 }
71 video_frame_pool_allocator *clone() const override {
72 return new cuda_buffer_data_allocator(*this);
73 }
74};
75
76struct state_video_compress_cuda_dxt {
77 struct module module_data;
78 struct video_desc saved_desc;
79 char *in_buffer;
80 char *cuda_uyvy_buffer;
81 char *cuda_in_buffer;
82 char *cuda_out_buffer;
83 codec_t in_codec;
84 codec_t out_codec;
85 decoder_t decoder;
86
87 video_frame_pool pool{0, cuda_buffer_data_allocator()};
88};
89
90static void cuda_dxt_compress_done(struct module *mod);
91
92struct module *cuda_dxt_compress_init(struct module *parent,
93 const char *fmt)
94{
95 state_video_compress_cuda_dxt *s =
96 new state_video_compress_cuda_dxt();
97 s->out_codec = DXT1;
98
99 if (fmt && fmt[0] != '\0') {
100 if (strcasecmp(fmt, "DXT5") == 0) {
101 s->out_codec = DXT5;
102 } else if (strcasecmp(fmt, "DXT1") == 0) {
103 s->out_codec = DXT1;
104 } else {
105 printf("usage:\n"
106 "\t-c cuda_dxt[:DXT1|:DXT5]\n");
107 delete s;
108 return NULL;
109 }
110 }
111
112 module_init_default(&s->module_data);
113 s->module_data.cls = MODULE_CLASS_DATA;
114 s->module_data.priv_data = s;
115 s->module_data.deleter = cuda_dxt_compress_done;
116 module_register(&s->module_data, parent);
117
118 return &s->module_data;
119}
120
121static void cleanup(struct state_video_compress_cuda_dxt *s)
122{
123 if (s->in_buffer) {
124 free(s->in_buffer);
125 s->in_buffer = NULL;
126 }
127 if (s->cuda_uyvy_buffer) {
128 cuda_wrapper_free(s->cuda_uyvy_buffer);
129 s->cuda_uyvy_buffer = NULL;
130 }
131 if (s->cuda_in_buffer) {
132 cuda_wrapper_free(s->cuda_in_buffer);
133 s->cuda_in_buffer = NULL;
134 }
135 if (s->cuda_out_buffer) {
136 cuda_wrapper_free(s->cuda_out_buffer);
137 s->cuda_out_buffer = NULL;
138 }
139}
140
141static bool configure_with(struct state_video_compress_cuda_dxt *s, struct video_desc desc)
142{
143 cleanup(s);
144
146 LOG(LOG_LEVEL_NOTICE) << "[CUDA DXT] Converting from " << get_bits_per_component(desc.color_spec) <<
147 " to 8 bits. You may directly capture 8-bit signal to improve performance.\n";
148 }
149
151 s->decoder = get_best_decoder_from(desc.color_spec, supported_codecs, &s->in_codec);
152 if (!s->decoder) {
153 fprintf(stderr, "Unsupported codec: %s\n", get_codec_name(desc.color_spec));
154 return false;
155 }
156
157 if (s->in_codec == UYVY) {
158 if (CUDA_WRAPPER_SUCCESS != cuda_wrapper_malloc((void **) &s->cuda_uyvy_buffer,
159 desc.width * desc.height * 2)) {
160 fprintf(stderr, "Could not allocate CUDA UYVY buffer.\n");
161 return false;
162 }
163 }
164
165 s->in_buffer = (char *) malloc(desc.width * desc.height * 3);
166
167 if (CUDA_WRAPPER_SUCCESS != cuda_wrapper_malloc((void **) &s->cuda_in_buffer,
168 desc.width * desc.height * 3)) {
169 fprintf(stderr, "Could not allocate CUDA output buffer.\n");
170 return false;
171 }
172
173 struct video_desc compressed_desc = desc;
174 compressed_desc.color_spec = s->out_codec;
175 compressed_desc.tile_count = 1;
176 size_t data_len = desc.width * desc.height / (s->out_codec == DXT1 ? 2 : 1);
177
178 s->pool.reconfigure(compressed_desc, data_len);
179
181 &s->cuda_out_buffer,
182 data_len)) {
183 fprintf(stderr, "Could not allocate CUDA output buffer.\n");
184 return false;
185 }
186
187 return true;
188}
189
190shared_ptr<video_frame> cuda_dxt_compress_tile(struct module *mod, shared_ptr<video_frame> tx)
191{
192 if (!tx) {
193 return {};
194 }
195
196 struct state_video_compress_cuda_dxt *s =
197 (struct state_video_compress_cuda_dxt *) mod->priv_data;
198
200
202 s->saved_desc, PARAM_TILE_COUNT)) {
204 s->saved_desc = video_desc_from_frame(tx.get());
205 } else {
206 fprintf(stderr, "[CUDA DXT] Reconfiguration failed!\n");
207 return NULL;
208 }
209 }
210
211 char *in_buffer;
212 if (tx->color_spec == s->in_codec) {
213 in_buffer = tx->tiles[0].data;
214 } else {
215 unsigned char *line1 = (unsigned char *) tx->tiles[0].data;
216 unsigned char *line2 = (unsigned char *) s->in_buffer;
217
218 for (int i = 0; i < (int) tx->tiles[0].height; ++i) {
219 s->decoder(line2, line1, vc_get_linesize(tx->tiles[0].width,
220 s->in_codec), 0, 8, 16);
221 line1 += vc_get_linesize(tx->tiles[0].width, tx->color_spec);
222 line2 += vc_get_linesize(tx->tiles[0].width, s->in_codec);
223 }
224 in_buffer = s->in_buffer;
225 }
226
227 if (s->in_codec == UYVY) {
228 if (cuda_wrapper_memcpy(s->cuda_uyvy_buffer, in_buffer, tx->tiles[0].width *
229 tx->tiles[0].height * 2,
231 fprintf(stderr, "Memcpy failed: %s\n", cuda_wrapper_last_error_string());
232 return NULL;
233 }
234 if (cuda_yuv422_to_yuv444(s->cuda_uyvy_buffer, s->cuda_in_buffer,
235 tx->tiles[0].width *
236 tx->tiles[0].height, 0) != CUDA_WRAPPER_SUCCESS) {
237 fprintf(stderr, "Kernel failed: %s\n", cuda_wrapper_last_error_string());
238 }
239 } else {
240 if (cuda_wrapper_memcpy(s->cuda_in_buffer, in_buffer, tx->tiles[0].width *
241 tx->tiles[0].height * 3,
243 fprintf(stderr, "Memcpy failed: %s\n", cuda_wrapper_last_error_string());
244 return NULL;
245 }
246 }
247
248 int (*cuda_dxt_enc_func)(const void * src, void * out, int size_x, int size_y,
249 cuda_wrapper_stream_t stream);
250
251 if (s->out_codec == DXT1) {
252 if (s->in_codec == RGB) {
253 cuda_dxt_enc_func = cuda_rgb_to_dxt1;
254 } else {
255 cuda_dxt_enc_func = cuda_yuv_to_dxt1;
256 }
257 } else {
258 if (s->in_codec == RGB) {
259 cuda_dxt_enc_func = cuda_rgb_to_dxt6;
260 } else {
261 cuda_dxt_enc_func = cuda_yuv_to_dxt6;
262 }
263 }
264 int ret = cuda_dxt_enc_func(s->cuda_in_buffer, s->cuda_out_buffer,
265 s->saved_desc.width, s->saved_desc.height, 0);
266 if (ret != 0) {
267 fprintf(stderr, "Encoding failed: %s\n", cuda_wrapper_last_error_string());
268 return NULL;
269 }
270
271 shared_ptr<video_frame> out = s->pool.get_frame();
272 if (cuda_wrapper_memcpy(out->tiles[0].data,
273 s->cuda_out_buffer,
274 out->tiles[0].data_len,
276 fprintf(stderr, "Memcpy failed: %s\n", cuda_wrapper_last_error_string());
277 return NULL;
278 }
279
280 return out;
281}
282
283static void cuda_dxt_compress_done(struct module *mod)
284{
285 struct state_video_compress_cuda_dxt *s =
286 (struct state_video_compress_cuda_dxt *) mod->priv_data;
287
288 cleanup(s);
289
290 delete s;
291}
292
293const struct video_compress_info cuda_dxt_info = {
294 "cuda_dxt",
295 cuda_dxt_compress_init,
296 NULL,
297 cuda_dxt_compress_tile,
298 NULL,
299 NULL,
300 NULL,
301 NULL,
302 NULL
303};
304
306
307} // end of anonymous namespace
308
struct video_desc desc
const char * fmt
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)
const char * get_codec_name(codec_t codec)
static const audio_codec_t supported_codecs[]
Definition libavcodec.c:785
int cuda_yuv_to_dxt1(const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
Definition cuda_dxt.cu:799
int cuda_yuv_to_dxt6(const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
Definition cuda_dxt.cu:821
int cuda_rgb_to_dxt6(const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
Definition cuda_dxt.cu:816
int cuda_rgb_to_dxt1(const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
Definition cuda_dxt.cu:782
int cuda_yuv422_to_yuv444(const void *src, void *out, int pix_count, cuda_wrapper_stream_t str)
Definition cuda_dxt.cu:762
Interface of DXT compression CUDA implementation.
int cuda_wrapper_set_device(int index)
int cuda_wrapper_malloc_host(void **buffer, size_t data_len)
void * cuda_wrapper_stream_t
int cuda_wrapper_free(void *buffer)
const char * cuda_wrapper_last_error_string(void)
int cuda_wrapper_memcpy(void *dst, const void *src, size_t count, int kind)
int cuda_wrapper_malloc(void **buffer, size_t data_len)
This file contais wrapper around CUDA functions.
#define CUDA_WRAPPER_SUCCESS
#define CUDA_WRAPPER_MEMCPY_HOST_TO_DEVICE
#define CUDA_WRAPPER_MEMCPY_DEVICE_TO_HOST
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define LOG(level)
Definition debug.h:313
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
@ MODULE_CLASS_DATA
Definition module.h:86
#define VIDEO_COMPRESS_ABI_VERSION
unsigned int cuda_devices[MAX_CUDA_DEVICES]
Definition host.cpp:167
@ LIBRARY_CLASS_VIDEO_COMPRESS
Definition lib_common.h:82
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
decoder_t get_best_decoder_from(codec_t in, const codec_t *out_candidates, codec_t *out)
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
static void cleanup()
Definition sdp.c:195
const char * parent
Definition settings.cpp:198
enum module_class cls
Definition module.h:115
void * priv_data
Definition module.h:126
module_deleter_t deleter
Definition module.h:118
unsigned int tile_count
Definition types.h:185
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
std::shared_ptr< video_frame > get_frame()
void reconfigure(struct video_desc new_desc, size_t new_size=SIZE_MAX)
codec_t
Definition types.h:65
@ DXT1
S3 Texture Compression DXT1.
Definition types.h:77
@ 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
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66
@ DXT5
S3 Texture Compression DXT5.
Definition types.h:79
This is an umbrella header for video functions.
int get_bits_per_component(codec_t codec)
static bool configure_with(struct state_video_compress_cineform *s, struct video_desc desc)
Definition cineform.cpp:243
API for video compress drivers.
bool video_desc_eq_excl_param(struct video_desc a, struct video_desc b, unsigned int excluded_params)
Compares two video descriptions.
#define PARAM_TILE_COUNT
Definition video_frame.h:68