UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
cmpto_j2k.cpp File Reference
#include <cassert>
#include <climits>
#include <condition_variable>
#include <mutex>
#include <utility>
#include <cmpto_j2k_enc.h>
#include "debug.h"
#include "host.h"
#include "lib_common.h"
#include "module.h"
#include "tv.h"
#include "utils/color_out.h"
#include "utils/macros.h"
#include "utils/misc.h"
#include "utils/parallel_conv.h"
#include "utils/video_frame_pool.h"
#include "video_codec.h"
#include "video_compress.h"
#include "video_frame.h"
Include dependency graph for cmpto_j2k.cpp:

Go to the source code of this file.

Classes

struct  custom_data
 auxilliary data structure passed with encoded frame More...
 
struct  state_video_compress_j2k
 
struct  state_video_compress_j2k::module_data
 

Macros

#define ASSIGN_CHECK_VAL(var, str, minval)
 
#define CHECK_OK(cmd, err_msg, action_fail)
 
#define CPU_CONV_PARAM   "j2k-enc-cpu-conv"
 
#define DEFAULT_MEM_LIMIT   1000000000LLU
 
#define DEFAULT_POOL_SIZE   4
 
#define DEFAULT_QUALITY   0.7
 
#define DEFAULT_TILE_LIMIT   1
 number of frames that encoder encodes at moment
 
#define HANDLE_ERROR_COMPRESS_POP   do { cmpto_j2k_enc_img_destroy(img); goto start; } while (0)
 
#define HANDLE_ERROR_COMPRESS_PUSH
 
#define MOD_NAME   "[Cmpto J2K enc.] "
 
#define NOOP   ((void) 0)
 

Functions

 ADD_TO_PARAM (CPU_CONV_PARAM, "* " CPU_CONV_PARAM "\n" " Enforce CPU conversion instead of CUDA (applicable to R12L now)\n")
 
static void cleanup_common (struct state_video_compress_j2k *s)
 
static bool configure_with (struct state_video_compress_j2k *s, struct video_desc desc)
 
static void do_gpu_copy (std::shared_ptr< video_frame > &ret, video_frame *in_frame)
 copies frame from RAM to GPU
 
static compress_module_info get_cmpto_j2k_module_info ()
 
static shared_ptr< video_frame > get_copy (struct state_video_compress_j2k *s, video_frame *frame)
 
static void j2k_compress_done (struct module *mod)
 
static struct module * j2k_compress_init (struct module *parent, const char *c_cfg)
 
static std::shared_ptr< video_frame > j2k_compress_pop (struct module *state)
 
static void j2k_compress_push (struct module *state, std::shared_ptr< video_frame > tx)
 
static void j2k_compressed_frame_dispose (struct video_frame *frame)
 
static void parallel_conv (video_frame *dst, video_frame *src)
 
 REGISTER_MODULE (cmpto_j2k, &j2k_compress_info, LIBRARY_CLASS_VIDEO_COMPRESS, VIDEO_COMPRESS_ABI_VERSION)
 
static void release_cstream (void *custom_data, size_t custom_data_size, const void *codestream, size_t codestream_size)
 
static void release_cstream_cuda (void *img_custom_data, size_t img_custom_data_size, int, const void *samples, size_t samples_size)
 
static void set_pool (struct state_video_compress_j2k *s, bool have_gpu_preprocess)
 
static void usage ()
 

Variables

struct { 
 
   enum cmpto_sample_format_type   cmpto_sf 
 
   codec_t   convert_codec 
 
   cmpto_j2k_enc_preprocessor_run_callback_cuda   cuda_convert_func 
 
   codec_t   ug_codec 
 
} codecs [] 
 
static struct video_compress_info j2k_compress_info
 
const cmpto_j2k_enc_preprocessor_run_callback_cuda r12l_to_rg48_cuda
 
struct { 
 
   const char *   description 
 
   const bool   is_boolean 
 
   const char *   key 
 
   const char *   label 
 
   const char *   opt_str 
 
   const char *   placeholder 
 
} usage_opts [] 
 

Detailed Description

Main idea behind the code below is to control how many frames the encoder holds. The codec itself doesn't have a limit, thus without that it is possible to run out of memory. This is possible even in the case when the GPU is powerful enough due to the fact that CUDA registers the new buffers which is very slow and because of that the frames cumulate before the GPU encoder.

Todo
  • check support for multiple CUDA devices with CUDA buffers

Definition in file cmpto_j2k.cpp.

Macro Definition Documentation

◆ ASSIGN_CHECK_VAL

#define ASSIGN_CHECK_VAL ( var,
str,
minval )
Value:
do { \
long long val = unit_evaluate_dbl(str, false, nullptr); \
if (val < (minval) || val > UINT_MAX) { \
<< "[J2K] Wrong value " << (str) \
<< " for " #var "! Value must be >= " << (minval) \
<< ".\n"; \
return NULL; \
} \
(var) = val; \
} while (0)
int void * val
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
double unit_evaluate_dbl(const char *str, bool case_sensitive, const char **endptr)
Definition misc.cpp:102

Definition at line 507 of file cmpto_j2k.cpp.

507#define ASSIGN_CHECK_VAL(var, str, minval) \
508 do { \
509 long long val = unit_evaluate_dbl(str, false, nullptr); \
510 if (val < (minval) || val > UINT_MAX) { \
511 LOG(LOG_LEVEL_ERROR) \
512 << "[J2K] Wrong value " << (str) \
513 << " for " #var "! Value must be >= " << (minval) \
514 << ".\n"; \
515 return NULL; \
516 } \
517 (var) = val; \
518 } while (0)

Referenced by j2k_compress_init().

◆ CHECK_OK

