Image-WebP

 view release on metacpan or  search on metacpan

webp-src/src/dec/vp8.c  view on Meta::CPAN

      }
    } else {
      const uint8_t* tab;
      const int bit1 = VP8GetBit(br, p[8]);
      const int bit0 = VP8GetBit(br, p[9 + bit1]);
      const int cat = 2 * bit1 + bit0;
      v = 0;
      for (tab = kCat3456[cat]; *tab; ++tab) {
        v += v + VP8GetBit(br, *tab);
      }
      v += 3 + (8 << cat);
    }
  }
  return v;
}

// Returns the position of the last non-zero coeff plus one
// (and 0 if there's no coeff at all)
static int GetCoeffs(VP8BitReader* const br, ProbaArray prob,
                     int ctx, const quant_t dq, int n, int16_t* out) {
  // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'.
  const uint8_t* p = prob[n][ctx];
  if (!VP8GetBit(br, p[0])) {   // first EOB is more a 'CBP' bit.
    return 0;
  }
  for (; n < 16; ++n) {
    const ProbaCtxArray p_ctx = prob[kBands[n + 1]];
    if (!VP8GetBit(br, p[1])) {
      p = p_ctx[0];
    } else {  // non zero coeff
      int v;
      if (!VP8GetBit(br, p[2])) {
        v = 1;
        p = p_ctx[1];
      } else {
        v = GetLargeValue(br, p);
        p = p_ctx[2];
      }
      out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
      if (n < 15 && !VP8GetBit(br, p[0])) {   // EOB
        return n + 1;
      }
    }
  }
  return 16;
}

// Alias-safe way of converting 4bytes to 32bits.
typedef union {
  uint8_t  i8[4];
  uint32_t i32;
} PackedNz;

// Table to unpack four bits into four bytes
static const PackedNz kUnpackTab[16] = {
  {{0, 0, 0, 0}},  {{1, 0, 0, 0}},  {{0, 1, 0, 0}},  {{1, 1, 0, 0}},
  {{0, 0, 1, 0}},  {{1, 0, 1, 0}},  {{0, 1, 1, 0}},  {{1, 1, 1, 0}},
  {{0, 0, 0, 1}},  {{1, 0, 0, 1}},  {{0, 1, 0, 1}},  {{1, 1, 0, 1}},
  {{0, 0, 1, 1}},  {{1, 0, 1, 1}},  {{0, 1, 1, 1}},  {{1, 1, 1, 1}} };

// Macro to pack four LSB of four bytes into four bits.
#if defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || \
    defined(__BIG_ENDIAN__)
#define PACK_CST 0x08040201U
#else
#define PACK_CST 0x01020408U
#endif
#define PACK(X, S) ((((X).i32 * PACK_CST) & 0xff000000) >> (S))

static void ParseResiduals(VP8Decoder* const dec,
                           VP8MB* const mb, VP8BitReader* const token_br) {
  int out_t_nz, out_l_nz, first;
  ProbaArray ac_prob;
  const VP8QuantMatrix* q = &dec->dqm_[dec->segment_];
  int16_t* dst = dec->coeffs_;
  VP8MB* const left_mb = dec->mb_info_ - 1;
  PackedNz nz_ac, nz_dc;
  PackedNz tnz, lnz;
  uint32_t non_zero_ac = 0;
  uint32_t non_zero_dc = 0;
  int x, y, ch;

  nz_dc.i32 = nz_ac.i32 = 0;
  memset(dst, 0, 384 * sizeof(*dst));
  if (!dec->is_i4x4_) {    // parse DC
    int16_t dc[16] = { 0 };
    const int ctx = mb->dc_nz_ + left_mb->dc_nz_;
    mb->dc_nz_ = left_mb->dc_nz_ =
        (GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[1],
                   ctx, q->y2_mat_, 0, dc) > 0);
    first = 1;
    ac_prob = (ProbaArray)dec->proba_.coeffs_[0];
    VP8TransformWHT(dc, dst);
  } else {
    first = 0;
    ac_prob = (ProbaArray)dec->proba_.coeffs_[3];
  }

  tnz = kUnpackTab[mb->nz_ & 0xf];
  lnz = kUnpackTab[left_mb->nz_ & 0xf];
  for (y = 0; y < 4; ++y) {
    int l = lnz.i8[y];
    for (x = 0; x < 4; ++x) {
      const int ctx = l + tnz.i8[x];
      const int nz = GetCoeffs(token_br, ac_prob, ctx,
                               q->y1_mat_, first, dst);
      tnz.i8[x] = l = (nz > 0);
      nz_dc.i8[x] = (dst[0] != 0);
      nz_ac.i8[x] = (nz > 1);
      dst += 16;
    }
    lnz.i8[y] = l;
    non_zero_dc |= PACK(nz_dc, 24 - y * 4);
    non_zero_ac |= PACK(nz_ac, 24 - y * 4);
  }
  out_t_nz = PACK(tnz, 24);
  out_l_nz = PACK(lnz, 24);

  tnz = kUnpackTab[mb->nz_ >> 4];
  lnz = kUnpackTab[left_mb->nz_ >> 4];
  for (ch = 0; ch < 4; ch += 2) {



( run in 0.810 second using v1.01-cache-2.11-cpan-39bf76dae61 )