UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
cmpto_j2k.cpp File Reference
#include <algorithm>
#include <cassert>
#include <cmpto_j2k_dec.h>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <mutex>
#include <ostream>
#include <pthread.h>
#include <queue>
#include <utility>
#include "cuda_wrapper/kernels.hpp"
#include "debug.h"
#include "host.h"
#include "lib_common.h"
#include "pixfmt_conv.h"
#include "types.h"
#include "utils/macros.h"
#include "utils/misc.h"
#include "utils/parallel_conv.h"
#include "video_codec.h"
#include "video_decompress.h"
Include dependency graph for cmpto_j2k.cpp:

Go to the source code of this file.

Classes

struct  conv_props
 
struct  state_decompress_j2k
 
struct  state_decompress_j2k::desc
 

Macros

#define CHECK_OK(cmd, err_msg, action_fail)
 
#define CPU_CONV_PARAM   "j2k-dec-cpu-conv"
 
#define NOOP   ((void) 0)
 

Functions

 ADD_TO_PARAM ("j2k-dec-encoder-queue", "* j2k-encoder-queue=<len>\n" " max number of frames held by encoder\n")
 
 ADD_TO_PARAM ("j2k-dec-mem-limit", "* j2k-dec-mem-limit=<limit>\n" " J2K max memory usage in bytes.\n")
 
 ADD_TO_PARAM ("j2k-dec-queue-len", "* j2k-queue-len=<len>\n" " max queue len\n")
 
 ADD_TO_PARAM ("j2k-dec-tile-limit", "* j2k-dec-tile-limit=<limit>\n" " number of tiles decoded at moment (less to reduce latency, more to increase performance, 0 unlimited)\n")
 
 ADD_TO_PARAM (CPU_CONV_PARAM, "* " CPU_CONV_PARAM "\n" " Enforce CPU conversion instead of CUDA (applicable to R12L now)\n")
 
static void * decompress_j2k_worker (void *args)
 
static decompress_status j2k_decompress (void *state, unsigned char *dst, unsigned char *buffer, unsigned int src_len, int, struct video_frame_callbacks *, struct pixfmt_desc *internal_prop)
 
static void j2k_decompress_cleanup_common (struct state_decompress_j2k *s)
 
static void j2k_decompress_done (void *state)
 
static int j2k_decompress_get_priority (codec_t compression, struct pixfmt_desc internal, codec_t ugc)
 
static int j2k_decompress_get_property (void *state, int property, void *val, size_t *len)
 
static void * j2k_decompress_init (void)
 
static int j2k_decompress_reconfigure (void *state, struct video_desc desc, int rshift, int gshift, int bshift, int pitch, codec_t out_codec)
 
static decompress_status j2k_probe_internal_codec (codec_t in_codec, unsigned char *buffer, size_t len, struct pixfmt_desc *internal_prop)
 
static void print_dropped (unsigned long long int dropped)
 
static void r12l_postprocessor_get_sz (void *, void *, size_t, int size_x, int size_y, struct cmpto_j2k_dec_comp_format *, int comp_count, size_t *temp_buffer_size, size_t *output_buffer_size)
 
 REGISTER_MODULE (j2k, &j2k_decompress_info, LIBRARY_CLASS_VIDEO_DECOMPRESS, VIDEO_DECOMPRESS_ABI_VERSION)
 
static void release_cstream (void *custom_data, size_t custom_data_size, const void *codestream, size_t codestream_size)
 
static void rg48_to_r12l (unsigned char *dst_buffer, unsigned char *src_buffer, unsigned int width, unsigned int height)
 
static bool set_postprocess_convert (struct state_decompress_j2k *s, struct cmpto_j2k_dec_ctx_cfg *ctx_cfg, const struct conv_props *codec)
 

Variables

static const struct conv_props codecs []
 
constexpr const int DEFAULT_MAX_IN_FRAMES = 4
 maximal number of concurrently decompressed frames
 
constexpr const int DEFAULT_MAX_QUEUE_SIZE = 2
 maximal size of queue for decompressed frames
 
constexpr const int64_t DEFAULT_MEM_LIMIT = 1000000000LL
 
constexpr const int DEFAULT_TILE_LIMIT = 2
 
static const struct video_decompress_info j2k_decompress_info
 
constexpr const char * MOD_NAME = "[J2K dec.] "
 
const cmpto_j2k_dec_postprocessor_run_callback_cuda r12l_postprocess_cuda
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z

Some of the concepts are similar to encoder (eg. keeping limited number of frames in decoder) so please refer to that file.

Problematic part of following code is that UltraGrid decompress API is synchronous only while the CMPTO J2K decoder is inherently asynchronous. Threrefore the integration works in following fashion:

  • there is a thread that waits for completed (decompressed) frames, if there is any, it put it in queue (or drop if full)
  • when a new frame arives, j2k_decompress() passes it to decoder (which is asynchronous, thus non-blocking)
  • then queue (filled by thread in first point) is checked - if it is non-empty, frame is copied to framebufffer. If not false is returned.