#define CHECK_OK ( cmd,
err_msg,
action_fail )
Value:
do { \
int j2k_error = cmd; \
if (j2k_error != CMPTO_OK) {\
log_msg(LOG_LEVEL_ERROR, "[J2K enc.] %s: %s\n", \
err_msg, cmpto_j2k_enc_get_last_error()); \
action_fail;\
} \
} while(0)

Definition at line 82 of file cmpto_j2k.cpp.

82#define CHECK_OK(cmd, err_msg, action_fail) do { \
83 int j2k_error = cmd; \
84 if (j2k_error != CMPTO_OK) {\
85 log_msg(LOG_LEVEL_ERROR, "[J2K enc.] %s: %s\n", \
86 err_msg, cmpto_j2k_enc_get_last_error()); \
87 action_fail;\
88 } \
89} while(0)

Referenced by configure_with(), j2k_compress_pop(), and j2k_compress_push().

◆ CPU_CONV_PARAM

#define CPU_CONV_PARAM   "j2k-enc-cpu-conv"

Definition at line 206 of file cmpto_j2k.cpp.

Referenced by configure_with(), and usage().

◆ DEFAULT_MEM_LIMIT

#define DEFAULT_MEM_LIMIT   1000000000LLU

Definition at line 99 of file cmpto_j2k.cpp.

◆ DEFAULT_POOL_SIZE

#define DEFAULT_POOL_SIZE   4

default max size of state_video_compress_j2k::pool and also value for state_video_compress_j2k::max_in_frames

Definition at line 95 of file cmpto_j2k.cpp.

◆ DEFAULT_QUALITY

#define DEFAULT_QUALITY   0.7

Definition at line 92 of file cmpto_j2k.cpp.

◆ DEFAULT_TILE_LIMIT

#define DEFAULT_TILE_LIMIT   1

number of frames that encoder encodes at moment

Definition at line 98 of file cmpto_j2k.cpp.

◆ HANDLE_ERROR_COMPRESS_POP

#define HANDLE_ERROR_COMPRESS_POP   do { cmpto_j2k_enc_img_destroy(img); goto start; } while (0)

Definition at line 397 of file cmpto_j2k.cpp.

Referenced by j2k_compress_pop().

◆ HANDLE_ERROR_COMPRESS_PUSH

#define HANDLE_ERROR_COMPRESS_PUSH
Value:
if (udata != nullptr) { \
udata->frame.~shared_ptr<video_frame>(); \
} \
if (img != nullptr) { \
cmpto_j2k_enc_img_destroy(img); \
} \
return
Struct video_frame represents a video frame and contains video description.
Definition types.h:305

Definition at line 592 of file cmpto_j2k.cpp.

592#define HANDLE_ERROR_COMPRESS_PUSH \
593 if (udata != nullptr) { \
594 udata->frame.~shared_ptr<video_frame>(); \
595 } \
596 if (img != nullptr) { \
597 cmpto_j2k_enc_img_destroy(img); \
598 } \
599 return

Referenced by j2k_compress_push().

◆ MOD_NAME

#define MOD_NAME   "[Cmpto J2K enc.] "

Definition at line 80 of file cmpto_j2k.cpp.

Referenced by j2k_compress_init().

◆ NOOP

#define NOOP   ((void) 0)

Definition at line 91 of file cmpto_j2k.cpp.

Referenced by configure_with(), j2k_compress_pop(), and j2k_compress_push().

Function Documentation

◆ ADD_TO_PARAM()

ADD_TO_PARAM ( CPU_CONV_PARAM ,
"* " CPU_CONV_PARAM "\n" " Enforce CPU conversion instead of CUDA (applicable to R12L now)\n"  )

◆ cleanup_common()

static void cleanup_common ( struct state_video_compress_j2k * s)
static

Definition at line 704 of file cmpto_j2k.cpp.

705{
706
707 if (s->enc_settings != nullptr) {
708 cmpto_j2k_enc_cfg_destroy(s->enc_settings);
709 }
710 s->enc_settings = nullptr;
711 if (s->context != nullptr) {
712 cmpto_j2k_enc_ctx_destroy(s->context);
713 }
714 s->context = nullptr;
715}
struct cmpto_j2k_enc_cfg * enc_settings
struct cmpto_j2k_enc_ctx * context

References state_video_compress_j2k::context, and state_video_compress_j2k::enc_settings.

Referenced by configure_with(), and j2k_compress_done().

◆ configure_with()

static bool configure_with ( struct state_video_compress_j2k * s,
struct video_desc desc )
static

Definition at line 237 of file cmpto_j2k.cpp.

