| // 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 |