// Copyright 2019 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 <stddef.h>
#include <stdint.h>
#include <va/va.h>

#include <memory>
#include <utility>
#include <vector>

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

#include "base/bind.h"
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_info.h"
#include "gpu/ipc/service/image_decode_accelerator_worker.h"
#include "media/gpu/vaapi/vaapi_image_decode_accelerator_worker.h"
#include "media/gpu/vaapi/vaapi_image_decoder.h"
#include "media/gpu/vaapi/vaapi_wrapper.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/linux/native_pixmap_dmabuf.h"
#include "ui/gfx/native_pixmap_handle.h"

using testing::_;
using testing::AllOf;
using testing::InSequence;
using testing::IsNull;
using testing::NotNull;
using testing::Property;
using testing::Return;
using testing::StrictMock;

namespace media {
namespace {

constexpr gfx::BufferFormat kFormatForDecodes = gfx::BufferFormat::YVU_420;

constexpr gfx::Size kVaSurfaceResolution(128, 256);

constexpr gfx::Size kVisibleSize(120, 250);

constexpr size_t kWebPFileAndVp8ChunkHeaderSizeInBytes = 20u;

// clang-format off
constexpr uint8_t kJpegPFileHeader[] = {0xFF, 0xD8, 0xFF};

constexpr uint8_t kLossyWebPFileHeader[] = {
    'R', 'I', 'F', 'F',
    0x0c, 0x00, 0x00, 0x00,  // == 12 (little endian)
    'W', 'E', 'B', 'P',
    'V', 'P', '8', ' ',
    0x00, 0x00, 0x00, 0x00  // == 0
};
// clang-format on

constexpr base::span<const uint8_t, 3u> kJpegEncodedData = kJpegPFileHeader;

constexpr base::span<const uint8_t, kWebPFileAndVp8ChunkHeaderSizeInBytes>
    kLossyWebPEncodedData = kLossyWebPFileHeader;

class MockNativePixmapDmaBuf : public gfx::NativePixmapDmaBuf {
 public:
  MockNativePixmapDmaBuf(const gfx::Size& size)
      : gfx::NativePixmapDmaBuf(size,
                                kFormatForDecodes,
                                gfx::NativePixmapHandle()) {}

  gfx::NativePixmapHandle ExportHandle() override {
    gfx::NativePixmapHandle handle{};
    DCHECK_EQ(gfx::BufferFormat::YVU_420, GetBufferFormat());
    handle.planes = std::vector<gfx::NativePixmapPlane>(3u);
    return handle;
  }

 protected:
  ~MockNativePixmapDmaBuf() override = default;
};

class MockVaapiImageDecoder : public VaapiImageDecoder {
 public:
  MockVaapiImageDecoder(gpu::ImageDecodeAcceleratorType type)
      : VaapiImageDecoder(VAProfileNone), type_(type) {}
  ~MockVaapiImageDecoder() override = default;

  gpu::ImageDecodeAcceleratorType GetType() const override { return type_; }
  SkYUVColorSpace GetYUVColorSpace() const override {
    switch (type_) {
      case gpu::ImageDecodeAcceleratorType::kJpeg:
        return SkYUVColorSpace::kJPEG_SkYUVColorSpace;
      case gpu::ImageDecodeAcceleratorType::kWebP:
        return SkYUVColorSpace::kRec601_SkYUVColorSpace;
      case gpu::ImageDecodeAcceleratorType::kUnknown:
        NOTREACHED();
        return SkYUVColorSpace::kIdentity_SkYUVColorSpace;
    }
  }

  gpu::ImageDecodeAcceleratorSupportedProfile GetSupportedProfile()
      const override {
    return gpu::ImageDecodeAcceleratorSupportedProfile();
  }

  MOCK_METHOD1(Initialize, bool(const ReportErrorToUMACB&));
  MOCK_METHOD1(Decode, VaapiImageDecodeStatus(base::span<const uint8_t>));
  MOCK_CONST_METHOD0(GetScopedVASurface, const ScopedVASurface*());
  MOCK_METHOD1(
      ExportAsNativePixmapDmaBuf,
      std::unique_ptr<NativePixmapAndSizeInfo>(VaapiImageDecodeStatus*));
  MOCK_METHOD1(AllocateVASurfaceAndSubmitVABuffers,
               VaapiImageDecodeStatus(base::span<const uint8_t>));