237 {
238 enum cmpto_sample_format_type sample_format;
239 cmpto_j2k_enc_preprocessor_run_callback_cuda cuda_convert_func =
240 nullptr;
241 bool found = false;
242
243 for(const auto &codec : codecs){
244 if(codec.ug_codec == desc.color_spec){
245 sample_format = codec.cmpto_sf;
246 s->precompress_codec = codec.convert_codec;
247 cuda_convert_func = codec.cuda_convert_func;
248 found = true;
249 break;
250 }
251 }
252
253 if(!found){
254 log_msg(LOG_LEVEL_ERROR, "[J2K] Failed to find suitable pixel format\n");
255 return false;
256 }
257
258 if (s->configured) {
259 unique_lock<mutex> lk(s->lock);
260 CHECK_OK(cmpto_j2k_enc_ctx_stop(s->context), "stop", abort());
261 s->frame_popped.wait(lk, [s] { return s->in_frames == 0; });
263 s->configured = false;
264 }
265
266 if (get_commandline_param(CPU_CONV_PARAM) != nullptr) {
267 cuda_convert_func = nullptr;
268 }
269
270 struct cmpto_j2k_enc_ctx_cfg *ctx_cfg = nullptr;
271 CHECK_OK(cmpto_j2k_enc_ctx_cfg_create(&ctx_cfg),
272 "Context configuration create", return false);
273 for (unsigned int i = 0; i < cuda_devices_count; ++i) {
274 CHECK_OK(
275 cmpto_j2k_enc_ctx_cfg_add_cuda_device(
276 ctx_cfg, cuda_devices[i], s->mem_limit, s->tile_limit),
277 "Setting CUDA device", return false);
278 }
279 if (cuda_convert_func != nullptr) {
280 CHECK_OK(cmpto_j2k_enc_ctx_cfg_set_preprocessor_cuda(
281 ctx_cfg, nullptr, nullptr, cuda_convert_func),
282 "Setting CUDA preprocess", return false);
283 }
284
285 CHECK_OK(cmpto_j2k_enc_ctx_create(ctx_cfg, &s->context),
286 "Context create", return false);
287 CHECK_OK(cmpto_j2k_enc_ctx_cfg_destroy(ctx_cfg),
288 "Context configuration destroy", NOOP);
289
290 CHECK_OK(cmpto_j2k_enc_cfg_create(s->context, &s->enc_settings),
291 "Creating context configuration:", return false);
292 CHECK_OK(cmpto_j2k_enc_cfg_set_quantization(
293 s->enc_settings,
294 s->quality /* 0.0 = poor quality, 1.0 = full quality */
295 ),
296 "Setting quantization", NOOP);
297
298 CHECK_OK(cmpto_j2k_enc_cfg_set_resolutions(s->enc_settings, 6),
299 "Setting DWT levels", NOOP);
300
301 CHECK_OK(cmpto_j2k_enc_cfg_set_samples_format_type(s->enc_settings, sample_format),
302 "Setting sample format", return false);
303 CHECK_OK(cmpto_j2k_enc_cfg_set_size(s->enc_settings, desc.width, desc.height),
304 "Setting image size", return false);
305 if (s->rate) {
306 CHECK_OK(cmpto_j2k_enc_cfg_set_rate_limit(s->enc_settings,
307 CMPTO_J2K_ENC_COMP_MASK_ALL,
308 CMPTO_J2K_ENC_RES_MASK_ALL, s->rate / 8 / desc.fps),
309 "Setting rate limit",
310 NOOP);
311 }
312
313 int mct = s->mct;
314 if (mct == -1) {
315 mct = codec_is_a_rgb(desc.color_spec) ? 1 : 0;
316 }
317 CHECK_OK(cmpto_j2k_enc_cfg_set_mct(s->enc_settings, mct),
318 "Setting MCT",
319 NOOP);
320
321 char rate[100];
322 snprintf_ch(rate, "%s", s->rate == 0 ? "unset" : format_in_si_units(s->rate));
323 MSG(INFO,
324 "Using parameters: quality=%.2f, bitrate=%sbps, mem_limit=%sB, "
325 "tile_limit=%u, pool_size=%u, mct=%d\n",
327 s->max_in_frames, mct);
328
329 set_pool(s, cuda_convert_func != nullptr);
330
334
335 s->saved_desc = desc;
336
337 s->configured = true;
338 s->configure_cv.notify_one();
339
340 return true;
341}
struct video_desc desc
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define MSG(l, fmt,...)
Definition debug.h:96
unsigned int cuda_devices_count
Definition host.cpp:168
const char * get_commandline_param(const char *key)
Definition host.cpp:894
unsigned int cuda_devices[MAX_CUDA_DEVICES]
Definition host.cpp:167
#define snprintf_ch(str,...)
shortcut for snprintf(var, sizeof var...), var must be a char array
Definition macros.h:101
const char * format_in_si_units(unsigned long long int val)
Definition misc.cpp:154
unsigned int max_in_frames
max number of frames between push and pop
condition_variable configure_cv
long long int rate
bitrate in bits per second
condition_variable frame_popped
unsigned int in_frames
number of currently encoding frames
unsigned int tile_count
Definition types.h:185
codec_t color_spec
Definition types.h:182
double fps
Definition types.h:183
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
@ J2KR
JPEG 2000 RGB.
Definition types.h:90
@ J2K
JPEG 2000.
Definition types.h:89
bool codec_is_a_rgb(codec_t codec)
Returns TRUE if specified pixelformat is some form of RGB (not YUV).
#define CPU_CONV_PARAM
#define CHECK_OK(cmd, err_msg, action_fail)
Definition cmpto_j2k.cpp:82
#define NOOP
Definition cmpto_j2k.cpp:91
cmpto_j2k_enc_preprocessor_run_callback_cuda cuda_convert_func
static void set_pool(struct state_video_compress_j2k *s, bool have_gpu_preprocess)
static struct @77 codecs[]
static void cleanup_common(struct state_video_compress_j2k *s)

References CHECK_OK, cleanup_common(), codec_is_a_rgb(), codecs, video_desc::color_spec, state_video_compress_j2k::compressed_desc, state_video_compress_j2k::configure_cv, state_video_compress_j2k::configured, state_video_compress_j2k::context, CPU_CONV_PARAM, cuda_convert_func, cuda_devices, cuda_devices_count, desc, state_video_compress_j2k::enc_settings, format_in_si_units(), video_desc::fps, state_video_compress_j2k::frame_popped, get_commandline_param(), video_desc::height, state_video_compress_j2k::in_frames, J2K, J2KR, state_video_compress_j2k::lock, LOG_LEVEL_ERROR, log_msg(), state_video_compress_j2k::max_in_frames, state_video_compress_j2k::mct, state_video_compress_j2k::mem_limit, MSG, NOOP, state_video_compress_j2k::precompress_codec, state_video_compress_j2k::quality, state_video_compress_j2k::rate, state_video_compress_j2k::saved_desc, set_pool(), snprintf_ch, video_desc::tile_count, state_video_compress_j2k::tile_limit, and video_desc::width.

Referenced by j2k_compress_push().

Here is the call graph for this function:

◆ do_gpu_copy()

static void do_gpu_copy ( std::shared_ptr< video_frame > & ret,
video_frame * in_frame )
static

