// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/media.h"

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

#if SB_API_VERSION >= 10
namespace starboard {
namespace nplb {
namespace {

constexpr int kVideoResolutions[][2] = {
    {kSbMediaVideoResolutionDimensionInvalid,
     kSbMediaVideoResolutionDimensionInvalid},
    {640, 480},
    {1280, 720},
    {1920, 1080},
    {2560, 1440},
    {3840, 2160},
};

constexpr int kBitsPerPixelValues[] = {
    kSbMediaBitsPerPixelInvalid, 8, 10, 12,
};

constexpr SbMediaVideoCodec kVideoCodecs[] = {
    kSbMediaVideoCodecNone,

    kSbMediaVideoCodecH264,   kSbMediaVideoCodecH265, kSbMediaVideoCodecMpeg2,
    kSbMediaVideoCodecTheora, kSbMediaVideoCodecVc1,  kSbMediaVideoCodecVp10,
    kSbMediaVideoCodecVp8,    kSbMediaVideoCodecVp9,
};

constexpr SbMediaType kMediaTypes[] = {
    kSbMediaTypeAudio,
    kSbMediaTypeVideo,
};

}  // namespace

TEST(SbMediaBufferTest, VideoCodecs) {
  // Perform a check to determine if new codecs have been added to the
  // enum, but not the array. If the compiler warns about a missing case here,
  // the value must be added to the array and the switch case.
  SbMediaVideoCodec codec = kVideoCodecs[0];
  switch (codec) {
    case kVideoCodecs[0]:
    case kVideoCodecs[1]:
    case kVideoCodecs[2]:
    case kVideoCodecs[3]:
    case kVideoCodecs[4]:
    case kVideoCodecs[5]:
    case kVideoCodecs[6]:
    case kVideoCodecs[7]:
    case kVideoCodecs[8]:
      break;
  }
}

TEST(SbMediaBufferTest, MediaTypes) {
  // Perform a check to determine if new types have been added to the
  // enum, but not the array. If the compiler warns about a missing case here,
  // the value must be added to the array and the switch case.
  SbMediaType type = kMediaTypes[0];
  switch (type) {
    case kMediaTypes[0]:
    case kMediaTypes[1]:
      break;
  }
}

TEST(SbMediaBufferTest, Alignment) {
  for (auto type : kMediaTypes) {
    int alignment = SbMediaGetBufferAlignment(type);
    // TODO: This currently accepts 0 or a power of 2. We should disallow 0 here
    // when we change the default value to be 1 instead of 0.
    EXPECT_GE(alignment, 0);
    EXPECT_EQ(alignment & (alignment - 1), 0)
        << "Alignment must always be a power of 2";
  }
}

TEST(SbMediaBufferTest, AllocationUnit) {
  // TODO: impose more bounds.
  EXPECT_GE(SbMediaGetBufferAllocationUnit(), 0);
}

TEST(SbMediaBufferTest, AudioBudget) {
  // TODO: refine this lower bound.
  const int kMinAudioBudget = 1 * 1024 * 1024;
  EXPECT_GT(SbMediaGetAudioBufferBudget(), kMinAudioBudget);
}

TEST(SbMediaBufferTest, GarbageCollectionDurationThreshold) {
  // TODO: impose reasonable bounds here.
  int kMinGarbargeCollectionDurationThreshold = 10 * kSbTimeSecond;
  int kMaxGarbargeCollectionDurationThreshold = 240 * kSbTimeSecond;
  int threshold = SbMediaGetBufferGarbageCollectionDurationThreshold();
  EXPECT_GE(threshold, kMinGarbargeCollectionDurationThreshold);
  EXPECT_LE(threshold, kMaxGarbargeCollectionDurationThreshold);
}

TEST(SbMediaBufferTest, InitialCapacity) {
  EXPECT_GE(SbMediaGetInitialBufferCapacity(), 0);
}

TEST(SbMediaBufferTest, MaxCapacity) {
  // TODO: set a reasonable upper bound.
  for (auto resolution : kVideoResolutions) {
    for (auto bits_per_pixel : kBitsPerPixelValues) {
      for (auto codec : kVideoCodecs) {
        EXPECT_GT(SbMediaGetMaxBufferCapacity(codec, resolution[0],
                                              resolution[1], bits_per_pixel),
                  0);
        EXPECT_GE(SbMediaGetMaxBufferCapacity(codec, resolution[0],
                                              resolution[1], bits_per_pixel),
                  SbMediaGetInitialBufferCapacity());
      }
    }
  }
}

TEST(SbMediaBufferTest, Padding) {
  for (auto type : kMediaTypes) {
    EXPECT_GE(SbMediaGetBufferPadding(type), 0);
  }
}

TEST(SbMediaBufferTest, PoolAllocateOnDemand) {
  // Just don't crash.
  SbMediaIsBufferPoolAllocateOnDemand();
}

TEST(SbMediaBufferTest, ProgressiveBudget) {
  const int kMinProgressiveBudget = 8 * 1024 * 1024;
  int audio_budget = SbMediaGetAudioBufferBudget();
  for (auto video_codec : kVideoCodecs) {
    for (auto bits_per_pixel : kBitsPerPixelValues) {
      int video_budget_1080p =
          SbMediaGetVideoBufferBudget(video_codec, 1920, 1080, bits_per_pixel);
      for (auto resolution : kVideoResolutions) {
        int progressive_budget = SbMediaGetProgressiveBufferBudget(
            video_codec, resolution[0], resolution[1], bits_per_pixel);
        EXPECT_LT(progressive_budget, video_budget_1080p + audio_budget)
            << "Progressive budget must be less than sum of 1080p video "
               "budget and audio budget";
        EXPECT_GE(progressive_budget, kMinProgressiveBudget);
      }
    }
  }
}

TEST(SbMediaBufferTest, StorageType) {
  // Just don't crash.
  SbMediaBufferStorageType type = SbMediaGetBufferStorageType();
  switch (type) {
    case kSbMediaBufferStorageTypeMemory:
    case kSbMediaBufferStorageTypeFile:
      return;
  }
  SB_NOTREACHED();
}

TEST(SbMediaBufferTest, UsingMemoryPool) {
  // Just don't crash.
  SbMediaIsBufferUsingMemoryPool();
}

TEST(SbMediaBufferTest, VideoBudget) {
  // TODO: refine this lower bound.
  const int kMinVideoBudget = 1 * 1024 * 1024;
  for (auto codec : kVideoCodecs) {
    for (auto resolution : kVideoResolutions) {
      for (auto bits_per_pixel : kBitsPerPixelValues) {
        EXPECT_GT(SbMediaGetVideoBufferBudget(codec, resolution[0],
                                              resolution[1], bits_per_pixel),
                  kMinVideoBudget);
      }
    }
  }
}
}  // namespace nplb
}  // namespace starboard
#endif  // SB_API_VERSION >= 10