Definition in file cmpto_j2k.cpp.

Macro Definition Documentation

◆ CHECK_OK

#define CHECK_OK ( cmd,
err_msg,
action_fail )
Value:
do { \
int j2k_error = cmd; \
if (j2k_error != CMPTO_OK) {\
LOG(LOG_LEVEL_ERROR) << MOD_NAME << (err_msg) << ": " << cmpto_j2k_dec_get_last_error() << "\n"; \
action_fail;\
} \
} while(0)
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
constexpr const char * MOD_NAME
Definition cmpto_j2k.cpp:86

Definition at line 125 of file cmpto_j2k.cpp.

125#define CHECK_OK(cmd, err_msg, action_fail) do { \
126 int j2k_error = cmd; \
127 if (j2k_error != CMPTO_OK) {\
128 LOG(LOG_LEVEL_ERROR) << MOD_NAME << (err_msg) << ": " << cmpto_j2k_dec_get_last_error() << "\n"; \
129 action_fail;\
130 } \
131} while(0)

Referenced by decompress_j2k_worker(), j2k_decompress(), j2k_decompress_reconfigure(), and set_postprocess_convert().

◆ CPU_CONV_PARAM

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

Definition at line 297 of file cmpto_j2k.cpp.

Referenced by set_postprocess_convert().

◆ NOOP

#define NOOP   ((void) 0)

Definition at line 133 of file cmpto_j2k.cpp.

Referenced by decompress_j2k_worker(), and j2k_decompress_reconfigure().

Function Documentation

◆ ADD_TO_PARAM() [1/5]

ADD_TO_PARAM ( "j2k-dec-encoder-queue" )

◆ ADD_TO_PARAM() [2/5]

ADD_TO_PARAM ( "j2k-dec-mem-limit" )

◆ ADD_TO_PARAM() [3/5]

ADD_TO_PARAM ( "j2k-dec-queue-len" )

◆ ADD_TO_PARAM() [4/5]

ADD_TO_PARAM ( "j2k-dec-tile-limit" )

◆ ADD_TO_PARAM() [5/5]

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

◆ decompress_j2k_worker()

static void * decompress_j2k_worker ( void * args)
static

This function just runs in thread and gets decompressed images from decoder putting them to queue (or dropping if full).

Definition at line 165 of file cmpto_j2k.cpp.

166{
167 struct state_decompress_j2k *s =
168 (struct state_decompress_j2k *) args;
169
170 while (true) {
171next_image:
172 struct cmpto_j2k_dec_img *img;
173 int decoded_img_status;
174 CHECK_OK(cmpto_j2k_dec_ctx_get_decoded_img(s->decoder, 1, &img, &decoded_img_status),
175 "Decode image", goto next_image);
176
177 {
178 lock_guard<mutex> lk(s->lock);
179 if (s->in_frames) s->in_frames--;
180 }
181
182 if (img == NULL) { // decoder stopped (poison pill)
183 break;
184 }
185
186 if (decoded_img_status != CMPTO_J2K_DEC_IMG_OK) {
187 const char * decoding_error = "";
188 CHECK_OK(cmpto_j2k_dec_img_get_error(img, &decoding_error), "get error status",
189 decoding_error = "(failed)");
190 log_msg(LOG_LEVEL_ERROR, "Image decoding failed: %s\n", decoding_error);
191 continue;
192 }
193
194 void *dec_data;
195 size_t len;
196 CHECK_OK(cmpto_j2k_dec_img_get_samples(img, &dec_data, &len),
197 "Error getting samples", cmpto_j2k_dec_img_destroy(img); goto next_image);
198
199 char *buffer = (char *) malloc(len);
200 if (s->convert) {
201 s->convert((unsigned char*) buffer, (unsigned char*) dec_data, s->desc.width, s->desc.height);
202 len = vc_get_linesize(s->desc.width, s->out_codec) * s->desc.height;
203 } else {
204 memcpy(buffer, dec_data, len);
205 }
206
207 CHECK_OK(cmpto_j2k_dec_img_destroy(img),
208 "Unable to to return processed image", NOOP);
209 lock_guard<mutex> lk(s->lock);
210 while (s->decompressed_frames.size() >= s->max_queue_size) {
212 auto decoded = s->decompressed_frames.front();
213 s->decompressed_frames.pop();
214 free(decoded.first);
215 }
216 s->decompressed_frames.push({buffer,len});
217 }
218
219 return NULL;
220}
int void size_t * len
int vc_get_linesize(unsigned int width, codec_t codec)
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
cmpto_j2k_dec_ctx * decoder
unsigned int max_queue_size
maximal length of decompressed_frames
void(* convert)(unsigned char *dst_buffer, unsigned char *src_buffer, unsigned int width, unsigned int height)
unsigned long long int dropped
number of dropped frames because queue was full
queue< pair< char *, size_t > > decompressed_frames
buffer, length
unsigned int in_frames
actual number of decompressed frames
#define CHECK_OK(cmd, err_msg, action_fail)
static void print_dropped(unsigned long long int dropped)
#define NOOP