copies frame from RAM to GPU

Does the pixel format conversion as well if specified.

Definition at line 349 of file cmpto_j2k.cpp.

350{
351#ifdef HAVE_CUDA
353 cuda_wrapper_memcpy(ret->tiles[0].data, in_frame->tiles[0].data,
354 in_frame->tiles[0].data_len,
356#else
357 (void) ret, (void) in_frame;
358 abort(); // must not reach here
359#endif
360}
int cuda_wrapper_set_device(int index)
int cuda_wrapper_memcpy(void *dst, const void *src, size_t count, int kind)
#define CUDA_WRAPPER_MEMCPY_HOST_TO_DEVICE
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
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345

References cuda_devices, cuda_wrapper_memcpy(), CUDA_WRAPPER_MEMCPY_HOST_TO_DEVICE, cuda_wrapper_set_device(), tile::data, tile::data_len, and video_frame::tiles.

Referenced by get_copy().

Here is the call graph for this function:

◆ get_cmpto_j2k_module_info()

static compress_module_info get_cmpto_j2k_module_info ( )
static

Definition at line 717 of file cmpto_j2k.cpp.

717 {
718 compress_module_info module_info;
719 module_info.name = "cmpto_j2k";
720
721 for(const auto& opt : usage_opts){
722 module_info.opts.emplace_back(module_option{opt.label,
723 opt.description, opt.placeholder, opt.key, opt.opt_str, opt.is_boolean});
724 }
725
727 codec_info.name = "Comprimato jpeg2000";
728 codec_info.priority = 400;
729 codec_info.encoders.emplace_back(encoder{"default", ""});
730
731 module_info.codecs.emplace_back(std::move(codec_info));
732
733 return module_info;
734}
const char * name
displayed name
std::vector< codec > codecs
std::vector< module_option > opts
static const struct codec_info_t codec_info[]
struct @78 usage_opts[]

References codec_info, compress_module_info::codecs, codec_info_t::name, compress_module_info::name, compress_module_info::opts, and usage_opts.

◆ get_copy()

static shared_ptr< video_frame > get_copy ( struct state_video_compress_j2k * s,
video_frame * frame )
static

Definition at line 362 of file cmpto_j2k.cpp.

362 {
363 std::shared_ptr<video_frame> ret = s->pool.get_frame();
364
365 if (s->pool_in_device_memory) {
366 do_gpu_copy(ret, frame);
367 } else if (s->precompress_codec != VC_NONE) {
368 parallel_conv(ret.get(), frame);
369 } else {
370 memcpy(ret->tiles[0].data, frame->tiles[0].data,
371 frame->tiles[0].data_len);
372 }
373
374 return ret;
375}
struct video_frame * frame
video_frame_pool pool
pool for frames allocated by us but not yet consumed by encoder
bool pool_in_device_memory
frames in pool are on GPU
std::shared_ptr< video_frame > get_frame()
@ VC_NONE
Definition types.h:67
static void do_gpu_copy(std::shared_ptr< video_frame > &ret, video_frame *in_frame)
copies frame from RAM to GPU
static void parallel_conv(video_frame *dst, video_frame *src)

References tile::data, tile::data_len, do_gpu_copy(), frame, video_frame_pool::get_frame(), parallel_conv(), state_video_compress_j2k::pool, state_video_compress_j2k::pool_in_device_memory, state_video_compress_j2k::precompress_codec, video_frame::tiles, and VC_NONE.

Referenced by j2k_compress_push().

Here is the call graph for this function:

◆ j2k_compress_done()

static void j2k_compress_done ( struct module * mod)
static

Definition at line 695 of file cmpto_j2k.cpp.

696{
697 struct state_video_compress_j2k *s =
698 (struct state_video_compress_j2k *) mod->priv_data;
700 delete s;
701}
void * priv_data
Definition module.h:126

References cleanup_common(), and module::priv_data.

Referenced by j2k_compress_init().

Here is the call graph for this function:

◆ j2k_compress_init()

static struct module * j2k_compress_init ( struct module * parent,
const char * c_cfg )
static

Definition at line 520 of file cmpto_j2k.cpp.

521{
522 const auto *version = cmpto_j2k_enc_get_version();
523 LOG(LOG_LEVEL_INFO) << MOD_NAME << "Using codec version: " << (version == nullptr ? "(unknown)" : version->name) << "\n";
524
525 auto *s = new state_video_compress_j2k();
526
527 char *tmp = (char *) alloca(strlen(c_cfg) + 1);
528 strcpy(tmp, c_cfg);
529 char *save_ptr, *item;
530 while ((item = strtok_r(tmp, ":", &save_ptr))) {
531 tmp = NULL;
532 if (IS_KEY_PREFIX(item, "rate")) {
533 ASSIGN_CHECK_VAL(s->rate, strchr(item, '=') + 1, 1);
534 } else if (IS_KEY_PREFIX(item, "quality")) {
535 s->quality = stod(strchr(item, '=') + 1);
536 } else if (strcasecmp("mct", item) == 0 || strcasecmp("nomct", item) == 0) {
537 s->mct = strcasecmp("mct", item) == 0 ? 1 : 0;
538 } else if (IS_KEY_PREFIX(item, "mem_limit")) {
539 ASSIGN_CHECK_VAL(s->mem_limit, strchr(item, '=') + 1, 1);
540 } else if (IS_KEY_PREFIX(item, "tile_limit")) {
541 ASSIGN_CHECK_VAL(s->tile_limit, strchr(item, '=') + 1, 0);
542 } else if (IS_KEY_PREFIX(item, "pool_size")) {
543 ASSIGN_CHECK_VAL(s->max_in_frames, strchr(item, '=') + 1, 1);
544 } else if (strcasecmp("help", item) == 0) {
545 usage();
546 return static_cast<module*>(INIT_NOERR);
547 } else {
548 log_msg(LOG_LEVEL_ERROR, "[J2K] Wrong option: %s\n", item);
549 goto error;
550 }
551 }
552
553 if (s->quality < 0.0 || s->quality > 1.0) {
554 LOG(LOG_LEVEL_ERROR) << "[J2K] Quality should be in interval [0-1]!\n";
555 goto error;
556 }
557
558 module_init_default(&s->module_data);
559 s->module_data.cls = MODULE_CLASS_DATA;
560 s->module_data.priv_data = s;
561 s->module_data.deleter = j2k_compress_done;
562 module_register(&s->module_data, parent);
563
564 return &s->module_data;
565
566error:
567 delete s;
568 return NULL;
569}
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#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 INIT_NOERR
Definition host.h:73
#define IS_KEY_PREFIX(tok, key)
expands to true value if <k> from tok in format <k>=<v> is prefix of key
Definition macros.h:138
const char * parent
Definition settings.cpp:198
Definition hd-rum.c:27
static void usage()
#define ASSIGN_CHECK_VAL(var, str, minval)
static void j2k_compress_done(struct module *mod)
#define MOD_NAME
Definition cmpto_j2k.cpp:80

References ASSIGN_CHECK_VAL, INIT_NOERR, IS_KEY_PREFIX, j2k_compress_done(), LOG, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, log_msg(), MOD_NAME, MODULE_CLASS_DATA, module_init_default(), module_register(), parent, and usage().

Here is the call graph for this function:

◆ j2k_compress_pop()

static std::shared_ptr< video_frame > j2k_compress_pop ( struct module * state)
static

Definition at line 398 of file cmpto_j2k.cpp.

399{
400 auto *s = (struct state_video_compress_j2k *) state;
401start:
402 {
403 unique_lock<mutex> lk(s->lock);
404 s->configure_cv.wait(lk, [s] { return s->configured ||
405 s->should_exit; });
406 if (s->should_exit) {
407 return {}; // pass poison pill further
408 }
409 }
410
411 struct cmpto_j2k_enc_img *img;
412 int status;
413 CHECK_OK(cmpto_j2k_enc_ctx_get_encoded_img(
414 s->context, 1, &img /* Set to NULL if encoder stopped */,
415 &status),
416 "Encode image pop", HANDLE_ERROR_COMPRESS_POP);
417 if (img == nullptr) {
418 // this happens when cmpto_j2k_enc_ctx_stop() is called
419 goto start; // reconfiguration or exit
420 } else {
421 unique_lock<mutex> lk(s->lock);
422 s->in_frames--;
423 s->frame_popped.notify_one();
424 }
425 if (status != CMPTO_J2K_ENC_IMG_OK) {
426 const char * encoding_error = "";
427 CHECK_OK(cmpto_j2k_enc_img_get_error(img, &encoding_error), "get error status",
428 encoding_error = "(failed)");
429 log_msg(LOG_LEVEL_ERROR, "Image encoding failed: %s\n", encoding_error);
430 goto start;
431 }
432 struct custom_data *udata = nullptr;
433 size_t len;
434 CHECK_OK(cmpto_j2k_enc_img_get_custom_data(img, (void **) &udata, &len),
435 "get custom data", HANDLE_ERROR_COMPRESS_POP);
436 size_t size;
437 void * ptr;
438 CHECK_OK(cmpto_j2k_enc_img_get_cstream(img, &ptr, &size),
439 "get cstream", HANDLE_ERROR_COMPRESS_POP);
440
441 struct video_frame *out = vf_alloc_desc(udata->desc);
442 vf_restore_metadata(out, udata->metadata);
443 out->tiles[0].data_len = size;
444 out->tiles[0].data = (char *) malloc(size);
445 memcpy(out->tiles[0].data, ptr, size);
446 CHECK_OK(cmpto_j2k_enc_img_destroy(img), "Destroy image", NOOP);
449 return shared_ptr<video_frame>(out, out->callbacks.dispose);
450}
void ** state
int void size_t * len
struct video_frame * vf_alloc_desc(struct video_desc desc)
Allocates video frame accordig given desc.
static void start()
Definition sdp.c:202
auxilliary data structure passed with encoded frame
char metadata[VF_METADATA_SIZE]
video_desc desc
void(* dispose)(struct video_frame *)
Definition types.h:245
struct video_frame_callbacks callbacks
Definition types.h:324
int64_t compress_end
in ns from epoch
Definition types.h:339
static time_ns_t get_time_in_ns()
Definition tv.h:101
static void j2k_compressed_frame_dispose(struct video_frame *frame)
#define HANDLE_ERROR_COMPRESS_POP
void vf_restore_metadata(struct video_frame *f, void *s)

References video_frame::callbacks, CHECK_OK, video_frame::compress_end, tile::data, tile::data_len, custom_data::desc, video_frame_callbacks::dispose, get_time_in_ns(), HANDLE_ERROR_COMPRESS_POP, j2k_compressed_frame_dispose(), len, LOG_LEVEL_ERROR, log_msg(), custom_data::metadata, NOOP, start(), state, video_frame::tiles, vf_alloc_desc(), and vf_restore_metadata().

Here is the call graph for this function:

◆ j2k_compress_push()

static void j2k_compress_push ( struct module * state,
std::shared_ptr< video_frame > tx )
static

Definition at line 601 of file cmpto_j2k.cpp.

602{
603 struct state_video_compress_j2k *s =
605 struct cmpto_j2k_enc_img *img = NULL;
606 struct custom_data *udata = nullptr;
607
608 if (tx == NULL) { // pass poison pill through encoder
609 unique_lock<mutex> lk(s->lock);
610 s->should_exit = true;
611 if (s->configured) {
612 CHECK_OK(cmpto_j2k_enc_ctx_stop(s->context), "stop",
613 NOOP);
614 } else {
615 s->configure_cv.notify_one();
616 }
617 return;
618 }
619
620 const struct video_desc desc = video_desc_from_frame(tx.get());
621 if (!video_desc_eq(s->saved_desc, desc)) {
622 int ret = configure_with(s, desc);
623 if (!ret) {
624 return;
625 }
626 struct video_desc pool_desc = desc;
627 if (s->precompress_codec != VC_NONE &&
629 pool_desc.color_spec = s->precompress_codec;
630 }
631 s->pool.reconfigure(
632 pool_desc, (size_t) vc_get_linesize(pool_desc.width,
633 pool_desc.color_spec) *
634 pool_desc.height);
635 }
636
637 assert(tx->tile_count == 1); // TODO
638
639 CHECK_OK(cmpto_j2k_enc_img_create(s->context, &img),
640 "Image create", return);
641
642 /*
643 * Copy video desc to udata (to be able to reconstruct in j2k_compress_pop().
644 * Further make a place for a shared pointer of allocated data, deleter
645 * returns frame to pool in call of release_cstream() callback (called when
646 * encoder no longer needs the input data).
647 */
648 CHECK_OK(cmpto_j2k_enc_img_allocate_custom_data(
649 img,
650 sizeof *udata,
651 (void **) &udata),
652 "Allocate custom image data",
654 memcpy(&udata->desc, &s->compressed_desc, sizeof(s->compressed_desc));
655 new (&udata->frame) shared_ptr<video_frame>(get_copy(s, tx.get()));
656 vf_store_metadata(tx.get(), udata->metadata);
657
658 if (s->pool_in_device_memory) {
659 // cmpto_j2k_enc requires the size after postprocess, which
660 // doesn't equeal the IN frame data_len for R12L
661 const codec_t device_codec = s->precompress_codec == VC_NONE
662 ? udata->frame->color_spec
664 const size_t data_len =
665 vc_get_datalen(udata->frame->tiles[0].width,
666 udata->frame->tiles[0].height, device_codec);
667 CHECK_OK(cmpto_j2k_enc_img_set_samples_cuda(
668 img, cuda_devices[0], udata->frame->tiles[0].data,
669 data_len, release_cstream_cuda),
670 "Setting image samples", HANDLE_ERROR_COMPRESS_PUSH);
671 } else {
672 CHECK_OK(cmpto_j2k_enc_img_set_samples(
673 img, udata->frame->tiles[0].data,
674 udata->frame->tiles[0].data_len, release_cstream),
675 "Setting image samples", HANDLE_ERROR_COMPRESS_PUSH);
676 }
677
678 unique_lock<mutex> lk(s->lock);
679 s->frame_popped.wait(lk, [s]{return s->in_frames < s->max_in_frames;});
680 lk.unlock();
681 bool failed = false;
682 CHECK_OK(cmpto_j2k_enc_img_encode(img, s->enc_settings),
683 "Encode image push", failed = true);
684 if (failed) {
685 udata->frame.~shared_ptr<video_frame>();
686 cmpto_j2k_enc_img_destroy(img);
687 return;
688 }
689 lk.lock();
690 s->in_frames++;
691 lk.unlock();
692
693}
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)
shared_ptr< video_frame > frame
void reconfigure(struct video_desc new_desc, size_t new_size=SIZE_MAX)
codec_t
Definition types.h:65
size_t vc_get_datalen(unsigned int width, unsigned int height, codec_t codec)
static shared_ptr< video_frame > get_copy(struct state_video_compress_j2k *s, video_frame *frame)
static void release_cstream(void *custom_data, size_t custom_data_size, const void *codestream, size_t codestream_size)
static void release_cstream_cuda(void *img_custom_data, size_t img_custom_data_size, int, const void *samples, size_t samples_size)
#define HANDLE_ERROR_COMPRESS_PUSH
static bool configure_with(struct state_video_compress_j2k *s, struct video_desc desc)
void vf_store_metadata(const struct video_frame *f, void *s)
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.

References CHECK_OK, video_desc::color_spec, state_video_compress_j2k::compressed_desc, state_video_compress_j2k::configure_cv, configure_with(), state_video_compress_j2k::configured, state_video_compress_j2k::context, cuda_devices, custom_data::desc, desc, state_video_compress_j2k::enc_settings, custom_data::frame, state_video_compress_j2k::frame_popped, get_copy(), HANDLE_ERROR_COMPRESS_PUSH, video_desc::height, state_video_compress_j2k::in_frames, state_video_compress_j2k::lock, state_video_compress_j2k::max_in_frames, custom_data::metadata, NOOP, state_video_compress_j2k::pool, state_video_compress_j2k::pool_in_device_memory, state_video_compress_j2k::precompress_codec, video_frame_pool::reconfigure(), release_cstream(), release_cstream_cuda(), state_video_compress_j2k::saved_desc, state_video_compress_j2k::should_exit, state, vc_get_datalen(), vc_get_linesize(), VC_NONE, vf_store_metadata(), video_desc_eq(), video_desc_from_frame(), and video_desc::width.

Here is the call graph for this function:

◆ j2k_compressed_frame_dispose()

static void j2k_compressed_frame_dispose ( struct video_frame * frame)
static

Definition at line 571 of file cmpto_j2k.cpp.

572{
573 free(frame->tiles[0].data);
574 vf_free(frame);
575}
void vf_free(struct video_frame *buf)
Frees video_frame structure.

References tile::data, frame, video_frame::tiles, and vf_free().

Referenced by j2k_compress_pop().

Here is the call graph for this function:

◆ parallel_conv()

static void parallel_conv ( video_frame * dst,
video_frame * src )
static

Definition at line 167 of file cmpto_j2k.cpp.

167 {
168 int src_pitch = vc_get_linesize(src->tiles[0].width, src->color_spec);
169 int dst_pitch = vc_get_linesize(dst->tiles[0].width, dst->color_spec);
170
171 decoder_t decoder =
173 assert(decoder != nullptr);
175 parallel_pix_conv((int) src->tiles[0].height, dst->tiles[0].data,
176 dst_pitch, src->tiles[0].data, src_pitch,
177 decoder, 0);
178 if (log_level >= LOG_LEVEL_DEBUG) {
179 MSG(DEBUG, "pixfmt conversion duration: %f ms\n",
180 NS_TO_MS((double) (get_time_in_ns() - t0)));
181 }
182}
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
volatile int log_level
Definition debug.cpp:65
#define DEBUG
Definition main.c:27
void parallel_pix_conv(int height, char *out, int out_linesize, const char *in, int in_linesize, decoder_t decode, int threads)
decoder_t get_decoder_from_to(codec_t in, codec_t out)
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
unsigned int width
Definition types.h:280
unsigned int height
Definition types.h:281
codec_t color_spec
Definition types.h:306
long long time_ns_t
Definition tv.h:81
#define NS_TO_MS(val_ns)
Definition tv.h:98

References video_frame::color_spec, tile::data, DEBUG, get_decoder_from_to(), get_time_in_ns(), tile::height, log_level, LOG_LEVEL_DEBUG, MSG, NS_TO_MS, parallel_pix_conv(), video_frame::tiles, vc_get_linesize(), and tile::width.

Referenced by get_copy().

Here is the call graph for this function:

◆ REGISTER_MODULE()

REGISTER_MODULE ( cmpto_j2k ,
& j2k_compress_info,
LIBRARY_CLASS_VIDEO_COMPRESS ,
VIDEO_COMPRESS_ABI_VERSION  )

◆ release_cstream()

static void release_cstream ( void * custom_data,
size_t custom_data_size,
const void * codestream,
size_t codestream_size )
static

Definition at line 577 of file cmpto_j2k.cpp.

578{
579 (void) codestream; (void) custom_data_size; (void) codestream_size;
580 auto *udata = static_cast<struct custom_data *>(custom_data);
581 udata->frame.~shared_ptr<video_frame>();
582}

References custom_data::frame.

Referenced by j2k_compress_push(), and release_cstream_cuda().

◆ release_cstream_cuda()

static void release_cstream_cuda ( void * img_custom_data,
size_t img_custom_data_size,
int ,
const void * samples,
size_t samples_size )
static

Definition at line 585 of file cmpto_j2k.cpp.

587{
588 release_cstream(img_custom_data, img_custom_data_size, samples,
589 samples_size);
590}

References release_cstream().

Referenced by j2k_compress_push().

Here is the call graph for this function:

◆ set_pool()

static void set_pool ( struct state_video_compress_j2k * s,
bool have_gpu_preprocess )
static

Definition at line 212 of file cmpto_j2k.cpp.

213{
214#ifdef HAVE_CUDA
215 s->pool_in_device_memory = false;
216 if (cuda_devices_count > 1) {
217 MSG(WARNING, "More than 1 CUDA device will use CPU buffers and "
218 "conversion...\n");
219 } else if (s->precompress_codec == VC_NONE || have_gpu_preprocess) {
220 s->pool_in_device_memory = true;
222 s->max_in_frames,
223 cmpto_j2k_enc_cuda_buffer_data_allocator<
225 return;
226 }
228 s->max_in_frames,
229 cmpto_j2k_enc_cuda_buffer_data_allocator<cuda_wrapper_malloc_host,
231#else
232 assert(!have_gpu_preprocess); // if CUDA not found, we shouldn't have
234#endif
235}
int cuda_wrapper_malloc_host(void **buffer, size_t data_len)
int cuda_wrapper_free_host(void *buffer)
int cuda_wrapper_free(void *buffer)
int cuda_wrapper_malloc(void **buffer, size_t data_len)

References cuda_devices_count, cuda_wrapper_free(), cuda_wrapper_free_host(), cuda_wrapper_malloc(), cuda_wrapper_malloc_host(), state_video_compress_j2k::max_in_frames, MSG, state_video_compress_j2k::pool, state_video_compress_j2k::pool_in_device_memory, state_video_compress_j2k::precompress_codec, and VC_NONE.

Referenced by configure_with().

Here is the call graph for this function:

◆ usage()

static void usage ( void )
static

Definition at line 468 of file cmpto_j2k.cpp.

468 {
469 col() << "J2K compress usage:\n";
470 col() << TERM_BOLD << TRED("\t-c cmpto_j2k");
471 for(const auto& opt : usage_opts){
472 assert(strlen(opt.opt_str) >= 2);
473 col() << "[" << opt.opt_str;
474 if (!opt.is_boolean) {
475 col() << "<" << opt.opt_str[1] << ">"; // :quality -> <q> (first letter used as ":quality=<q>")
476 }
477 col() << "]";
478 }
479 col() << "\n\t\t[--cuda-device <c_index>] [--param " CPU_CONV_PARAM "]\n" << TERM_RESET;
480
481 col() << "where:\n";
482 for(const auto& opt : usage_opts){
483 if (opt.is_boolean) {
484 col() << TBOLD("\t" << opt.opt_str + 1 <<);
485 } else {
486 col() << TBOLD("\t<" << opt.opt_str[1] << ">");
487 }
488 col() << " - " << opt.description << "\n";
489 }
490 col() << TBOLD("\t<c_index>") << " - CUDA device(s) to use (comma separated)\n";
491 col() << TBOLD("\t--param " CPU_CONV_PARAM)
492 << " - use CPU for pixfmt conversion (useful if GPU\n\t\tis fully "
493 "occupied by the encoder; an option for decoder exists as "
494 "well)\n";
495 color_printf("\nOption prefixes (eg. 'q=' for quality) can be used. SI "
496 "suffixes are recognized (eg. 'r=7.5M').\n");
497#ifdef HAVE_CUDA
498 constexpr char cuda_supported[] = "YES";
499#else
500 constexpr char cuda_supported[] = TRED("NO");
501#endif
503 "\nUltraGrid compiled with " TBOLD("CUDA") " support: %s\n",
504 cuda_supported);
505}
int color_printf(const char *format,...)
#define TERM_BOLD
Definition color_out.h:48
#define TERM_RESET
Definition color_out.h:47
#define TRED(x)
Definition color_out.h:75
#define TBOLD(x)
Definition color_out.h:70

