blob: 9f61744eefdadb37420aec2b727be91b9590f19d [file] [log] [blame]
// Copyright 2016 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/audio_sink.h"
#include <vector>
#include "starboard/nplb/audio_sink_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace starboard {
namespace nplb {
namespace {
void UpdateSourceStatusFuncStub(int* frames_in_buffer,
int* offset_in_frames,
bool* is_playing,
bool* is_eos_reached,
void* context) {
*frames_in_buffer = 0;
*offset_in_frames = 0;
*is_playing = false;
*is_eos_reached = false;
}
#if SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
void ConsumeFramesFuncStub(int frames_consumed, void* context) {}
#else // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
void ConsumeFramesFuncStub(int frames_consumed,
SbTime frames_consumed_at,
void* context) {}
#endif // SB_API_VERSION >= 12 || !SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
} // namespace
TEST(SbAudioSinkCreateTest, SunnyDay) {
ASSERT_GE(SbAudioSinkGetMaxChannels(), 1);
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels());
SbAudioSink audio_sink = SbAudioSinkCreate(
frame_buffers.channels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub,
reinterpret_cast<void*>(1));
EXPECT_TRUE(SbAudioSinkIsValid(audio_sink));
SbAudioSinkDestroy(audio_sink);
}
TEST(SbAudioSinkCreateTest, MultiSink) {
ASSERT_GE(SbAudioSinkGetMaxChannels(), 1);
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels());
const int kMaxSinks = 16;
std::vector<SbAudioSink> created_sinks;
for (int i = 0; i < kMaxSinks; ++i) {
created_sinks.push_back(SbAudioSinkCreate(
frame_buffers.channels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub,
reinterpret_cast<void*>(1)));
if (!SbAudioSinkIsValid(created_sinks[i])) {
created_sinks.pop_back();
break;
}
}
SB_DLOG(INFO) << "Created " << created_sinks.size() << " valid audio sinks";
for (auto sink : created_sinks) {
SbAudioSinkDestroy(sink);
}
}
TEST(SbAudioSinkCreateTest, SunnyDayAllCombinations) {
std::vector<SbMediaAudioSampleType> sample_types;
if (SbAudioSinkIsAudioSampleTypeSupported(
kSbMediaAudioSampleTypeInt16Deprecated)) {
sample_types.push_back(kSbMediaAudioSampleTypeInt16Deprecated);
}
if (SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32)) {
sample_types.push_back(kSbMediaAudioSampleTypeFloat32);
}
std::vector<SbMediaAudioFrameStorageType> storage_types;
if (SbAudioSinkIsAudioFrameStorageTypeSupported(
kSbMediaAudioFrameStorageTypeInterleaved)) {
storage_types.push_back(kSbMediaAudioFrameStorageTypeInterleaved);
}
if (SbAudioSinkIsAudioFrameStorageTypeSupported(
kSbMediaAudioFrameStorageTypePlanar)) {
storage_types.push_back(kSbMediaAudioFrameStorageTypePlanar);
}
for (size_t sample_type = 0; sample_type < sample_types.size();
++sample_type) {
for (size_t storage_type = 0; storage_type < storage_types.size();
++storage_type) {
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels(),
sample_types[sample_type],
storage_types[storage_type]);
// It should at least support stereo and the claimed max channels.
SbAudioSink audio_sink = SbAudioSinkCreate(
frame_buffers.channels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub, NULL);
EXPECT_TRUE(SbAudioSinkIsValid(audio_sink));
SbAudioSinkDestroy(audio_sink);
if (SbAudioSinkGetMaxChannels() > 2) {
AudioSinkTestFrameBuffers frame_buffers(2, sample_types[sample_type],
storage_types[storage_type]);
audio_sink = SbAudioSinkCreate(
frame_buffers.channels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub, NULL);
EXPECT_TRUE(SbAudioSinkIsValid(audio_sink));
SbAudioSinkDestroy(audio_sink);
}
}
}
}
TEST(SbAudioSinkCreateTest, RainyDayInvalidChannels) {
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels());
SbAudioSink audio_sink = SbAudioSinkCreate(
0, // |channels| is 0
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub, NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
}
TEST(SbAudioSinkCreateTest, RainyDayInvalidFrequency) {
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels());
SbAudioSink audio_sink = SbAudioSinkCreate(
frame_buffers.channels(), 0, // |sampling_frequency_hz| is 0
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub, NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
const int kOddFrequency = 12345;
if (SbAudioSinkGetNearestSupportedSampleFrequency(kOddFrequency) !=
kOddFrequency) {
audio_sink = SbAudioSinkCreate(
frame_buffers.channels(),
kOddFrequency, // |sampling_frequency_hz| is unsupported
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub, NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
}
}
TEST(SbAudioSinkCreateTest, RainyDayInvalidSampleType) {
SbMediaAudioSampleType invalid_sample_type;
if (SbAudioSinkIsAudioSampleTypeSupported(
kSbMediaAudioSampleTypeInt16Deprecated)) {
if (SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32)) {
return;
}
invalid_sample_type = kSbMediaAudioSampleTypeFloat32;
} else {
invalid_sample_type = kSbMediaAudioSampleTypeInt16Deprecated;
}
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels(),
invalid_sample_type);
SbAudioSink audio_sink = SbAudioSinkCreate(
SbAudioSinkGetMaxChannels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
invalid_sample_type, // |sample_type| is invalid
frame_buffers.storage_type(), frame_buffers.frame_buffers(),
frame_buffers.frames_per_channel(), UpdateSourceStatusFuncStub,
ConsumeFramesFuncStub, NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
}
TEST(SbAudioSinkCreateTest, RainyDayInvalidFrameStorageType) {
SbMediaAudioFrameStorageType invalid_storage_type;
if (SbAudioSinkIsAudioFrameStorageTypeSupported(
kSbMediaAudioFrameStorageTypeInterleaved)) {
if (SbAudioSinkIsAudioFrameStorageTypeSupported(
kSbMediaAudioFrameStorageTypePlanar)) {
return;
}
invalid_storage_type = kSbMediaAudioFrameStorageTypePlanar;
} else {
invalid_storage_type = kSbMediaAudioFrameStorageTypeInterleaved;
}
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels(),
invalid_storage_type);
SbAudioSink audio_sink = SbAudioSinkCreate(
SbAudioSinkGetMaxChannels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(),
invalid_storage_type, // |storage_type| is invalid
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub, NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
}
TEST(SbAudioSinkCreateTest, RainyDayInvalidFrameBuffers) {
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels());
SbAudioSink audio_sink = SbAudioSinkCreate(
frame_buffers.channels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
NULL, // |frame_buffers| is NULL
frame_buffers.frames_per_channel(), UpdateSourceStatusFuncStub,
ConsumeFramesFuncStub, NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
audio_sink = SbAudioSinkCreate(
frame_buffers.channels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(),
0, // |frames_per_channel| is 0
UpdateSourceStatusFuncStub, ConsumeFramesFuncStub, NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
}
TEST(SbAudioSinkCreateTest, RainyDayInvalidCallback) {
AudioSinkTestFrameBuffers frame_buffers(SbAudioSinkGetMaxChannels());
SbAudioSink audio_sink = SbAudioSinkCreate(
frame_buffers.channels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
NULL, // |update_source_status_func| is NULL
ConsumeFramesFuncStub, NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
audio_sink = SbAudioSinkCreate(
frame_buffers.channels(),
SbAudioSinkGetNearestSupportedSampleFrequency(44100),
frame_buffers.sample_type(), frame_buffers.storage_type(),
frame_buffers.frame_buffers(), frame_buffers.frames_per_channel(),
UpdateSourceStatusFuncStub,
NULL, // |consume_frames_func| is NULL
NULL);
EXPECT_FALSE(SbAudioSinkIsValid(audio_sink));
}
} // namespace nplb
} // namespace starboard