References CHECK_OK, state_decompress_j2k::convert, state_decompress_j2k::decoder, state_decompress_j2k::decompressed_frames, state_decompress_j2k::dropped, state_decompress_j2k::in_frames, len, state_decompress_j2k::lock, LOG_LEVEL_ERROR, log_msg(), state_decompress_j2k::max_queue_size, NOOP, state_decompress_j2k::out_codec, print_dropped(), and vc_get_linesize().

Referenced by j2k_decompress_reconfigure().

Here is the call graph for this function:

◆ j2k_decompress()

static decompress_status j2k_decompress ( void * state,
unsigned char * dst,
unsigned char * buffer,
unsigned int src_len,
int ,
struct video_frame_callbacks * ,
struct pixfmt_desc * internal_prop )
static

Main decompress function - passes frame to the codec and checks if there are some decoded frames. If so, copies that to framebuffer. In the opposite case it just returns false.

Definition at line 468 of file cmpto_j2k.cpp.

470{
471 struct state_decompress_j2k *s =
472 (struct state_decompress_j2k *) state;
473 struct cmpto_j2k_dec_img *img;
474 pair<char *, size_t> decoded;
475 void *tmp;
476
477 if (s->out_codec == VIDEO_CODEC_NONE) {
478 return j2k_probe_internal_codec(s->desc.color_spec, buffer, src_len, internal_prop);
479 }
480
481 if (s->in_frames >= s->max_in_frames + 1) {
483 goto return_previous;
484 }
485
486 CHECK_OK(cmpto_j2k_dec_img_create(s->decoder, &img),
487 "Could not create frame", goto return_previous);
488
489 tmp = malloc(src_len);
490 memcpy(tmp, buffer, src_len);
491 CHECK_OK(cmpto_j2k_dec_img_set_cstream(img, tmp, src_len, &release_cstream),
492 "Error setting cstream", cmpto_j2k_dec_img_destroy(img); goto return_previous);
493
494 CHECK_OK(cmpto_j2k_dec_img_decode(img, s->settings), "Decode image",
495 cmpto_j2k_dec_img_destroy(img); goto return_previous);
496 {
497 lock_guard<mutex> lk(s->lock);
498 s->in_frames++;
499 }
500
501return_previous:
502 unique_lock<mutex> lk(s->lock);
503 if (s->decompressed_frames.size() == 0) {
504 return DECODER_NO_FRAME;
505 }
506 decoded = s->decompressed_frames.front();
507 s->decompressed_frames.pop();
508 lk.unlock();
509
510 size_t linesize = vc_get_linesize(s->desc.width, s->out_codec);
511 size_t frame_size = linesize * s->desc.height;
512 if ((decoded.second + 3) / 4 * 4 != frame_size) { // for "RGBA with non-standard shift" (search) it would be (frame_size - 1)
513 LOG(LOG_LEVEL_WARNING) << MOD_NAME << "Incorrect decoded size (" << frame_size << " vs. " << decoded.second << ")\n";
514 }
515
516 for (size_t i = 0; i < s->desc.height; ++i) {
517 memcpy(dst + i * s->pitch, decoded.first + i * linesize, min(linesize, decoded.second - min(decoded.second, i * linesize)));
518 }
519
520 free(decoded.first);
521
522 return DECODER_GOT_FRAME;
523}
void ** state
#define LOG(level)
Definition debug.h:313
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
@ DECODER_NO_FRAME
@ DECODER_GOT_FRAME
cmpto_j2k_dec_cfg * settings
unsigned int max_in_frames
maximal frames that can be "in progress"
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66
static decompress_status j2k_probe_internal_codec(codec_t in_codec, unsigned char *buffer, size_t len, struct pixfmt_desc *internal_prop)
static void release_cstream(void *custom_data, size_t custom_data_size, const void *codestream, size_t codestream_size)

References CHECK_OK, state_decompress_j2k::decoder, DECODER_GOT_FRAME, DECODER_NO_FRAME, state_decompress_j2k::decompressed_frames, state_decompress_j2k::dropped, state_decompress_j2k::in_frames, j2k_probe_internal_codec(), state_decompress_j2k::lock, LOG, LOG_LEVEL_WARNING, state_decompress_j2k::max_in_frames, MOD_NAME, state_decompress_j2k::out_codec, state_decompress_j2k::pitch, print_dropped(), release_cstream(), state_decompress_j2k::settings, state, vc_get_linesize(), and VIDEO_CODEC_NONE.

Here is the call graph for this function:

◆ j2k_decompress_cleanup_common()