References color_printf(), CPU_CONV_PARAM, TBOLD, TERM_BOLD, TERM_RESET, TRED, and usage_opts.

Referenced by j2k_compress_init().

Here is the call graph for this function:

Variable Documentation

◆ cmpto_sf

enum cmpto_sample_format_type cmpto_sf

Definition at line 193 of file cmpto_j2k.cpp.

Referenced by j2k_decompress_reconfigure().

◆ [struct]

struct { ... } codecs[]
Initial value:
= {
{UYVY, CMPTO_422_U8_P1020, VIDEO_CODEC_NONE, nullptr},
{v210, CMPTO_422_U10_V210, VIDEO_CODEC_NONE, nullptr},
{RGB, CMPTO_444_U8_P012, VIDEO_CODEC_NONE, nullptr},
{RGBA, CMPTO_444_U8_P012Z, VIDEO_CODEC_NONE, nullptr},
{R10k, CMPTO_444_U10U10U10_MSB32BE_P210, VIDEO_CODEC_NONE, nullptr},
{RG48, CMPTO_444_U12_MSB16LE_P012, VC_NONE, nullptr},
{R12L, CMPTO_444_U12_MSB16LE_P012, RG48, r12l_to_rg48_cuda},
}
@ R10k
RGB 10-bit packed - RGBX, big-endian (2 bit padding)
Definition types.h:73
@ 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
@ RG48
16-bit RGB little-endian (RlRhGl...)
Definition types.h:95
@ R12L
RGB 12-bit packed, little-endian.
Definition types.h:74
@ 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
const cmpto_j2k_enc_preprocessor_run_callback_cuda r12l_to_rg48_cuda

