15a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved.
27c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
37c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// This code is licensed under the same terms as WebM:
47c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  Software License Agreement:  http://www.webmproject.org/license/software/
57c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
67c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// -----------------------------------------------------------------------------
77c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
87c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// VP8Iterator: block iterator
97c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Author: Skal (pascal.massimino@gmail.com)
117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <string.h>
135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./vp8enci.h"
157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if defined(__cplusplus) || defined(c_plusplus)
177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraextern "C" {
187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif
197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// VP8Iterator
225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void InitLeft(VP8EncIterator* const it) {
257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const VP8Encoder* const enc = it->enc_;
267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  enc->y_left_[-1] = enc->u_left_[-1] = enc->v_left_[-1] =
275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      (it->y_ > 0) ? 129 : 127;
287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  memset(enc->y_left_, 129, 16);
297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  memset(enc->u_left_, 129, 8);
307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  memset(enc->v_left_, 129, 8);
317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->left_nz_[8] = 0;
327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void InitTop(VP8EncIterator* const it) {
357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const VP8Encoder* const enc = it->enc_;
365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const size_t top_size = enc->mb_w_ * 16;
377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  memset(enc->y_top_, 127, 2 * top_size);
387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_));
397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8IteratorReset(VP8EncIterator* const it) {
427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Encoder* const enc = it->enc_;
437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->x_ = 0;
447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->y_ = 0;
457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->y_offset_ = 0;
467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->uv_offset_ = 0;
477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->mb_ = enc->mb_info_;
487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->preds_ = enc->preds_;
497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->nz_ = enc->nz_;
507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->bw_ = &enc->parts_[0];
517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->done_ = enc->mb_w_* enc->mb_h_;
527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  InitTop(it);
537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  InitLeft(it);
547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  memset(it->bit_count_, 0, sizeof(it->bit_count_));
557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->do_trellis_ = 0;
567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->enc_ = enc;
607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->y_stride_  = enc->pic_->y_stride;
617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->uv_stride_ = enc->pic_->uv_stride;
627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // TODO(later): for multithreading, these should be owned by 'it'.
637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->yuv_in_   = enc->yuv_in_;
647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->yuv_out_  = enc->yuv_out_;
657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->yuv_out2_ = enc->yuv_out2_;
667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->yuv_p_    = enc->yuv_p_;
677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->lf_stats_ = enc->lf_stats_;
685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  it->percent0_ = enc->percent_;
697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorReset(it);
707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
725a50414796e9a458925c7a13a15055d02406bf43Vikas Aroraint VP8IteratorProgress(const VP8EncIterator* const it, int delta) {
735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  VP8Encoder* const enc = it->enc_;
745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (delta && enc->pic_->progress_hook) {
755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int percent = (enc->mb_h_ <= 1)
765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                      ? it->percent0_
775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                      : it->percent0_ + delta * it->y_ / (enc->mb_h_ - 1);
785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return WebPReportProgress(enc->pic_, percent, &enc->percent_);
795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return 1;
815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Import the source samples into the cache. Takes care of replicating
857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// boundary pixels if necessary.
867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
875a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ImportBlock(const uint8_t* src, int src_stride,
885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                        uint8_t* dst, int w, int h, int size) {
895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int i;
905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (i = 0; i < h; ++i) {
915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    memcpy(dst, src, w);
925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (w < size) {
935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      memset(dst + w, dst[w - 1], size - w);
945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    dst += BPS;
965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    src += src_stride;
975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (i = h; i < size; ++i) {
995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    memcpy(dst, dst - BPS, size);
1005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    dst += BPS;
1015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
1025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
1035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8IteratorImport(const VP8EncIterator* const it) {
1057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const VP8Encoder* const enc = it->enc_;
1067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int x = it->x_, y = it->y_;
1077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const WebPPicture* const pic = enc->pic_;
1085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16;
1095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8;
1105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8;
1115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint8_t* const ydst = it->yuv_in_ + Y_OFF;
1125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint8_t* const udst = it->yuv_in_ + U_OFF;
1135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint8_t* const vdst = it->yuv_in_ + V_OFF;
1147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int w = (pic->width - x * 16);
1157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int h = (pic->height - y * 16);
1167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (w > 16) w = 16;
1187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (h > 16) h = 16;
1195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Luma plane
1215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  ImportBlock(ysrc, pic->y_stride, ydst, w, h, 16);
1225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  {   // U/V planes
1245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int uv_w = (w + 1) >> 1;
1255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int uv_h = (h + 1) >> 1;
1265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    ImportBlock(usrc, pic->uv_stride, udst, uv_w, uv_h, 8);
1275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    ImportBlock(vsrc, pic->uv_stride, vdst, uv_w, uv_h, 8);
1287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
1297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
1307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
1327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Copy back the compressed samples into user space if requested.
1337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1345a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride,
1355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                        int w, int h) {
1365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (h-- > 0) {
1375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    memcpy(dst, src, w);
1385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    dst += dst_stride;
1395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    src += BPS;
1405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
1415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
1425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8IteratorExport(const VP8EncIterator* const it) {
1447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const VP8Encoder* const enc = it->enc_;
1457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (enc->config_->show_compressed) {
1467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const int x = it->x_, y = it->y_;
1477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const uint8_t* const ysrc = it->yuv_out_ + Y_OFF;
1487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const uint8_t* const usrc = it->yuv_out_ + U_OFF;
1497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const uint8_t* const vsrc = it->yuv_out_ + V_OFF;
1507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const WebPPicture* const pic = enc->pic_;
1515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16;
1525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8;
1535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    uint8_t* const vdst = pic->v + (y * pic->uv_stride + x) * 8;
1547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    int w = (pic->width - x * 16);
1557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    int h = (pic->height - y * 16);
1567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (w > 16) w = 16;
1587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (h > 16) h = 16;
1597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    // Luma plane
1615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    ExportBlock(ysrc, ydst, pic->y_stride, w, h);
1625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    {   // U/V planes
1645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int uv_w = (w + 1) >> 1;
1655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int uv_h = (h + 1) >> 1;
1665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ExportBlock(usrc, udst, pic->uv_stride, uv_w, uv_h);
1675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ExportBlock(vsrc, vdst, pic->uv_stride, uv_w, uv_h);
1687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
1697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
1707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
1717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
1737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Non-zero contexts setup/teardown
1747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Nz bits:
1767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  0  1  2  3  Y
1777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  4  5  6  7
1787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  8  9 10 11
1797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 12 13 14 15
1807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 16 17        U
1817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 18 19
1827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 20 21        V
1837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 22 23
1847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 24           DC-intra16
1857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Convert packed context to byte array
1877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#define BIT(nz, n) (!!((nz) & (1 << (n))))
1887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8IteratorNzToBytes(VP8EncIterator* const it) {
1907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const int tnz = it->nz_[0], lnz = it->nz_[-1];
1915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int* const top_nz = it->top_nz_;
1925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int* const left_nz = it->left_nz_;
1937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
1947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Top-Y
1955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[0] = BIT(tnz, 12);
1965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[1] = BIT(tnz, 13);
1975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[2] = BIT(tnz, 14);
1985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[3] = BIT(tnz, 15);
1997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Top-U
2005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[4] = BIT(tnz, 18);
2015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[5] = BIT(tnz, 19);
2027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Top-V
2035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[6] = BIT(tnz, 22);
2045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[7] = BIT(tnz, 23);
2057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // DC
2065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  top_nz[8] = BIT(tnz, 24);
2077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // left-Y
2095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  left_nz[0] = BIT(lnz,  3);
2105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  left_nz[1] = BIT(lnz,  7);
2115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  left_nz[2] = BIT(lnz, 11);
2125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  left_nz[3] = BIT(lnz, 15);
2137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // left-U
2145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  left_nz[4] = BIT(lnz, 17);
2155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  left_nz[5] = BIT(lnz, 19);
2167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // left-V
2175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  left_nz[6] = BIT(lnz, 21);
2185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  left_nz[7] = BIT(lnz, 23);
2197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // left-DC is special, iterated separately
2207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8IteratorBytesToNz(VP8EncIterator* const it) {
2237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  uint32_t nz = 0;
2245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int* const top_nz = it->top_nz_;
2255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int* const left_nz = it->left_nz_;
2267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // top
2275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  nz |= (top_nz[0] << 12) | (top_nz[1] << 13);
2285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  nz |= (top_nz[2] << 14) | (top_nz[3] << 15);
2295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  nz |= (top_nz[4] << 18) | (top_nz[5] << 19);
2305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  nz |= (top_nz[6] << 22) | (top_nz[7] << 23);
2315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  nz |= (top_nz[8] << 24);  // we propagate the _top_ bit, esp. for intra4
2327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // left
2335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  nz |= (left_nz[0] << 3) | (left_nz[1] << 7);
2345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  nz |= (left_nz[2] << 11);
2355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  nz |= (left_nz[4] << 17) | (left_nz[6] << 21);
2367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  *it->nz_ = nz;
2387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#undef BIT
2417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
2437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Advance to the next position, doing the bookeeping.
2447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraint VP8IteratorNext(VP8EncIterator* const it,
2467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora                    const uint8_t* const block_to_save) {
2477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8Encoder* const enc = it->enc_;
2487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (block_to_save) {
2497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const int x = it->x_, y = it->y_;
2507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const uint8_t* const ysrc = block_to_save + Y_OFF;
2517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    const uint8_t* const usrc = block_to_save + U_OFF;
2527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (x < enc->mb_w_ - 1) {   // left
2537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      int i;
2547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      for (i = 0; i < 16; ++i) {
2557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        enc->y_left_[i] = ysrc[15 + i * BPS];
2567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
2577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      for (i = 0; i < 8; ++i) {
2587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        enc->u_left_[i] = usrc[7 + i * BPS];
2597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora        enc->v_left_[i] = usrc[15 + i * BPS];
2607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      }
2617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      // top-left (before 'top'!)
2627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      enc->y_left_[-1] = enc->y_top_[x * 16 + 15];
2637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      enc->u_left_[-1] = enc->uv_top_[x * 16 + 0 + 7];
2647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      enc->v_left_[-1] = enc->uv_top_[x * 16 + 8 + 7];
2657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
2667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (y < enc->mb_h_ - 1) {  // top
2677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      memcpy(enc->y_top_ + x * 16, ysrc + 15 * BPS, 16);
2687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      memcpy(enc->uv_top_ + x * 16, usrc + 7 * BPS, 8 + 8);
2697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
2707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->mb_++;
2737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->preds_ += 4;
2747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->nz_++;
2757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->x_++;
2767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (it->x_ == enc->mb_w_) {
2777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->x_ = 0;
2787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->y_++;
2797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->bw_ = &enc->parts_[it->y_ & (enc->num_parts_ - 1)];
2807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->preds_ = enc->preds_ + it->y_ * 4 * enc->preds_w_;
2817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->nz_ = enc->nz_;
2827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    InitLeft(it);
2837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return (0 < --it->done_);
2857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
2887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Helper function to set mode properties
2897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) {
2917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  uint8_t* preds = it->preds_;
2925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int y;
2937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (y = 0; y < 4; ++y) {
2947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    memset(preds, mode, 4);
2957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    preds += it->enc_->preds_w_;
2967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->mb_->type_ = 1;
2987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3005a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes) {
3017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  uint8_t* preds = it->preds_;
3025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int y;
3035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (y = 4; y > 0; --y) {
3045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    memcpy(preds, modes, 4 * sizeof(*modes));
3057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    preds += it->enc_->preds_w_;
3065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    modes += 4;
3077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
3087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->mb_->type_ = 0;
3097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
3107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8SetIntraUVMode(const VP8EncIterator* const it, int mode) {
3127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->mb_->uv_mode_ = mode;
3137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
3147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8SetSkip(const VP8EncIterator* const it, int skip) {
3167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->mb_->skip_ = skip;
3177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
3187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8SetSegment(const VP8EncIterator* const it, int segment) {
3207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->mb_->segment_ = segment;
3217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
3227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
3247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Intra4x4 sub-blocks iteration
3257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
3267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  We store and update the boundary samples into an array of 37 pixels. They
3277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  are updated as we iterate and reconstructs each intra4x4 blocks in turn.
3287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  The position of the samples has the following snake pattern:
3297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
3307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36  <- Top-right
3317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// --+-----------+-----------+-----------+-----------+
3327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 15|         19|         23|         27|         31|
3337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 14|         18|         22|         26|         30|
3347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 13|         17|         21|         25|         29|
3357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28|
3367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// --+-----------+-----------+-----------+-----------+
3377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 11|         15|         19|         23|         27|
3387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 10|         14|         18|         22|         26|
3397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  9|         13|         17|         21|         25|
3407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24|
3417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// --+-----------+-----------+-----------+-----------+
3427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  7|         11|         15|         19|         23|
3437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  6|         10|         14|         18|         22|
3447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  5|          9|         13|         17|         21|
3457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  4| 5  6  7  8| 9 10 11 12|13 14 15 16|17 18 19 20|
3467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// --+-----------+-----------+-----------+-----------+
3477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  3|          7|         11|         15|         19|
3487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  2|          6|         10|         14|         18|
3497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  1|          5|          9|         13|         17|
3507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//  0| 1  2  3  4| 5  6  7  8| 9 10 11 12|13 14 15 16|
3517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// --+-----------+-----------+-----------+-----------+
3527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Array to record the position of the top sample to pass to the prediction
3547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// functions in dsp.c.
3557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic const uint8_t VP8TopLeftI4[16] = {
3567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  17, 21, 25, 29,
3577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  13, 17, 21, 25,
3587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  9,  13, 17, 21,
3597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  5,   9, 13, 17
3607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora};
3617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroravoid VP8IteratorStartI4(VP8EncIterator* const it) {
3635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const VP8Encoder* const enc = it->enc_;
3647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int i;
3657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->i4_ = 0;    // first 4x4 sub-block
3677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0];
3687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Import the boundary samples
3707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (i = 0; i < 17; ++i) {    // left
3717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->i4_boundary_[i] = enc->y_left_[15 - i];
3727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
3737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (i = 0; i < 16; ++i) {    // top
3747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i];
3757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
3767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // top-right samples have a special case on the far right of the picture
3777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (it->x_ < enc->mb_w_ - 1) {
3787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (i = 16; i < 16 + 4; ++i) {
3797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i];
3807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
3817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  } else {    // else, replicate the last valid pixel four times
3827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (i = 16; i < 16 + 4; ++i) {
3837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15];
3847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
3857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
3867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  VP8IteratorNzToBytes(it);  // import the non-zero context
3877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
3887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraint VP8IteratorRotateI4(VP8EncIterator* const it,
3907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora                        const uint8_t* const yuv_out) {
3917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  const uint8_t* const blk = yuv_out + VP8Scan[it->i4_];
3927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  uint8_t* const top = it->i4_top_;
3937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int i;
3947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
3957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // Update the cache with 7 fresh samples
3967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  for (i = 0; i <= 3; ++i) {
3977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    top[-4 + i] = blk[i + 3 * BPS];   // store future top samples
3987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
3997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if ((it->i4_ & 3) != 3) {  // if not on the right sub-blocks #3, #7, #11, #15
4007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (i = 0; i <= 2; ++i) {        // store future left samples
4017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      top[i] = blk[3 + (2 - i) * BPS];
4027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
4037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  } else {  // else replicate top-right samples, as says the specs.
4047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    for (i = 0; i <= 3; ++i) {
4057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      top[i] = top[i + 4];
4067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
4077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
4087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  // move pointers to next sub-block
4095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  ++it->i4_;
4107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (it->i4_ == 16) {    // we're done
4117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    return 0;
4127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
4137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_];
4157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return 1;
4167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
4177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
4197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if defined(__cplusplus) || defined(c_plusplus)
4217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}    // extern "C"
4227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif
423