15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_audio.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_audio_config.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_audio.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/testing_instance.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_utils.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#if defined(__native_client__) 160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "native_client/src/untrusted/irt/irt.h" 170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ppapi/native_client/src/untrusted/irt_stub/thread_creator.h" 180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#endif 190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ARRAYSIZE_UNSAFE(a) \ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((sizeof(a) / sizeof(*(a))) / \ 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#if defined(__native_client__) 250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace { 260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid GetNaClIrtPpapiHook(struct nacl_irt_ppapihook* hooks) { 280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch nacl_interface_query(NACL_IRT_PPAPIHOOK_v0_1, hooks, sizeof(*hooks)); 290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstruct PP_ThreadFunctions g_thread_funcs = {}; 320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ThreadFunctionsGetter(const struct PP_ThreadFunctions* thread_funcs) { 340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch g_thread_funcs = *thread_funcs; 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// In order to check if the thread_create is called, CountingThreadCreate() 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// increments this variable. Callers can check if the function is actually 390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// called by looking at this value. 400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint g_num_thread_create_called = 0; 410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint g_num_thread_join_called = 0; 420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint CountingThreadCreate(uintptr_t* tid, 440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch void (*func)(void* thread_argument), 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch void* thread_argument) { 460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++g_num_thread_create_called; 470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return g_thread_funcs.thread_create(tid, func, thread_argument); 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint CountingThreadJoin(uintptr_t tid) { 510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++g_num_thread_join_called; 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return g_thread_funcs.thread_join(tid); 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Sets NULL for PP_ThreadFunctions to emulate the situation that 560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// ppapi_register_thread_creator() is not yet called. 570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SetNullThreadFunctions() { 580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch nacl_irt_ppapihook hooks; 590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GetNaClIrtPpapiHook(&hooks); 600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PP_ThreadFunctions thread_functions = {}; 610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hooks.ppapi_register_thread_creator(&thread_functions); 620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid InjectCountingThreadFunctions() { 650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // First of all, we extract the system default thread functions. 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Internally, __nacl_register_thread_creator calls 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // hooks.ppapi_register_thread_creator with default PP_ThreadFunctions 680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // instance. ThreadFunctionGetter stores it to g_thread_funcs. 690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch nacl_irt_ppapihook hooks = { NULL, ThreadFunctionsGetter }; 700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch __nacl_register_thread_creator(&hooks); 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Here g_thread_funcs stores the thread functions. 730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Inject the CountingThreadCreate. 740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PP_ThreadFunctions thread_functions = { 750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CountingThreadCreate, 760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CountingThreadJoin, 770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch }; 780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GetNaClIrtPpapiHook(&hooks); 790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch hooks.ppapi_register_thread_creator(&thread_functions); 800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Resets the PP_ThreadFunctions on exit from the scope. 830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass ScopedThreadFunctionsResetter { 840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch public: 850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScopedThreadFunctionsResetter() {} 860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ~ScopedThreadFunctionsResetter() { 870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch nacl_irt_ppapihook hooks; 880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GetNaClIrtPpapiHook(&hooks); 890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch __nacl_register_thread_creator(&hooks); 900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}; 920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} // namespace 940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#endif // __native_client__ 950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_TEST_CASE(Audio); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestAudio::TestAudio(TestingInstance* instance) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : TestCase(instance), 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_(NULL), 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_(instance->pp_instance()), 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) test_done_(false), 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_interface_(NULL), 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_interface_1_0_(NULL), 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_config_interface_(NULL), 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) core_interface_(NULL) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestAudio::~TestAudio() { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestAudio::Init() { 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_interface_ = static_cast<const PPB_Audio_1_1*>( 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) pp::Module::Get()->GetBrowserInterface(PPB_AUDIO_INTERFACE_1_1)); 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_interface_1_0_ = static_cast<const PPB_Audio_1_0*>( 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) pp::Module::Get()->GetBrowserInterface(PPB_AUDIO_INTERFACE_1_0)); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_config_interface_ = static_cast<const PPB_AudioConfig*>( 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Module::Get()->GetBrowserInterface(PPB_AUDIO_CONFIG_INTERFACE)); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_ = static_cast<const PPB_Core*>( 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return audio_interface_ && audio_interface_1_0_ && audio_config_interface_ && 12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) core_interface_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestAudio::RunTests(const std::string& filter) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN_TEST(Creation, filter); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN_TEST(DestroyNoStop, filter); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN_TEST(Failures, filter); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN_TEST(AudioCallback1, filter); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN_TEST(AudioCallback2, filter); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN_TEST(AudioCallback3, filter); 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RUN_TEST(AudioCallback4, filter); 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#if defined(__native_client__) 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RUN_TEST(AudioThreadCreatorIsRequired, filter); 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RUN_TEST(AudioThreadCreatorIsCalled, filter); 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#endif 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test creating audio resources for all guaranteed sample rates and various 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// frame counts. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestAudio::TestCreation() { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const PP_AudioSampleRate kSampleRates[] = { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_AUDIOSAMPLERATE_44100, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_AUDIOSAMPLERATE_48000 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const uint32_t kRequestFrameCounts[] = { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_AUDIOMINSAMPLEFRAMECOUNT, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_AUDIOMAXSAMPLEFRAMECOUNT, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Include some "okay-looking" frame counts; check their validity below. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_AUDIOSAMPLERATE_44100 / 100, // 10ms @ 44.1kHz 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_AUDIOSAMPLERATE_48000 / 100, // 10ms @ 48kHz 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2 * PP_AUDIOSAMPLERATE_44100 / 100, // 20ms @ 44.1kHz 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2 * PP_AUDIOSAMPLERATE_48000 / 100, // 20ms @ 48kHz 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1024, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2048, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4096 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_AudioSampleRate sample_rate = audio_config_interface_->RecommendSampleRate( 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance()); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(sample_rate == PP_AUDIOSAMPLERATE_NONE || 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sample_rate == PP_AUDIOSAMPLERATE_44100 || 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sample_rate == PP_AUDIOSAMPLERATE_48000); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSampleRates); i++) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_AudioSampleRate sample_rate = kSampleRates[i]; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kRequestFrameCounts); j++) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make a config, create the audio resource, and release the config. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t request_frame_count = kRequestFrameCounts[j]; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t frame_count = audio_config_interface_->RecommendSampleFrameCount( 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), sample_rate, request_frame_count); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Resource ac = audio_config_interface_->CreateStereo16Bit( 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), sample_rate, frame_count); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(ac); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Resource audio = audio_interface_->Create( 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), ac, AudioCallbackTrampoline, this); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(ac); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ac = 0; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->IsAudio(audio)); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the config returned for |audio| matches what we gave it. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ac = audio_interface_->GetCurrentConfig(audio); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(ac); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_config_interface_->IsAudioConfig(ac)); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(sample_rate, audio_config_interface_->GetSampleRate(ac)); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(frame_count, audio_config_interface_->GetSampleFrameCount(ac)); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(ac); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ac = 0; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start and stop audio playback. The documentation indicates that 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |StartPlayback()| and |StopPlayback()| may fail, but gives no 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // indication as to why ... so check that they succeed. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = &TestAudio::AudioCallbackTrivial; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StartPlayback(audio)); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StopPlayback(audio)); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(audio); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PASS(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that releasing the resource without calling |StopPlayback()| "works". 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestAudio::TestDestroyNoStop() { 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 2048); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(ac); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Resource audio = audio_interface_->Create( 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), ac, AudioCallbackTrampoline, this); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(ac); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ac = 0; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->IsAudio(audio)); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start playback and release the resource. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = &TestAudio::AudioCallbackTrivial; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StartPlayback(audio)); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(audio); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PASS(); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestAudio::TestFailures() { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test invalid parameters to |Create()|. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want a valid config for some of our tests of |Create()|. 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 2048); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(ac); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Failure cases should never lead to the callback being called. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid instance -> failure. 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Resource audio = audio_interface_->Create( 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, ac, AudioCallbackTrampoline, this); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(0, audio); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid config -> failure. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio = audio_interface_->Create( 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), 0, AudioCallbackTrampoline, this); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(0, audio); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Null callback -> failure. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio = audio_interface_->Create( 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), ac, NULL, NULL); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(0, audio); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(ac); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ac = 0; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test the other functions with an invalid audio resource. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(audio_interface_->IsAudio(0)); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(0, audio_interface_->GetCurrentConfig(0)); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(audio_interface_->StartPlayback(0)); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(audio_interface_->StopPlayback(0)); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PASS(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// NOTE: |TestAudioCallbackN| assumes that the audio callback is called at least 26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// once. If the audio stream does not start up correctly or is interrupted this 26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// may not be the case and these tests will fail. However, in order to properly 26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// test the audio callbacks, we must have a configuration where audio can 27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// successfully play, so we assume this is the case on bots. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test starts playback and verifies that: 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1) the audio callback is actually called; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2) that |StopPlayback()| waits for the audio callback to finish. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestAudio::TestAudioCallback1() { 27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(ac); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Resource audio = audio_interface_->Create( 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), ac, AudioCallbackTrampoline, this); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(ac); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ac = 0; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Reset(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_done_ = false; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = &TestAudio::AudioCallbackTest; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StartPlayback(audio)); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the audio callback to be called. 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Wait(); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StopPlayback(audio)); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_done_ = true; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If any more audio callbacks are generated, we should crash (which is good). 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(audio); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PASS(); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the same as |TestAudioCallback1()|, except that instead of calling 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |StopPlayback()|, it just releases the resource. 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestAudio::TestAudioCallback2() { 30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(ac); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Resource audio = audio_interface_->Create( 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), ac, AudioCallbackTrampoline, this); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(ac); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ac = 0; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Reset(); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_done_ = false; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = &TestAudio::AudioCallbackTest; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StartPlayback(audio)); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the audio callback to be called. 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Wait(); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(audio); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_done_ = true; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If any more audio callbacks are generated, we should crash (which is good). 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PASS(); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the same as |TestAudioCallback1()|, except that it attempts a second 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// round of |StartPlayback| and |StopPlayback| to make sure the callback 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function still responds when using the same audio resource. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestAudio::TestAudioCallback3() { 33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(ac); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Resource audio = audio_interface_->Create( 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance_->pp_instance(), ac, AudioCallbackTrampoline, this); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(ac); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ac = 0; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Reset(); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_done_ = false; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = &TestAudio::AudioCallbackTest; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StartPlayback(audio)); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the audio callback to be called. 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Wait(); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StopPlayback(audio)); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Repeat one more |StartPlayback| & |StopPlayback| cycle, and verify again 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the callback function was invoked. 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Reset(); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StartPlayback(audio)); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the audio callback to be called. 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Wait(); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(audio_interface_->StopPlayback(audio)); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) test_done_ = true; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If any more audio callbacks are generated, we should crash (which is good). 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_callback_method_ = NULL; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_interface_->ReleaseResource(audio); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PASS(); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// This is the same as |TestAudioCallback1()|, except that it uses 37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// PPB_Audio_1_0. 37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string TestAudio::TestAudioCallback4() { 37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024); 37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ASSERT_TRUE(ac); 37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_callback_method_ = NULL; 38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_Resource audio = audio_interface_1_0_->Create( 38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) instance_->pp_instance(), ac, AudioCallbackTrampoline1_0, this); 38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) core_interface_->ReleaseResource(ac); 38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ac = 0; 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_callback_event_.Reset(); 38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) test_done_ = false; 38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_callback_method_ = &TestAudio::AudioCallbackTest; 38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ASSERT_TRUE(audio_interface_1_0_->StartPlayback(audio)); 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Wait for the audio callback to be called. 39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_callback_event_.Wait(); 39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ASSERT_TRUE(audio_interface_1_0_->StopPlayback(audio)); 39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) test_done_ = true; 39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If any more audio callbacks are generated, we should crash (which is good). 39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) audio_callback_method_ = NULL; 39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 39958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) core_interface_->ReleaseResource(audio); 40058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PASS(); 40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#if defined(__native_client__) 4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Tests the behavior of the thread_create functions. 4060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// For PPB_Audio_Shared to work properly, the user code must call 4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// ppapi_register_thread_creator(). This test checks the error handling for the 4080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// case when user code doesn't call ppapi_register_thread_creator(). 4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstd::string TestAudio::TestAudioThreadCreatorIsRequired() { 4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // We'll inject some thread functions in this test case. 4110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Reset them at the end of this case. 4120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScopedThreadFunctionsResetter thread_resetter; 4130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Set the thread functions to NULLs to emulate the situation where 4150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // ppapi_register_thread_creator() is not called by user code. 4160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SetNullThreadFunctions(); 4170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024); 4190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(ac); 4200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_callback_method_ = NULL; 4210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PP_Resource audio = audio_interface_->Create( 4220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch instance_->pp_instance(), ac, AudioCallbackTrampoline, this); 4230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch core_interface_->ReleaseResource(ac); 4240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ac = 0; 4250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // StartPlayback() fails, because no thread creating function 4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // is available. 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_FALSE(audio_interface_->StartPlayback(audio)); 4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If any more audio callbacks are generated, 4310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // we should crash (which is good). 4320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_callback_method_ = NULL; 4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch core_interface_->ReleaseResource(audio); 4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PASS(); 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Tests whether the thread functions passed from the user code are actually 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// called. 4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstd::string TestAudio::TestAudioThreadCreatorIsCalled() { 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // We'll inject some thread functions in this test case. 4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Reset them at the end of this case. 4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScopedThreadFunctionsResetter thread_resetter; 4450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Inject the thread counting function. In the injected function, 4470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // when called, g_num_thread_create_called is incremented. 4480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch g_num_thread_create_called = 0; 4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch g_num_thread_join_called = 0; 4500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch InjectCountingThreadFunctions(); 4510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024); 4530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(ac); 4540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_callback_method_ = NULL; 4550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PP_Resource audio = audio_interface_->Create( 4560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch instance_->pp_instance(), ac, AudioCallbackTrampoline, this); 4570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch core_interface_->ReleaseResource(ac); 4580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ac = 0; 4590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_callback_event_.Reset(); 4610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch test_done_ = false; 4620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_callback_method_ = &TestAudio::AudioCallbackTest; 4640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(audio_interface_->StartPlayback(audio)); 4650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Wait for the audio callback to be called. 4670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_callback_event_.Wait(); 4680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Here, the injected thread_create is called, but thread_join is not yet. 4690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(1, g_num_thread_create_called); 4700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(0, g_num_thread_join_called); 4710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_TRUE(audio_interface_->StopPlayback(audio)); 4730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch test_done_ = true; 4750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Here, the injected thread_join is called. 4770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(1, g_num_thread_join_called); 4780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If any more audio callbacks are generated, 4800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // we should crash (which is good). 4810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_callback_method_ = NULL; 4820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch core_interface_->ReleaseResource(audio); 4840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PASS(); 4860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#endif 4880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(raymes): Test that actually playback happens correctly, etc. 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Crash() { 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *static_cast<volatile unsigned*>(NULL) = 0xdeadbeef; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestAudio::AudioCallbackTrampoline(void* sample_buffer, 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t buffer_size_in_bytes, 49858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_TimeDelta latency, 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* user_data) { 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestAudio* thiz = static_cast<TestAudio*>(user_data); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Crash if on the main thread. 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thiz->core_interface_->IsMainThread()) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Crash(); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioCallbackMethod method = thiz->audio_callback_method_; 50758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) (thiz->*method)(sample_buffer, buffer_size_in_bytes, latency); 50858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 50958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 51058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static 51158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TestAudio::AudioCallbackTrampoline1_0(void* sample_buffer, 51258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) uint32_t buffer_size_in_bytes, 51358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void* user_data) { 51458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AudioCallbackTrampoline(sample_buffer, buffer_size_in_bytes, 0.0, user_data); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestAudio::AudioCallbackTrivial(void* sample_buffer, 51858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) uint32_t buffer_size_in_bytes, 51958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_TimeDelta latency) { 52058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (latency < 0) 52158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Crash(); 52258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(sample_buffer, 0, buffer_size_in_bytes); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestAudio::AudioCallbackTest(void* sample_buffer, 52758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) uint32_t buffer_size_in_bytes, 52858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_TimeDelta latency) { 52958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (test_done_ || latency < 0) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Crash(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memset(sample_buffer, 0, buffer_size_in_bytes); 533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_callback_event_.Signal(); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 53558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 53658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)PP_Resource TestAudio::CreateAudioConfig( 53758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_AudioSampleRate sample_rate, 53858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) uint32_t requested_sample_frame_count) { 53958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) uint32_t frame_count = audio_config_interface_->RecommendSampleFrameCount( 54058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) instance_->pp_instance(), sample_rate, requested_sample_frame_count); 54158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return audio_config_interface_->CreateStereo16Bit( 54258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) instance_->pp_instance(), sample_rate, frame_count); 54358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 544