Referenced by configure_with().

◆ convert_codec

codec_t convert_codec

Definition at line 194 of file cmpto_j2k.cpp.

◆ cuda_convert_func

cmpto_j2k_enc_preprocessor_run_callback_cuda cuda_convert_func

Definition at line 195 of file cmpto_j2k.cpp.

Referenced by configure_with().

◆ description

const char* description

Definition at line 455 of file cmpto_j2k.cpp.

◆ is_boolean

const bool is_boolean

Definition at line 457 of file cmpto_j2k.cpp.

Referenced by dev_add_option().

◆ j2k_compress_info

struct video_compress_info j2k_compress_info
static
Initial value:
= {
"cmpto_j2k",
NULL,
NULL,
NULL,
NULL,
}
static void j2k_compress_push(struct module *state, std::shared_ptr< video_frame > tx)
static std::shared_ptr< video_frame > j2k_compress_pop(struct module *state)
static compress_module_info get_cmpto_j2k_module_info()
static struct module * j2k_compress_init(struct module *parent, const char *c_cfg)

Definition at line 736 of file cmpto_j2k.cpp.

736 {
737 "cmpto_j2k",
739 NULL,
740 NULL,
741 NULL,
742 NULL,
746};

◆ key

const char* key

Definition at line 454 of file cmpto_j2k.cpp.