 private:
  const gpu::ImageDecodeAcceleratorType type_;
};

}  // namespace

class VaapiImageDecodeAcceleratorWorkerTest : public testing::Test {
 public:
  VaapiImageDecodeAcceleratorWorkerTest() {
    feature_list_.InitWithFeatures(
        {features::kVaapiJpegImageDecodeAcceleration,
         features::kVaapiWebPImageDecodeAcceleration} /* enabled_features */,
        {} /* disabled_features */);
    VaapiImageDecoderVector decoders;
    decoders.push_back(std::make_unique<StrictMock<MockVaapiImageDecoder>>(
        gpu::ImageDecodeAcceleratorType::kJpeg));
    decoders.push_back(std::make_unique<StrictMock<MockVaapiImageDecoder>>(
        gpu::ImageDecodeAcceleratorType::kWebP));
    worker_ = base::WrapUnique(
        new VaapiImageDecodeAcceleratorWorker(std::move(decoders)));
  }

  MockVaapiImageDecoder* GetJpegDecoder() const {
    auto result =
        worker_->decoders_.find(gpu::ImageDecodeAcceleratorType::kJpeg);
    return result == worker_->decoders_.end()
               ? nullptr
               : static_cast<MockVaapiImageDecoder*>(result->second.get());
  }

  MockVaapiImageDecoder* GetWebPDecoder() const {
    auto result =
        worker_->decoders_.find(gpu::ImageDecodeAcceleratorType::kWebP);
    return result == worker_->decoders_.end()
               ? nullptr
               : static_cast<MockVaapiImageDecoder*>(result->second.get());
  }

  MOCK_METHOD1(
      OnDecodeCompleted,
      void(std::unique_ptr<gpu::ImageDecodeAcceleratorWorker::DecodeResult>));

 protected:
  base::test::TaskEnvironment task_environment_;
  base::test::ScopedFeatureList feature_list_;
  std::unique_ptr<VaapiImageDecodeAcceleratorWorker> worker_;

