// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/mac/video_frame_mac.h"

#include <stddef.h>

#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "media/base/video_frame.h"

#include "testing/gtest/include/gtest/gtest.h"

namespace media {

namespace {

const int kWidth = 64;
const int kHeight = 48;
const int kVisibleRectOffset = 8;
const base::TimeDelta kTimestamp = base::Microseconds(1337);

struct FormatPair {
  VideoPixelFormat chrome;
  OSType corevideo;
};

void Increment(int* i) {
  ++(*i);
}

}  // namespace

TEST(VideoFrameMac, CheckBasicAttributes) {
  gfx::Size size(kWidth, kHeight);
  auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_I420, size, gfx::Rect(size),
                                       size, kTimestamp);
  ASSERT_TRUE(frame.get());

  auto pb = WrapVideoFrameInCVPixelBuffer(*frame);
  ASSERT_TRUE(pb.get());

  const gfx::Size coded_size = frame->coded_size();
  const VideoPixelFormat format = frame->format();

  EXPECT_EQ(coded_size.width(), static_cast<int>(CVPixelBufferGetWidth(pb)));
  EXPECT_EQ(coded_size.height(), static_cast<int>(CVPixelBufferGetHeight(pb)));
  EXPECT_EQ(VideoFrame::NumPlanes(format), CVPixelBufferGetPlaneCount(pb));

  CVPixelBufferLockBaseAddress(pb, 0);
  for (size_t i = 0; i < VideoFrame::NumPlanes(format); ++i) {
    const gfx::Size plane_size = VideoFrame::PlaneSize(format, i, coded_size);
    EXPECT_EQ(plane_size.width(),
              static_cast<int>(CVPixelBufferGetWidthOfPlane(pb, i)));
    EXPECT_EQ(plane_size.height(),
              static_cast<int>(CVPixelBufferGetHeightOfPlane(pb, i)));
    EXPECT_EQ(frame->data(i), CVPixelBufferGetBaseAddressOfPlane(pb, i));
  }
  CVPixelBufferUnlockBaseAddress(pb, 0);
}

TEST(VideoFrameMac, CheckFormats) {
  // CreateFrame() does not support non planar YUV, e.g. NV12.
  const FormatPair format_pairs[] = {
      {PIXEL_FORMAT_I420, kCVPixelFormatType_420YpCbCr8Planar},
      {PIXEL_FORMAT_YV12, 0},
      {PIXEL_FORMAT_I422, 0},
      {PIXEL_FORMAT_I420A, 0},
      {PIXEL_FORMAT_I444, 0},
  };

  gfx::Size size(kWidth, kHeight);
  for (const auto& format_pair : format_pairs) {
    auto frame = VideoFrame::CreateFrame(format_pair.chrome, size,
                                         gfx::Rect(size), size, kTimestamp);
    ASSERT_TRUE(frame.get());
    auto pb = WrapVideoFrameInCVPixelBuffer(*frame);
    if (format_pair.corevideo) {
      EXPECT_EQ(format_pair.corevideo, CVPixelBufferGetPixelFormatType(pb));
    } else {
      EXPECT_EQ(nullptr, pb.get());
    }
  }
}

TEST(VideoFrameMac, CheckLifetime) {
  gfx::Size size(kWidth, kHeight);
  auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_I420, size, gfx::Rect(size),
                                       size, kTimestamp);
  ASSERT_TRUE(frame.get());

  int instances_destroyed = 0;
  auto wrapper_frame = VideoFrame::WrapVideoFrame(
      frame, frame->format(), frame->visible_rect(), frame->natural_size());
  wrapper_frame->AddDestructionObserver(
      base::BindOnce(&Increment, &instances_destroyed));
  ASSERT_TRUE(wrapper_frame.get());

  auto pb = WrapVideoFrameInCVPixelBuffer(*wrapper_frame);
  ASSERT_TRUE(pb.get());

  wrapper_frame = nullptr;
  EXPECT_EQ(0, instances_destroyed);
  pb.reset();
  EXPECT_EQ(1, instances_destroyed);
}

