UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
gpujpeg.c File Reference
#include "debug.h"
#include "host.h"
#include "video.h"
#include "video_decompress.h"
#include <libgpujpeg/gpujpeg_decoder.h>
#include <libgpujpeg/gpujpeg_version.h>
#include <pthread.h>
#include <stdlib.h>
#include "lib_common.h"
#include "utils/macros.h"
Include dependency graph for gpujpeg.c:

Go to the source code of this file.

Classes

struct  state_decompress_gpujpeg
 

Macros

#define MOD_NAME   "[GPUJPEG dec.] "
 
#define NEW_PARAM_IMG_NO_COMP_COUNT
 

Functions

static int configure_with (struct state_decompress_gpujpeg *s, struct video_desc desc)
 
static decompress_status gpujpeg_decompress (void *state, unsigned char *dst, unsigned char *buffer, unsigned int src_len, int frame_seq, struct video_frame_callbacks *callbacks, struct pixfmt_desc *internal_prop)
 
static void gpujpeg_decompress_done (void *state)
 
static int gpujpeg_decompress_get_priority (codec_t compression, struct pixfmt_desc internal, codec_t ugc)
 
static int gpujpeg_decompress_get_property (void *state, int property, void *val, size_t *len)
 
static void * gpujpeg_decompress_init (void)
 
static int gpujpeg_decompress_reconfigure (void *state, struct video_desc desc, int rshift, int gshift, int bshift, int pitch, codec_t out_codec)
 
static decompress_status gpujpeg_probe_internal_codec (unsigned char *buffer, size_t len, struct pixfmt_desc *internal_prop)
 
 REGISTER_MODULE (gpujpeg, &gpujpeg_info, LIBRARY_CLASS_VIDEO_DECOMPRESS, VIDEO_DECOMPRESS_ABI_VERSION)
 

Variables

static const struct video_decompress_info gpujpeg_info
 

Detailed Description

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

Definition in file gpujpeg.c.

Macro Definition Documentation

◆ MOD_NAME

#define MOD_NAME   "[GPUJPEG dec.] "

Definition at line 57 of file gpujpeg.c.

Referenced by gpujpeg_decompress_init(), and gpujpeg_probe_internal_codec().

◆ NEW_PARAM_IMG_NO_COMP_COUNT

#define NEW_PARAM_IMG_NO_COMP_COUNT

Definition at line 60 of file gpujpeg.c.

Referenced by configure_with().

Function Documentation

◆ configure_with()

static int configure_with ( struct state_decompress_gpujpeg * s,
struct video_desc desc )
static

Definition at line 74 of file gpujpeg.c.

