blob: 66640dd890772f50389994f06aa76372db5cfb94 [file] [log] [blame]
// 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 "starboard/nplb/performance_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
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,
kSbMediaVideoCodecAv1,
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 kMinGarbageCollectionDurationThreshold = 10 * kSbTimeSecond;
int kMaxGarbageCollectionDurationThreshold = 240 * kSbTimeSecond;
int threshold = SbMediaGetBufferGarbageCollectionDurationThreshold();
EXPECT_GE(threshold, kMinGarbageCollectionDurationThreshold);
EXPECT_LE(threshold, kMaxGarbageCollectionDurationThreshold);
}
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);
}
}
}
}
TEST(SbMediaBufferTest, ValidatePerformance) {
TEST_PERF_FUNCNOARGS_DEFAULT(SbMediaGetBufferAllocationUnit);
TEST_PERF_FUNCNOARGS_DEFAULT(SbMediaGetAudioBufferBudget);
TEST_PERF_FUNCNOARGS_DEFAULT(
SbMediaGetBufferGarbageCollectionDurationThreshold);
TEST_PERF_FUNCNOARGS_DEFAULT(SbMediaGetInitialBufferCapacity);
TEST_PERF_FUNCNOARGS_DEFAULT(SbMediaIsBufferPoolAllocateOnDemand);
TEST_PERF_FUNCNOARGS_DEFAULT(SbMediaGetBufferStorageType);
TEST_PERF_FUNCNOARGS_DEFAULT(SbMediaIsBufferUsingMemoryPool);
for (auto type : kMediaTypes) {
TEST_PERF_FUNCWITHARGS_DEFAULT(SbMediaGetBufferAlignment, type);
TEST_PERF_FUNCWITHARGS_DEFAULT(SbMediaGetBufferPadding, type);
}
for (auto resolution : kVideoResolutions) {
for (auto bits_per_pixel : kBitsPerPixelValues) {
for (auto codec : kVideoCodecs) {
TEST_PERF_FUNCWITHARGS_DEFAULT(SbMediaGetMaxBufferCapacity, codec,
resolution[0], resolution[1],
bits_per_pixel);
TEST_PERF_FUNCWITHARGS_DEFAULT(SbMediaGetProgressiveBufferBudget, codec,
resolution[0], resolution[1],
bits_per_pixel);
TEST_PERF_FUNCWITHARGS_DEFAULT(SbMediaGetVideoBufferBudget, codec,
resolution[0], resolution[1],
bits_per_pixel);
}
}
}
}
} // namespace nplb
} // namespace starboard