  DISALLOW_COPY_AND_ASSIGN(VaapiImageDecodeAcceleratorWorkerTest);
};

ACTION_P2(ExportAsNativePixmapDmaBufSuccessfully,
          va_surface_resolution,
          visible_size) {
  *arg0 = VaapiImageDecodeStatus::kSuccess;
  auto exported_pixmap = std::make_unique<NativePixmapAndSizeInfo>();
  exported_pixmap->va_surface_resolution = va_surface_resolution;
  exported_pixmap->byte_size = 1u;
  exported_pixmap->pixmap =
      base::MakeRefCounted<MockNativePixmapDmaBuf>(visible_size);
  return exported_pixmap;
}

TEST_F(VaapiImageDecodeAcceleratorWorkerTest, ImageDecodeSucceeds) {
  std::vector<uint8_t> jpeg_encoded_data(kJpegEncodedData.begin(),
                                         kJpegEncodedData.end());
  std::vector<uint8_t> webp_encoded_data(kLossyWebPEncodedData.begin(),
                                         kLossyWebPEncodedData.end());
  {
    InSequence sequence;
    MockVaapiImageDecoder* jpeg_decoder = GetJpegDecoder();
    ASSERT_TRUE(jpeg_decoder);
    EXPECT_CALL(
        *jpeg_decoder,
        Decode(AllOf(Property(&base::span<const uint8_t>::data,
                              jpeg_encoded_data.data()),
                     Property(&base::span<const uint8_t>::size,
                              jpeg_encoded_data.size())) /* encoded_data */))
        .WillOnce(Return(VaapiImageDecodeStatus::kSuccess));
    EXPECT_CALL(*jpeg_decoder,
                ExportAsNativePixmapDmaBuf(NotNull() /* status */))
        .WillOnce(ExportAsNativePixmapDmaBufSuccessfully(kVaSurfaceResolution,
                                                         kVisibleSize));
    EXPECT_CALL(*this, OnDecodeCompleted(NotNull()));

    MockVaapiImageDecoder* webp_decoder = GetWebPDecoder();
    ASSERT_TRUE(webp_decoder);
    EXPECT_CALL(
        *webp_decoder,
        Decode(AllOf(Property(&base::span<const uint8_t>::data,
                              webp_encoded_data.data()),
                     Property(&base::span<const uint8_t>::size,
                              webp_encoded_data.size())) /* encoded_data */))
        .WillOnce(Return(VaapiImageDecodeStatus::kSuccess));
    EXPECT_CALL(*webp_decoder,
                ExportAsNativePixmapDmaBuf(NotNull() /* status */))
        .WillOnce(ExportAsNativePixmapDmaBufSuccessfully(kVaSurfaceResolution,
                                                         kVisibleSize));
    EXPECT_CALL(*this, OnDecodeCompleted(NotNull()));
  }

  worker_->Decode(
      std::move(jpeg_encoded_data), kVisibleSize,
      base::BindOnce(&VaapiImageDecodeAcceleratorWorkerTest::OnDecodeCompleted,
                     base::Unretained(this)));

  worker_->Decode(
      std::move(webp_encoded_data), kVisibleSize,
      base::BindOnce(&VaapiImageDecodeAcceleratorWorkerTest::OnDecodeCompleted,
                     base::Unretained(this)));
  task_environment_.RunUntilIdle();
}

TEST_F(VaapiImageDecodeAcceleratorWorkerTest, ImageDecodeFails) {
  std::vector<uint8_t> jpeg_encoded_data(kJpegEncodedData.begin(),
                                         kJpegEncodedData.end());
  std::vector<uint8_t> webp_encoded_data(kLossyWebPEncodedData.begin(),
                                         kLossyWebPEncodedData.end());
  {
    InSequence sequence;
    MockVaapiImageDecoder* jpeg_decoder = GetJpegDecoder();
    ASSERT_TRUE(jpeg_decoder);
    EXPECT_CALL(
        *jpeg_decoder,
        Decode(AllOf(Property(&base::span<const uint8_t>::data,
                              jpeg_encoded_data.data()),
                     Property(&base::span<const uint8_t>::size,
                              jpeg_encoded_data.size())) /* encoded_data */))
        .WillOnce(Return(VaapiImageDecodeStatus::kExecuteDecodeFailed));
    EXPECT_CALL(*this, OnDecodeCompleted(IsNull()));

    MockVaapiImageDecoder* webp_decoder = GetWebPDecoder();
    ASSERT_TRUE(webp_decoder);
    EXPECT_CALL(
        *webp_decoder,
        Decode(AllOf(Property(&base::span<const uint8_t>::data,
                              webp_encoded_data.data()),
                     Property(&base::span<const uint8_t>::size,
                              webp_encoded_data.size())) /* encoded_data */))
        .WillOnce(Return(VaapiImageDecodeStatus::kExecuteDecodeFailed));
    EXPECT_CALL(*this, OnDecodeCompleted(IsNull()));
  }

  worker_->Decode(
      std::move(jpeg_encoded_data), kVisibleSize,
      base::BindOnce(&VaapiImageDecodeAcceleratorWorkerTest::OnDecodeCompleted,
                     base::Unretained(this)));

  worker_->Decode(
      std::move(webp_encoded_data), kVisibleSize,
      base::BindOnce(&VaapiImageDecodeAcceleratorWorkerTest::OnDecodeCompleted,
                     base::Unretained(this)));
  task_environment_.RunUntilIdle();
}

TEST_F(VaapiImageDecodeAcceleratorWorkerTest, UnknownImageDecodeFails) {
  std::vector<uint8_t> encoded_data = {1u, 2u, 3u};
  EXPECT_CALL(*this, OnDecodeCompleted(IsNull()));
  worker_->Decode(
      std::move(encoded_data), kVisibleSize,
      base::BindOnce(&VaapiImageDecodeAcceleratorWorkerTest::OnDecodeCompleted,
                     base::Unretained(this)));
  task_environment_.RunUntilIdle();
}

}  // namespace media