75{
76 s->desc = desc;
77
78 s->decoder = gpujpeg_decoder_create(NULL);
79 if(!s->decoder) {
80 return FALSE;
81 }
82
83 // setting verbosity - a bit tricky now, gpujpeg_decoder_init needs to be called with some "valid" data
84 // otherwise, parameter setting is unneeded - it is done automaticaly by the image
85 struct gpujpeg_parameters param;
86 gpujpeg_set_default_parameters(&param);
87 param.color_space_internal = GPUJPEG_YCBCR_BT709; // see comment bellow
88 param.verbose = MAX(0, log_level - LOG_LEVEL_INFO);
89 struct gpujpeg_image_parameters param_image;
90 gpujpeg_image_set_default_parameters(&param_image);
91 param_image.width = desc.width; // size must be non-zero in order the init to succeed
92 param_image.height = desc.height;
93 param_image.color_space = GPUJPEG_YCBCR_BT709; // assume now BT.709 as default - this is mainly applicable for FFmpeg-encoded
94 // JPEGs that doesn't indicate explicitly color spec (no JFIF marker, only CS=ITU601
95 // for BT.601 limited range - not enabled by UG encoder because FFmpeg emits it also for 709)
96 int rc = gpujpeg_decoder_init(s->decoder, &param, &param_image);
97 assert(rc == 0);
98
99 switch (s->out_codec) {
100 case I420:
101 gpujpeg_decoder_set_output_format(s->decoder, GPUJPEG_YCBCR_BT709,
102 GPUJPEG_420_U8_P0P1P2);
103 break;
104 case RGBA:
105 gpujpeg_decoder_set_output_format(s->decoder, GPUJPEG_RGB,
106 s->out_codec == RGBA && s->rshift == 0 && s->gshift == 8 && s->bshift == 16 && vc_get_linesize(desc.width, RGBA) == s->pitch ?
108 GPUJPEG_4444_U8_P0123 : GPUJPEG_444_U8_P012);
109#else
110 GPUJPEG_444_U8_P012A : GPUJPEG_444_U8_P012);
111#endif
112 break;
113 case RGB:
114 gpujpeg_decoder_set_output_format(s->decoder, GPUJPEG_RGB,
115 GPUJPEG_444_U8_P012);
116 break;
117 case UYVY:
118 gpujpeg_decoder_set_output_format(s->decoder, GPUJPEG_YCBCR_BT709,
119 GPUJPEG_422_U8_P1020);
120 break;
121 case VIDEO_CODEC_NONE:
122 break;
123 default:
124 assert("Invalid codec!" && 0);
125 }
126
127 return TRUE;
128}
struct video_desc desc
int vc_get_linesize(unsigned int width, codec_t codec)
#define TRUE
#define FALSE
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define NEW_PARAM_IMG_NO_COMP_COUNT
Definition gpujpeg.c:60
volatile int log_level
Definition debug.cpp:65
#define MAX(a, b)
Definition macros.h:65
const char * param
Definition settings.cpp:195
struct gpujpeg_decoder * decoder
Definition gpujpeg.c:64
struct video_desc desc
Definition gpujpeg.c:66
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
@ 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
@ I420
planar YCbCr 4:2:0
Definition types.h:97
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70

References state_decompress_gpujpeg::bshift, state_decompress_gpujpeg::decoder, desc, state_decompress_gpujpeg::desc, FALSE, state_decompress_gpujpeg::gshift, video_desc::height, I420, log_level, LOG_LEVEL_INFO, MAX, NEW_PARAM_IMG_NO_COMP_COUNT, state_decompress_gpujpeg::out_codec, param, state_decompress_gpujpeg::pitch, RGB, RGBA, state_decompress_gpujpeg::rshift, TRUE, UYVY, vc_get_linesize(), VIDEO_CODEC_NONE, and video_desc::width.

Referenced by gpujpeg_decompress_reconfigure().

Here is the call graph for this function:

◆ gpujpeg_decompress()

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

Definition at line 250 of file gpujpeg.c.

252{
253 UNUSED(frame_seq);
254 UNUSED(callbacks);
256 int ret;
257 struct gpujpeg_decoder_output decoder_output;
258 int linesize;
259
260 if (s->out_codec == VIDEO_CODEC_NONE) {
261 return gpujpeg_probe_internal_codec(buffer, src_len, internal_prop);
262 }
263
264 linesize = vc_get_linesize(s->desc.width, s->out_codec);
265
266 gpujpeg_set_device(cuda_devices[0]);
267
268 if (s->pitch == linesize && (s->out_codec == UYVY || s->out_codec == RGB
269 || (s->out_codec == RGBA && s->rshift == 0 && s->gshift == 8 && s->bshift == 16)
270 )) {
271 gpujpeg_decoder_output_set_custom(&decoder_output, dst);
272 //int data_decompressed_size = decoder_output.data_size;
273
274 ret = gpujpeg_decoder_decode(s->decoder, (uint8_t*) buffer, src_len, &decoder_output);
275 if (ret != 0) return DECODER_NO_FRAME;
276 } else {
277 unsigned char *line_src, *line_dst;
278
279 gpujpeg_decoder_output_set_default(&decoder_output);
280 decoder_output.type = GPUJPEG_DECODER_OUTPUT_INTERNAL_BUFFER;
281 //int data_decompressed_size = decoder_output.data_size;
282
283 ret = gpujpeg_decoder_decode(s->decoder, (uint8_t*) buffer, src_len, &decoder_output);
284
285 if (ret != 0) return DECODER_NO_FRAME;
286
287 line_dst = dst;
288 line_src = decoder_output.data;
289 for (unsigned i = 0u; i < s->desc.height; i++) {
290 if (s->out_codec == RGBA) {
291 vc_copylineRGBtoRGBA(line_dst, line_src, linesize,
292 s->rshift, s->gshift, s->bshift);
293 } else {
294 assert(s->out_codec == UYVY || s->out_codec == I420);
295 memcpy(line_dst, line_src, linesize);
296 }
297
298 line_dst += s->pitch;
299 line_src += vc_get_linesize(s->desc.width, s->out_codec);
300 }
301 }
302
303 return DECODER_GOT_FRAME;
304}
#define UNUSED(x)
void ** state
static decompress_status gpujpeg_probe_internal_codec(unsigned char *buffer, size_t len, struct pixfmt_desc *internal_prop)
Definition gpujpeg.c:184
@ DECODER_NO_FRAME
@ DECODER_GOT_FRAME
unsigned int cuda_devices[MAX_CUDA_DEVICES]
Definition host.cpp:167
decoder_func_t vc_copylineRGBtoRGBA

