X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=qdc.cpp;h=556a8a5d541315a54d6bddf332cdd746a5c1769a;hb=34138d5b1a1302a7a1050fd46d2fb95c0186140a;hp=b5594b76856918d9b14bee3f55dd5bcec24fdd7a;hpb=cd50d72afd7a54ec57827049c8bb934cfbb5a42c;p=narabu diff --git a/qdc.cpp b/qdc.cpp index b5594b7..556a8a5 100644 --- a/qdc.cpp +++ b/qdc.cpp @@ -18,6 +18,11 @@ #define WIDTH 1280 #define HEIGHT 720 +#define WIDTH_BLOCKS (WIDTH/8) +#define WIDTH_BLOCKS_CHROMA (WIDTH/16) +#define HEIGHT_BLOCKS (HEIGHT/8) +#define NUM_BLOCKS (WIDTH_BLOCKS * HEIGHT_BLOCKS) +#define NUM_BLOCKS_CHROMA (WIDTH_BLOCKS_CHROMA * HEIGHT_BLOCKS) #define NUM_SYMS 256 #define ESCAPE_LIMIT (NUM_SYMS - 1) @@ -25,7 +30,7 @@ // of coefficients to rANS probability distributions. This is randomized, // so you might want to run it a few times. #define FIND_OPTIMAL_STREAM_ASSIGNMENT 0 -#define NUM_CLUSTERS 8 +#define NUM_CLUSTERS 4 static constexpr uint32_t prob_bits = 12; static constexpr uint32_t prob_scale = 1 << prob_bits; @@ -154,12 +159,37 @@ SymbolStats stats[128]; float kl_dist[64][64]; #endif +const int luma_mapping[64] = { + 0, 0, 1, 1, 2, 2, 3, 3, + 0, 0, 1, 2, 2, 2, 3, 3, + 1, 1, 2, 2, 2, 3, 3, 3, + 1, 1, 2, 2, 2, 3, 3, 3, + 1, 2, 2, 2, 2, 3, 3, 3, + 2, 2, 2, 2, 3, 3, 3, 3, + 2, 2, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, +}; +const int chroma_mapping[64] = { + 0, 1, 1, 2, 2, 2, 3, 3, + 1, 1, 2, 2, 2, 3, 3, 3, + 2, 2, 2, 2, 3, 3, 3, 3, + 2, 2, 2, 3, 3, 3, 3, 3, + 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, +}; + int pick_stats_for(int x, int y, bool is_chroma) { #if FIND_OPTIMAL_STREAM_ASSIGNMENT return y * 8 + x + is_chroma * 64; #else - return std::min(x + y, 7) + is_chroma * 8; + if (is_chroma) { + return chroma_mapping[y * 8 + x] + 4; + } else { + return luma_mapping[y * 8 + x]; + } #endif } @@ -187,7 +217,7 @@ public: printf("%d: cumfreqs=%d freqs=%d prob_bits=%d\n", i, s.cum_freqs[i], s.freqs[i], prob_bits + 1); RansEncSymbolInit(&esyms[i], s.cum_freqs[i], s.freqs[i], prob_bits + 1); } - sign_bias = s.cum_freqs[256]; + sign_bias = s.cum_freqs[NUM_SYMS]; } void clear() @@ -245,7 +275,7 @@ public: RansEncPut(&rans, &ptr, k, 1, prob_bits); k = ESCAPE_LIMIT; } - RansEncPutSymbol(&rans, &ptr, &esyms[(k - 1) & 255]); + RansEncPutSymbol(&rans, &ptr, &esyms[(k - 1) & (NUM_SYMS - 1)]); if (signed_k < 0) { rans += sign_bias; } @@ -379,7 +409,7 @@ void find_optimal_stream_assignment(int base) double inv_sum[64]; for (unsigned i = 0; i < 64; ++i) { double s = 0.0; - for (unsigned k = 0; k < 256; ++k) { + for (unsigned k = 0; k < NUM_SYMS; ++k) { s += stats[i + base].freqs[k] + 0.5; } inv_sum[i] = 1.0 / s; @@ -388,7 +418,7 @@ void find_optimal_stream_assignment(int base) for (unsigned i = 0; i < 64; ++i) { for (unsigned j = 0; j < 64; ++j) { double d = 0.0; - for (unsigned k = 0; k < 256; ++k) { + for (unsigned k = 0; k < NUM_SYMS; ++k) { double p1 = (stats[i + base].freqs[k] + 0.5) * inv_sum[i]; double p2 = (stats[j + base].freqs[k] + 0.5) * inv_sum[j]; @@ -695,6 +725,12 @@ int main(int argc, char **argv) coeff_y[yb * WIDTH + xb] -= coeff_y[yb * WIDTH + (xb + 8)]; } } + for (unsigned yb = 0; yb < HEIGHT; yb += 8) { + for (unsigned xb = 0; xb < WIDTH/2 - 8; xb += 8) { + coeff_cb[yb * WIDTH/2 + xb] -= coeff_cb[yb * WIDTH/2 + (xb + 8)]; + coeff_cr[yb * WIDTH/2 + xb] -= coeff_cr[yb * WIDTH/2 + (xb + 8)]; + } + } FILE *fp = fopen("reconstructed.pgm", "wb"); fprintf(fp, "P5\n%d %d\n255\n", WIDTH, HEIGHT); @@ -746,7 +782,7 @@ int main(int argc, char **argv) k = ESCAPE_LIMIT; extra_bits += 12; // escape this one } - ++s_luma.freqs[(k - 1) & 255]; + ++s_luma.freqs[(k - 1) & (NUM_SYMS - 1)]; } } // Chroma @@ -762,8 +798,8 @@ int main(int argc, char **argv) k_cr = ESCAPE_LIMIT; extra_bits += 12; // escape this one } - ++s_chroma.freqs[(k_cb - 1) & 255]; - ++s_chroma.freqs[(k_cr - 1) & 255]; + ++s_chroma.freqs[(k_cb - 1) & (NUM_SYMS - 1)]; + ++s_chroma.freqs[(k_cr - 1) & (NUM_SYMS - 1)]; } } } @@ -778,10 +814,10 @@ int main(int argc, char **argv) #endif for (unsigned i = 0; i < 64; ++i) { - stats[i].freqs[255] /= 2; // zero, has no sign bits (yes, this is trickery) + stats[i].freqs[NUM_SYMS - 1] /= 2; // zero, has no sign bits (yes, this is trickery) stats[i].normalize_freqs(prob_scale); - stats[i].cum_freqs[256] += stats[i].freqs[255]; - stats[i].freqs[255] *= 2; + stats[i].cum_freqs[NUM_SYMS] += stats[i].freqs[NUM_SYMS - 1]; + stats[i].freqs[NUM_SYMS - 1] *= 2; } FILE *codedfp = fopen("coded.dat", "wb"); @@ -817,21 +853,20 @@ int main(int argc, char **argv) // need to reverse later rans_encoder.clear(); size_t num_bytes = 0; - for (unsigned yb = 0; yb < HEIGHT; yb += 8) { - for (unsigned xb = 0; xb < WIDTH; xb += 8) { - int k = coeff_y[(yb + y) * WIDTH + (xb + x)]; - //printf("encoding coeff %d xb,yb=%d,%d: %d\n", y*8+x, xb, yb, k); - rans_encoder.encode_coeff(k); - } - if (yb % 16 == 8) { + for (unsigned block_idx = 0; block_idx < NUM_BLOCKS; ++block_idx) { + unsigned yb = block_idx / WIDTH_BLOCKS; + unsigned xb = block_idx % WIDTH_BLOCKS; + + int k = coeff_y[(yb * 8 + y) * WIDTH + (xb * 8 + x)]; + //printf("encoding coeff %d xb,yb=%d,%d: %d\n", y*8+x, xb, yb, k); + rans_encoder.encode_coeff(k); + + if (block_idx % 320 == 319 || block_idx == NUM_BLOCKS - 1) { int l = rans_encoder.save_block(codedfp); num_bytes += l; lens.push_back(l); } } - if (HEIGHT % 16 != 0) { - num_bytes += rans_encoder.save_block(codedfp); - } tot_bytes += num_bytes; printf("coeff %d Y': %ld bytes\n", y * 8 + x, num_bytes); @@ -858,18 +893,18 @@ int main(int argc, char **argv) rans_encoder.clear(); size_t num_bytes = 0; - for (unsigned yb = 0; yb < HEIGHT; yb += 8) { - for (unsigned xb = 0; xb < WIDTH/2; xb += 8) { - int k = coeff_cb[(yb + y) * WIDTH/2 + (xb + x)]; - rans_encoder.encode_coeff(k); - } - if (yb % 16 == 8) { + for (unsigned block_idx = 0; block_idx < NUM_BLOCKS_CHROMA; ++block_idx) { + unsigned yb = block_idx / WIDTH_BLOCKS_CHROMA; + unsigned xb = block_idx % WIDTH_BLOCKS_CHROMA; + + int k = coeff_cb[(yb * 8 + y) * WIDTH/2 + (xb * 8 + x)]; + //printf("encoding coeff %d xb,yb=%d,%d: %d\n", y*8+x, xb, yb, k); + rans_encoder.encode_coeff(k); + + if (block_idx % 320 == 319 || block_idx == NUM_BLOCKS - 1) { num_bytes += rans_encoder.save_block(codedfp); } } - if (HEIGHT % 16 != 0) { - num_bytes += rans_encoder.save_block(codedfp); - } tot_bytes += num_bytes; printf("coeff %d Cb: %ld bytes\n", y * 8 + x, num_bytes); } @@ -883,18 +918,18 @@ int main(int argc, char **argv) rans_encoder.clear(); size_t num_bytes = 0; - for (unsigned yb = 0; yb < HEIGHT; yb += 8) { - for (unsigned xb = 0; xb < WIDTH/2; xb += 8) { - int k = coeff_cr[(yb + y) * WIDTH/2 + (xb + x)]; - rans_encoder.encode_coeff(k); - } - if (yb % 16 == 8) { + for (unsigned block_idx = 0; block_idx < NUM_BLOCKS_CHROMA; ++block_idx) { + unsigned yb = block_idx / WIDTH_BLOCKS_CHROMA; + unsigned xb = block_idx % WIDTH_BLOCKS_CHROMA; + + int k = coeff_cr[(yb * 8 + y) * WIDTH/2 + (xb * 8 + x)]; + //printf("encoding coeff %d xb,yb=%d,%d: %d\n", y*8+x, xb, yb, k); + rans_encoder.encode_coeff(k); + + if (block_idx % 320 == 319 || block_idx == NUM_BLOCKS - 1) { num_bytes += rans_encoder.save_block(codedfp); } } - if (HEIGHT % 16 != 0) { - num_bytes += rans_encoder.save_block(codedfp); - } tot_bytes += num_bytes; printf("coeff %d Cr: %ld bytes\n", y * 8 + x, num_bytes); }