Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LUT mapping #100

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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=FILE 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 @@ -78,6 +78,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);

service_init_backends(service);

return 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
60 changes: 60 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,52 @@ 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