Skip to content

Commit

Permalink
LUT mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
sundermann committed Feb 24, 2023
1 parent e32bebb commit 51cca3c
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static struct option long_options[] = {
{ "no-vsync", no_argument, 0, 'n' },
{ "no-hdr", no_argument, 0, 'r' },
{ "no-powerstate", no_argument, 0, 's' },
{ "lut-table", required_argument, 0, 't' },
{ "backend", required_argument, 0, 'b' },
{ "ui-backend", required_argument, 0, 'u' },
{ "quirks", required_argument, 0, 'q' },
Expand Down Expand Up @@ -62,6 +63,7 @@ static void print_usage()
printf(" -n, --no-vsync Disable vsync (may increase framerate at the cost of tearing/artifacts)\n");
printf(" -r, --no-hdr Disable automatic HDR mode switching\n");
printf(" -s, --no-powerstate Disable automatic powerstate switching\n");
printf(" -t, --lut-table LUT table file\n");
printf(" -q, --quirks=QUIRKS Enable certain handling for per-device quirks\n");
printf(" -c, --config=PATH Absolute path for configfile to load settings. Giving additional runtime arguments will overwrite loaded ones.\n");
printf(" -d, --dump-frames Dump raw video frames to /tmp/.\n");
Expand All @@ -76,7 +78,7 @@ static int parse_options(int argc, char* argv[])
int opt, longindex;
int ret;

while ((opt = getopt_long(argc, argv, "x:y:a:p:f:b:u:q:c:lvnhdVGrs", long_options, &longindex)) != -1) {
while ((opt = getopt_long(argc, argv, "x:y:a:p:f:b:u:q:c:t:lvnhdVGrs", long_options, &longindex)) != -1) {
switch (opt) {
case 'x':
settings.width = atoi(optarg);
Expand Down Expand Up @@ -129,6 +131,10 @@ static int parse_options(int argc, char* argv[])
case 'q':
settings.quirks = atoi(optarg);
break;
case 't':
free(settings.lut_table);
settings.lut_table = strdup(optarg);
break;
case 'c':
DBG("Loading config file %s...", optarg);
if ((ret = settings_load_file(&settings, optarg)) != 0) {
Expand Down
2 changes: 2 additions & 0 deletions src/service.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ int service_init(service_t* service, settings_t* settings)
service->unicapture.callback_data = (void*)service;
service->unicapture.dump_frames = settings->dump_frames;

unicapture_load_lut_table(&service->unicapture, settings->lut_table);

char* ui_backends[] = { "libgm_backend.so", "libhalgal_backend.so", NULL };
char* video_backends[] = { "libvtcapture_backend.so", "libdile_vt_backend.so", NULL };
char backend_name[FILENAME_MAX] = { 0 };
Expand Down
11 changes: 11 additions & 0 deletions src/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ void settings_init(settings_t* settings)
settings->height = 180;
settings->quirks = 0;

settings->lut_table = strdup("");

settings->no_video = false;
settings->no_gui = false;
settings->autostart = false;
Expand Down Expand Up @@ -58,6 +60,13 @@ int settings_load_json(settings_t* settings, jvalue_ref source)
if ((value = jobject_get(source, j_cstr_to_buffer("unix-socket"))) && jis_boolean(value))
jboolean_get(value, &settings->unix_socket);

if ((value = jobject_get(source, j_cstr_to_buffer("lut-table"))) && jis_string(value)) {
free(settings->lut_table);
raw_buffer str = jstring_get(value);
settings->lut_table = strdup(str.m_str);
jstring_free_buffer(str);
}

if ((value = jobject_get(source, j_cstr_to_buffer("fps"))) && jis_number(value))
jnumber_get_i32(value, &settings->fps);
if ((value = jobject_get(source, j_cstr_to_buffer("width"))) && jis_number(value))
Expand Down Expand Up @@ -94,6 +103,8 @@ int settings_save_json(settings_t* settings, jvalue_ref target)
jobject_set(target, j_cstr_to_buffer("priority"), jnumber_create_i32(settings->priority));
jobject_set(target, j_cstr_to_buffer("unix-socket"), jboolean_create(settings->unix_socket));

jobject_set(target, j_cstr_to_buffer("lut-table"), jstring_create(settings->lut_table));

jobject_set(target, j_cstr_to_buffer("fps"), jnumber_create_i32(settings->fps));
jobject_set(target, j_cstr_to_buffer("width"), jnumber_create_i32(settings->width));
jobject_set(target, j_cstr_to_buffer("height"), jnumber_create_i32(settings->height));
Expand Down
2 changes: 2 additions & 0 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ typedef struct _settings_t {
bool vsync;
int quirks;

char* lut_table;

bool no_video;
bool no_gui;

Expand Down
59 changes: 59 additions & 0 deletions src/unicapture.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <string.h>
#include <unistd.h>

#define LUT_INDEX(y,u,v) ((y + (u<<8) + (v<<16))*3)
#define LUT_FILE_SIZE 256 * 256 * 256 * 3

#define DLSYM_ERROR_CHECK() \
if ((error = dlerror()) != NULL) { \
ERR("Error! dlsym failed, msg: %s", error); \
Expand Down Expand Up @@ -189,6 +192,17 @@ void* unicapture_run(void* data)

if (video_frame.pixel_format != PIXFMT_INVALID) {
converter_run(&video_converter, &video_frame, &video_frame_converted, PIXFMT_ARGB);

if (this->lut_table != NULL) {
for (int i = 0; i < video_frame_converted.width * video_frame_converted.height * 4; i += 4) {
// This is somehow RGBA instead of the supposed ARGB
uint8_t r = ((uint8_t*)(video_frame_converted.planes[0].buffer))[i + 0];
uint8_t g = ((uint8_t*)(video_frame_converted.planes[0].buffer))[i + 1];
uint8_t b = ((uint8_t*)(video_frame_converted.planes[0].buffer))[i + 2];

memcpy(&((uint8_t*)video_frame_converted.planes[0].buffer)[i + 0], &this->lut_table[LUT_INDEX(r, g, b)], 3);
}
}
}

uint64_t frame_converted = getticks_us();
Expand Down Expand Up @@ -339,6 +353,51 @@ void unicapture_init(unicapture_state_t* this)
{
memset(this, 0, sizeof(unicapture_state_t));
this->vsync = true;
this->lut_table = NULL;
}

int unicapture_load_lut_table(unicapture_state_t* this, char* lut_table_file) {
if (this->lut_table) {
free(this->lut_table);
}
this->lut_table = NULL;

if (strcmp(lut_table_file, "") == 0) {
return 1;
}

FILE* file = fopen(lut_table_file, "r");

if (!file) {
INFO("LUT file could not be read: %s", lut_table_file);
return 1;
}

size_t length;
INFO("LUT file read: %s", lut_table_file);

fseek(file, 0, SEEK_END);
length = ftell(file);
fseek(file, 0, SEEK_SET);

if (length != LUT_FILE_SIZE) {
ERR("LUT file has invalid length: %i", length);
fclose(file);
return 1;
}

this->lut_table = (unsigned char*)malloc(length + 1);
if (fread(this->lut_table, 1, length, file) != length) {
free(this->lut_table);
this->lut_table = NULL;
ERR("Error reading LUT file");
fclose(file);
return 1;
}

INFO("LUT file has been loaded");

return 0;
}

int unicapture_start(unicapture_state_t* this)
Expand Down
3 changes: 3 additions & 0 deletions src/unicapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ typedef struct _unicapture_state {
struct {
double framerate;
} metrics;

uint8_t* lut_table;
} unicapture_state_t;

#ifdef __cplusplus
Expand All @@ -112,6 +114,7 @@ int unicapture_try_backends(cap_backend_config_t* config, capture_backend_t* bac
int unicapture_init_backend(cap_backend_config_t* config, capture_backend_t* backend, char* name);
int unicapture_start(unicapture_state_t* state);
int unicapture_stop(unicapture_state_t* state);
int unicapture_load_lut_table(unicapture_state_t* state, char* lut_table_file);
#ifdef __cplusplus
}
#endif

0 comments on commit 51cca3c

Please sign in to comment.