X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=qdc.cpp;h=a0919bd750d476e0e6aace471532fafedf4df94c;hb=7417c69ce221dac7361f5982809a3833c75b5f6b;hp=951915225f8784ff1ede25c8978db48ea6395a2a;hpb=0d22d7fb73e0c14431a15c7bb0522d0691452a31;p=narabu diff --git a/qdc.cpp b/qdc.cpp index 9519152..a0919bd 100644 --- a/qdc.cpp +++ b/qdc.cpp @@ -18,8 +18,15 @@ #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) +#define BLOCKS_PER_STREAM 320 // If you set this to 1, the program will try to optimize the placement // of coefficients to rANS probability distributions. This is randomized, @@ -212,7 +219,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() @@ -270,7 +277,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; } @@ -404,7 +411,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; @@ -413,7 +420,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]; @@ -714,10 +721,35 @@ int main(int argc, char **argv) chroma_energy / (WIDTH * HEIGHT), chroma_energy_pred / (WIDTH * HEIGHT)); #endif - // DC coefficient pred from the right to left - for (unsigned yb = 0; yb < HEIGHT; yb += 8) { - for (unsigned xb = 0; xb < WIDTH - 8; xb += 8) { - coeff_y[yb * WIDTH + xb] -= coeff_y[yb * WIDTH + (xb + 8)]; + // DC coefficient pred from the right to left (within each slice) + for (unsigned block_idx = 0; block_idx < NUM_BLOCKS; block_idx += BLOCKS_PER_STREAM) { + int prev_k = 128; + + for (unsigned subblock_idx = BLOCKS_PER_STREAM; subblock_idx --> 0; ) { + unsigned yb = (block_idx + subblock_idx) / WIDTH_BLOCKS; + unsigned xb = (block_idx + subblock_idx) % WIDTH_BLOCKS; + int k = coeff_y[(yb * 8) * WIDTH + (xb * 8)]; + + coeff_y[(yb * 8) * WIDTH + (xb * 8)] = k - prev_k; + + prev_k = k; + } + } + for (unsigned block_idx = 0; block_idx < NUM_BLOCKS_CHROMA; block_idx += BLOCKS_PER_STREAM) { + int prev_k_cb = 0; + int prev_k_cr = 0; + + for (unsigned subblock_idx = BLOCKS_PER_STREAM; subblock_idx --> 0; ) { + unsigned yb = (block_idx + subblock_idx) / WIDTH_BLOCKS_CHROMA; + unsigned xb = (block_idx + subblock_idx) % WIDTH_BLOCKS_CHROMA; + int k_cb = coeff_cb[(yb * 8) * WIDTH/2 + (xb * 8)]; + int k_cr = coeff_cr[(yb * 8) * WIDTH/2 + (xb * 8)]; + + coeff_cb[(yb * 8) * WIDTH/2 + (xb * 8)] = k_cb - prev_k_cb; + coeff_cr[(yb * 8) * WIDTH/2 + (xb * 8)] = k_cr - prev_k_cr; + + prev_k_cb = k_cb; + prev_k_cr = k_cr; } } @@ -771,7 +803,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 @@ -787,8 +819,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)]; } } } @@ -803,10 +835,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"); @@ -842,21 +874,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 % BLOCKS_PER_STREAM == (BLOCKS_PER_STREAM - 1) || 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); @@ -883,18 +914,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 % BLOCKS_PER_STREAM == (BLOCKS_PER_STREAM - 1) || 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); } @@ -908,18 +939,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 % BLOCKS_PER_STREAM == (BLOCKS_PER_STREAM - 1) || 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); }