15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2011 Google Inc. All Rights Reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that can be found in the COPYING file in the root of the source
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// tree. An additional intellectual property rights grant can be found
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in the file PATENTS. All contributing project authors may
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be found in the AUTHORS file in the root of the source tree.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VP8Iterator: block iterator
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Skal (pascal.massimino@gmail.com)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8enci.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__cplusplus) || defined(c_plusplus)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VP8Iterator
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void InitLeft(VP8EncIterator* const it) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VP8Encoder* const enc = it->enc_;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->y_left_[-1] = enc->u_left_[-1] = enc->v_left_[-1] =
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (it->y_ > 0) ? 129 : 127;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(enc->y_left_, 129, 16);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(enc->u_left_, 129, 8);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(enc->v_left_, 129, 8);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->left_nz_[8] = 0;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void InitTop(VP8EncIterator* const it) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VP8Encoder* const enc = it->enc_;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t top_size = enc->mb_w_ * 16;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(enc->y_top_, 127, 2 * top_size);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_));
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8IteratorReset(VP8EncIterator* const it) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Encoder* const enc = it->enc_;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->x_ = 0;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->y_ = 0;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->y_offset_ = 0;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->uv_offset_ = 0;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->mb_ = enc->mb_info_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->preds_ = enc->preds_;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->nz_ = enc->nz_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->bw_ = &enc->parts_[0];
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->done_ = enc->mb_w_* enc->mb_h_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitTop(it);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitLeft(it);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(it->bit_count_, 0, sizeof(it->bit_count_));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->do_trellis_ = 0;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->enc_ = enc;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->y_stride_  = enc->pic_->y_stride;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->uv_stride_ = enc->pic_->uv_stride;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(later): for multithreading, these should be owned by 'it'.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->yuv_in_   = enc->yuv_in_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->yuv_out_  = enc->yuv_out_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->yuv_out2_ = enc->yuv_out2_;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->yuv_p_    = enc->yuv_p_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->lf_stats_ = enc->lf_stats_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->percent0_ = enc->percent_;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8IteratorReset(it);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VP8IteratorProgress(const VP8EncIterator* const it, int delta) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Encoder* const enc = it->enc_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delta && enc->pic_->progress_hook) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int percent = (enc->mb_h_ <= 1)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ? it->percent0_
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      : it->percent0_ + delta * it->y_ / (enc->mb_h_ - 1);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WebPReportProgress(enc->pic_, percent, &enc->percent_);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Import the source samples into the cache. Takes care of replicating
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// boundary pixels if necessary.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ImportBlock(const uint8_t* src, int src_stride,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        uint8_t* dst, int w, int h, int size) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < h; ++i) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(dst, src, w);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (w < size) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memset(dst + w, dst[w - 1], size - w);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dst += BPS;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    src += src_stride;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = h; i < size; ++i) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(dst, dst - BPS, size);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dst += BPS;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8IteratorImport(const VP8EncIterator* const it) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VP8Encoder* const enc = it->enc_;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int x = it->x_, y = it->y_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WebPPicture* const pic = enc->pic_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t* const ysrc = pic->y + (y * pic->y_stride + x) * 16;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t* const usrc = pic->u + (y * pic->uv_stride + x) * 8;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 8;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* const ydst = it->yuv_in_ + Y_OFF;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* const udst = it->yuv_in_ + U_OFF;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* const vdst = it->yuv_in_ + V_OFF;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int w = (pic->width - x * 16);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int h = (pic->height - y * 16);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (w > 16) w = 16;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (h > 16) h = 16;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Luma plane
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImportBlock(ysrc, pic->y_stride, ydst, w, h, 16);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {   // U/V planes
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int uv_w = (w + 1) >> 1;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int uv_h = (h + 1) >> 1;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImportBlock(usrc, pic->uv_stride, udst, uv_w, uv_h, 8);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImportBlock(vsrc, pic->uv_stride, vdst, uv_w, uv_h, 8);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copy back the compressed samples into user space if requested.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ExportBlock(const uint8_t* src, uint8_t* dst, int dst_stride,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int w, int h) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (h-- > 0) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(dst, src, w);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dst += dst_stride;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    src += BPS;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8IteratorExport(const VP8EncIterator* const it) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VP8Encoder* const enc = it->enc_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enc->config_->show_compressed) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int x = it->x_, y = it->y_;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8_t* const ysrc = it->yuv_out_ + Y_OFF;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8_t* const usrc = it->yuv_out_ + U_OFF;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8_t* const vsrc = it->yuv_out_ + V_OFF;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WebPPicture* const pic = enc->pic_;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const ydst = pic->y + (y * pic->y_stride + x) * 16;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const udst = pic->u + (y * pic->uv_stride + x) * 8;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const vdst = pic->v + (y * pic->uv_stride + x) * 8;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int w = (pic->width - x * 16);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int h = (pic->height - y * 16);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (w > 16) w = 16;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (h > 16) h = 16;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Luma plane
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExportBlock(ysrc, ydst, pic->y_stride, w, h);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {   // U/V planes
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int uv_w = (w + 1) >> 1;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int uv_h = (h + 1) >> 1;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExportBlock(usrc, udst, pic->uv_stride, uv_w, uv_h);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExportBlock(vsrc, vdst, pic->uv_stride, uv_w, uv_h);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Non-zero contexts setup/teardown
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Nz bits:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  0  1  2  3  Y
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  4  5  6  7
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  8  9 10 11
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 12 13 14 15
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 16 17        U
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 18 19
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 20 21        V
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 22 23
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 24           DC-intra16
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert packed context to byte array
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BIT(nz, n) (!!((nz) & (1 << (n))))
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8IteratorNzToBytes(VP8EncIterator* const it) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int tnz = it->nz_[0], lnz = it->nz_[-1];
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int* const top_nz = it->top_nz_;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int* const left_nz = it->left_nz_;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Top-Y
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[0] = BIT(tnz, 12);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[1] = BIT(tnz, 13);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[2] = BIT(tnz, 14);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[3] = BIT(tnz, 15);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Top-U
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[4] = BIT(tnz, 18);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[5] = BIT(tnz, 19);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Top-V
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[6] = BIT(tnz, 22);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[7] = BIT(tnz, 23);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DC
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  top_nz[8] = BIT(tnz, 24);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // left-Y
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_nz[0] = BIT(lnz,  3);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_nz[1] = BIT(lnz,  7);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_nz[2] = BIT(lnz, 11);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_nz[3] = BIT(lnz, 15);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // left-U
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_nz[4] = BIT(lnz, 17);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_nz[5] = BIT(lnz, 19);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // left-V
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_nz[6] = BIT(lnz, 21);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  left_nz[7] = BIT(lnz, 23);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // left-DC is special, iterated separately
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8IteratorBytesToNz(VP8EncIterator* const it) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t nz = 0;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int* const top_nz = it->top_nz_;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int* const left_nz = it->left_nz_;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // top
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nz |= (top_nz[0] << 12) | (top_nz[1] << 13);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nz |= (top_nz[2] << 14) | (top_nz[3] << 15);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nz |= (top_nz[4] << 18) | (top_nz[5] << 19);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nz |= (top_nz[6] << 22) | (top_nz[7] << 23);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nz |= (top_nz[8] << 24);  // we propagate the _top_ bit, esp. for intra4
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // left
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nz |= (left_nz[0] << 3) | (left_nz[1] << 7);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nz |= (left_nz[2] << 11);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nz |= (left_nz[4] << 17) | (left_nz[6] << 21);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *it->nz_ = nz;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef BIT
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Advance to the next position, doing the bookeeping.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VP8IteratorNext(VP8EncIterator* const it,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const uint8_t* const block_to_save) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Encoder* const enc = it->enc_;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (block_to_save) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int x = it->x_, y = it->y_;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8_t* const ysrc = block_to_save + Y_OFF;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8_t* const usrc = block_to_save + U_OFF;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (x < enc->mb_w_ - 1) {   // left
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int i;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < 16; ++i) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        enc->y_left_[i] = ysrc[15 + i * BPS];
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < 8; ++i) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        enc->u_left_[i] = usrc[7 + i * BPS];
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        enc->v_left_[i] = usrc[15 + i * BPS];
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // top-left (before 'top'!)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enc->y_left_[-1] = enc->y_top_[x * 16 + 15];
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enc->u_left_[-1] = enc->uv_top_[x * 16 + 0 + 7];
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enc->v_left_[-1] = enc->uv_top_[x * 16 + 8 + 7];
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (y < enc->mb_h_ - 1) {  // top
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(enc->y_top_ + x * 16, ysrc + 15 * BPS, 16);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(enc->uv_top_ + x * 16, usrc + 7 * BPS, 8 + 8);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->mb_++;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->preds_ += 4;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->nz_++;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->x_++;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it->x_ == enc->mb_w_) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->x_ = 0;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->y_++;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->bw_ = &enc->parts_[it->y_ & (enc->num_parts_ - 1)];
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->preds_ = enc->preds_ + it->y_ * 4 * enc->preds_w_;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->nz_ = enc->nz_;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitLeft(it);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (0 < --it->done_);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to set mode properties
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8SetIntra16Mode(const VP8EncIterator* const it, int mode) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* preds = it->preds_;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (y = 0; y < 4; ++y) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(preds, mode, 4);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preds += it->enc_->preds_w_;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->mb_->type_ = 1;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8SetIntra4Mode(const VP8EncIterator* const it, const uint8_t* modes) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* preds = it->preds_;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (y = 4; y > 0; --y) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(preds, modes, 4 * sizeof(*modes));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preds += it->enc_->preds_w_;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modes += 4;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->mb_->type_ = 0;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8SetIntraUVMode(const VP8EncIterator* const it, int mode) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->mb_->uv_mode_ = mode;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8SetSkip(const VP8EncIterator* const it, int skip) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->mb_->skip_ = skip;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8SetSegment(const VP8EncIterator* const it, int segment) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->mb_->segment_ = segment;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Intra4x4 sub-blocks iteration
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  We store and update the boundary samples into an array of 37 pixels. They
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  are updated as we iterate and reconstructs each intra4x4 blocks in turn.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  The position of the samples has the following snake pattern:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36  <- Top-right
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --+-----------+-----------+-----------+-----------+
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 15|         19|         23|         27|         31|
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 14|         18|         22|         26|         30|
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 13|         17|         21|         25|         29|
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28|
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --+-----------+-----------+-----------+-----------+
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 11|         15|         19|         23|         27|
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 10|         14|         18|         22|         26|
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  9|         13|         17|         21|         25|
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24|
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --+-----------+-----------+-----------+-----------+
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  7|         11|         15|         19|         23|
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  6|         10|         14|         18|         22|
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  5|          9|         13|         17|         21|
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  4| 5  6  7  8| 9 10 11 12|13 14 15 16|17 18 19 20|
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --+-----------+-----------+-----------+-----------+
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  3|          7|         11|         15|         19|
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  2|          6|         10|         14|         18|
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  1|          5|          9|         13|         17|
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  0| 1  2  3  4| 5  6  7  8| 9 10 11 12|13 14 15 16|
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --+-----------+-----------+-----------+-----------+
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Array to record the position of the top sample to pass to the prediction
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions in dsp.c.
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uint8_t VP8TopLeftI4[16] = {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  17, 21, 25, 29,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  13, 17, 21, 25,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  9,  13, 17, 21,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  5,   9, 13, 17
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8IteratorStartI4(VP8EncIterator* const it) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VP8Encoder* const enc = it->enc_;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->i4_ = 0;    // first 4x4 sub-block
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[0];
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Import the boundary samples
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < 17; ++i) {    // left
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->i4_boundary_[i] = enc->y_left_[15 - i];
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < 16; ++i) {    // top
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i];
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // top-right samples have a special case on the far right of the picture
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it->x_ < enc->mb_w_ - 1) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 16; i < 16 + 4; ++i) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it->i4_boundary_[17 + i] = enc->y_top_[it->x_ * 16 + i];
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {    // else, replicate the last valid pixel four times
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 16; i < 16 + 4; ++i) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it->i4_boundary_[17 + i] = it->i4_boundary_[17 + 15];
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8IteratorNzToBytes(it);  // import the non-zero context
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VP8IteratorRotateI4(VP8EncIterator* const it,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const uint8_t* const yuv_out) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t* const blk = yuv_out + VP8Scan[it->i4_];
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* const top = it->i4_top_;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the cache with 7 fresh samples
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i <= 3; ++i) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    top[-4 + i] = blk[i + 3 * BPS];   // store future top samples
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((it->i4_ & 3) != 3) {  // if not on the right sub-blocks #3, #7, #11, #15
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i <= 2; ++i) {        // store future left samples
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      top[i] = blk[3 + (2 - i) * BPS];
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {  // else replicate top-right samples, as says the specs.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i <= 3; ++i) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      top[i] = top[i + 4];
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // move pointers to next sub-block
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++it->i4_;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it->i4_ == 16) {    // we're done
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it->i4_top_ = it->i4_boundary_ + VP8TopLeftI4[it->i4_];
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__cplusplus) || defined(c_plusplus)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}    // extern "C"
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
425