References state_decompress_gpujpeg::bshift, cuda_devices, state_decompress_gpujpeg::decoder, DECODER_GOT_FRAME, DECODER_NO_FRAME, state_decompress_gpujpeg::desc, gpujpeg_probe_internal_codec(), state_decompress_gpujpeg::gshift, video_desc::height, I420, state_decompress_gpujpeg::out_codec, state_decompress_gpujpeg::pitch, RGB, RGBA, state_decompress_gpujpeg::rshift, state, UNUSED, UYVY, vc_copylineRGBtoRGBA, vc_get_linesize(), VIDEO_CODEC_NONE, and video_desc::width.

Here is the call graph for this function:

◆ gpujpeg_decompress_done()

static void gpujpeg_decompress_done ( void * state)
static

Definition at line 327 of file gpujpeg.c.

328{
330
331 if(s->decoder) {
332 gpujpeg_decoder_destroy(s->decoder);
333 }
334 free(s);
335}

References state_decompress_gpujpeg::decoder, and state.

◆ gpujpeg_decompress_get_priority()

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

Definition at line 337 of file gpujpeg.c.

337 {
338 if (compression != JPEG && compression != MJPG) {
339 return -1;
340 }
341 switch (ugc) {
342 case VIDEO_CODEC_NONE:
343 return compression == JPEG ? 50 : 90; // for probe
344 case I420:
345 case RGB:
346 case RGBA:
347 case UYVY:
348 break;
349 default:
350 return -1;
351 }
352 bool out_rgb = codec_is_a_rgb(ugc);
353 if (compression == JPEG) {
354 if (internal.depth == 0) { // unspecified
355 return 900;
356 }
357 return internal.rgb == out_rgb ? 200 : 500;
358 }
359 // decoding from FFmpeg MJPG has lower priority than libavcodec
360 // decoder because those files doesn't has much independent
361 // segments (1 per MCU row -> 68 for HD) -> lavd may be better
362 if (internal.depth == 0) {
363 return 920;
364 }
365 return internal.rgb == out_rgb ? 600 : 800;
366}
@ JPEG
JPEG image, restart intervals may be used. Compatible with GPUJPEG.
Definition types.h:81
@ MJPG
JPEG image, without restart intervals.
Definition types.h:85
bool codec_is_a_rgb(codec_t codec)
Returns TRUE if specified pixelformat is some form of RGB (not YUV).

References codec_is_a_rgb(), I420, JPEG, MJPG, RGB, RGBA, UYVY, and VIDEO_CODEC_NONE.

Here is the call graph for this function:

◆ gpujpeg_decompress_get_property()

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

Definition at line 306 of file gpujpeg.c.

307{
308 struct state_decompress *s = (struct state_decompress *) state;
309 UNUSED(s);
310 int ret = FALSE;
311
312 switch(property) {
314 if(*len >= sizeof(int)) {
315 *(int *) val = FALSE;
316 *len = sizeof(int);
317 ret = TRUE;
318 }
319 break;
320 default:
321 ret = FALSE;
322 }
323
324 return ret;
325}
int void * val
int void size_t * len
int property
#define DECOMPRESS_PROPERTY_ACCEPTS_CORRUPTED_FRAME

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

