int VP8IteratorProgress(VP8EncIterator* it, int delta) { if (delta && it.enc_.pic_.progress_hook) { int percent = it.percent0_ + delta * it.y_ / (it.enc_.mb_h_ - 1); return WebPReportProgress(it.enc_, percent); } return 1; }
//------------------------------------------------------------------------------ // VP8Iterator //------------------------------------------------------------------------------ static void InitLeft(VP8EncIterator* it) { VP8Encoder* enc = it.enc_; enc.y_left_[-1] = enc.u_left_[-1] = enc.v_left_[-1] = (it.y_ > 0) ? 129 : 127; memset(enc.y_left_, 129, 16); memset(enc.u_left_, 129, 8); memset(enc.v_left_, 129, 8); it.left_nz_[8] = 0; }
void VP8IteratorInit(VP8Encoder* enc, VP8EncIterator* it) { it.enc_ = enc; it.y_stride_ = enc.pic_.y_stride; it.uv_stride_ = enc.pic_.uv_stride; // TODO(later): for multithreading, these should be owned by 'it'. it.yuv_in_ = enc.yuv_in_; it.yuv_out_ = enc.yuv_out_; it.yuv_out2_ = enc.yuv_out2_; it.yuv_p_ = enc.yuv_p_; it.lf_stats_ = enc.lf_stats_; it.percent0_ = enc.percent_; VP8IteratorReset(it); }
void VP8IteratorReset(VP8EncIterator* it) { VP8Encoder* enc = it.enc_; it.x_ = 0; it.y_ = 0; it.y_offset_ = 0; it.uv_offset_ = 0; it.mb_ = enc.mb_info_; it.preds_ = enc.preds_; it.nz_ = enc.nz_; it.bw_ = &enc.parts_[0]; it.done_ = enc.mb_w_* enc.mb_h_; InitTop(it); InitLeft(it); memset(it.bit_count_, 0, sizeof(it.bit_count_)); it.do_trellis_ = 0; }
void VP8IteratorImport(VP8EncIterator* it) { VP8Encoder* enc = it.enc_; int x = it.x_, y = it.y_; WebPPicture* pic = enc.pic_; byte* ysrc = pic.y + (y * pic.y_stride + x) * 16; byte* usrc = pic.u + (y * pic.uv_stride + x) * 8; byte* vsrc = pic.v + (y * pic.uv_stride + x) * 8; byte* ydst = it.yuv_in_ + Y_OFF; byte* udst = it.yuv_in_ + U_OFF; byte* vdst = it.yuv_in_ + V_OFF; int w = (pic.width - x * 16); int h = (pic.height - y * 16); if (w > 16) w = 16; if (h > 16) h = 16; // Luma plane ImportBlock(ysrc, pic.y_stride, ydst, w, h, 16); { // U/V planes int uv_w = (w + 1) >> 1; int uv_h = (h + 1) >> 1; ImportBlock(usrc, pic.uv_stride, udst, uv_w, uv_h, 8); ImportBlock(vsrc, pic.uv_stride, vdst, uv_w, uv_h, 8); } }
void VP8SetSegment(VP8EncIterator* it, int segment) { it.mb_.segment_ = segment; }
void VP8SetSkip(VP8EncIterator* it, int skip) { it.mb_.skip_ = skip; }
void VP8SetIntraUVMode(VP8EncIterator* it, int mode) { it.mb_.uv_mode_ = mode; }
void VP8SetIntra4Mode(VP8EncIterator* it, byte* modes) { byte* preds = it.preds_; int y; for (y = 4; y > 0; --y) { memcpy(preds, modes, 4 * sizeof(*modes)); preds += it.enc_.preds_w_; modes += 4; } it.mb_.type_ = 0; }
//------------------------------------------------------------------------------ // Helper function to set mode properties void VP8SetIntra16Mode(VP8EncIterator* it, int mode) { byte* preds = it.preds_; int y; for (y = 0; y < 4; ++y) { memset(preds, mode, 4); preds += it.enc_.preds_w_; } it.mb_.type_ = 1; }
static void InitTop(VP8EncIterator* it) { VP8Encoder* enc = it.enc_; uint top_size = enc.mb_w_ * 16; memset(enc.y_top_, 127, 2 * top_size); memset(enc.nz_, 0, enc.mb_w_ * sizeof(*enc.nz_)); }
//------------------------------------------------------------------------------ // Advance to the next position, doing the bookeeping. int VP8IteratorNext(VP8EncIterator* it, byte* block_to_save) { VP8Encoder* enc = it.enc_; if (block_to_save) { int x = it.x_, y = it.y_; byte* ysrc = block_to_save + Y_OFF; byte* usrc = block_to_save + U_OFF; if (x < enc.mb_w_ - 1) { // left int i; for (i = 0; i < 16; ++i) { enc.y_left_[i] = ysrc[15 + i * BPS]; } for (i = 0; i < 8; ++i) { enc.u_left_[i] = usrc[7 + i * BPS]; enc.v_left_[i] = usrc[15 + i * BPS]; } // top-left (before 'top'!) enc.y_left_[-1] = enc.y_top_[x * 16 + 15]; enc.u_left_[-1] = enc.uv_top_[x * 16 + 0 + 7]; enc.v_left_[-1] = enc.uv_top_[x * 16 + 8 + 7]; } if (y < enc.mb_h_ - 1) { // top memcpy(enc.y_top_ + x * 16, ysrc + 15 * BPS, 16); memcpy(enc.uv_top_ + x * 16, usrc + 7 * BPS, 8 + 8); } } it.mb_++; it.preds_ += 4; it.nz_++; it.x_++; if (it.x_ == enc.mb_w_) { it.x_ = 0; it.y_++; it.bw_ = &enc.parts_[it.y_ & (enc.num_parts_ - 1)]; it.preds_ = enc.preds_ + it.y_ * 4 * enc.preds_w_; it.nz_ = enc.nz_; InitLeft(it); } return (0 < --it.done_); }
void VP8IteratorBytesToNz(VP8EncIterator* it) { uint nz = 0; int* top_nz = it.top_nz_; int* left_nz = it.left_nz_; // top nz |= (top_nz[0] << 12) | (top_nz[1] << 13); nz |= (top_nz[2] << 14) | (top_nz[3] << 15); nz |= (top_nz[4] << 18) | (top_nz[5] << 19); nz |= (top_nz[6] << 22) | (top_nz[7] << 23); nz |= (top_nz[8] << 24); // we propagate the _top_ bit, esp. for intra4 // left nz |= (left_nz[0] << 3) | (left_nz[1] << 7); nz |= (left_nz[2] << 11); nz |= (left_nz[4] << 17) | (left_nz[6] << 21); *it.nz_ = nz; }
void VP8IteratorNzToBytes(VP8EncIterator* it) { int tnz = it.nz_[0], lnz = it.nz_[-1]; int* top_nz = it.top_nz_; int* left_nz = it.left_nz_; // Top-Y top_nz[0] = BIT(tnz, 12); top_nz[1] = BIT(tnz, 13); top_nz[2] = BIT(tnz, 14); top_nz[3] = BIT(tnz, 15); // Top-U top_nz[4] = BIT(tnz, 18); top_nz[5] = BIT(tnz, 19); // Top-V top_nz[6] = BIT(tnz, 22); top_nz[7] = BIT(tnz, 23); // DC top_nz[8] = BIT(tnz, 24); // left-Y left_nz[0] = BIT(lnz, 3); left_nz[1] = BIT(lnz, 7); left_nz[2] = BIT(lnz, 11); left_nz[3] = BIT(lnz, 15); // left-U left_nz[4] = BIT(lnz, 17); left_nz[5] = BIT(lnz, 19); // left-V left_nz[6] = BIT(lnz, 21); left_nz[7] = BIT(lnz, 23); // left-DC is special, iterated separately }
void VP8IteratorExport(VP8EncIterator* it) { VP8Encoder* enc = it.enc_; if (enc.config_.show_compressed) { int x = it.x_, y = it.y_; byte* ysrc = it.yuv_out_ + Y_OFF; byte* usrc = it.yuv_out_ + U_OFF; byte* vsrc = it.yuv_out_ + V_OFF; WebPPicture* pic = enc.pic_; byte* ydst = pic.y + (y * pic.y_stride + x) * 16; byte* udst = pic.u + (y * pic.uv_stride + x) * 8; byte* vdst = pic.v + (y * pic.uv_stride + x) * 8; int w = (pic.width - x * 16); int h = (pic.height - y * 16); if (w > 16) w = 16; if (h > 16) h = 16; // Luma plane ExportBlock(ysrc, ydst, pic.y_stride, w, h); { // U/V planes int uv_w = (w + 1) >> 1; int uv_h = (h + 1) >> 1; ExportBlock(usrc, udst, pic.uv_stride, uv_w, uv_h); ExportBlock(vsrc, vdst, pic.uv_stride, uv_w, uv_h); } } }