/*
 *  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 <stdio.h>
#include <string.h>

#include "webrtc/api/video/i420_buffer.h"
#include "webrtc/api/video/video_frame.h"
#include "webrtc/test/frame_utils.h"

namespace webrtc {
namespace test {

bool EqualPlane(const uint8_t* data1,
                const uint8_t* data2,
                int stride1,
                int stride2,
                int width,
                int height) {
  for (int y = 0; y < height; ++y) {
    if (memcmp(data1, data2, width) != 0)
      return false;
    data1 += stride1;
    data2 += stride2;
  }
  return true;
}

bool FramesEqual(const webrtc::VideoFrame& f1, const webrtc::VideoFrame& f2) {
  if (f1.timestamp() != f2.timestamp() ||
      f1.ntp_time_ms() != f2.ntp_time_ms() ||
      f1.render_time_ms() != f2.render_time_ms()) {
    return false;
  }
  return FrameBufsEqual(f1.video_frame_buffer(), f2.video_frame_buffer());
}

bool FrameBufsEqual(const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f1,
                    const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f2) {
  if (f1 == f2) {
    return true;
  }
  // Exlude nullptr (except if both are nullptr, as above)
  if (!f1 || !f2) {
    return false;
  }

  if (f1->width() != f2->width() || f1->height() != f2->height() ||
      f1->type() != f2->type()) {
    return false;
  }

  rtc::scoped_refptr<webrtc::I420BufferInterface> f1_i420 = f1->ToI420();
  rtc::scoped_refptr<webrtc::I420BufferInterface> f2_i420 = f2->ToI420();
  return EqualPlane(f1_i420->DataY(), f2_i420->DataY(),
                    f1_i420->StrideY(), f2_i420->StrideY(),
                    f1_i420->width(), f1_i420->height()) &&
         EqualPlane(f1_i420->DataU(), f2_i420->DataU(),
                    f1_i420->StrideU(), f2_i420->StrideU(),
                    f1_i420->ChromaWidth(), f1_i420->ChromaHeight()) &&
         EqualPlane(f1_i420->DataV(), f2_i420->DataV(),
                    f1_i420->StrideV(), f2_i420->StrideV(),
                    f1_i420->ChromaWidth(), f1_i420->ChromaHeight());
}

rtc::scoped_refptr<I420Buffer> ReadI420Buffer(int width, int height, FILE *f) {
  int half_width = (width + 1) / 2;
  rtc::scoped_refptr<I420Buffer> buffer(
      // Explicit stride, no padding between rows.
      I420Buffer::Create(width, height, width, half_width, half_width));
  size_t size_y = static_cast<size_t>(width) * height;
  size_t size_uv = static_cast<size_t>(half_width) * ((height + 1) / 2);

  if (fread(buffer->MutableDataY(), 1, size_y, f) < size_y)
    return nullptr;
  if (fread(buffer->MutableDataU(), 1, size_uv, f) < size_uv)
    return nullptr;
  if (fread(buffer->MutableDataV(), 1, size_uv, f) < size_uv)
    return nullptr;
  return buffer;
}

}  // namespace test
}  // namespace webrtc