◆ gpujpeg_decompress_init()

static void * gpujpeg_decompress_init ( void )
static

Definition at line 130 of file gpujpeg.c.

131{
132 if (gpujpeg_version() >> 8 != GPUJPEG_VERSION_INT >> 8) {
133 char ver_req[128] = "";
134 char ver_lib[128] = "";
135 strncpy(ver_req, gpujpeg_version_to_string(GPUJPEG_VERSION_INT), sizeof ver_req - 1);
136 strncpy(ver_lib, gpujpeg_version_to_string(gpujpeg_version()), sizeof ver_lib - 1);
137 log_msg(LOG_LEVEL_WARNING, "GPUJPEG API version mismatch! (compiled: %s, library present: %s, required same minor version)\n",
138 ver_req, ver_lib);
139 }
140
141 struct state_decompress_gpujpeg *s = (struct state_decompress_gpujpeg *) calloc(1, sizeof(struct state_decompress_gpujpeg));
142
143 int ret;
144 printf("Initializing CUDA device %d...\n", cuda_devices[0]);
145 ret = gpujpeg_init_device(cuda_devices[0], TRUE);
146 if(ret != 0) {
147 log_msg(LOG_LEVEL_ERROR, MOD_NAME "initializing CUDA device %d failed.\n", cuda_devices[0]);
148 free(s);
149 return NULL;
150 }
151
152
153 return s;
154}
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define MOD_NAME
Definition gpujpeg.c:57

References cuda_devices, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, and TRUE.

Here is the call graph for this function:

◆ gpujpeg_decompress_reconfigure()

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

Definition at line 156 of file gpujpeg.c.