static void j2k_decompress_cleanup_common ( struct state_decompress_j2k * s)
static

Definition at line 546 of file cmpto_j2k.cpp.

547{
548 cmpto_j2k_dec_ctx_stop(s->decoder);
549 pthread_join(s->thread_id, NULL);
550 log_msg(LOG_LEVEL_VERBOSE, "[J2K dec.] Decoder stopped.\n");
551
552 if (s->settings != nullptr) {
553 cmpto_j2k_dec_cfg_destroy(s->settings);
554 s->settings = nullptr;
555 }
556 if (s->decoder != nullptr) {
557 cmpto_j2k_dec_ctx_destroy(s->decoder);
558 s->decoder = nullptr;
559 }
560
561 while (s->decompressed_frames.size() > 0) {
562 auto decoded = s->decompressed_frames.front();
563 s->decompressed_frames.pop();
564 free(decoded.first);
565 }
566
567 s->convert = nullptr;
568}
#define LOG_LEVEL_VERBOSE
Definition debug.h:63

References state_decompress_j2k::convert, state_decompress_j2k::decoder, state_decompress_j2k::decompressed_frames, LOG_LEVEL_VERBOSE, log_msg(), state_decompress_j2k::settings, and state_decompress_j2k::thread_id.

Referenced by j2k_decompress_done(), and j2k_decompress_reconfigure().

Here is the call graph for this function:

◆ j2k_decompress_done()

static void j2k_decompress_done ( void * state)
static

Definition at line 570 of file cmpto_j2k.cpp.

571{
572 auto *s = (struct state_decompress_j2k *) state;
574 delete s;
575}
static void j2k_decompress_cleanup_common(struct state_decompress_j2k *s)

References j2k_decompress_cleanup_common(), and state.

Here is the call graph for this function:

◆ j2k_decompress_get_priority()

static int j2k_decompress_get_priority ( codec_t compression,
struct pixfmt_desc internal,
codec_t ugc )
static

Definition at line 577 of file cmpto_j2k.cpp.

577 {
578 if (compression != J2K && compression != J2KR) {
579 return -1;
580 }
581 if (ugc == VC_NONE) { // probe
582 return VDEC_PRIO_PROBE_HI;
583 }
584 bool codec_found = false;
585 for (const auto &codec : codecs) {
586 if (codec.ug_codec == ugc) {
587 codec_found = true;
588 break;
589 }
590 }
591 if (!codec_found) {
592 return VDEC_PRIO_NA;
593 }
594 if (internal.depth == 0) { // fallback - internal undefined
595 return 800;
596 }
597 return internal.rgb == codec_is_a_rgb(ugc) ? 300 : -1;
598}
@ VDEC_PRIO_NA
decoder cannot handle the codec in any way
@ VDEC_PRIO_PROBE_HI
decoder can probe
@ VC_NONE
Definition types.h:67
@ 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).
static const struct conv_props codecs[]

References codec_is_a_rgb(), codecs, J2K, J2KR, VC_NONE, VDEC_PRIO_NA, and VDEC_PRIO_PROBE_HI.

Here is the call graph for this function:

◆ j2k_decompress_get_property()

static int j2k_decompress_get_property ( void * state,
int property,
void * val,
size_t * len )
static

Definition at line 525 of file cmpto_j2k.cpp.

526{
527 UNUSED(state);
528 int ret = false;
529
530 switch(property) {
532 if(*len >= sizeof(int)) {
533 *(int *) val = false;
534 *len = sizeof(int);
535 ret = true;
536 }
537 break;
538 default:
539 ret = false;
540 }
541
542 return ret;
543}
#define UNUSED(x)
int void * val
int property
#define DECOMPRESS_PROPERTY_ACCEPTS_CORRUPTED_FRAME

References DECOMPRESS_PROPERTY_ACCEPTS_CORRUPTED_FRAME, len, property, state, UNUSED, and val.

◆ j2k_decompress_init()

static void * j2k_decompress_init ( void )
static

Definition at line 230 of file cmpto_j2k.cpp.