◆ label

const char* label

Definition at line 453 of file cmpto_j2k.cpp.

◆ opt_str

const char* opt_str

Definition at line 456 of file cmpto_j2k.cpp.

◆ placeholder

const char* placeholder

Definition at line 458 of file cmpto_j2k.cpp.

◆ r12l_to_rg48_cuda

const cmpto_j2k_enc_preprocessor_run_callback_cuda r12l_to_rg48_cuda
Initial value:
=
nullptr

Definition at line 184 of file cmpto_j2k.cpp.

◆ ug_codec

codec_t ug_codec

Definition at line 192 of file cmpto_j2k.cpp.

◆ [struct]

struct { ... } usage_opts[]
Initial value:
= {
{"Bitrate", "quality", "Target bitrate", ":rate=", false, "70M"},
{"Quality", "quant_coeff", "Quality in range [0-1], default: " TOSTRING(DEFAULT_QUALITY), ":quality=", false, TOSTRING(DEFAULT_QUALITY)},
{"Mem limit", "mem_limit", "CUDA device memory limit (in bytes), default: " TOSTRING(DEFAULT_MEM_LIMIT), ":mem_limit=", false, TOSTRING(DEFAULT_MEM_LIMIT)},
{"Tile limit", "tile_limit", "Number of tiles encoded at moment (less to reduce latency, more to increase performance, 0 means infinity), default: " TOSTRING(DEFAULT_TILE_LIMIT), ":tile_limit=", false, TOSTRING(DEFAULT_TILE_LIMIT)},
{"Pool size", "pool_size", "Total number of tiles encoder can hold at moment (same meaning as above), default: " TOSTRING(DEFAULT_POOL_SIZE) ", should be greater than <t>", ":pool_size=", false, TOSTRING(DEFAULT_POOL_SIZE)},
{"Use MCT", "mct", "use MCT", ":mct", true, ""},
}
#define TOSTRING(A)
Definition macros.h:49
#define DEFAULT_POOL_SIZE
Definition cmpto_j2k.cpp:95
#define DEFAULT_QUALITY
Definition cmpto_j2k.cpp:92
#define DEFAULT_TILE_LIMIT
number of frames that encoder encodes at moment
Definition cmpto_j2k.cpp:98
#define DEFAULT_MEM_LIMIT
Definition cmpto_j2k.cpp:99

Referenced by get_cmpto_j2k_module_info(), and usage().