158{
160
161 assert(out_codec == I420 || out_codec == RGB || out_codec == RGBA
163
164 if(s->out_codec == out_codec &&
165 s->pitch == pitch &&
166 s->rshift == rshift &&
167 s->gshift == gshift &&
168 s->bshift == bshift &&
170 return TRUE;
171 } else {
172 s->out_codec = out_codec;
173 s->pitch = pitch;
174 s->rshift = rshift;
175 s->gshift = gshift;
176 s->bshift = bshift;
177 if(s->decoder) {
178 gpujpeg_decoder_destroy(s->decoder);
179 }
180 return configure_with(s, desc);
181 }
182}
static int configure_with(struct state_decompress_gpujpeg *s, struct video_desc desc)
Definition gpujpeg.c:74
bool video_desc_eq_excl_param(struct video_desc a, struct video_desc b, unsigned int excluded_params)
Compares two video descriptions.
#define PARAM_INTERLACING
Definition video_frame.h:66

References state_decompress_gpujpeg::bshift, configure_with(), state_decompress_gpujpeg::decoder, desc, state_decompress_gpujpeg::desc, state_decompress_gpujpeg::gshift, I420, state_decompress_gpujpeg::out_codec, PARAM_INTERLACING, state_decompress_gpujpeg::pitch, RGB, RGBA, state_decompress_gpujpeg::rshift, state, TRUE, UYVY, VIDEO_CODEC_NONE, and video_desc_eq_excl_param().

Here is the call graph for this function:

◆ gpujpeg_probe_internal_codec()

static decompress_status gpujpeg_probe_internal_codec ( unsigned char * buffer,
size_t len,
struct pixfmt_desc * internal_prop )
static

Definition at line 184 of file gpujpeg.c.

184 {
185 struct gpujpeg_image_parameters image_params = { 0 };
186 gpujpeg_image_set_default_parameters(&image_params);
187#if GPUJPEG_VERSION_INT >= GPUJPEG_MK_VERSION_INT(0, 20, 0)
188 struct gpujpeg_parameters params;
189 gpujpeg_set_default_parameters(&params);
190 params.restart_interval = 0; // workaround for broken GPUJPEG from 2024-04 to 2024-08
191 params.verbose = MAX(0, log_level - LOG_LEVEL_INFO);
192 if (gpujpeg_decoder_get_image_info(buffer, len, &image_params, &params, NULL) != 0) {
193#else
194 if (gpujpeg_decoder_get_image_info(buffer, len, &image_params, NULL, MAX(0, log_level - LOG_LEVEL_INFO)) != 0) {
195#endif
196 log_msg(LOG_LEVEL_WARNING, MOD_NAME "probe - cannot get image info!\n");
197 return DECODER_NO_FRAME;
198 }
199
200 internal_prop->depth = 8;
201
202 switch (image_params.color_space) {
203 case GPUJPEG_NONE:
204 abort();
205 case GPUJPEG_RGB:
206 internal_prop->rgb = true;
207 break;
208 case GPUJPEG_YUV:
209 case GPUJPEG_YCBCR_BT601:
210 case GPUJPEG_YCBCR_BT601_256LVLS:
211 case GPUJPEG_YCBCR_BT709:
212 internal_prop->rgb = false;
213 break;
214 }
215
216 switch (image_params.pixel_format) {
217 case GPUJPEG_PIXFMT_NONE:
218 abort();
219 case GPUJPEG_U8:
220 internal_prop->subsampling = 4000;
221 break;
222 case GPUJPEG_422_U8_P1020:
223 case GPUJPEG_422_U8_P0P1P2:
224 internal_prop->subsampling = 4220;
225 break;
226 case GPUJPEG_420_U8_P0P1P2:
227 internal_prop->subsampling = 4200;
228 break;
229 case GPUJPEG_444_U8_P012:
230 case GPUJPEG_444_U8_P0P1P2:
231#if !defined NEW_PARAM_IMG_NO_COMP_COUNT
232 case GPUJPEG_444_U8_P012Z:
233#endif
234 internal_prop->subsampling = 4440;
235 break;
236#ifdef NEW_PARAM_IMG_NO_COMP_COUNT
237 case GPUJPEG_4444_U8_P0123:
238#else
239 case GPUJPEG_444_U8_P012A:
240#endif
241 internal_prop->subsampling = 4444;
242 break;
243
244 }
245
246 log_msg(LOG_LEVEL_VERBOSE, "JPEG color space: %s\n", gpujpeg_color_space_get_name(image_params.color_space));
247 return DECODER_GOT_CODEC;
248}
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
@ 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

References DECODER_GOT_CODEC, DECODER_NO_FRAME, pixfmt_desc::depth, len, log_level, LOG_LEVEL_INFO, LOG_LEVEL_VERBOSE, LOG_LEVEL_WARNING, log_msg(), MAX, MOD_NAME, pixfmt_desc::rgb, and pixfmt_desc::subsampling.

Referenced by gpujpeg_decompress().

Here is the call graph for this function:

◆ REGISTER_MODULE()

REGISTER_MODULE ( gpujpeg ,
& gpujpeg_info,
LIBRARY_CLASS_VIDEO_DECOMPRESS ,
VIDEO_DECOMPRESS_ABI_VERSION  )

Variable Documentation

◆ gpujpeg_info

const struct video_decompress_info gpujpeg_info
static
Initial value:
= {
}
static void gpujpeg_decompress_done(void *state)
Definition gpujpeg.c:327
static int gpujpeg_decompress_reconfigure(void *state, struct video_desc desc, int rshift, int gshift, int bshift, int pitch, codec_t out_codec)
Definition gpujpeg.c:156
static int gpujpeg_decompress_get_property(void *state, int property, void *val, size_t *len)
Definition gpujpeg.c:306
static void * gpujpeg_decompress_init(void)
Definition gpujpeg.c:130
static decompress_status gpujpeg_decompress(void *state, unsigned char *dst, unsigned char *buffer, unsigned int src_len, int frame_seq, struct video_frame_callbacks *callbacks, struct pixfmt_desc *internal_prop)
Definition gpujpeg.c:250
static int gpujpeg_decompress_get_priority(codec_t compression, struct pixfmt_desc internal, codec_t ugc)
Definition gpujpeg.c:337

Definition at line 368 of file gpujpeg.c.