231{
232 unsigned int queue_len = DEFAULT_MAX_QUEUE_SIZE;
233 unsigned int encoder_in_frames = DEFAULT_MAX_IN_FRAMES;
234
235 if (get_commandline_param("j2k-dec-queue-len")) {
236 queue_len = atoi(get_commandline_param("j2k-dec-queue-len"));
237 }
238
239 if (get_commandline_param("j2k-dec-encoder-queue")) {
240 encoder_in_frames = atoi(get_commandline_param("j2k-dec-encoder-queue"));
241 }
242
243 auto *s = new state_decompress_j2k(queue_len, encoder_in_frames);
244 if (get_commandline_param("j2k-dec-mem-limit") != nullptr) {
245 s->req_mem_limit = unit_evaluate_dbl(
246 get_commandline_param("j2k-dec-mem-limit"), false, nullptr);
247 }
248
249 if (get_commandline_param("j2k-dec-tile-limit") != nullptr) {
250 s->req_tile_limit = stoi(get_commandline_param("j2k-dec-tile-limit"));
251 }
252
253 const auto *version = cmpto_j2k_dec_get_version();
254 LOG(LOG_LEVEL_INFO) << MOD_NAME << "Using codec version: " << (version == nullptr ? "(unknown)" : version->name) << "\n";
255
256 return s;
257}
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
const char * get_commandline_param(const char *key)
Definition host.cpp:894
double unit_evaluate_dbl(const char *str, bool case_sensitive, const char **endptr)
Definition misc.cpp:102
constexpr const int DEFAULT_MAX_IN_FRAMES
maximal number of concurrently decompressed frames
Definition cmpto_j2k.cpp:84
constexpr const int DEFAULT_MAX_QUEUE_SIZE
maximal size of queue for decompressed frames
Definition cmpto_j2k.cpp:82

References DEFAULT_MAX_IN_FRAMES, DEFAULT_MAX_QUEUE_SIZE, get_commandline_param(), LOG, LOG_LEVEL_INFO, MOD_NAME, and unit_evaluate_dbl().

Here is the call graph for this function:

◆ j2k_decompress_reconfigure()

static int j2k_decompress_reconfigure ( void * state,
struct video_desc desc,
int rshift,
int gshift,
int bshift,
int pitch,
codec_t out_codec )
static

Definition at line 329 of file cmpto_j2k.cpp.

331{
332 struct state_decompress_j2k *s = (struct state_decompress_j2k *) state;
333
334 if (out_codec == VIDEO_CODEC_NONE) { // probe format
336 s->desc = desc;
337 return true;
338 }
339
341
342 if (out_codec == R12L) {
343 LOG(LOG_LEVEL_NOTICE) << MOD_NAME << "Decoding to 12-bit RGB.\n";
344 }
345
346 enum cmpto_sample_format_type cmpto_sf = (cmpto_sample_format_type) 0;
347
348 struct cmpto_j2k_dec_ctx_cfg *ctx_cfg = nullptr;
349 CHECK_OK(cmpto_j2k_dec_ctx_cfg_create(&ctx_cfg), "Error creating dec cfg", return false);
350 for (unsigned int i = 0; i < cuda_devices_count; ++i) {
351 CHECK_OK(cmpto_j2k_dec_ctx_cfg_add_cuda_device(
352 ctx_cfg, cuda_devices[i], s->req_mem_limit,
353 s->req_tile_limit),
354 "Error setting CUDA device", return false);
355 }
356
357 for(const auto &codec : codecs){
358 if(codec.ug_codec != out_codec){
359 continue;
360 }
361 cmpto_sf = codec.cmpto_sf;
362 if (!set_postprocess_convert(s, ctx_cfg, &codec)) {
363 return false;
364 }
365 }
366
367 if (!cmpto_sf) {
368 LOG(LOG_LEVEL_ERROR) << MOD_NAME << "Unsupported output codec: " <<
369 get_codec_name(out_codec) << "\n";
370 abort();
371 }
372
373 CHECK_OK(cmpto_j2k_dec_ctx_create(ctx_cfg, &s->decoder),
374 "Error initializing context", return false);
375
376 CHECK_OK(cmpto_j2k_dec_ctx_cfg_destroy(ctx_cfg), "Destroy cfg", NOOP);
377
378 CHECK_OK(cmpto_j2k_dec_cfg_create(s->decoder, &s->settings),
379 "Error creating configuration", return false);
380
381 if (out_codec != RGBA || (rshift == 0 && gshift == 8 && bshift == 16)) {
382 CHECK_OK(cmpto_j2k_dec_cfg_set_samples_format_type(s->settings, cmpto_sf),
383 "Error setting sample format type", return false);
384 } else { // RGBA with non-standard shift
385 if (rshift % 8 != 0 || gshift % 8 != 0 || bshift % 8 != 0) {
386 LOG(LOG_LEVEL_ERROR) << MOD_NAME << "Component shifts not aligned to a "
387 "byte boundary is not supported.\n";
388 return false;
389 }
390 cmpto_j2k_dec_comp_format fmt[3] = {};
391 const int shifts[3] = { rshift, gshift, bshift };
392 for (int i = 0; i < 3; ++i) {
393 fmt[i].comp_index = i;
394 fmt[i].data_type = CMPTO_INT8;
395 fmt[i].offset = shifts[i] / 8;
396 fmt[i].stride_x = get_bpp(out_codec);
397 fmt[i].stride_y = vc_get_linesize(desc.width, out_codec);
398 fmt[i].bit_depth = get_bits_per_component(out_codec);
399 fmt[i].bit_shift = 0;
400 fmt[i].is_or_combined = 0;
401 fmt[i].is_signed = 0;
402 fmt[i].sampling_factor_x = 1;
403 fmt[i].sampling_factor_y = 1;
404 }
405
406 CHECK_OK(cmpto_j2k_dec_cfg_set_samples_format(s->settings, fmt, 3),
407 "Error setting sample format", return false);
408 }
409
410 s->desc = desc;
411 s->out_codec = out_codec;
412 s->pitch = pitch;
413
414 int ret = pthread_create(&s->thread_id, NULL, decompress_j2k_worker, (void *) s);
415 assert(ret == 0 && "Unable to create thread");
416
417 return true;
418}
struct video_desc desc
const char * fmt
const char * get_codec_name(codec_t codec)
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
unsigned int cuda_devices_count
Definition host.cpp:168
unsigned int cuda_devices[MAX_CUDA_DEVICES]
Definition host.cpp:167
unsigned int req_tile_limit
long long int req_mem_limit
unsigned int width
width of every tile (!)
Definition types.h:179
@ R12L
RGB 12-bit packed, little-endian.
Definition types.h:74
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70
double get_bpp(codec_t codec)
int get_bits_per_component(codec_t codec)
enum cmpto_sample_format_type cmpto_sf
static void * decompress_j2k_worker(void *args)
static bool set_postprocess_convert(struct state_decompress_j2k *s, struct cmpto_j2k_dec_ctx_cfg *ctx_cfg, const struct conv_props *codec)

