Files
HyperDRM/native/continuity.h
T
2026-10-06 22:01:38 +02:00

77 lines
2.6 KiB
C

#ifndef HYPERDRM_CONTINUITY_H
#define HYPERDRM_CONTINUITY_H
/* Zero population is missing data, while populated bin zero is real black. */
static inline bool histogram_populated(const Histogram hist[16]) {
for (unsigned r = 0; r < 16; r++)
for (unsigned c = 0; c < 3; c++) {
uint64_t total = 0;
for (unsigned b = 0; b < 256; b++)
total += hist[r].bins[c][b];
if (!total)
return false;
}
return true;
}
typedef struct {
unsigned char last[16][3], from[16][3];
uint64_t valid_at, fade_at, missing_at;
bool available, fading, holding;
} Continuity;
static inline void continuity_seed(Continuity *s, const unsigned char colors[16][3], uint64_t now) {
memcpy(s->last, colors, sizeof(s->last));
memcpy(s->from, colors, sizeof(s->from));
s->valid_at = now;
s->available = true;
s->fading = true;
s->fade_at = 0;
s->missing_at = 0;
s->holding = false;
}
static inline void continuity_mix(const unsigned char from[16][3], const unsigned char to[16][3],
unsigned elapsed, unsigned char out[16][3]) {
if (elapsed > 500)
elapsed = 500;
for (unsigned r = 0; r < 16; r++)
for (unsigned c = 0; c < 3; c++)
out[r][c] = (from[r][c] * (500 - elapsed) + to[r][c] * elapsed + 250) / 500;
}
static inline bool continuity_frame(Continuity *s, bool valid, const unsigned char input[16][3],
uint64_t now, unsigned char out[16][3]) {
if (!valid) {
if (!s->missing_at)
s->missing_at = now;
s->holding = s->available && now - s->missing_at < 1500;
if (s->holding)
memcpy(out, s->last, sizeof(s->last));
return s->holding;
}
if (s->holding) {
memcpy(s->from, s->last, sizeof(s->from));
s->fading = true;
s->fade_at = 0;
}
s->holding = false;
s->missing_at = 0;
/* Near-black codec rounding is valid darkness, not a lost measurement. */
bool black = true;
for (unsigned r = 0; r < 16; r++)
for (unsigned c = 0; c < 3; c++)
if (input[r][c] > 3)
black = false;
if (black)
s->fading = false;
if (s->fading) {
if (!s->fade_at)
s->fade_at = now;
continuity_mix(s->from, input, (unsigned)(now - s->fade_at), out);
if (now - s->fade_at >= 500)
s->fading = false;
} else
memcpy(out, input, sizeof(s->last));
memcpy(s->last, out, sizeof(s->last));
s->available = true;
s->valid_at = now;
return true;
}
#endif