Skip to content

Commit 51cca3c

Browse files
committed
LUT mapping
1 parent e32bebb commit 51cca3c

File tree

6 files changed

+84
-1
lines changed

6 files changed

+84
-1
lines changed

src/main.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ static struct option long_options[] = {
3131
{ "no-vsync", no_argument, 0, 'n' },
3232
{ "no-hdr", no_argument, 0, 'r' },
3333
{ "no-powerstate", no_argument, 0, 's' },
34+
{ "lut-table", required_argument, 0, 't' },
3435
{ "backend", required_argument, 0, 'b' },
3536
{ "ui-backend", required_argument, 0, 'u' },
3637
{ "quirks", required_argument, 0, 'q' },
@@ -62,6 +63,7 @@ static void print_usage()
6263
printf(" -n, --no-vsync Disable vsync (may increase framerate at the cost of tearing/artifacts)\n");
6364
printf(" -r, --no-hdr Disable automatic HDR mode switching\n");
6465
printf(" -s, --no-powerstate Disable automatic powerstate switching\n");
66+
printf(" -t, --lut-table LUT table file\n");
6567
printf(" -q, --quirks=QUIRKS Enable certain handling for per-device quirks\n");
6668
printf(" -c, --config=PATH Absolute path for configfile to load settings. Giving additional runtime arguments will overwrite loaded ones.\n");
6769
printf(" -d, --dump-frames Dump raw video frames to /tmp/.\n");
@@ -76,7 +78,7 @@ static int parse_options(int argc, char* argv[])
7678
int opt, longindex;
7779
int ret;
7880

79-
while ((opt = getopt_long(argc, argv, "x:y:a:p:f:b:u:q:c:lvnhdVGrs", long_options, &longindex)) != -1) {
81+
while ((opt = getopt_long(argc, argv, "x:y:a:p:f:b:u:q:c:t:lvnhdVGrs", long_options, &longindex)) != -1) {
8082
switch (opt) {
8183
case 'x':
8284
settings.width = atoi(optarg);
@@ -129,6 +131,10 @@ static int parse_options(int argc, char* argv[])
129131
case 'q':
130132
settings.quirks = atoi(optarg);
131133
break;
134+
case 't':
135+
free(settings.lut_table);
136+
settings.lut_table = strdup(optarg);
137+
break;
132138
case 'c':
133139
DBG("Loading config file %s...", optarg);
134140
if ((ret = settings_load_file(&settings, optarg)) != 0) {

src/service.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ int service_init(service_t* service, settings_t* settings)
8484
service->unicapture.callback_data = (void*)service;
8585
service->unicapture.dump_frames = settings->dump_frames;
8686

87+
unicapture_load_lut_table(&service->unicapture, settings->lut_table);
88+
8789
char* ui_backends[] = { "libgm_backend.so", "libhalgal_backend.so", NULL };
8890
char* video_backends[] = { "libvtcapture_backend.so", "libdile_vt_backend.so", NULL };
8991
char backend_name[FILENAME_MAX] = { 0 };

src/settings.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ void settings_init(settings_t* settings)
1616
settings->height = 180;
1717
settings->quirks = 0;
1818

19+
settings->lut_table = strdup("");
20+
1921
settings->no_video = false;
2022
settings->no_gui = false;
2123
settings->autostart = false;
@@ -58,6 +60,13 @@ int settings_load_json(settings_t* settings, jvalue_ref source)
5860
if ((value = jobject_get(source, j_cstr_to_buffer("unix-socket"))) && jis_boolean(value))
5961
jboolean_get(value, &settings->unix_socket);
6062

63+
if ((value = jobject_get(source, j_cstr_to_buffer("lut-table"))) && jis_string(value)) {
64+
free(settings->lut_table);
65+
raw_buffer str = jstring_get(value);
66+
settings->lut_table = strdup(str.m_str);
67+
jstring_free_buffer(str);
68+
}
69+
6170
if ((value = jobject_get(source, j_cstr_to_buffer("fps"))) && jis_number(value))
6271
jnumber_get_i32(value, &settings->fps);
6372
if ((value = jobject_get(source, j_cstr_to_buffer("width"))) && jis_number(value))
@@ -94,6 +103,8 @@ int settings_save_json(settings_t* settings, jvalue_ref target)
94103
jobject_set(target, j_cstr_to_buffer("priority"), jnumber_create_i32(settings->priority));
95104
jobject_set(target, j_cstr_to_buffer("unix-socket"), jboolean_create(settings->unix_socket));
96105

106+
jobject_set(target, j_cstr_to_buffer("lut-table"), jstring_create(settings->lut_table));
107+
97108
jobject_set(target, j_cstr_to_buffer("fps"), jnumber_create_i32(settings->fps));
98109
jobject_set(target, j_cstr_to_buffer("width"), jnumber_create_i32(settings->width));
99110
jobject_set(target, j_cstr_to_buffer("height"), jnumber_create_i32(settings->height));

src/settings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ typedef struct _settings_t {
2222
bool vsync;
2323
int quirks;
2424

25+
char* lut_table;
26+
2527
bool no_video;
2628
bool no_gui;
2729

src/unicapture.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#include <string.h>
1010
#include <unistd.h>
1111

12+
#define LUT_INDEX(y,u,v) ((y + (u<<8) + (v<<16))*3)
13+
#define LUT_FILE_SIZE 256 * 256 * 256 * 3
14+
1215
#define DLSYM_ERROR_CHECK() \
1316
if ((error = dlerror()) != NULL) { \
1417
ERR("Error! dlsym failed, msg: %s", error); \
@@ -189,6 +192,17 @@ void* unicapture_run(void* data)
189192

190193
if (video_frame.pixel_format != PIXFMT_INVALID) {
191194
converter_run(&video_converter, &video_frame, &video_frame_converted, PIXFMT_ARGB);
195+
196+
if (this->lut_table != NULL) {
197+
for (int i = 0; i < video_frame_converted.width * video_frame_converted.height * 4; i += 4) {
198+
// This is somehow RGBA instead of the supposed ARGB
199+
uint8_t r = ((uint8_t*)(video_frame_converted.planes[0].buffer))[i + 0];
200+
uint8_t g = ((uint8_t*)(video_frame_converted.planes[0].buffer))[i + 1];
201+
uint8_t b = ((uint8_t*)(video_frame_converted.planes[0].buffer))[i + 2];
202+
203+
memcpy(&((uint8_t*)video_frame_converted.planes[0].buffer)[i + 0], &this->lut_table[LUT_INDEX(r, g, b)], 3);
204+
}
205+
}
192206
}
193207

194208
uint64_t frame_converted = getticks_us();
@@ -339,6 +353,51 @@ void unicapture_init(unicapture_state_t* this)
339353
{
340354
memset(this, 0, sizeof(unicapture_state_t));
341355
this->vsync = true;
356+
this->lut_table = NULL;
357+
}
358+
359+
int unicapture_load_lut_table(unicapture_state_t* this, char* lut_table_file) {
360+
if (this->lut_table) {
361+
free(this->lut_table);
362+
}
363+
this->lut_table = NULL;
364+
365+
if (strcmp(lut_table_file, "") == 0) {
366+
return 1;
367+
}
368+
369+
FILE* file = fopen(lut_table_file, "r");
370+
371+
if (!file) {
372+
INFO("LUT file could not be read: %s", lut_table_file);
373+
return 1;
374+
}
375+
376+
size_t length;
377+
INFO("LUT file read: %s", lut_table_file);
378+
379+
fseek(file, 0, SEEK_END);
380+
length = ftell(file);
381+
fseek(file, 0, SEEK_SET);
382+
383+
if (length != LUT_FILE_SIZE) {
384+
ERR("LUT file has invalid length: %i", length);
385+
fclose(file);
386+
return 1;
387+
}
388+
389+
this->lut_table = (unsigned char*)malloc(length + 1);
390+
if (fread(this->lut_table, 1, length, file) != length) {
391+
free(this->lut_table);
392+
this->lut_table = NULL;
393+
ERR("Error reading LUT file");
394+
fclose(file);
395+
return 1;
396+
}
397+
398+
INFO("LUT file has been loaded");
399+
400+
return 0;
342401
}
343402

344403
int unicapture_start(unicapture_state_t* this)

src/unicapture.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ typedef struct _unicapture_state {
102102
struct {
103103
double framerate;
104104
} metrics;
105+
106+
uint8_t* lut_table;
105107
} unicapture_state_t;
106108

107109
#ifdef __cplusplus
@@ -112,6 +114,7 @@ int unicapture_try_backends(cap_backend_config_t* config, capture_backend_t* bac
112114
int unicapture_init_backend(cap_backend_config_t* config, capture_backend_t* backend, char* name);
113115
int unicapture_start(unicapture_state_t* state);
114116
int unicapture_stop(unicapture_state_t* state);
117+
int unicapture_load_lut_table(unicapture_state_t* state, char* lut_table_file);
115118
#ifdef __cplusplus
116119
}
117120
#endif

0 commit comments

Comments
 (0)