References CHECK_OK, cmpto_sf, codecs, cuda_devices, cuda_devices_count, state_decompress_j2k::decoder, decompress_j2k_worker(), desc, fmt, get_bits_per_component(), get_bpp(), get_codec_name(), j2k_decompress_cleanup_common(), LOG, LOG_LEVEL_ERROR, LOG_LEVEL_NOTICE, MOD_NAME, NOOP, state_decompress_j2k::out_codec, state_decompress_j2k::pitch, R12L, state_decompress_j2k::req_mem_limit, state_decompress_j2k::req_tile_limit, RGBA, set_postprocess_convert(), state_decompress_j2k::settings, state, state_decompress_j2k::thread_id, vc_get_linesize(), VIDEO_CODEC_NONE, and video_desc::width.

Here is the call graph for this function:

◆ j2k_probe_internal_codec()

static decompress_status j2k_probe_internal_codec ( codec_t in_codec,
unsigned char * buffer,
size_t len,
struct pixfmt_desc * internal_prop )
static

Definition at line 429 of file cmpto_j2k.cpp.

429 {
430 struct cmpto_j2k_dec_img_info info;
431 struct cmpto_j2k_dec_comp_info comp_info[3];
432 if (cmpto_j2k_dec_cstream_get_img_info(buffer, len, &info) != CMPTO_OK ||
433 cmpto_j2k_dec_cstream_get_comp_info(buffer, len, 0, &comp_info[0]) != CMPTO_OK) {
434 log_msg(LOG_LEVEL_ERROR, "J2K Failed to get image or first component info.\n");
435 return DECODER_NO_FRAME;
436 }
437
438 internal_prop->depth = comp_info[0].bit_depth;
439 internal_prop->rgb = in_codec == J2KR;
440 if (info.comp_count == 3) {
441 if (cmpto_j2k_dec_cstream_get_comp_info(buffer, len, 1, &comp_info[1]) != CMPTO_OK ||
442 cmpto_j2k_dec_cstream_get_comp_info(buffer, len, 2, &comp_info[2]) != CMPTO_OK) {
443 log_msg(LOG_LEVEL_ERROR, "J2K Failed to get componentt 1 or 2 info.\n");
444 return DECODER_NO_FRAME;
445 }
446 if (comp_info[0].sampling_factor_x == 1 && comp_info[0].sampling_factor_y == 1 &&
447 comp_info[1].sampling_factor_x == comp_info[2].sampling_factor_x &&
448 comp_info[1].sampling_factor_y == comp_info[2].sampling_factor_y) {
449 int a = 4 / comp_info[1].sampling_factor_x;
450 internal_prop->subsampling = 4000 + a * 100;
451 if (comp_info[1].sampling_factor_y == 1) {
452 internal_prop->subsampling += a * 10;
453 }
454 }
455 }
456
457 int msg_level = internal_prop->subsampling == 0 ? LOG_LEVEL_WARNING /* bogus? */ : LOG_LEVEL_VERBOSE;
458 log_msg(msg_level, "J2K stream properties: %s\n", get_pixdesc_desc(*internal_prop));
459
460 return DECODER_GOT_CODEC;
461}
@ DECODER_GOT_CODEC
Internal pixel format was determined.
int depth
bit depth; 0 means that whole struct is undefined
Definition types.h:140
bool rgb
Definition types.h:142
int subsampling
in 'JabA' format, eg. '4444'
Definition types.h:141
const char * get_pixdesc_desc(struct pixfmt_desc desc)

