/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/desktop_capture/differ.h"

#include "string.h"

#include "webrtc/modules/desktop_capture/differ_block.h"
#include "webrtc/system_wrappers/include/logging.h"

namespace webrtc {

Differ::Differ(int width, int height, int bpp, int stride) {
  // Dimensions of screen.
  width_ = width;
  height_ = height;
  bytes_per_pixel_ = bpp;
  bytes_per_row_ = stride;

  // Calc number of blocks (full and partial) required to cover entire image.
  // One additional row/column is added as a boundary on the right & bottom.
  diff_info_width_ = ((width_ + kBlockSize - 1) / kBlockSize) + 1;
  diff_info_height_ = ((height_ + kBlockSize - 1) / kBlockSize) + 1;
  diff_info_size_ = diff_info_width_ * diff_info_height_ * sizeof(bool);
  diff_info_.reset(new bool[diff_info_size_]);
}

Differ::~Differ() {}

void Differ::CalcDirtyRegion(const uint8_t* prev_buffer,
                             const uint8_t* curr_buffer,
                             DesktopRegion* region) {
  // Identify all the blocks that contain changed pixels.
  MarkDirtyBlocks(prev_buffer, curr_buffer);

  // Now that we've identified the blocks that have changed, merge adjacent
  // blocks to minimize the number of rects that we return.
  MergeBlocks(region);
}

void Differ::MarkDirtyBlocks(const uint8_t* prev_buffer,
                             const uint8_t* curr_buffer) {
  memset(diff_info_.get(), 0, diff_info_size_);

  // Calc number of full blocks.
  int x_full_blocks = width_ / kBlockSize;
  int y_full_blocks = height_ / kBlockSize;

  // Calc size of partial blocks which may be present on right and bottom edge.
  int partial_column_width = width_ - (x_full_blocks * kBlockSize);
  int partial_row_height = height_ - (y_full_blocks * kBlockSize);

  // Offset from the start of one block-column to the next.
  int block_x_offset = bytes_per_pixel_ * kBlockSize;
  // Offset from the start of one block-row to the next.
  int block_y_stride = (width_ * bytes_per_pixel_) * kBlockSize;
  // Offset from the start of one diff_info row to the next.
  int diff_info_stride = diff_info_width_ * sizeof(bool);

  const uint8_t* prev_block_row_start = prev_buffer;
  const uint8_t* curr_block_row_start = curr_buffer;
  bool* diff_info_row_start = diff_info_.get();

  for (int y = 0; y < y_full_blocks; y++) {
    const uint8_t* prev_block = prev_block_row_start;
    const uint8_t* curr_block = curr_block_row_start;
    bool* diff_info = diff_info_row_start;

    for (int x = 0; x < x_full_blocks; x++) {
      // Mark this block as being modified so that it gets incorporated into
      // a dirty rect.
      *diff_info = BlockDifference(prev_block, curr_block, bytes_per_row_);
      prev_block += block_x_offset;
      curr_block += block_x_offset;
      diff_info += sizeof(bool);
    }

    // If there is a partial column at the end, handle it.
    // This condition should rarely, if ever, occur.
    if (partial_column_width != 0) {
      *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_,
                                       partial_column_width, kBlockSize);
      diff_info += sizeof(bool);
    }

    // Update pointers for next row.
    prev_block_row_start += block_y_stride;
    curr_block_row_start += block_y_stride;
    diff_info_row_start += diff_info_stride;
  }

  // If the screen height is not a multiple of the block size, then this
  // handles the last partial row. This situation is far more common than the
  // 'partial column' case.
  if (partial_row_height != 0) {
    const uint8_t* prev_block = prev_block_row_start;
    const uint8_t* curr_block = curr_block_row_start;
    bool* diff_info = diff_info_row_start;
    for (int x = 0; x < x_full_blocks; x++) {
      *diff_info = !PartialBlocksEqual(prev_block, curr_block,
                                       bytes_per_row_,
                                       kBlockSize, partial_row_height);
      prev_block += block_x_offset;
      curr_block += block_x_offset;
      diff_info += sizeof(bool);
    }
    if (partial_column_width != 0) {
      *diff_info = !PartialBlocksEqual(prev_block, curr_block, bytes_per_row_,
                                       partial_column_width,
                                       partial_row_height);
      diff_info += sizeof(bool);
    }
  }
}

bool Differ::PartialBlocksEqual(const uint8_t* prev_buffer,
                                const uint8_t* curr_buffer,
                                int stride, int width, int height) {
  int width_bytes = width * bytes_per_pixel_;
  for (int y = 0; y < height; y++) {
    if (memcmp(prev_buffer, curr_buffer, width_bytes) != 0)
      return false;
    prev_buffer += bytes_per_row_;
    curr_buffer += bytes_per_row_;
  }
  return true;
}

void Differ::MergeBlocks(DesktopRegion* region) {
  region->Clear();

  bool* diff_info_row_start = diff_info_.get();
  int diff_info_stride = diff_info_width_ * sizeof(bool);

  for (int y = 0; y < diff_info_height_; y++) {
    bool* diff_info = diff_info_row_start;
    for (int x = 0; x < diff_info_width_; x++) {
      if (*diff_info) {
        // We've found a modified block. Look at blocks to the right and below
        // to group this block with as many others as we can.
        int left = x * kBlockSize;
        int top = y * kBlockSize;
        int width = 1;
        int height = 1;
        *diff_info = false;

        // Group with blocks to the right.
        // We can keep looking until we find an unchanged block because we
        // have a boundary block which is never marked as having diffs.
        bool* right = diff_info + 1;
        while (*right) {
          *right++ = false;
          width++;
        }

        // Group with blocks below.
        // The entire width of blocks that we matched above much match for
        // each row that we add.
        bool* bottom = diff_info;
        bool found_new_row;
        do {
          found_new_row = true;
          bottom += diff_info_stride;
          right = bottom;
          for (int x2 = 0; x2 < width; x2++) {
            if (!*right++) {
              found_new_row = false;
            }
          }

          if (found_new_row) {
            height++;

            // We need to go back and erase the diff markers so that we don't
            // try to add these blocks a second time.
            right = bottom;
            for (int x2 = 0; x2 < width; x2++) {
              *right++ = false;
            }
          }
        } while (found_new_row);

        // Add rect to list of dirty rects.
        width *= kBlockSize;
        if (left + width > width_) {
          width = width_ - left;
        }
        height *= kBlockSize;
        if (top + height > height_) {
          height = height_ - top;
        }
        region->AddRect(DesktopRect::MakeXYWH(left, top, width, height));
      }

      // Increment to next block in this row.
      diff_info++;
    }

    // Go to start of next row.
    diff_info_row_start += diff_info_stride;
  }
}

}  // namespace webrtc