TEST(VideoFrameMac, CheckWrapperFrame) {
  const FormatPair format_pairs[] = {
      {PIXEL_FORMAT_I420, kCVPixelFormatType_420YpCbCr8Planar},
      {PIXEL_FORMAT_NV12, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange},
  };

  for (const auto& format_pair : format_pairs) {
    base::ScopedCFTypeRef<CVPixelBufferRef> pb;
    CVPixelBufferCreate(nullptr, kWidth, kHeight, format_pair.corevideo,
                        nullptr, pb.InitializeInto());
    ASSERT_TRUE(pb.get());

    auto frame = VideoFrame::WrapCVPixelBuffer(pb.get(), kTimestamp);
    ASSERT_TRUE(frame.get());
    EXPECT_EQ(pb.get(), frame->CvPixelBuffer());
    EXPECT_EQ(format_pair.chrome, frame->format());

    frame = nullptr;
    EXPECT_EQ(1, CFGetRetainCount(pb.get()));
  }
}

static void FillFrameWithPredictableValues(const VideoFrame& frame) {
  for (size_t i = 0; i < VideoFrame::NumPlanes(frame.format()); ++i) {
    const gfx::Size& size =
        VideoFrame::PlaneSize(frame.format(), i, frame.coded_size());
    uint8_t* plane_ptr = const_cast<uint8_t*>(frame.data(i));
    for (int h = 0; h < size.height(); ++h) {
      const int row_index = h * frame.stride(i);
      for (int w = 0; w < size.width(); ++w) {
        const int index = row_index + w;
        plane_ptr[index] = static_cast<uint8_t>(w ^ h);
      }
    }
  }
}

TEST(VideoFrameMac, CorrectlyWrapsFramesWithPadding) {
  const gfx::Size coded_size(kWidth, kHeight);
  const gfx::Rect visible_rect(kVisibleRectOffset, kVisibleRectOffset,
                               kWidth - 2 * kVisibleRectOffset,
                               kHeight - 2 * kVisibleRectOffset);
  auto frame =
      VideoFrame::CreateFrame(PIXEL_FORMAT_I420, coded_size, visible_rect,
                              visible_rect.size(), kTimestamp);
  ASSERT_TRUE(frame.get());
  FillFrameWithPredictableValues(*frame);

  auto pb = WrapVideoFrameInCVPixelBuffer(*frame);
  ASSERT_TRUE(pb.get());
  EXPECT_EQ(kCVPixelFormatType_420YpCbCr8Planar,
            CVPixelBufferGetPixelFormatType(pb));
  EXPECT_EQ(visible_rect.width(), static_cast<int>(CVPixelBufferGetWidth(pb)));
  EXPECT_EQ(visible_rect.height(),
            static_cast<int>(CVPixelBufferGetHeight(pb)));

  CVPixelBufferLockBaseAddress(pb, 0);
  for (size_t i = 0; i < VideoFrame::NumPlanes(frame->format()); ++i) {
    const gfx::Size plane_size =
        VideoFrame::PlaneSize(frame->format(), i, visible_rect.size());
    EXPECT_EQ(plane_size.width(),
              static_cast<int>(CVPixelBufferGetWidthOfPlane(pb, i)));
    EXPECT_EQ(plane_size.height(),
              static_cast<int>(CVPixelBufferGetHeightOfPlane(pb, i)));

    uint8_t* plane_ptr =
        reinterpret_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(pb, i));
    EXPECT_EQ(frame->visible_data(i), plane_ptr);
    const int stride =
        static_cast<int>(CVPixelBufferGetBytesPerRowOfPlane(pb, i));
    EXPECT_EQ(frame->stride(i), stride);
    const int offset = kVisibleRectOffset / ((i == 0) ? 1 : 2);
    for (int h = 0; h < plane_size.height(); ++h) {
      const int row_index = h * stride;
      for (int w = 0; w < plane_size.width(); ++w) {
        const int index = row_index + w;
        EXPECT_EQ(static_cast<uint8_t>((w + offset) ^ (h + offset)),
                  plane_ptr[index]);
      }
    }
  }
  CVPixelBufferUnlockBaseAddress(pb, 0);
}

}  // namespace media