References DECODER_GOT_CODEC, DECODER_NO_FRAME, pixfmt_desc::depth, get_pixdesc_desc(), J2KR, len, LOG_LEVEL_ERROR, LOG_LEVEL_VERBOSE, LOG_LEVEL_WARNING, log_msg(), pixfmt_desc::rgb, and pixfmt_desc::subsampling.

Referenced by j2k_decompress().

Here is the call graph for this function:

◆ print_dropped()

static void print_dropped ( unsigned long long int dropped)
static

Definition at line 153 of file cmpto_j2k.cpp.

153 {
154 if (dropped % 10 == 1) {
155 log_msg(LOG_LEVEL_WARNING, "[J2K dec] Some frames (%llu) dropped.\n", dropped);
156 log_msg_once(LOG_LEVEL_INFO, to_fourcc('J', '2', 'D', 'W'), "[J2K dec] You may try to increase "
157 "tile limit to increase the throughput by adding parameter: --param j2k-dec-tile-limit=4\n");
158 }
159}
void log_msg_once(int level, uint32_t id, const char *msg,...)
Definition debug.cpp:137
#define to_fourcc(a, b, c, d)
Creates FourCC word.
Definition macros.h:114

References LOG_LEVEL_INFO, LOG_LEVEL_WARNING, log_msg(), log_msg_once(), and to_fourcc.

Referenced by decompress_j2k_worker(), and j2k_decompress().

Here is the call graph for this function:

◆ r12l_postprocessor_get_sz()

static void r12l_postprocessor_get_sz ( void * ,
void * ,
size_t ,
int size_x,
int size_y,
struct cmpto_j2k_dec_comp_format * ,
int comp_count,
size_t * temp_buffer_size,
size_t * output_buffer_size )
static

Definition at line 260 of file cmpto_j2k.cpp.

264{
265 assert(comp_count == 3);
266 *temp_buffer_size = 0; // no temp buffer required
267 *output_buffer_size = vc_get_datalen(size_x, size_y, R12L);
268}
size_t vc_get_datalen(unsigned int width, unsigned int height, codec_t codec)

References R12L, and vc_get_datalen().

Here is the call graph for this function:

◆ REGISTER_MODULE()

REGISTER_MODULE ( j2k ,
& j2k_decompress_info,
LIBRARY_CLASS_VIDEO_DECOMPRESS ,
VIDEO_DECOMPRESS_ABI_VERSION  )

◆ release_cstream()

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

Callback called by the codec when codestream is no longer required.

Definition at line 423 of file cmpto_j2k.cpp.

424{
425 (void) custom_data; (void) custom_data_size; (void) codestream_size;
426 free(const_cast<void *>(codestream));
427}
auxilliary data structure passed with encoded frame

Referenced by j2k_decompress().

◆ rg48_to_r12l()

static void rg48_to_r12l ( unsigned char * dst_buffer,
unsigned char * src_buffer,
unsigned int width,
unsigned int height )
static

Definition at line 135 of file cmpto_j2k.cpp.

