void BvcEncoder::encode_coef(int v, int active) { int sign = v >> 7; v &= 0x7f; if ((v & ~active) != 0 || active == 0) abort(); int n; for (n = 0; ((1 << n) & active) != 0; ++n) ; PUT_BITS(v, n, nbb_, bb_, bs_); if (v != 0) { PUT_BITS(sign, 1, nbb_, bb_, bs_); } }
/* * "active" is of form 000...011...1 */ int BvcEncoder::prune_layers(int active, int cm) { if (active == 0) abort(); int next; int n = 0; while (((next = active >> 1) & cm) == cm) { ++n; active = next; if (active == 0) break; } if (active == 0) { PUT_BITS(0, n, nbb_, bb_, bs_); } else { PUT_BITS(1, n + 1, nbb_, bb_, bs_); } return (active); }
flush_bits (working_state *state) { JOCTET _buffer[BUFSIZE], *buffer; size_t put_buffer; int put_bits; size_t bytes, bytestocopy; int localbuf = 0; put_buffer = state->cur.put_buffer; put_bits = state->cur.put_bits; LOAD_BUFFER() /* fill any partial byte with ones */ PUT_BITS(0x7F, 7) while (put_bits >= 8) EMIT_BYTE() state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ state->cur.put_bits = 0; STORE_BUFFER() return TRUE; }
/*XXX*/ int BvcEncoder::consume(const VideoFrame* vf) { if (!samesize(vf)) size(vf->width_, vf->height_); YuvFrame* p = (YuvFrame*)vf; tx_->flush(); int layer = p->layer_; u_char* frm = (u_char*)p->bp_; const u_char* chm = frm + framesize_; blkno_ = -1; pktbuf* pb = getpkt(p->ts_, layer); const u_int8_t* crv = p->crvec_; memset(&b, 0, sizeof(b)); #ifdef SBC_STAT if (f[0] == 0) { f[0] = fopen("sbc0", "w"); f[1] = fopen("sbc1", "w"); f[2] = fopen("sbc2", "w"); f[3] = fopen("sbc3", "w"); } #endif int cc = 0; int blkw = width_ >> 4; int blkh = height_ >> 4; int blkno = 0; for (int y = 0; y < blkh; ++y) { for (int x = 0; x < blkw; ++blkno, frm += 16, chm += 8, ++x, ++crv) { int s = crv[0]; if ((s & CR_SEND) == 0) continue; #define MAXMBSIZE (16*16+2*8*8+4) if (bs_ + MAXMBSIZE >= es_) { cc += flush(pb, 0); pb = getpkt(p->ts_, layer); } int dblk = blkno - blkno_; blkno_ = blkno; if (dblk <= 0) abort(); if (dblk == 1) { PUT_BITS(1, 1, nbb_, bb_, bs_); b.mba += 1; } else if (dblk <= 17) { PUT_BITS(0x10 | (dblk - 2), 6, nbb_, bb_, bs_); b.mba += 6; } else { PUT_BITS(dblk, 13, nbb_, bb_, bs_); b.mba += 13; } /* * Deal with boundaries of image. This is * simply ugly, but it's the price we have * to pay for using a four tap filter stage. * For the 1-3-3-1 filter set, we use symmetric * extension at both analysis and synthesis * to give perfect reconstruction. * If we're at the top of the image, we simply * copy the top row up (since the grabber's * reserve one line of extra space). Otherwise, * we save pixels, do the symmetrization, * encode the block, then restore the pixels. */ u_char ysave[16]; u_char xsave[16]; if (y == 0) memcpy(frm - width_, frm, 16); else if (y == blkh - 1) { u_char* p = frm + (width_ << 4); memcpy(ysave, p, 16); memcpy(p, p - width_, 16); } if (x == 0) { u_char* s = xsave; u_char* p = frm; for (int k = 0; k < 16; ++k) { *s++ = p[-1]; p[-1] = p[0]; p += width_; } } else if (x == blkw - 1) { u_char* s = xsave; u_char* p = frm + 16; for (int k = 0; k < 16; ++k) { *s++ = p[0]; p[0] = p[-1]; p += width_; } } encode_block(frm); encode_color(chm); encode_color(chm + (framesize_ >> 2)); /* * Now restore the pixels. We don't bother * with the "y = 0" case because the affected * memory will not be used. */ if (y == blkh - 1) { u_char* p = frm + (width_ << 4); memcpy(p, ysave, 16); } if (x == 0) { u_char* s = xsave; u_char* p = frm; for (int k = 0; k < 16; ++k) { p[-1] = *s++; p += width_; } } else if (x == blkw - 1) { u_char* s = xsave; u_char* p = frm + 16; for (int k = 0; k < 16; ++k) { p[0] = *s++; p += width_; } } } frm += 15 * width_; chm += 7 * (width_ >> 1); } #ifdef notdef double t = b.dc + b.mba; for (int i = 0; i < 4; ++i) t += b.zt[i] + b.sbc[i] + b.sbz[i]; printf("dc\t%.3f\n", b.dc / t); printf("mba\t%.3f\n", b.mba / t); for (i = 0; i < 4; ++i) { printf("sbc%d\t%.3f (%.3f)\n", i, (b.sbc[i] + b.sbz[i]) / t, b.sbz[i] / double(b.sbc[i] + b.sbz[i])); printf("zt%d\t%.3f\n", i, b.zt[i] / t); } #endif cc += flush(pb, 1); return (cc); }
void BvcEncoder::encode_sbc(const u_int8_t* p) { #ifdef notyet u_int bb = bb_; int nbb = nbb_; #endif u_char stack[3*64]; u_char* sp = stack; u_char children[64]; u_char grandchildren[64]; smquant((u_int8_t*)p, qs_); find_children(p, children); find_grandchildren(children, grandchildren); /*XXX dpcm & entropy */ PUT_BITS(p[0], 8, nbb_, bb_, bs_); b.dc += 8; int active = prune_layers(0x7f, children[0]); if (active == 0) return; int ga = prune_layers(active, grandchildren[0]); *sp++ = ga; *sp++ = active|0x80; *sp++ = 9; *sp++ = ga; *sp++ = active|0x80; *sp++ = 8; *sp++ = ga; *sp++ = active|0x80; *sp++ = 1; do { int k = *--sp; int active = *--sp; encode_coef(p[k], active & 0x7f); if (active & 0x80) { active = *--sp; if (active & 0x80) abort(); if (active == 0) continue; active = prune_layers(active, children[k]); if (active == 0) continue; k = child[k]; if (k < 64) { *sp++ = active; *sp++ = k + 9; *sp++ = active; *sp++ = k + 8; *sp++ = active; *sp++ = k + 1; *sp++ = active; *sp++ = k; } else { #ifndef HAVE_HH if (k >= 192) k -= 156; #endif encode_coef(p[k], active); encode_coef(p[k + 1], active); encode_coef(p[k + 8], active); encode_coef(p[k + 9], active); } } else { active = prune_layers(active, children[k]); if (active == 0) continue; int c = child[k]; if (c < 64) { int ga = prune_layers(active, grandchildren[k]); k = c; *sp++ = ga; *sp++ = active|0x80; *sp++ = k + 9; *sp++ = ga; *sp++ = active|0x80; *sp++ = k + 8; *sp++ = ga; *sp++ = active|0x80; *sp++ = k + 1; *sp++ = ga; *sp++ = active|0x80; *sp++ = k; } else { k = c; #ifndef HAVE_HH if (k >= 192) k -= 156; #endif encode_coef(p[k], active); encode_coef(p[k + 1], active); encode_coef(p[k + 8], active); encode_coef(p[k + 9], active); } } } while (sp > stack); #ifdef notyet bb_ = bb; nbb_ = nbb; #endif }
/* * get_segment grabs another record segment from the data stream. * fio->scc will be set as follows: * SCCMIDL fio->segbits = fio_cnt (all or rest of data in fio * buffer) and no EOR was found * SCCFULL an EOR was found * * return values are as follows: * 2 encountered end of data -> stat will be set * 1 encountered end of file -> stat will be set * 0 segment (or part) is received -> stat will NOT be set * ERR encountered an error -> stat will be set */ static int get_segment(struct fdinfo *fio, struct ffsw *stat) { long tword; int left; ssize_t ret; unsigned char *cp; bitptr tbptr; struct text_f *text_info; text_info = (struct text_f *)fio->lyr_info; fio->lastscc = fio->scc; /* * If buffer is empty, or not enough to hold entire EOF marker, * get more data. */ if (fio->_cnt == 0 || fio->_cnt < text_info->eof_len) { /* * If num of bits not enough to hold EOF, move remainder * to base of buffer and read in at base+remainder. Adjust * pointers and counts accordingly. */ left = 0; if (fio->_cnt > 0) { bitptr tptr; left = fio->_cnt; /* * Move tail of data to the first word of the * buffer (right justified). */ GET_BITS(tword, fio->_ptr, left); SET_BPTR(tptr, fio->_base); PUT_BITS(tptr, tword, left); SET_BPTR(fio->_ptr, INC_BPTR(fio->_base, left)); } else fio->_ptr = fio->_base; /* reset _ptr */ zero = 0; READBLK(ret, fio, (size_t)((uint64)fio->maxblksize >> 3), stat, PARTIAL, &zero); /* * Add back in the 'extra' data */ fio->_ptr = fio->_base; /* reset _ptr */ fio->_cnt = fio->_cnt + left; if (ret < (ssize_t)0) return(ERR); if (zero != 0) ERETURN(stat, FDC_ERR_UBC, 0); if (fio->_cnt == 0) /* must be at EOD */ { return(setend(fio, stat)); } }
/* * Much of the compression algorithm used here is based very loosely on ideas * from isdn_lzscomp.c by Andre Beck: http://micky.ibh.de/~beck/stuff/lzs4i4l/ */ int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen) { int length, offset; int inpos = 0, outpos = 0; uint16_t longest_match_len; uint16_t hofs, longest_match_ofs; uint16_t hash; uint32_t outbits = 0; int nr_outbits = 0; /* * This is theoretically a hash. But RAM is cheap and just loading the * 16-bit value and using it as a hash is *much* faster. */ #define HASH_BITS 16 #define HASH_TABLE_SIZE (1ULL << HASH_BITS) #define HASH(p) (((struct oc_packed_uint16_t *)(p))->d) /* * There are two data structures for tracking the history. The first * is the true hash table, an array indexed by the hash value described * above. It yields the offset in the input buffer at which the given * hash was most recently seen. We use INVALID_OFS (0xffff) for none * since we know IP packets are limited to 64KiB and we can never be * *starting* a match at the penultimate byte of the packet. */ #define INVALID_OFS 0xffff uint16_t hash_table[HASH_TABLE_SIZE]; /* Buffer offset for first match */ /* * The second data structure allows us to find the previous occurrences * of the same hash value. It is a ring buffer containing links only for * the latest MAX_HISTORY bytes of the input. The lookup for a given * offset will yield the previous offset at which the same data hash * value was found. */ #define MAX_HISTORY (1<<11) /* Highest offset LZS can represent is 11 bits */ uint16_t hash_chain[MAX_HISTORY]; /* Just in case anyone tries to use this in a more general-purpose * scenario... */ if (srclen > INVALID_OFS + 1) return -EFBIG; /* No need to initialise hash_chain since we can only ever follow * links to it that have already been initialised. */ memset(hash_table, 0xff, sizeof(hash_table)); while (inpos < srclen - 2) { hash = HASH(src + inpos); hofs = hash_table[hash]; hash_chain[inpos & (MAX_HISTORY - 1)] = hofs; hash_table[hash] = inpos; if (hofs == INVALID_OFS || hofs + MAX_HISTORY <= inpos) { PUT_BITS(9, src[inpos]); inpos++; continue; } /* Since the hash is 16-bits, we *know* the first two bytes match */ longest_match_len = 2; longest_match_ofs = hofs; for (; hofs != INVALID_OFS && hofs + MAX_HISTORY > inpos; hofs = hash_chain[hofs & (MAX_HISTORY - 1)]) { /* We only get here if longest_match_len is >= 2. We need to find a match of longest_match_len + 1 for it to be interesting. */ if (!memcmp(src + hofs + 2, src + inpos + 2, longest_match_len - 1)) { longest_match_ofs = hofs; do { longest_match_len++; /* If we cannot *have* a longer match because we're at the * end of the input, stop looking */ if (longest_match_len + inpos == srclen) goto got_match; } while (src[longest_match_len + inpos] == src[longest_match_len + hofs]); } /* Typical compressor tuning would have a break out of the loop here depending on the number of potential match locations we've tried, or a value of longest_match_len that's considered "good enough" so we stop looking for something better. We could also do a hybrid where we count the total bytes compared, so 5 attempts to find a match better than 10 bytes is worth the same as 10 attempts to find a match better than 5 bytes. Or something. Anyway, we currently don't give up until we run out of reachable history — maximal compression. */ } got_match: /* Output offset, as 7-bit or 11-bit as appropriate */ offset = inpos - longest_match_ofs; length = longest_match_len; if (offset < 0x80) PUT_BITS(9, 0x180 | offset); else PUT_BITS(13, 0x1000 | offset); /* Output length */ if (length < 5) PUT_BITS(2, length - 2); else if (length < 8) PUT_BITS(4, length + 7); else { length += 7; while (length >= 30) { PUT_BITS(8, 0xff); length -= 30; } if (length >= 15) PUT_BITS(8, 0xf0 + length - 15); else PUT_BITS(4, length); } /* If we're already done, don't bother updating the hash tables. */ if (inpos + longest_match_len >= srclen - 2) { inpos += longest_match_len; break; } /* We already added the first byte to the hash tables. Add the rest. */ inpos++; while (--longest_match_len) { hash = HASH(src + inpos); hash_chain[inpos & (MAX_HISTORY - 1)] = hash_table[hash]; hash_table[hash] = inpos++; } } /* Special cases at the end */ if (inpos == srclen - 2) { hash = HASH(src + inpos); hofs = hash_table[hash]; if (hofs != INVALID_OFS && hofs + MAX_HISTORY > inpos) { offset = inpos - hofs; if (offset < 0x80) PUT_BITS(9, 0x180 | offset); else PUT_BITS(13, 0x1000 | offset); /* The length is 2 bytes */ PUT_BITS(2, 0); } else { PUT_BITS(9, src[inpos]); PUT_BITS(9, src[inpos + 1]); } } else if (inpos == srclen - 1) { PUT_BITS(9, src[inpos]); } /* End marker, with 7 trailing zero bits to ensure that it's flushed. */ PUT_BITS(16, 0xc000); return outpos; }
encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) { int temp, temp2, temp3; int nbits; int r, code, size; JOCTET _buffer[BUFSIZE], *buffer; size_t put_buffer; int put_bits; int code_0xf0 = actbl->ehufco[0xf0], size_0xf0 = actbl->ehufsi[0xf0]; size_t bytes, bytestocopy; int localbuf = 0; put_buffer = state->cur.put_buffer; put_bits = state->cur.put_bits; LOAD_BUFFER() /* Encode the DC coefficient difference per section F.1.2.1 */ temp = temp2 = block[0] - last_dc_val; /* This is a well-known technique for obtaining the absolute value without a * branch. It is derived from an assembly language technique presented in * "How to Optimize for the Pentium Processors", Copyright (c) 1996, 1997 by * Agner Fog. */ temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); temp ^= temp3; temp -= temp3; /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2 += temp3; /* Find the number of bits needed for the magnitude of the coefficient */ nbits = JPEG_NBITS(temp); /* Emit the Huffman-coded symbol for the number of bits */ code = dctbl->ehufco[nbits]; size = dctbl->ehufsi[nbits]; PUT_BITS(code, size) CHECKBUF15() /* Mask off any extra bits in code */ temp2 &= (((INT32) 1)<<nbits) - 1; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ PUT_BITS(temp2, nbits) CHECKBUF15() /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ /* Manually unroll the k loop to eliminate the counter variable. This * improves performance greatly on systems with a limited number of * registers (such as x86.) */ #define kloop(jpeg_natural_order_of_k) { \ if ((temp = block[jpeg_natural_order_of_k]) == 0) { \ r++; \ } else { \ temp2 = temp; \ /* Branch-less absolute value, bitwise complement, etc., same as above */ \ temp3 = temp >> (CHAR_BIT * sizeof(int) - 1); \ temp ^= temp3; \ temp -= temp3; \ temp2 += temp3; \ nbits = JPEG_NBITS_NONZERO(temp); \ /* if run length > 15, must emit special run-length-16 codes (0xF0) */ \ while (r > 15) { \ EMIT_BITS(code_0xf0, size_0xf0) \ r -= 16; \ } \ /* Emit Huffman symbol for run length / number of bits */ \ temp3 = (r << 4) + nbits; \ code = actbl->ehufco[temp3]; \ size = actbl->ehufsi[temp3]; \ EMIT_CODE(code, size) \ r = 0; \ } \ } /* One iteration for each value in jpeg_natural_order[] */ kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3); kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18); kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26); kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27); kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21); kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57); kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15); kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58); kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39); kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47); kloop(55); kloop(62); kloop(63); /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) { code = actbl->ehufco[0]; size = actbl->ehufsi[0]; EMIT_BITS(code, size) }