diff --git a/starboard/android/shared/test_filters.py b/starboard/android/shared/test_filters.py index 3c0ec7b95d92..e61c6eb3d2c9 100644 --- a/starboard/android/shared/test_filters.py +++ b/starboard/android/shared/test_filters.py @@ -59,6 +59,7 @@ # These tests are disabled due to not receiving the kEndOfStream # player state update within the specified timeout. + 'MultiplePlayerTests/MultiplePlayerTest.NoInput/*', 'SbPlayerGetAudioConfigurationTests/SbPlayerGetAudioConfigurationTest.NoInput/*', 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.NoInput/*', diff --git a/starboard/android/x86/test_filters.py b/starboard/android/x86/test_filters.py index 435e482cd929..88cf3f04f6f8 100644 --- a/starboard/android/x86/test_filters.py +++ b/starboard/android/x86/test_filters.py @@ -19,6 +19,7 @@ # A map of failing or crashing tests per target _FILTERED_TESTS = { 'nplb': [ + 'MultiplePlayerTests/*', 'SbAccessibilityTest.CallSetCaptionsEnabled', 'SbAccessibilityTest.GetCaptionSettingsReturnIsValid', 'SbAudioSinkTest.*', diff --git a/starboard/evergreen/x64/test_filters.py b/starboard/evergreen/x64/test_filters.py index 4af49ccaff16..5b1b30d5277f 100644 --- a/starboard/evergreen/x64/test_filters.py +++ b/starboard/evergreen/x64/test_filters.py @@ -22,6 +22,8 @@ # pylint: disable=line-too-long _FILTERED_TESTS = { 'nplb': [ + 'MultiplePlayerTests/*/*sintel_329_ec3_dmp*', + 'MultiplePlayerTests/*/*sintel_381_ac3_dmp*', 'SbPlayerGetAudioConfigurationTests/*audio_sintel_329_ec3_dmp_*', 'SbPlayerGetAudioConfigurationTests/*audio_sintel_381_ac3_dmp_*', 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteSingleBatch/audio_sintel_329_ec3_dmp_*', diff --git a/starboard/linux/shared/test_filters.py b/starboard/linux/shared/test_filters.py index 31d4f158c706..42e89eae8ba3 100644 --- a/starboard/linux/shared/test_filters.py +++ b/starboard/linux/shared/test_filters.py @@ -22,14 +22,12 @@ # pylint: disable=line-too-long _MODULAR_BUILD_FILTERED_TESTS = { 'nplb': [ - 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteSingleBatch/audio_sintel_329_ec3_dmp_video__null__output_DecodeToTexture', - 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteSingleBatch/audio_sintel_329_ec3_dmp_video__null__output_Punchout', - 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteSingleBatch/audio_sintel_381_ac3_dmp_video__null__output_DecodeToTexture', - 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteSingleBatch/audio_sintel_381_ac3_dmp_video__null__output_Punchout', - 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteMultipleBatches/audio_sintel_329_ec3_dmp_video__null__output_DecodeToTexture', - 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteMultipleBatches/audio_sintel_329_ec3_dmp_video__null__output_Punchout', - 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteMultipleBatches/audio_sintel_381_ac3_dmp_video__null__output_DecodeToTexture', - 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteMultipleBatches/audio_sintel_381_ac3_dmp_video__null__output_Punchout', + 'MultiplePlayerTests/*/*sintel_329_ec3_dmp*', + 'MultiplePlayerTests/*/*sintel_381_ac3_dmp*', + 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteSingleBatch/audio_sintel_329_ec3_dmp_*', + 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteSingleBatch/audio_sintel_381_ac3_dmp_*', + 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteMultipleBatches/audio_sintel_329_ec3_dmp_*', + 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.WriteMultipleBatches/audio_sintel_381_ac3_dmp_*', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDayDestination/type_ipv6', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDaySourceForDestination/type_ipv6', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDaySourceNotLoopback/type_ipv6', diff --git a/starboard/nplb/BUILD.gn b/starboard/nplb/BUILD.gn index 8865ea7bc1e4..ea357e28c06d 100644 --- a/starboard/nplb/BUILD.gn +++ b/starboard/nplb/BUILD.gn @@ -110,6 +110,7 @@ target(gtest_target_type, "nplb") { "microphone_is_sample_rate_supported_test.cc", "microphone_open_test.cc", "microphone_read_test.cc", + "multiple_player_test.cc", "murmurhash2_test.cc", "mutex_acquire_test.cc", "mutex_acquire_try_test.cc", diff --git a/starboard/nplb/multiple_player_test.cc b/starboard/nplb/multiple_player_test.cc new file mode 100644 index 000000000000..1fa741f4e552 --- /dev/null +++ b/starboard/nplb/multiple_player_test.cc @@ -0,0 +1,182 @@ +// Copyright 2023 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 +#include + +#include "starboard/common/string.h" +#include "starboard/nplb/player_test_fixture.h" +#include "starboard/nplb/player_test_util.h" +#include "starboard/nplb/thread_helpers.h" +#include "starboard/testing/fake_graphics_context_provider.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace nplb { +namespace { + +using ::starboard::testing::FakeGraphicsContextProvider; +using ::testing::ValuesIn; + +typedef SbPlayerTestFixture::GroupedSamples GroupedSamples; +typedef std::vector SbPlayerMultiplePlayerTestConfig; +typedef std::function + MultiplePlayerTestFunctor; + +class PlayerThread : public AbstractTestThread { + public: + explicit PlayerThread(const std::function& functor) + : functor_(functor) {} + + void Run() override { functor_(); } + + private: + std::function functor_; +}; + +class MultiplePlayerTest + : public ::testing::TestWithParam { + protected: + void RunTest(const MultiplePlayerTestFunctor& functor); + FakeGraphicsContextProvider fake_graphics_context_provider_; +}; + +void MultiplePlayerTest::RunTest(const MultiplePlayerTestFunctor& functor) { + const SbPlayerMultiplePlayerTestConfig& multiplayer_test_config = GetParam(); + std::list player_threads; + for (const SbPlayerTestConfig& player_config : multiplayer_test_config) { + player_threads.emplace_back( + std::bind(functor, player_config, &fake_graphics_context_provider_)); + } + for (auto& player_thread : player_threads) { + player_thread.Start(); + } + for (auto& player_thread : player_threads) { + player_thread.Join(); + } +} + +void NoInput(const SbPlayerTestConfig& player_config, + FakeGraphicsContextProvider* fake_graphics_context_provider) { + SbPlayerTestFixture player_fixture(player_config, + fake_graphics_context_provider); + if (::testing::Test::HasFatalFailure()) { + return; + } + + GroupedSamples samples; + if (player_fixture.HasAudio()) { + samples.AddAudioSamplesWithEOS(0, 0); + } + if (player_fixture.HasVideo()) { + samples.AddVideoSamplesWithEOS(0, 0); + } + ASSERT_NO_FATAL_FAILURE(player_fixture.Write(samples)); + ASSERT_NO_FATAL_FAILURE(player_fixture.WaitForPlayerEndOfStream()); +} + +TEST_P(MultiplePlayerTest, NoInput) { + RunTest(NoInput); +} + +void WriteSamples(const SbPlayerTestConfig& player_config, + FakeGraphicsContextProvider* fake_graphics_context_provider) { + SbPlayerTestFixture player_fixture(player_config, + fake_graphics_context_provider); + if (::testing::Test::HasFatalFailure()) { + return; + } + + const SbTime kDurationToPlay = kSbTimeMillisecond * 200; + + GroupedSamples samples; + if (player_fixture.HasAudio()) { + samples.AddAudioSamplesWithEOS( + 0, player_fixture.ConvertDurationToAudioBufferCount(kDurationToPlay)); + } + if (player_fixture.HasVideo()) { + samples.AddVideoSamplesWithEOS( + 0, player_fixture.ConvertDurationToVideoBufferCount(kDurationToPlay)); + } + + ASSERT_NO_FATAL_FAILURE(player_fixture.Write(samples)); + ASSERT_NO_FATAL_FAILURE(player_fixture.WaitForPlayerEndOfStream()); +} + +TEST_P(MultiplePlayerTest, WriteSamples) { + RunTest(WriteSamples); +} + +std::string GetMultipleSbPlayerTestConfigName( + ::testing::TestParamInfo info) { + const SbPlayerMultiplePlayerTestConfig& multiplayer_test_config = info.param; + + SB_DCHECK(multiplayer_test_config.size() > 0); + const SbPlayerOutputMode output_mode = + std::get<2>(multiplayer_test_config[0]); + const char* key_system = std::get<3>(multiplayer_test_config[0]); + + std::string name; + for (int i = 0; i < multiplayer_test_config.size(); i++) { + const SbPlayerTestConfig& config = multiplayer_test_config[i]; + const char* audio_filename = std::get<0>(config); + const char* video_filename = std::get<1>(config); + SB_DCHECK(std::get<2>(multiplayer_test_config[i]) == output_mode); + // We simply check the string pointers here. + SB_DCHECK(std::get<3>(multiplayer_test_config[i]) == key_system); + + if (i > 0) { + name += "_"; + } + name += FormatString( + "audio%d_%s_video%d_%s", i, + audio_filename && strlen(audio_filename) > 0 ? audio_filename : "null", + i, + video_filename && strlen(video_filename) > 0 ? video_filename : "null"); + } + + name += FormatString("_output_%s_key_system_%s", + output_mode == kSbPlayerOutputModeDecodeToTexture + ? "decode_to_texture" + : "punch_out", + strlen(key_system) > 0 ? key_system : "null"); + std::replace(name.begin(), name.end(), '.', '_'); + std::replace(name.begin(), name.end(), '(', '_'); + std::replace(name.begin(), name.end(), ')', '_'); + return name; +} + +std::vector GetSupportedTestConfigs() { + std::vector configs_to_return; + // TODO(cweichun): wait for maximum configuration explorer, set to 1 now. + const int num_of_players = 1; + std::vector supported_configs = + GetSupportedSbPlayerTestConfigs(); + for (auto& config : supported_configs) { + SbPlayerMultiplePlayerTestConfig multiplayer_test_config(num_of_players, + config); + configs_to_return.emplace_back(multiplayer_test_config); + } + return configs_to_return; +} + +INSTANTIATE_TEST_CASE_P(MultiplePlayerTests, + MultiplePlayerTest, + ValuesIn(GetSupportedTestConfigs()), + GetMultipleSbPlayerTestConfigName); + +} // namespace +} // namespace nplb +} // namespace starboard diff --git a/starboard/nplb/player_get_audio_configuration_test.cc b/starboard/nplb/player_get_audio_configuration_test.cc index 89fd29c77298..f982ff08e3c1 100644 --- a/starboard/nplb/player_get_audio_configuration_test.cc +++ b/starboard/nplb/player_get_audio_configuration_test.cc @@ -16,6 +16,7 @@ #include "starboard/nplb/player_test_fixture.h" #include "starboard/string.h" +#include "starboard/testing/fake_graphics_context_provider.h" #include "testing/gtest/include/gtest/gtest.h" #if SB_API_VERSION >= 15 @@ -29,6 +30,7 @@ namespace starboard { namespace nplb { namespace { +using ::starboard::testing::FakeGraphicsContextProvider; using ::testing::ValuesIn; typedef SbPlayerTestFixture::GroupedSamples GroupedSamples; @@ -98,12 +100,15 @@ class SbPlayerGetAudioConfigurationTest ASSERT_TRUE(coding_type_is_valid); ASSERT_GE(configuration.number_of_channels, 0); } + + FakeGraphicsContextProvider fake_graphics_context_provider_; }; TEST_P(SbPlayerGetAudioConfigurationTest, SunnyDay) { const int kSamplesToWrite = 8; - SbPlayerTestFixture player_fixture(GetParam()); + SbPlayerTestFixture player_fixture(GetParam(), + &fake_graphics_context_provider_); if (HasFatalFailure()) { return; } @@ -148,7 +153,8 @@ TEST_P(SbPlayerGetAudioConfigurationTest, SunnyDay) { } TEST_P(SbPlayerGetAudioConfigurationTest, NoInput) { - SbPlayerTestFixture player_fixture(GetParam()); + SbPlayerTestFixture player_fixture(GetParam(), + &fake_graphics_context_provider_); if (HasFatalFailure()) { return; } @@ -188,7 +194,8 @@ TEST_P(SbPlayerGetAudioConfigurationTest, NoInput) { TEST_P(SbPlayerGetAudioConfigurationTest, MultipleSeeks) { const int kSamplesToWrite = 8; - SbPlayerTestFixture player_fixture(GetParam()); + SbPlayerTestFixture player_fixture(GetParam(), + &fake_graphics_context_provider_); if (HasFatalFailure()) { return; } diff --git a/starboard/nplb/player_test_fixture.cc b/starboard/nplb/player_test_fixture.cc index 730a4514d5eb..02a75f54dbce 100644 --- a/starboard/nplb/player_test_fixture.cc +++ b/starboard/nplb/player_test_fixture.cc @@ -46,8 +46,12 @@ SbPlayerTestFixture::CallbackEvent::CallbackEvent(SbPlayer player, player_state(state), ticket(ticket) {} -SbPlayerTestFixture::SbPlayerTestFixture(const SbPlayerTestConfig& config) - : output_mode_(std::get<2>(config)), key_system_(std::get<3>(config)) { +SbPlayerTestFixture::SbPlayerTestFixture( + const SbPlayerTestConfig& config, + FakeGraphicsContextProvider* fake_graphics_context_provider) + : output_mode_(std::get<2>(config)), + key_system_(std::get<3>(config)), + fake_graphics_context_provider_(fake_graphics_context_provider) { SB_DCHECK(output_mode_ == kSbPlayerOutputModeDecodeToTexture || output_mode_ == kSbPlayerOutputModePunchOut); @@ -291,10 +295,10 @@ void SbPlayerTestFixture::Initialize() { video_codec = video_dmp_reader_->video_codec(); } player_ = CallSbPlayerCreate( - fake_graphics_context_provider_.window(), video_codec, audio_codec, + fake_graphics_context_provider_->window(), video_codec, audio_codec, drm_system_, audio_stream_info, "", DummyDeallocateSampleFunc, DecoderStatusCallback, PlayerStatusCallback, ErrorCallback, this, - output_mode_, fake_graphics_context_provider_.decoder_target_provider()); + output_mode_, fake_graphics_context_provider_->decoder_target_provider()); ASSERT_TRUE(SbPlayerIsValid(player_)); ASSERT_NO_FATAL_FAILURE(WaitForPlayerState(kSbPlayerStateInitialized)); ASSERT_NO_FATAL_FAILURE(Seek(0)); @@ -466,7 +470,7 @@ void SbPlayerTestFixture::GetDecodeTargetWhenSupported() { return; } #if SB_HAS(GLES2) - fake_graphics_context_provider_.RunOnGlesContextThread([&]() { + fake_graphics_context_provider_->RunOnGlesContextThread([&]() { ASSERT_TRUE(SbPlayerIsValid(player_)); if (output_mode_ != kSbPlayerOutputModeDecodeToTexture) { ASSERT_EQ(SbPlayerGetCurrentFrame(player_), kSbDecodeTargetInvalid); diff --git a/starboard/nplb/player_test_fixture.h b/starboard/nplb/player_test_fixture.h index 0ea98bf4abe9..7fdf1444c15c 100644 --- a/starboard/nplb/player_test_fixture.h +++ b/starboard/nplb/player_test_fixture.h @@ -74,7 +74,9 @@ class SbPlayerTestFixture { bool write_video_eos_ = false; }; - explicit SbPlayerTestFixture(const SbPlayerTestConfig& config); + SbPlayerTestFixture( + const SbPlayerTestConfig& config, + testing::FakeGraphicsContextProvider* fake_graphics_context_provider); ~SbPlayerTestFixture(); void Seek(const SbTime time); @@ -192,7 +194,7 @@ class SbPlayerTestFixture { std::string key_system_; scoped_ptr audio_dmp_reader_; scoped_ptr video_dmp_reader_; - testing::FakeGraphicsContextProvider fake_graphics_context_provider_; + testing::FakeGraphicsContextProvider* fake_graphics_context_provider_; SbPlayer player_ = kSbPlayerInvalid; SbDrmSystem drm_system_ = kSbDrmSystemInvalid; diff --git a/starboard/nplb/player_write_sample_test.cc b/starboard/nplb/player_write_sample_test.cc index eca004124b47..a10d1b02fb77 100644 --- a/starboard/nplb/player_write_sample_test.cc +++ b/starboard/nplb/player_write_sample_test.cc @@ -16,6 +16,7 @@ #include "starboard/nplb/player_test_fixture.h" #include "starboard/nplb/player_test_util.h" #include "starboard/string.h" +#include "starboard/testing/fake_graphics_context_provider.h" #include "testing/gtest/include/gtest/gtest.h" namespace starboard { @@ -25,12 +26,17 @@ namespace { using ::testing::ValuesIn; typedef SbPlayerTestFixture::GroupedSamples GroupedSamples; +typedef testing::FakeGraphicsContextProvider FakeGraphicsContextProvider; class SbPlayerWriteSampleTest - : public ::testing::TestWithParam {}; + : public ::testing::TestWithParam { + protected: + FakeGraphicsContextProvider fake_graphics_context_provider_; +}; TEST_P(SbPlayerWriteSampleTest, SeekAndDestroy) { - SbPlayerTestFixture player_fixture(GetParam()); + SbPlayerTestFixture player_fixture(GetParam(), + &fake_graphics_context_provider_); if (HasFatalFailure()) { return; } @@ -38,7 +44,8 @@ TEST_P(SbPlayerWriteSampleTest, SeekAndDestroy) { } TEST_P(SbPlayerWriteSampleTest, NoInput) { - SbPlayerTestFixture player_fixture(GetParam()); + SbPlayerTestFixture player_fixture(GetParam(), + &fake_graphics_context_provider_); if (HasFatalFailure()) { return; } @@ -55,7 +62,8 @@ TEST_P(SbPlayerWriteSampleTest, NoInput) { } TEST_P(SbPlayerWriteSampleTest, WriteSingleBatch) { - SbPlayerTestFixture player_fixture(GetParam()); + SbPlayerTestFixture player_fixture(GetParam(), + &fake_graphics_context_provider_); if (HasFatalFailure()) { return; } @@ -77,7 +85,8 @@ TEST_P(SbPlayerWriteSampleTest, WriteSingleBatch) { } TEST_P(SbPlayerWriteSampleTest, WriteMultipleBatches) { - SbPlayerTestFixture player_fixture(GetParam()); + SbPlayerTestFixture player_fixture(GetParam(), + &fake_graphics_context_provider_); if (HasFatalFailure()) { return; } diff --git a/starboard/nplb/vertical_video_test.cc b/starboard/nplb/vertical_video_test.cc index 335b355fd657..eef1fb36d840 100644 --- a/starboard/nplb/vertical_video_test.cc +++ b/starboard/nplb/vertical_video_test.cc @@ -22,6 +22,7 @@ #include "starboard/nplb/player_test_util.h" #include "starboard/player.h" #include "starboard/shared/starboard/player/video_dmp_reader.h" +#include "starboard/testing/fake_graphics_context_provider.h" #include "starboard/time.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,6 +36,8 @@ using ::testing::ValuesIn; typedef SbPlayerTestFixture::GroupedSamples GroupedSamples; class VerticalVideoTest : public ::testing::TestWithParam { + protected: + testing::FakeGraphicsContextProvider fake_graphics_context_provider_; }; void CheckVerticalResolutionSupport(const char* mime) { @@ -117,7 +120,8 @@ TEST(VerticalVideoTest, CapabilityQuery) { } TEST_P(VerticalVideoTest, WriteSamples) { - SbPlayerTestFixture player_fixture(GetParam()); + SbPlayerTestFixture player_fixture(GetParam(), + &fake_graphics_context_provider_); if (HasFatalFailure()) { return; } diff --git a/starboard/raspi/shared/test_filters.py b/starboard/raspi/shared/test_filters.py index bf435817efd4..57d4ba0239dd 100644 --- a/starboard/raspi/shared/test_filters.py +++ b/starboard/raspi/shared/test_filters.py @@ -23,6 +23,7 @@ # Permanently filter out drm system related tests as raspi doesn't # support any drm systems and there is no plan to implement such # support. + 'MultiplePlayerTests*', 'SbDrmTest.AnySupportedKeySystems', 'SbMediaCanPlayMimeAndKeySystem.AnySupportedKeySystems', 'SbMediaCanPlayMimeAndKeySystem.KeySystemWithAttributes', diff --git a/starboard/win/win32/test_filters.py b/starboard/win/win32/test_filters.py index 6bf85fa8a368..afa9f695f69d 100644 --- a/starboard/win/win32/test_filters.py +++ b/starboard/win/win32/test_filters.py @@ -29,6 +29,7 @@ # performs an optimization that defeats the SB_C_NOINLINE 'noinline' # attribute. 'SbSystemGetStackTest.SunnyDayStackDirection', + 'MultiplePlayerTests/*beneath_the_canopy_137_avc_dmp*', # Failures tracked by b/256160416. 'SbSystemGetPathTest.ReturnsRequiredPaths',