138{
139 int src_pitch = vc_get_linesize(width, RG48);
140 int dst_len = vc_get_linesize(width, R12L);
142
144 parallel_pix_conv((int) height, (char *) dst_buffer, dst_len,
145 (const char *) src_buffer, src_pitch,
147 if (log_level >= LOG_LEVEL_DEBUG) {
148 MSG(DEBUG, "pixfmt conversion duration: %f ms\n",
149 NS_TO_MS((double) (get_time_in_ns() - t0)));
150 }
151}
#define MSG(l, fmt,...)
Definition debug.h:96
#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)
static void vc_copylineRG48toR12L(unsigned char *__restrict dst, const unsigned char *__restrict src, int dst_len, int rshift, int gshift, int bshift)
Converts RG48 to R12L. Converts 16-bit RGB to 12-bit packed RGB in full range (compatible with SMPTE ...
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
long long time_ns_t
Definition tv.h:81
static time_ns_t get_time_in_ns()
Definition tv.h:101
#define NS_TO_MS(val_ns)
Definition tv.h:98
@ RG48
16-bit RGB little-endian (RlRhGl...)
Definition types.h:95

References DEBUG, get_decoder_from_to(), get_time_in_ns(), log_level, LOG_LEVEL_DEBUG, MSG, NS_TO_MS, parallel_pix_conv(), R12L, RG48, vc_copylineRG48toR12L(), and vc_get_linesize().

Here is the call graph for this function:

◆ set_postprocess_convert()

static bool set_postprocess_convert ( struct state_decompress_j2k * s,
struct cmpto_j2k_dec_ctx_cfg * ctx_cfg,
const struct conv_props * codec )
static

Definition at line 303 of file cmpto_j2k.cpp.

306{
307 const bool force_cpu_conv =
309 if (codec->run_callback != nullptr && !force_cpu_conv) {
310 if (cuda_devices_count == 1) {
311 CHECK_OK(cmpto_j2k_dec_ctx_cfg_set_postprocessor_cuda(
312 ctx_cfg, nullptr, nullptr,
313 codec->size_callback, codec->run_callback),
314 "add postprocessor", return false);
315 return true;
316 }
317 MSG(WARNING,
318 "More than 1 CUDA device set, will use CPU conversion...\n");
319 }
320 s->convert = codec->convert;
321 if (s->convert != nullptr && codec->run_callback == nullptr &&
322 !force_cpu_conv) {
323 MSG(WARNING, "Compiled without CUDA, pixfmt conv will "
324 "be processed on CPU...\n");
325 }
326 return true;
327}
#define CPU_CONV_PARAM

References CHECK_OK, state_decompress_j2k::convert, CPU_CONV_PARAM, cuda_devices_count, get_commandline_param(), and MSG.

Referenced by j2k_decompress_reconfigure().

Here is the call graph for this function:

Variable Documentation

◆ codecs

const struct conv_props codecs[]
static
Initial value:
= {
{ UYVY, CMPTO_422_U8_P1020, nullptr, nullptr, nullptr },
{ v210, CMPTO_422_U10_V210, nullptr, nullptr, nullptr },
{ RGB, CMPTO_444_U8_P012, nullptr, nullptr, nullptr },
{ BGR, CMPTO_444_U8_P210, nullptr, nullptr, nullptr },
{ RGBA, CMPTO_444_U8_P012Z, nullptr, nullptr, nullptr },
{ R10k, CMPTO_444_U10U10U10_MSB32BE_P210, nullptr, nullptr, nullptr },
{ RG48, CMPTO_444_U12_MSB16LE_P012, nullptr, nullptr, nullptr },
{ R12L, CMPTO_444_U12_MSB16LE_P012, rg48_to_r12l,
}
@ 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
@ BGR
8-bit BGR
Definition types.h:88
@ v210
YCbCr 422 10-bit - xVY0U|xY2UY1|xUY3V|xY5VY4, little-endian (2 bit padding /'x'/),...
Definition types.h:75
static void rg48_to_r12l(unsigned char *dst_buffer, unsigned char *src_buffer, unsigned int width, unsigned int height)
static void r12l_postprocessor_get_sz(void *, void *, size_t, int size_x, int size_y, struct cmpto_j2k_dec_comp_format *, int comp_count, size_t *temp_buffer_size, size_t *output_buffer_size)
const cmpto_j2k_dec_postprocessor_run_callback_cuda r12l_postprocess_cuda

Referenced by j2k_decompress_get_priority(), and j2k_decompress_reconfigure().

◆ DEFAULT_MAX_IN_FRAMES

const int DEFAULT_MAX_IN_FRAMES = 4
constexpr

maximal number of concurrently decompressed frames

Definition at line 84 of file cmpto_j2k.cpp.

Referenced by j2k_decompress_init().

◆ DEFAULT_MAX_QUEUE_SIZE

const int DEFAULT_MAX_QUEUE_SIZE = 2
constexpr

maximal size of queue for decompressed frames

Definition at line 82 of file cmpto_j2k.cpp.

Referenced by j2k_decompress_init().

◆ DEFAULT_MEM_LIMIT

const int64_t DEFAULT_MEM_LIMIT = 1000000000LL
constexpr

Definition at line 85 of file cmpto_j2k.cpp.

◆ DEFAULT_TILE_LIMIT

const int DEFAULT_TILE_LIMIT = 2
constexpr

Definition at line 80 of file cmpto_j2k.cpp.

◆ j2k_decompress_info

const struct video_decompress_info j2k_decompress_info
static
Initial value:
= {
}
static int j2k_decompress_get_priority(codec_t compression, struct pixfmt_desc internal, codec_t ugc)
static decompress_status j2k_decompress(void *state, unsigned char *dst, unsigned char *buffer, unsigned int src_len, int, struct video_frame_callbacks *, struct pixfmt_desc *internal_prop)
static int j2k_decompress_get_property(void *state, int property, void *val, size_t *len)
static void j2k_decompress_done(void *state)
static int j2k_decompress_reconfigure(void *state, struct video_desc desc, int rshift, int gshift, int bshift, int pitch, codec_t out_codec)
static void * j2k_decompress_init(void)

Definition at line 600 of file cmpto_j2k.cpp.

◆ MOD_NAME

const char* MOD_NAME = "[J2K dec.] "
constexpr

Definition at line 86 of file cmpto_j2k.cpp.

Referenced by j2k_decompress(), j2k_decompress_init(), and j2k_decompress_reconfigure().

◆ r12l_postprocess_cuda

const cmpto_j2k_dec_postprocessor_run_callback_cuda r12l_postprocess_cuda
Initial value:
=
nullptr

Definition at line 273 of file cmpto_j2k.cpp.