Private
Public Access
151 lines
5.1 KiB
C
151 lines
5.1 KiB
C
/* Capture scheduler and histogram processing. */
|
|
static int tick(void *unused) {
|
|
(void)unused;
|
|
uint64_t now = milliseconds();
|
|
model_tick(now);
|
|
test_tick(&playback_json, now);
|
|
layout_refresh_tick(&playback_json, now, capture || capture_source == SOURCE_PICCAP);
|
|
stream_tick(&playback_json, now, handover_enabled && !retries.paused && !retries.blocked);
|
|
bool owned = handover_tick();
|
|
bridge_tick(now);
|
|
if (owned)
|
|
return 1;
|
|
if (!capture) {
|
|
retry_update(&retries, boot_enabled() && geteuid() == 0, false, milliseconds());
|
|
if (retry_take(&retries, milliseconds())) {
|
|
start(NULL, NULL, NULL);
|
|
if (!capture)
|
|
retry_failure(&retries, milliseconds());
|
|
}
|
|
return 1;
|
|
}
|
|
if (revoked) {
|
|
set_error("LG revoked capture; recovering after source transition");
|
|
capture_recoveries++;
|
|
recovery_started = milliseconds();
|
|
release_capture(false);
|
|
retry_source_transition(&retries, milliseconds());
|
|
return 1;
|
|
}
|
|
if (settling) {
|
|
settling--;
|
|
return 1;
|
|
}
|
|
if (!CALIBRATION_ACTIVE && letterbox_mode && capture_preset == 1 &&
|
|
milliseconds() >= next_border_probe) {
|
|
if (vt_preset(capture, 0) != 0) {
|
|
set_error("Border probe preset failed");
|
|
stop_capture();
|
|
return 1;
|
|
}
|
|
capture_preset = 0;
|
|
settling = 2;
|
|
return 1;
|
|
}
|
|
Histogram hist[16] = {0};
|
|
int rc = vt_get(capture, hist);
|
|
bool populated = !rc && histogram_populated(hist);
|
|
if (!populated) {
|
|
unsigned char held[16][3];
|
|
color_valid = false;
|
|
if (!continuity_frame(&continuity, false, rgb, now, held)) {
|
|
set_error("Histogram data unavailable beyond hold window; recovering capture");
|
|
release_capture(false);
|
|
retry_source_transition(&retries, now);
|
|
return 1;
|
|
}
|
|
char *line = region_command(held, led_blends, led_count,
|
|
(unsigned)(1500 - (now - continuity.missing_at)));
|
|
if (!line || send_line(line)) {
|
|
free(line);
|
|
set_error("Receiver connection lost while holding colors");
|
|
stop_capture();
|
|
return 1;
|
|
}
|
|
free(line);
|
|
if (!receiver_ack()) {
|
|
set_error("Receiver did not acknowledge held colors");
|
|
stop_capture();
|
|
return 1;
|
|
}
|
|
last_output_at = now;
|
|
return 1;
|
|
}
|
|
sample_at = now;
|
|
sample_sequence++;
|
|
unsigned aggregate[3] = {0};
|
|
for (int i = 0; i < 16; i++) {
|
|
black_percent[i] = 100;
|
|
for (int c = 0; c < 3; c++) {
|
|
uint64_t total = 0, black = 0;
|
|
for (int b = 0; b < 256; b++) {
|
|
total += hist[i].bins[c][b];
|
|
if (b <= 12)
|
|
black += hist[i].bins[c][b];
|
|
}
|
|
unsigned fraction = total ? (unsigned)(100 * black / total) : 0;
|
|
if (fraction < black_percent[i])
|
|
black_percent[i] = fraction;
|
|
}
|
|
}
|
|
for (int i = 0; i < 16; i++)
|
|
for (int c = 0; c < 3; c++) {
|
|
rgb[i][c] = histogram_mean(hist[i].bins[c]);
|
|
aggregate[c] += rgb[i][c];
|
|
}
|
|
if (!CALIBRATION_ACTIVE && capture_preset == 0) {
|
|
int candidate = letterbox_candidate(black_percent, rgb);
|
|
uint64_t now = milliseconds();
|
|
if (candidate < 0)
|
|
pending_letterbox = -1;
|
|
else if (candidate != pending_letterbox) {
|
|
pending_letterbox = candidate;
|
|
candidate_since = now;
|
|
} else if ((unsigned)candidate != letterbox_mode && now - candidate_since >= 2000)
|
|
letterbox_mode = (unsigned)candidate;
|
|
if (letterbox_mode) {
|
|
if (vt_preset(capture, 1) != 0) {
|
|
set_error("Letterbox preset failed");
|
|
stop_capture();
|
|
return 1;
|
|
}
|
|
capture_preset = 1;
|
|
settling = 2;
|
|
next_border_probe = now + 2000;
|
|
return 1;
|
|
}
|
|
}
|
|
for (int c = 0; c < 3; c++)
|
|
sent_rgb[c] = (unsigned char)(aggregate[c] / 16);
|
|
unsigned char boosted_mean[3];
|
|
boost_color(sent_rgb, boosted_mean);
|
|
memcpy(sent_rgb, boosted_mean, 3);
|
|
unsigned char mapped_rgb[16][3], stable_rgb[16][3];
|
|
calibration_colors(rgb, mapped_rgb);
|
|
continuity_frame(&continuity, true, mapped_rgb, now, stable_rgb);
|
|
interpolation_enabled = led_count && calibration_effective() != CAL_AVERAGE;
|
|
char *line = region_command(stable_rgb, led_blends, led_count, 1500);
|
|
if (!line) {
|
|
set_error("Color buffer allocation failed");
|
|
stop_capture();
|
|
return 1;
|
|
}
|
|
int failed = send_line(line);
|
|
free(line);
|
|
if (failed) {
|
|
set_error("Receiver connection lost");
|
|
stop_capture();
|
|
return 1;
|
|
}
|
|
if (!receiver_ack()) {
|
|
set_error("Receiver did not acknowledge color data");
|
|
stop_capture();
|
|
return 1;
|
|
}
|
|
last_error[0] = 0;
|
|
color_valid = true;
|
|
last_output_at = milliseconds();
|
|
frames++;
|
|
return 1;
|
|
}
|