Commit 6b151126 authored by yzshen@chromium.org's avatar yzshen@chromium.org

Add a new parameter |latency| to PPB_Audio.

This CL updates the version of PPB_Audio and PPB_Audio_Callback.

BUG=240900
TEST=updated test_audio.{h,cc}

Review URL: https://chromiumcodereview.appspot.com/22320004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221788 0039d316-1c4b-4281-b951-d872f2087c98
parent 1151b025
...@@ -1325,35 +1325,45 @@ IN_PROC_BROWSER_TEST_F(PPAPITest, MAYBE_Audio) { ...@@ -1325,35 +1325,45 @@ IN_PROC_BROWSER_TEST_F(PPAPITest, MAYBE_Audio) {
LIST_TEST(Audio_DestroyNoStop) LIST_TEST(Audio_DestroyNoStop)
LIST_TEST(Audio_Failures) LIST_TEST(Audio_Failures)
LIST_TEST(Audio_AudioCallback1) LIST_TEST(Audio_AudioCallback1)
LIST_TEST(Audio_AudioCallback2)); LIST_TEST(Audio_AudioCallback2)
LIST_TEST(Audio_AudioCallback3)
LIST_TEST(Audio_AudioCallback4));
} }
IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, Audio) { IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, Audio) {
RunTest(LIST_TEST(Audio_Creation) RunTest(LIST_TEST(Audio_Creation)
LIST_TEST(Audio_DestroyNoStop) LIST_TEST(Audio_DestroyNoStop)
LIST_TEST(Audio_Failures) LIST_TEST(Audio_Failures)
LIST_TEST(Audio_AudioCallback1) LIST_TEST(Audio_AudioCallback1)
LIST_TEST(Audio_AudioCallback2)); LIST_TEST(Audio_AudioCallback2)
LIST_TEST(Audio_AudioCallback3)
LIST_TEST(Audio_AudioCallback4));
} }
IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, Audio) { IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, Audio) {
RunTestViaHTTP(LIST_TEST(Audio_Creation) RunTestViaHTTP(LIST_TEST(Audio_Creation)
LIST_TEST(Audio_DestroyNoStop) LIST_TEST(Audio_DestroyNoStop)
LIST_TEST(Audio_Failures) LIST_TEST(Audio_Failures)
LIST_TEST(Audio_AudioCallback1) LIST_TEST(Audio_AudioCallback1)
LIST_TEST(Audio_AudioCallback2)); LIST_TEST(Audio_AudioCallback2)
LIST_TEST(Audio_AudioCallback3)
LIST_TEST(Audio_AudioCallback4));
} }
IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(Audio)) { IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(Audio)) {
RunTestViaHTTP(LIST_TEST(Audio_Creation) RunTestViaHTTP(LIST_TEST(Audio_Creation)
LIST_TEST(Audio_DestroyNoStop) LIST_TEST(Audio_DestroyNoStop)
LIST_TEST(Audio_Failures) LIST_TEST(Audio_Failures)
LIST_TEST(Audio_AudioCallback1) LIST_TEST(Audio_AudioCallback1)
LIST_TEST(Audio_AudioCallback2)); LIST_TEST(Audio_AudioCallback2)
LIST_TEST(Audio_AudioCallback3)
LIST_TEST(Audio_AudioCallback4));
} }
IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, Audio) { IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, Audio) {
RunTestViaHTTP(LIST_TEST(Audio_Creation) RunTestViaHTTP(LIST_TEST(Audio_Creation)
LIST_TEST(Audio_DestroyNoStop) LIST_TEST(Audio_DestroyNoStop)
LIST_TEST(Audio_Failures) LIST_TEST(Audio_Failures)
LIST_TEST(Audio_AudioCallback1) LIST_TEST(Audio_AudioCallback1)
LIST_TEST(Audio_AudioCallback2)); LIST_TEST(Audio_AudioCallback2)
LIST_TEST(Audio_AudioCallback3)
LIST_TEST(Audio_AudioCallback4));
} }
TEST_PPAPI_IN_PROCESS(View_CreatedVisible); TEST_PPAPI_IN_PROCESS(View_CreatedVisible);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "content/renderer/pepper/audio_helper.h" #include "content/renderer/pepper/audio_helper.h"
#include "content/renderer/render_thread_impl.h" #include "content/renderer/render_thread_impl.h"
#include "media/base/audio_hardware_config.h" #include "media/base/audio_hardware_config.h"
#include "ppapi/shared_impl/ppb_audio_config_shared.h"
namespace content { namespace content {
...@@ -126,7 +127,8 @@ bool PepperPlatformAudioOutput::Initialize( ...@@ -126,7 +127,8 @@ bool PepperPlatformAudioOutput::Initialize(
media::AudioParameters params( media::AudioParameters params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO, sample_rate, 16, frames_per_buffer); media::CHANNEL_LAYOUT_STEREO, sample_rate,
ppapi::kBitsPerAudioOutputSample, frames_per_buffer);
io_message_loop_proxy_->PostTask( io_message_loop_proxy_->PostTask(
FROM_HERE, FROM_HERE,
......
...@@ -30,8 +30,7 @@ namespace content { ...@@ -30,8 +30,7 @@ namespace content {
PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance) PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance)
: Resource(ppapi::OBJECT_IS_IMPL, instance), : Resource(ppapi::OBJECT_IS_IMPL, instance),
audio_(NULL), audio_(NULL) {
sample_frame_count_(0) {
} }
PPB_Audio_Impl::~PPB_Audio_Impl() { PPB_Audio_Impl::~PPB_Audio_Impl() {
...@@ -47,10 +46,11 @@ PPB_Audio_Impl::~PPB_Audio_Impl() { ...@@ -47,10 +46,11 @@ PPB_Audio_Impl::~PPB_Audio_Impl() {
} }
// static // static
PP_Resource PPB_Audio_Impl::Create(PP_Instance instance, PP_Resource PPB_Audio_Impl::Create(
PP_Resource config, PP_Instance instance,
PPB_Audio_Callback audio_callback, PP_Resource config,
void* user_data) { const ppapi::AudioCallbackCombined& audio_callback,
void* user_data) {
scoped_refptr<PPB_Audio_Impl> audio(new PPB_Audio_Impl(instance)); scoped_refptr<PPB_Audio_Impl> audio(new PPB_Audio_Impl(instance));
if (!audio->Init(config, audio_callback, user_data)) if (!audio->Init(config, audio_callback, user_data))
return 0; return 0;
...@@ -62,14 +62,15 @@ PPB_Audio_API* PPB_Audio_Impl::AsPPB_Audio_API() { ...@@ -62,14 +62,15 @@ PPB_Audio_API* PPB_Audio_Impl::AsPPB_Audio_API() {
} }
bool PPB_Audio_Impl::Init(PP_Resource config, bool PPB_Audio_Impl::Init(PP_Resource config,
PPB_Audio_Callback callback, void* user_data) { const ppapi::AudioCallbackCombined& callback,
void* user_data) {
// Validate the config and keep a reference to it. // Validate the config and keep a reference to it.
EnterResourceNoLock<PPB_AudioConfig_API> enter(config, true); EnterResourceNoLock<PPB_AudioConfig_API> enter(config, true);
if (enter.failed()) if (enter.failed())
return false; return false;
config_ = config; config_ = config;
if (!callback) if (!callback.IsValid())
return false; return false;
SetCallback(callback, user_data); SetCallback(callback, user_data);
...@@ -84,7 +85,6 @@ bool PPB_Audio_Impl::Init(PP_Resource config, ...@@ -84,7 +85,6 @@ bool PPB_Audio_Impl::Init(PP_Resource config,
static_cast<int>(enter.object()->GetSampleFrameCount()), static_cast<int>(enter.object()->GetSampleFrameCount()),
instance->GetRenderView()->GetRoutingID(), instance->GetRenderView()->GetRoutingID(),
this); this);
sample_frame_count_ = enter.object()->GetSampleFrameCount();
return audio_ != NULL; return audio_ != NULL;
} }
...@@ -158,8 +158,10 @@ void PPB_Audio_Impl::OnSetStreamInfo( ...@@ -158,8 +158,10 @@ void PPB_Audio_Impl::OnSetStreamInfo(
base::SharedMemoryHandle shared_memory_handle, base::SharedMemoryHandle shared_memory_handle,
size_t shared_memory_size, size_t shared_memory_size,
base::SyncSocket::Handle socket_handle) { base::SyncSocket::Handle socket_handle) {
EnterResourceNoLock<PPB_AudioConfig_API> enter(config_, true);
SetStreamInfo(pp_instance(), shared_memory_handle, shared_memory_size, SetStreamInfo(pp_instance(), shared_memory_handle, shared_memory_size,
socket_handle, sample_frame_count_); socket_handle, enter.object()->GetSampleRate(),
enter.object()->GetSampleFrameCount());
} }
} // namespace content } // namespace content
...@@ -37,12 +37,12 @@ class PPB_Audio_Impl : public ppapi::Resource, ...@@ -37,12 +37,12 @@ class PPB_Audio_Impl : public ppapi::Resource,
// and will return 0 on failure. // and will return 0 on failure.
static PP_Resource Create(PP_Instance instance, static PP_Resource Create(PP_Instance instance,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback audio_callback, const ppapi::AudioCallbackCombined& audio_callback,
void* user_data); void* user_data);
// Initialization function for trusted init. // Initialization function for trusted init.
bool Init(PP_Resource config_id, bool Init(PP_Resource config_id,
PPB_Audio_Callback user_callback, const ppapi::AudioCallbackCombined& user_callback,
void* user_data); void* user_data);
// Resource overrides. // Resource overrides.
...@@ -73,9 +73,6 @@ class PPB_Audio_Impl : public ppapi::Resource, ...@@ -73,9 +73,6 @@ class PPB_Audio_Impl : public ppapi::Resource,
// own this pointer but are responsible for calling Shutdown on it. // own this pointer but are responsible for calling Shutdown on it.
PepperPlatformAudioOutput* audio_; PepperPlatformAudioOutput* audio_;
// Track frame count for passing on to PPB_Audio_Shared::SetStreamInfo().
int sample_frame_count_;
DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Impl); DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Impl);
}; };
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "content/renderer/pepper/ppb_video_decoder_impl.h" #include "content/renderer/pepper/ppb_video_decoder_impl.h"
#include "ppapi/c/pp_size.h" #include "ppapi/c/pp_size.h"
#include "ppapi/shared_impl/ppb_audio_config_shared.h" #include "ppapi/shared_impl/ppb_audio_config_shared.h"
#include "ppapi/shared_impl/ppb_audio_shared.h"
#include "ppapi/shared_impl/ppb_image_data_shared.h" #include "ppapi/shared_impl/ppb_image_data_shared.h"
#include "ppapi/shared_impl/ppb_input_event_shared.h" #include "ppapi/shared_impl/ppb_input_event_shared.h"
#include "ppapi/shared_impl/ppb_resource_array_shared.h" #include "ppapi/shared_impl/ppb_resource_array_shared.h"
...@@ -34,13 +35,24 @@ ResourceCreationImpl::ResourceCreationImpl(PepperPluginInstanceImpl* instance) { ...@@ -34,13 +35,24 @@ ResourceCreationImpl::ResourceCreationImpl(PepperPluginInstanceImpl* instance) {
ResourceCreationImpl::~ResourceCreationImpl() { ResourceCreationImpl::~ResourceCreationImpl() {
} }
PP_Resource ResourceCreationImpl::CreateAudio1_0(
PP_Instance instance,
PP_Resource config_id,
PPB_Audio_Callback_1_0 audio_callback,
void* user_data) {
return PPB_Audio_Impl::Create(
instance, config_id, ppapi::AudioCallbackCombined(audio_callback),
user_data);
}
PP_Resource ResourceCreationImpl::CreateAudio( PP_Resource ResourceCreationImpl::CreateAudio(
PP_Instance instance, PP_Instance instance,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback audio_callback, PPB_Audio_Callback audio_callback,
void* user_data) { void* user_data) {
return PPB_Audio_Impl::Create(instance, config_id, audio_callback, return PPB_Audio_Impl::Create(
user_data); instance, config_id, ppapi::AudioCallbackCombined(audio_callback),
user_data);
} }
PP_Resource ResourceCreationImpl::CreateAudioConfig( PP_Resource ResourceCreationImpl::CreateAudioConfig(
......
...@@ -23,6 +23,10 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI { ...@@ -23,6 +23,10 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
virtual ~ResourceCreationImpl(); virtual ~ResourceCreationImpl();
// ResourceCreationAPI implementation. // ResourceCreationAPI implementation.
virtual PP_Resource CreateAudio1_0(PP_Instance instance,
PP_Resource config_id,
PPB_Audio_Callback_1_0 audio_callback,
void* user_data) OVERRIDE;
virtual PP_Resource CreateAudio(PP_Instance instance, virtual PP_Resource CreateAudio(PP_Instance instance,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback audio_callback, PPB_Audio_Callback audio_callback,
......
...@@ -8,10 +8,9 @@ ...@@ -8,10 +8,9 @@
* realtime stereo audio streaming capabilities. * realtime stereo audio streaming capabilities.
*/ */
[generate_thunk]
label Chrome { label Chrome {
M14 = 1.0 M14 = 1.0,
M31 = 1.1
}; };
/** /**
...@@ -19,9 +18,16 @@ label Chrome { ...@@ -19,9 +18,16 @@ label Chrome {
* function used to fill the audio buffer with data. Please see the * function used to fill the audio buffer with data. Please see the
* Create() function in the <code>PPB_Audio</code> interface for * Create() function in the <code>PPB_Audio</code> interface for
* more details on this callback. * more details on this callback.
*
* @param[in] sample_buffer A buffer to fill with audio data.
* @param[in] buffer_size_in_bytes The size of the buffer in bytes.
* @param[in] latency How long before the audio data is to be presented.
* @param[inout] user_data An opaque pointer that was passed into
* <code>PPB_Audio.Create()</code>.
*/ */
typedef void PPB_Audio_Callback([out] mem_t sample_buffer, typedef void PPB_Audio_Callback([out] mem_t sample_buffer,
[in] uint32_t buffer_size_in_bytes, [in] uint32_t buffer_size_in_bytes,
[in, version=1.1] PP_TimeDelta latency,
[inout] mem_t user_data); [inout] mem_t user_data);
/** /**
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
/* From ppb_audio.idl modified Mon Jul 9 12:03:36 2012. */ /* From ppb_audio.idl modified Thu Aug 01 13:19:46 2013. */
#ifndef PPAPI_C_PPB_AUDIO_H_ #ifndef PPAPI_C_PPB_AUDIO_H_
#define PPAPI_C_PPB_AUDIO_H_ #define PPAPI_C_PPB_AUDIO_H_
...@@ -13,9 +13,11 @@ ...@@ -13,9 +13,11 @@
#include "ppapi/c/pp_macros.h" #include "ppapi/c/pp_macros.h"
#include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_resource.h"
#include "ppapi/c/pp_stdint.h" #include "ppapi/c/pp_stdint.h"
#include "ppapi/c/pp_time.h"
#define PPB_AUDIO_INTERFACE_1_0 "PPB_Audio;1.0" #define PPB_AUDIO_INTERFACE_1_0 "PPB_Audio;1.0"
#define PPB_AUDIO_INTERFACE PPB_AUDIO_INTERFACE_1_0 #define PPB_AUDIO_INTERFACE_1_1 "PPB_Audio;1.1"
#define PPB_AUDIO_INTERFACE PPB_AUDIO_INTERFACE_1_1
/** /**
* @file * @file
...@@ -33,10 +35,21 @@ ...@@ -33,10 +35,21 @@
* function used to fill the audio buffer with data. Please see the * function used to fill the audio buffer with data. Please see the
* Create() function in the <code>PPB_Audio</code> interface for * Create() function in the <code>PPB_Audio</code> interface for
* more details on this callback. * more details on this callback.
*
* @param[in] sample_buffer A buffer to fill with audio data.
* @param[in] buffer_size_in_bytes The size of the buffer in bytes.
* @param[in] latency How long before the audio data is to be presented.
* @param[inout] user_data An opaque pointer that was passed into
* <code>PPB_Audio.Create()</code>.
*/ */
typedef void (*PPB_Audio_Callback)(void* sample_buffer, typedef void (*PPB_Audio_Callback)(void* sample_buffer,
uint32_t buffer_size_in_bytes, uint32_t buffer_size_in_bytes,
PP_TimeDelta latency,
void* user_data); void* user_data);
typedef void (*PPB_Audio_Callback_1_0)(void* sample_buffer,
uint32_t buffer_size_in_bytes,
void* user_data);
/** /**
* @} * @}
*/ */
...@@ -78,7 +91,7 @@ typedef void (*PPB_Audio_Callback)(void* sample_buffer, ...@@ -78,7 +91,7 @@ typedef void (*PPB_Audio_Callback)(void* sample_buffer,
* ...audio_callback() will now be periodically invoked on a separate thread... * ...audio_callback() will now be periodically invoked on a separate thread...
* @endcode * @endcode
*/ */
struct PPB_Audio_1_0 { struct PPB_Audio_1_1 {
/** /**
* Create() creates an audio resource. No sound will be heard until * Create() creates an audio resource. No sound will be heard until
* StartPlayback() is called. The callback is called with the buffer address * StartPlayback() is called. The callback is called with the buffer address
...@@ -157,7 +170,18 @@ struct PPB_Audio_1_0 { ...@@ -157,7 +170,18 @@ struct PPB_Audio_1_0 {
PP_Bool (*StopPlayback)(PP_Resource audio); PP_Bool (*StopPlayback)(PP_Resource audio);
}; };
typedef struct PPB_Audio_1_0 PPB_Audio; typedef struct PPB_Audio_1_1 PPB_Audio;
struct PPB_Audio_1_0 {
PP_Resource (*Create)(PP_Instance instance,
PP_Resource config,
PPB_Audio_Callback_1_0 audio_callback,
void* user_data);
PP_Bool (*IsAudio)(PP_Resource resource);
PP_Resource (*GetCurrentConfig)(PP_Resource audio);
PP_Bool (*StartPlayback)(PP_Resource audio);
PP_Bool (*StopPlayback)(PP_Resource audio);
};
/** /**
* @} * @}
*/ */
......
...@@ -15,13 +15,30 @@ template <> const char* interface_name<PPB_Audio_1_0>() { ...@@ -15,13 +15,30 @@ template <> const char* interface_name<PPB_Audio_1_0>() {
return PPB_AUDIO_INTERFACE_1_0; return PPB_AUDIO_INTERFACE_1_0;
} }
template <> const char* interface_name<PPB_Audio_1_1>() {
return PPB_AUDIO_INTERFACE_1_1;
}
} // namespace } // namespace
Audio::Audio(const InstanceHandle& instance, Audio::Audio(const InstanceHandle& instance,
const AudioConfig& config, const AudioConfig& config,
PPB_Audio_Callback callback, PPB_Audio_Callback callback,
void* user_data) void* user_data)
: config_(config) { : config_(config),
use_1_0_interface_(false) {
if (has_interface<PPB_Audio_1_1>()) {
PassRefFromConstructor(get_interface<PPB_Audio_1_1>()->Create(
instance.pp_instance(), config.pp_resource(), callback, user_data));
}
}
Audio::Audio(const InstanceHandle& instance,
const AudioConfig& config,
PPB_Audio_Callback_1_0 callback,
void* user_data)
: config_(config),
use_1_0_interface_(true) {
if (has_interface<PPB_Audio_1_0>()) { if (has_interface<PPB_Audio_1_0>()) {
PassRefFromConstructor(get_interface<PPB_Audio_1_0>()->Create( PassRefFromConstructor(get_interface<PPB_Audio_1_0>()->Create(
instance.pp_instance(), config.pp_resource(), callback, user_data)); instance.pp_instance(), config.pp_resource(), callback, user_data));
...@@ -29,13 +46,27 @@ Audio::Audio(const InstanceHandle& instance, ...@@ -29,13 +46,27 @@ Audio::Audio(const InstanceHandle& instance,
} }
bool Audio::StartPlayback() { bool Audio::StartPlayback() {
return has_interface<PPB_Audio_1_0>() && if (has_interface<PPB_Audio_1_1>() && !use_1_0_interface_) {
get_interface<PPB_Audio_1_0>()->StartPlayback(pp_resource()); return PP_ToBool(get_interface<PPB_Audio_1_1>()->StartPlayback(
pp_resource()));
}
if (has_interface<PPB_Audio_1_0>()) {
return PP_ToBool(get_interface<PPB_Audio_1_0>()->StartPlayback(
pp_resource()));
}
return false;
} }
bool Audio::StopPlayback() { bool Audio::StopPlayback() {
return has_interface<PPB_Audio_1_0>() && if (has_interface<PPB_Audio_1_1>() && !use_1_0_interface_) {
get_interface<PPB_Audio_1_0>()->StopPlayback(pp_resource()); return PP_ToBool(get_interface<PPB_Audio_1_1>()->StopPlayback(
pp_resource()));
}
if (has_interface<PPB_Audio_1_0>()) {
return PP_ToBool(get_interface<PPB_Audio_1_0>()->StopPlayback(
pp_resource()));
}
return false;
} }
} // namespace pp } // namespace pp
...@@ -41,19 +41,30 @@ class Audio : public Resource { ...@@ -41,19 +41,30 @@ class Audio : public Resource {
/// ///
/// @param[in] instance The instance with which this resource will be /// @param[in] instance The instance with which this resource will be
/// associated. /// associated.
//
/// @param[in] config An <code>AudioConfig</code> containing the audio config /// @param[in] config An <code>AudioConfig</code> containing the audio config
/// resource. /// resource.
//
/// @param[in] callback A <code>PPB_Audio_Callback</code> callback function /// @param[in] callback A <code>PPB_Audio_Callback</code> callback function
/// that the browser calls when it needs more samples to play. /// that the browser calls when it needs more samples to play.
//
/// @param[in] user_data A pointer to user data used in the callback function. /// @param[in] user_data A pointer to user data used in the callback function.
Audio(const InstanceHandle& instance, Audio(const InstanceHandle& instance,
const AudioConfig& config, const AudioConfig& config,
PPB_Audio_Callback callback, PPB_Audio_Callback callback,
void* user_data); void* user_data);
/// A constructor that creates an Audio resource.
///
/// @param[in] instance The instance with which this resource will be
/// associated.
/// @param[in] config An <code>AudioConfig</code> containing the audio config
/// resource.
/// @param[in] callback A <code>PPB_Audio_Callback_1_0</code> callback
/// function that the browser calls when it needs more samples to play.
/// @param[in] user_data A pointer to user data used in the callback function.
Audio(const InstanceHandle& instance,
const AudioConfig& config,
PPB_Audio_Callback_1_0 callback,
void* user_data);
/// Getter function for returning the internal <code>PPB_AudioConfig</code> /// Getter function for returning the internal <code>PPB_AudioConfig</code>
/// struct. /// struct.
/// ///
...@@ -79,6 +90,7 @@ class Audio : public Resource { ...@@ -79,6 +90,7 @@ class Audio : public Resource {
private: private:
AudioConfig config_; AudioConfig config_;
bool use_1_0_interface_;
}; };
} // namespace pp } // namespace pp
......
...@@ -234,6 +234,8 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Ext_Socket_Dev_0_2; ...@@ -234,6 +234,8 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Ext_Socket_Dev_0_2;
/* Not generating wrapper methods for PPB_Audio_1_0 */ /* Not generating wrapper methods for PPB_Audio_1_0 */
/* Not generating wrapper methods for PPB_Audio_1_1 */
/* Not generating wrapper methods for PPB_AudioConfig_1_0 */ /* Not generating wrapper methods for PPB_AudioConfig_1_0 */
/* Not generating wrapper methods for PPB_AudioConfig_1_1 */ /* Not generating wrapper methods for PPB_AudioConfig_1_1 */
...@@ -3935,6 +3937,8 @@ static int32_t Pnacl_M29_PPB_Ext_Socket_Dev_GetJoinedGroups(PP_Instance instance ...@@ -3935,6 +3937,8 @@ static int32_t Pnacl_M29_PPB_Ext_Socket_Dev_GetJoinedGroups(PP_Instance instance
/* Not generating wrapper interface for PPB_Audio_1_0 */ /* Not generating wrapper interface for PPB_Audio_1_0 */
/* Not generating wrapper interface for PPB_Audio_1_1 */
/* Not generating wrapper interface for PPB_AudioConfig_1_0 */ /* Not generating wrapper interface for PPB_AudioConfig_1_0 */
/* Not generating wrapper interface for PPB_AudioConfig_1_1 */ /* Not generating wrapper interface for PPB_AudioConfig_1_1 */
......
...@@ -37,7 +37,7 @@ class Audio : public Resource, public PPB_Audio_Shared { ...@@ -37,7 +37,7 @@ class Audio : public Resource, public PPB_Audio_Shared {
public: public:
Audio(const HostResource& audio_id, Audio(const HostResource& audio_id,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback callback, const AudioCallbackCombined& callback,
void* user_data); void* user_data);
virtual ~Audio(); virtual ~Audio();
...@@ -64,7 +64,7 @@ class Audio : public Resource, public PPB_Audio_Shared { ...@@ -64,7 +64,7 @@ class Audio : public Resource, public PPB_Audio_Shared {
Audio::Audio(const HostResource& audio_id, Audio::Audio(const HostResource& audio_id,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback callback, const AudioCallbackCombined& callback,
void* user_data) void* user_data)
: Resource(OBJECT_IS_PROXY, audio_id), : Resource(OBJECT_IS_PROXY, audio_id),
config_(config_id) { config_(config_id) {
...@@ -138,7 +138,7 @@ PPB_Audio_Proxy::~PPB_Audio_Proxy() { ...@@ -138,7 +138,7 @@ PPB_Audio_Proxy::~PPB_Audio_Proxy() {
PP_Resource PPB_Audio_Proxy::CreateProxyResource( PP_Resource PPB_Audio_Proxy::CreateProxyResource(
PP_Instance instance_id, PP_Instance instance_id,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback audio_callback, const AudioCallbackCombined& audio_callback,
void* user_data) { void* user_data) {
PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id); PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
if (!dispatcher) if (!dispatcher)
...@@ -148,7 +148,7 @@ PP_Resource PPB_Audio_Proxy::CreateProxyResource( ...@@ -148,7 +148,7 @@ PP_Resource PPB_Audio_Proxy::CreateProxyResource(
if (config.failed()) if (config.failed())
return 0; return 0;
if (!audio_callback) if (!audio_callback.IsValid())
return 0; return 0;
HostResource result; HostResource result;
...@@ -341,6 +341,7 @@ void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated( ...@@ -341,6 +341,7 @@ void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated(
enter.resource()->pp_instance(), handle.shmem(), enter.resource()->pp_instance(), handle.shmem(),
media::PacketSizeInBytes(handle.size()), media::PacketSizeInBytes(handle.size()),
IPC::PlatformFileForTransitToPlatformFile(socket_handle.descriptor()), IPC::PlatformFileForTransitToPlatformFile(socket_handle.descriptor()),
config.object()->GetSampleRate(),
config.object()->GetSampleFrameCount()); config.object()->GetSampleFrameCount());
} }
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
namespace ppapi { namespace ppapi {
class AudioCallbackCombined;
class HostResource; class HostResource;
namespace proxy { namespace proxy {
...@@ -33,11 +34,11 @@ class PPB_Audio_Proxy : public InterfaceProxy { ...@@ -33,11 +34,11 @@ class PPB_Audio_Proxy : public InterfaceProxy {
virtual ~PPB_Audio_Proxy(); virtual ~PPB_Audio_Proxy();
// Creates an Audio object in the plugin process. // Creates an Audio object in the plugin process.
static PP_Resource CreateProxyResource(PP_Instance instance_id, static PP_Resource CreateProxyResource(
PP_Resource config_id, PP_Instance instance_id,
PPB_Audio_Callback audio_callback, PP_Resource config_id,
void* user_data); const AudioCallbackCombined& audio_callback,
void* user_data);
// InterfaceProxy implementation. // InterfaceProxy implementation.
virtual bool OnMessageReceived(const IPC::Message& msg); virtual bool OnMessageReceived(const IPC::Message& msg);
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "ppapi/shared_impl/api_id.h" #include "ppapi/shared_impl/api_id.h"
#include "ppapi/shared_impl/host_resource.h" #include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/ppb_audio_config_shared.h" #include "ppapi/shared_impl/ppb_audio_config_shared.h"
#include "ppapi/shared_impl/ppb_audio_shared.h"
#include "ppapi/shared_impl/ppb_input_event_shared.h" #include "ppapi/shared_impl/ppb_input_event_shared.h"
#include "ppapi/shared_impl/ppb_resource_array_shared.h" #include "ppapi/shared_impl/ppb_resource_array_shared.h"
#include "ppapi/shared_impl/var.h" #include "ppapi/shared_impl/var.h"
...@@ -185,13 +186,22 @@ PP_Resource ResourceCreationProxy::CreateWheelInputEvent( ...@@ -185,13 +186,22 @@ PP_Resource ResourceCreationProxy::CreateWheelInputEvent(
wheel_delta, wheel_ticks, scroll_by_page); wheel_delta, wheel_ticks, scroll_by_page);
} }
PP_Resource ResourceCreationProxy::CreateAudio1_0(
PP_Instance instance,
PP_Resource config_id,
PPB_Audio_Callback_1_0 audio_callback,
void* user_data) {
return PPB_Audio_Proxy::CreateProxyResource(
instance, config_id, AudioCallbackCombined(audio_callback), user_data);
}
PP_Resource ResourceCreationProxy::CreateAudio( PP_Resource ResourceCreationProxy::CreateAudio(
PP_Instance instance, PP_Instance instance,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback audio_callback, PPB_Audio_Callback audio_callback,
void* user_data) { void* user_data) {
return PPB_Audio_Proxy::CreateProxyResource(instance, config_id, return PPB_Audio_Proxy::CreateProxyResource(
audio_callback, user_data); instance, config_id, AudioCallbackCombined(audio_callback), user_data);
} }
PP_Resource ResourceCreationProxy::CreateAudioTrusted(PP_Instance instance) { PP_Resource ResourceCreationProxy::CreateAudioTrusted(PP_Instance instance) {
......
...@@ -91,7 +91,10 @@ class ResourceCreationProxy : public InterfaceProxy, ...@@ -91,7 +91,10 @@ class ResourceCreationProxy : public InterfaceProxy,
const PP_FloatPoint* wheel_delta, const PP_FloatPoint* wheel_delta,
const PP_FloatPoint* wheel_ticks, const PP_FloatPoint* wheel_ticks,
PP_Bool scroll_by_page) OVERRIDE; PP_Bool scroll_by_page) OVERRIDE;
virtual PP_Resource CreateAudio1_0(PP_Instance instance,
PP_Resource config_id,
PPB_Audio_Callback_1_0 audio_callback,
void* user_data) OVERRIDE;
virtual PP_Resource CreateAudio(PP_Instance instance, virtual PP_Resource CreateAudio(PP_Instance instance,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback audio_callback, PPB_Audio_Callback audio_callback,
......
...@@ -15,6 +15,8 @@ namespace ppapi { ...@@ -15,6 +15,8 @@ namespace ppapi {
const int kBitsPerAudioInputSample = 16; const int kBitsPerAudioInputSample = 16;
const int kAudioInputChannels = 1; const int kAudioInputChannels = 1;
// TODO(dalecurtis, yzshen): PPAPI shouldn't hard code these values for all
// clients.
const int kBitsPerAudioOutputSample = 16; const int kBitsPerAudioOutputSample = 16;
const int kAudioOutputChannels = 2; const int kAudioOutputChannels = 2;
......
...@@ -7,12 +7,9 @@ ...@@ -7,12 +7,9 @@
#include "base/logging.h" #include "base/logging.h"
#include "media/audio/shared_memory_util.h" #include "media/audio/shared_memory_util.h"
#include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/ppb_audio_config_shared.h"
#include "ppapi/shared_impl/proxy_lock.h" #include "ppapi/shared_impl/proxy_lock.h"
// Hard coded values from PepperPlatformAudioOutputImpl.
// TODO(dalecurtis): PPAPI shouldn't hard code these values for all clients.
enum { kChannels = 2, kBytesPerSample = 2 };
namespace ppapi { namespace ppapi {
#if defined(OS_NACL) #if defined(OS_NACL)
...@@ -22,6 +19,41 @@ PP_ThreadFunctions thread_functions; ...@@ -22,6 +19,41 @@ PP_ThreadFunctions thread_functions;
} }
#endif // defined(OS_NACL) #endif // defined(OS_NACL)
AudioCallbackCombined::AudioCallbackCombined() : callback_1_0_(NULL),
callback_(NULL) {
}
AudioCallbackCombined::AudioCallbackCombined(
PPB_Audio_Callback_1_0 callback_1_0)
: callback_1_0_(callback_1_0),
callback_(NULL) {
}
AudioCallbackCombined::AudioCallbackCombined(PPB_Audio_Callback callback)
: callback_1_0_(NULL),
callback_(callback) {
}
AudioCallbackCombined::~AudioCallbackCombined() {
}
bool AudioCallbackCombined::IsValid() const {
return callback_1_0_ || callback_;
}
void AudioCallbackCombined::Run(void* sample_buffer,
uint32_t buffer_size_in_bytes,
PP_TimeDelta latency,
void* user_data) const {
if (callback_) {
callback_(sample_buffer, buffer_size_in_bytes, latency, user_data);
} else if (callback_1_0_) {
callback_1_0_(sample_buffer, buffer_size_in_bytes, user_data);
} else {
NOTREACHED();
}
}
PPB_Audio_Shared::PPB_Audio_Shared() PPB_Audio_Shared::PPB_Audio_Shared()
: playing_(false), : playing_(false),
shared_memory_size_(0), shared_memory_size_(0),
...@@ -29,9 +61,9 @@ PPB_Audio_Shared::PPB_Audio_Shared() ...@@ -29,9 +61,9 @@ PPB_Audio_Shared::PPB_Audio_Shared()
thread_id_(0), thread_id_(0),
thread_active_(false), thread_active_(false),
#endif #endif
callback_(NULL),
user_data_(NULL), user_data_(NULL),
client_buffer_size_bytes_(0) { client_buffer_size_bytes_(0),
bytes_per_second_(0) {
} }
PPB_Audio_Shared::~PPB_Audio_Shared() { PPB_Audio_Shared::~PPB_Audio_Shared() {
...@@ -41,7 +73,7 @@ PPB_Audio_Shared::~PPB_Audio_Shared() { ...@@ -41,7 +73,7 @@ PPB_Audio_Shared::~PPB_Audio_Shared() {
StopThread(); StopThread();
} }
void PPB_Audio_Shared::SetCallback(PPB_Audio_Callback callback, void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback,
void* user_data) { void* user_data) {
callback_ = callback; callback_ = callback;
user_data_ = user_data; user_data_ = user_data;
...@@ -74,10 +106,13 @@ void PPB_Audio_Shared::SetStreamInfo( ...@@ -74,10 +106,13 @@ void PPB_Audio_Shared::SetStreamInfo(
base::SharedMemoryHandle shared_memory_handle, base::SharedMemoryHandle shared_memory_handle,
size_t shared_memory_size, size_t shared_memory_size,
base::SyncSocket::Handle socket_handle, base::SyncSocket::Handle socket_handle,
PP_AudioSampleRate sample_rate,
int sample_frame_count) { int sample_frame_count) {
socket_.reset(new base::CancelableSyncSocket(socket_handle)); socket_.reset(new base::CancelableSyncSocket(socket_handle));
shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false));
shared_memory_size_ = shared_memory_size; shared_memory_size_ = shared_memory_size;
bytes_per_second_ = kAudioOutputChannels * (kBitsPerAudioOutputSample / 8) *
sample_rate;
if (!shared_memory_->Map( if (!shared_memory_->Map(
media::TotalSharedMemorySizeInBytes(shared_memory_size_))) { media::TotalSharedMemorySizeInBytes(shared_memory_size_))) {
...@@ -88,10 +123,11 @@ void PPB_Audio_Shared::SetStreamInfo( ...@@ -88,10 +123,11 @@ void PPB_Audio_Shared::SetStreamInfo(
"Failed to map shared memory for PPB_Audio_Shared."); "Failed to map shared memory for PPB_Audio_Shared.");
} else { } else {
audio_bus_ = media::AudioBus::WrapMemory( audio_bus_ = media::AudioBus::WrapMemory(
kChannels, sample_frame_count, shared_memory_->memory()); kAudioOutputChannels, sample_frame_count, shared_memory_->memory());
// Setup integer audio buffer for user audio data. // Setup integer audio buffer for user audio data.
client_buffer_size_bytes_ = client_buffer_size_bytes_ =
audio_bus_->frames() * audio_bus_->channels() * kBytesPerSample; audio_bus_->frames() * audio_bus_->channels() *
kBitsPerAudioOutputSample / 8;
client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]); client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]);
} }
...@@ -100,8 +136,9 @@ void PPB_Audio_Shared::SetStreamInfo( ...@@ -100,8 +136,9 @@ void PPB_Audio_Shared::SetStreamInfo(
void PPB_Audio_Shared::StartThread() { void PPB_Audio_Shared::StartThread() {
// Don't start the thread unless all our state is set up correctly. // Don't start the thread unless all our state is set up correctly.
if (!playing_ || !callback_ || !socket_.get() || !shared_memory_->memory() || if (!playing_ || !callback_.IsValid() || !socket_.get() ||
!audio_bus_.get() || !client_buffer_.get()) !shared_memory_->memory() || !audio_bus_.get() || !client_buffer_.get() ||
bytes_per_second_ == 0)
return; return;
// Clear contents of shm buffer before starting audio thread. This will // Clear contents of shm buffer before starting audio thread. This will
// prevent a burst of static if for some reason the audio thread doesn't // prevent a burst of static if for some reason the audio thread doesn't
...@@ -173,11 +210,15 @@ void PPB_Audio_Shared::Run() { ...@@ -173,11 +210,15 @@ void PPB_Audio_Shared::Run() {
while (sizeof(pending_data) == while (sizeof(pending_data) ==
socket_->Receive(&pending_data, sizeof(pending_data)) && socket_->Receive(&pending_data, sizeof(pending_data)) &&
pending_data != media::kPauseMark) { pending_data != media::kPauseMark) {
callback_(client_buffer_.get(), client_buffer_size_bytes_, user_data_); PP_TimeDelta latency =
static_cast<double>(pending_data) / bytes_per_second_;
callback_.Run(client_buffer_.get(), client_buffer_size_bytes_, latency,
user_data_);
// Deinterleave the audio data into the shared memory as float. // Deinterleave the audio data into the shared memory as float.
audio_bus_->FromInterleaved( audio_bus_->FromInterleaved(
client_buffer_.get(), audio_bus_->frames(), kBytesPerSample); client_buffer_.get(), audio_bus_->frames(),
kBitsPerAudioOutputSample / 8);
// Let the host know we are done. // Let the host know we are done.
// TODO(dalecurtis): Technically this is not the exact size. Due to channel // TODO(dalecurtis): Technically this is not the exact size. Due to channel
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/threading/simple_thread.h" #include "base/threading/simple_thread.h"
#include "media/base/audio_bus.h" #include "media/base/audio_bus.h"
#include "ppapi/c/ppb_audio.h" #include "ppapi/c/ppb_audio.h"
#include "ppapi/c/ppb_audio_config.h"
#include "ppapi/shared_impl/resource.h" #include "ppapi/shared_impl/resource.h"
#include "ppapi/thunk/ppb_audio_api.h" #include "ppapi/thunk/ppb_audio_api.h"
...@@ -20,6 +21,26 @@ ...@@ -20,6 +21,26 @@
namespace ppapi { namespace ppapi {
class PPAPI_SHARED_EXPORT AudioCallbackCombined {
public:
AudioCallbackCombined();
explicit AudioCallbackCombined(PPB_Audio_Callback_1_0 callback_1_0);
explicit AudioCallbackCombined(PPB_Audio_Callback callback);
~AudioCallbackCombined();
bool IsValid() const;
void Run(void* sample_buffer,
uint32_t buffer_size_in_bytes,
PP_TimeDelta latency,
void* user_data) const;
private:
PPB_Audio_Callback_1_0 callback_1_0_;
PPB_Audio_Callback callback_;
};
// Implements the logic to map shared memory and run the audio thread signaled // Implements the logic to map shared memory and run the audio thread signaled
// from the sync socket. Both the proxy and the renderer implementation use // from the sync socket. Both the proxy and the renderer implementation use
// this code. // this code.
...@@ -36,7 +57,7 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared ...@@ -36,7 +57,7 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared
// is optional. Without a callback, the thread will not be run. This // is optional. Without a callback, the thread will not be run. This
// non-callback mode is used in the renderer with the proxy, since the proxy // non-callback mode is used in the renderer with the proxy, since the proxy
// handles the callback entirely within the plugin process. // handles the callback entirely within the plugin process.
void SetCallback(PPB_Audio_Callback callback, void* user_data); void SetCallback(const AudioCallbackCombined& callback, void* user_data);
// Configures the current state to be playing or not. The caller is // Configures the current state to be playing or not. The caller is
// responsible for ensuring the new state is the opposite of the current one. // responsible for ensuring the new state is the opposite of the current one.
...@@ -55,6 +76,7 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared ...@@ -55,6 +76,7 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared
base::SharedMemoryHandle shared_memory_handle, base::SharedMemoryHandle shared_memory_handle,
size_t shared_memory_size, size_t shared_memory_size,
base::SyncSocket::Handle socket_handle, base::SyncSocket::Handle socket_handle,
PP_AudioSampleRate sample_rate,
int sample_frame_count); int sample_frame_count);
#if defined(OS_NACL) #if defined(OS_NACL)
...@@ -99,7 +121,7 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared ...@@ -99,7 +121,7 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared
#endif #endif
// Callback to call when audio is ready to accept new samples. // Callback to call when audio is ready to accept new samples.
PPB_Audio_Callback callback_; AudioCallbackCombined callback_;
// User data pointer passed verbatim to the callback function. // User data pointer passed verbatim to the callback function.
void* user_data_; void* user_data_;
...@@ -111,6 +133,9 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared ...@@ -111,6 +133,9 @@ class PPAPI_SHARED_EXPORT PPB_Audio_Shared
int client_buffer_size_bytes_; int client_buffer_size_bytes_;
scoped_ptr<uint8_t[]> client_buffer_; scoped_ptr<uint8_t[]> client_buffer_;
// The size (in bytes) of one second of audio data. Used to calculate latency.
size_t bytes_per_second_;
DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Shared); DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Shared);
}; };
......
...@@ -24,20 +24,27 @@ TestAudio::TestAudio(TestingInstance* instance) ...@@ -24,20 +24,27 @@ TestAudio::TestAudio(TestingInstance* instance)
: TestCase(instance), : TestCase(instance),
audio_callback_method_(NULL), audio_callback_method_(NULL),
audio_callback_event_(instance->pp_instance()), audio_callback_event_(instance->pp_instance()),
test_done_(false) { test_done_(false),
audio_interface_(NULL),
audio_interface_1_0_(NULL),
audio_config_interface_(NULL),
core_interface_(NULL) {
} }
TestAudio::~TestAudio() { TestAudio::~TestAudio() {
} }
bool TestAudio::Init() { bool TestAudio::Init() {
audio_interface_ = static_cast<const PPB_Audio*>( audio_interface_ = static_cast<const PPB_Audio_1_1*>(
pp::Module::Get()->GetBrowserInterface(PPB_AUDIO_INTERFACE)); pp::Module::Get()->GetBrowserInterface(PPB_AUDIO_INTERFACE_1_1));
audio_interface_1_0_ = static_cast<const PPB_Audio_1_0*>(
pp::Module::Get()->GetBrowserInterface(PPB_AUDIO_INTERFACE_1_0));
audio_config_interface_ = static_cast<const PPB_AudioConfig*>( audio_config_interface_ = static_cast<const PPB_AudioConfig*>(
pp::Module::Get()->GetBrowserInterface(PPB_AUDIO_CONFIG_INTERFACE)); pp::Module::Get()->GetBrowserInterface(PPB_AUDIO_CONFIG_INTERFACE));
core_interface_ = static_cast<const PPB_Core*>( core_interface_ = static_cast<const PPB_Core*>(
pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
return audio_interface_ && audio_config_interface_ && core_interface_; return audio_interface_ && audio_interface_1_0_ && audio_config_interface_ &&
core_interface_;
} }
void TestAudio::RunTests(const std::string& filter) { void TestAudio::RunTests(const std::string& filter) {
...@@ -47,6 +54,7 @@ void TestAudio::RunTests(const std::string& filter) { ...@@ -47,6 +54,7 @@ void TestAudio::RunTests(const std::string& filter) {
RUN_TEST(AudioCallback1, filter); RUN_TEST(AudioCallback1, filter);
RUN_TEST(AudioCallback2, filter); RUN_TEST(AudioCallback2, filter);
RUN_TEST(AudioCallback3, filter); RUN_TEST(AudioCallback3, filter);
RUN_TEST(AudioCallback4, filter);
} }
// Test creating audio resources for all guaranteed sample rates and various // Test creating audio resources for all guaranteed sample rates and various
...@@ -118,13 +126,7 @@ std::string TestAudio::TestCreation() { ...@@ -118,13 +126,7 @@ std::string TestAudio::TestCreation() {
// Test that releasing the resource without calling |StopPlayback()| "works". // Test that releasing the resource without calling |StopPlayback()| "works".
std::string TestAudio::TestDestroyNoStop() { std::string TestAudio::TestDestroyNoStop() {
const PP_AudioSampleRate kSampleRate = PP_AUDIOSAMPLERATE_44100; PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 2048);
const uint32_t kRequestFrameCount = 2048;
uint32_t frame_count = audio_config_interface_->RecommendSampleFrameCount(
instance_->pp_instance(), kSampleRate, kRequestFrameCount);
PP_Resource ac = audio_config_interface_->CreateStereo16Bit(
instance_->pp_instance(), kSampleRate, frame_count);
ASSERT_TRUE(ac); ASSERT_TRUE(ac);
audio_callback_method_ = NULL; audio_callback_method_ = NULL;
PP_Resource audio = audio_interface_->Create( PP_Resource audio = audio_interface_->Create(
...@@ -145,16 +147,10 @@ std::string TestAudio::TestDestroyNoStop() { ...@@ -145,16 +147,10 @@ std::string TestAudio::TestDestroyNoStop() {
} }
std::string TestAudio::TestFailures() { std::string TestAudio::TestFailures() {
const PP_AudioSampleRate kSampleRate = PP_AUDIOSAMPLERATE_44100;
const uint32_t kRequestFrameCount = 2048;
// Test invalid parameters to |Create()|. // Test invalid parameters to |Create()|.
// We want a valid config for some of our tests of |Create()|. // We want a valid config for some of our tests of |Create()|.
uint32_t frame_count = audio_config_interface_->RecommendSampleFrameCount( PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 2048);
instance_->pp_instance(), kSampleRate, kRequestFrameCount);
PP_Resource ac = audio_config_interface_->CreateStereo16Bit(
instance_->pp_instance(), kSampleRate, frame_count);
ASSERT_TRUE(ac); ASSERT_TRUE(ac);
// Failure cases should never lead to the callback being called. // Failure cases should never lead to the callback being called.
...@@ -187,24 +183,17 @@ std::string TestAudio::TestFailures() { ...@@ -187,24 +183,17 @@ std::string TestAudio::TestFailures() {
PASS(); PASS();
} }
// NOTE: |TestAudioCallback1| and |TestAudioCallback2| assume that the audio // NOTE: |TestAudioCallbackN| assumes that the audio callback is called at least
// callback is called at least once. If the audio stream does not start up // once. If the audio stream does not start up correctly or is interrupted this
// correctly or is interrupted this may not be the case and these tests will // may not be the case and these tests will fail. However, in order to properly
// fail. However, in order to properly test the audio callbacks, we must have // test the audio callbacks, we must have a configuration where audio can
// a configuration where audio can successfully play, so we assume this is the // successfully play, so we assume this is the case on bots.
// case on bots.
// This test starts playback and verifies that: // This test starts playback and verifies that:
// 1) the audio callback is actually called; // 1) the audio callback is actually called;
// 2) that |StopPlayback()| waits for the audio callback to finish. // 2) that |StopPlayback()| waits for the audio callback to finish.
std::string TestAudio::TestAudioCallback1() { std::string TestAudio::TestAudioCallback1() {
const PP_AudioSampleRate kSampleRate = PP_AUDIOSAMPLERATE_44100; PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024);
const uint32_t kRequestFrameCount = 1024;
uint32_t frame_count = audio_config_interface_->RecommendSampleFrameCount(
instance_->pp_instance(), kSampleRate, kRequestFrameCount);
PP_Resource ac = audio_config_interface_->CreateStereo16Bit(
instance_->pp_instance(), kSampleRate, frame_count);
ASSERT_TRUE(ac); ASSERT_TRUE(ac);
audio_callback_method_ = NULL; audio_callback_method_ = NULL;
PP_Resource audio = audio_interface_->Create( PP_Resource audio = audio_interface_->Create(
...@@ -234,13 +223,7 @@ std::string TestAudio::TestAudioCallback1() { ...@@ -234,13 +223,7 @@ std::string TestAudio::TestAudioCallback1() {
// This is the same as |TestAudioCallback1()|, except that instead of calling // This is the same as |TestAudioCallback1()|, except that instead of calling
// |StopPlayback()|, it just releases the resource. // |StopPlayback()|, it just releases the resource.
std::string TestAudio::TestAudioCallback2() { std::string TestAudio::TestAudioCallback2() {
const PP_AudioSampleRate kSampleRate = PP_AUDIOSAMPLERATE_44100; PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024);
const uint32_t kRequestFrameCount = 1024;
uint32_t frame_count = audio_config_interface_->RecommendSampleFrameCount(
instance_->pp_instance(), kSampleRate, kRequestFrameCount);
PP_Resource ac = audio_config_interface_->CreateStereo16Bit(
instance_->pp_instance(), kSampleRate, frame_count);
ASSERT_TRUE(ac); ASSERT_TRUE(ac);
audio_callback_method_ = NULL; audio_callback_method_ = NULL;
PP_Resource audio = audio_interface_->Create( PP_Resource audio = audio_interface_->Create(
...@@ -250,7 +233,6 @@ std::string TestAudio::TestAudioCallback2() { ...@@ -250,7 +233,6 @@ std::string TestAudio::TestAudioCallback2() {
audio_callback_event_.Reset(); audio_callback_event_.Reset();
test_done_ = false; test_done_ = false;
callback_fired_ = false;
audio_callback_method_ = &TestAudio::AudioCallbackTest; audio_callback_method_ = &TestAudio::AudioCallbackTest;
ASSERT_TRUE(audio_interface_->StartPlayback(audio)); ASSERT_TRUE(audio_interface_->StartPlayback(audio));
...@@ -272,13 +254,7 @@ std::string TestAudio::TestAudioCallback2() { ...@@ -272,13 +254,7 @@ std::string TestAudio::TestAudioCallback2() {
// round of |StartPlayback| and |StopPlayback| to make sure the callback // round of |StartPlayback| and |StopPlayback| to make sure the callback
// function still responds when using the same audio resource. // function still responds when using the same audio resource.
std::string TestAudio::TestAudioCallback3() { std::string TestAudio::TestAudioCallback3() {
const PP_AudioSampleRate kSampleRate = PP_AUDIOSAMPLERATE_44100; PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024);
const uint32_t kRequestFrameCount = 1024;
uint32_t frame_count = audio_config_interface_->RecommendSampleFrameCount(
instance_->pp_instance(), kSampleRate, kRequestFrameCount);
PP_Resource ac = audio_config_interface_->CreateStereo16Bit(
instance_->pp_instance(), kSampleRate, frame_count);
ASSERT_TRUE(ac); ASSERT_TRUE(ac);
audio_callback_method_ = NULL; audio_callback_method_ = NULL;
PP_Resource audio = audio_interface_->Create( PP_Resource audio = audio_interface_->Create(
...@@ -288,7 +264,6 @@ std::string TestAudio::TestAudioCallback3() { ...@@ -288,7 +264,6 @@ std::string TestAudio::TestAudioCallback3() {
audio_callback_event_.Reset(); audio_callback_event_.Reset();
test_done_ = false; test_done_ = false;
callback_fired_ = false;
audio_callback_method_ = &TestAudio::AudioCallbackTest; audio_callback_method_ = &TestAudio::AudioCallbackTest;
ASSERT_TRUE(audio_interface_->StartPlayback(audio)); ASSERT_TRUE(audio_interface_->StartPlayback(audio));
...@@ -316,6 +291,35 @@ std::string TestAudio::TestAudioCallback3() { ...@@ -316,6 +291,35 @@ std::string TestAudio::TestAudioCallback3() {
PASS(); PASS();
} }
// This is the same as |TestAudioCallback1()|, except that it uses
// PPB_Audio_1_0.
std::string TestAudio::TestAudioCallback4() {
PP_Resource ac = CreateAudioConfig(PP_AUDIOSAMPLERATE_44100, 1024);
ASSERT_TRUE(ac);
audio_callback_method_ = NULL;
PP_Resource audio = audio_interface_1_0_->Create(
instance_->pp_instance(), ac, AudioCallbackTrampoline1_0, this);
core_interface_->ReleaseResource(ac);
ac = 0;
audio_callback_event_.Reset();
test_done_ = false;
audio_callback_method_ = &TestAudio::AudioCallbackTest;
ASSERT_TRUE(audio_interface_1_0_->StartPlayback(audio));
// Wait for the audio callback to be called.
audio_callback_event_.Wait();
ASSERT_TRUE(audio_interface_1_0_->StopPlayback(audio));
test_done_ = true;
// If any more audio callbacks are generated, we should crash (which is good).
audio_callback_method_ = NULL;
core_interface_->ReleaseResource(audio);
PASS();
}
// TODO(raymes): Test that actually playback happens correctly, etc. // TODO(raymes): Test that actually playback happens correctly, etc.
...@@ -326,6 +330,7 @@ static void Crash() { ...@@ -326,6 +330,7 @@ static void Crash() {
// static // static
void TestAudio::AudioCallbackTrampoline(void* sample_buffer, void TestAudio::AudioCallbackTrampoline(void* sample_buffer,
uint32_t buffer_size_in_bytes, uint32_t buffer_size_in_bytes,
PP_TimeDelta latency,
void* user_data) { void* user_data) {
TestAudio* thiz = static_cast<TestAudio*>(user_data); TestAudio* thiz = static_cast<TestAudio*>(user_data);
...@@ -334,19 +339,40 @@ void TestAudio::AudioCallbackTrampoline(void* sample_buffer, ...@@ -334,19 +339,40 @@ void TestAudio::AudioCallbackTrampoline(void* sample_buffer,
Crash(); Crash();
AudioCallbackMethod method = thiz->audio_callback_method_; AudioCallbackMethod method = thiz->audio_callback_method_;
(thiz->*method)(sample_buffer, buffer_size_in_bytes); (thiz->*method)(sample_buffer, buffer_size_in_bytes, latency);
}
// static
void TestAudio::AudioCallbackTrampoline1_0(void* sample_buffer,
uint32_t buffer_size_in_bytes,
void* user_data) {
AudioCallbackTrampoline(sample_buffer, buffer_size_in_bytes, 0.0, user_data);
} }
void TestAudio::AudioCallbackTrivial(void* sample_buffer, void TestAudio::AudioCallbackTrivial(void* sample_buffer,
uint32_t buffer_size_in_bytes) { uint32_t buffer_size_in_bytes,
PP_TimeDelta latency) {
if (latency < 0)
Crash();
memset(sample_buffer, 0, buffer_size_in_bytes); memset(sample_buffer, 0, buffer_size_in_bytes);
} }
void TestAudio::AudioCallbackTest(void* sample_buffer, void TestAudio::AudioCallbackTest(void* sample_buffer,
uint32_t buffer_size_in_bytes) { uint32_t buffer_size_in_bytes,
if (test_done_) PP_TimeDelta latency) {
if (test_done_ || latency < 0)
Crash(); Crash();
memset(sample_buffer, 0, buffer_size_in_bytes); memset(sample_buffer, 0, buffer_size_in_bytes);
audio_callback_event_.Signal(); audio_callback_event_.Signal();
} }
PP_Resource TestAudio::CreateAudioConfig(
PP_AudioSampleRate sample_rate,
uint32_t requested_sample_frame_count) {
uint32_t frame_count = audio_config_interface_->RecommendSampleFrameCount(
instance_->pp_instance(), sample_rate, requested_sample_frame_count);
return audio_config_interface_->CreateStereo16Bit(
instance_->pp_instance(), sample_rate, frame_count);
}
...@@ -28,14 +28,20 @@ class TestAudio : public TestCase { ...@@ -28,14 +28,20 @@ class TestAudio : public TestCase {
std::string TestAudioCallback1(); std::string TestAudioCallback1();
std::string TestAudioCallback2(); std::string TestAudioCallback2();
std::string TestAudioCallback3(); std::string TestAudioCallback3();
std::string TestAudioCallback4();
// Calls |audio_callback_method_| (where |user_data| is "this"). // Calls |audio_callback_method_| (where |user_data| is "this").
static void AudioCallbackTrampoline(void* sample_buffer, static void AudioCallbackTrampoline(void* sample_buffer,
uint32_t buffer_size_in_bytes, uint32_t buffer_size_in_bytes,
PP_TimeDelta latency,
void* user_data); void* user_data);
static void AudioCallbackTrampoline1_0(void* sample_buffer,
uint32_t buffer_size_in_bytes,
void* user_data);
typedef void (TestAudio::*AudioCallbackMethod)(void* sample_buffer, typedef void (TestAudio::*AudioCallbackMethod)(void* sample_buffer,
uint32_t buffer_size_in_bytes); uint32_t buffer_size_in_bytes,
PP_TimeDelta latency);
// Method called by |AudioCallbackTrampoline()|. Set only when the callback // Method called by |AudioCallbackTrampoline()|. Set only when the callback
// can't be running (before |StartPlayback()|, after |StopPlayback()| or // can't be running (before |StartPlayback()|, after |StopPlayback()| or
...@@ -43,19 +49,26 @@ class TestAudio : public TestCase { ...@@ -43,19 +49,26 @@ class TestAudio : public TestCase {
AudioCallbackMethod audio_callback_method_; AudioCallbackMethod audio_callback_method_;
// An |AudioCallbackMethod| that just clears |sample_buffer|. // An |AudioCallbackMethod| that just clears |sample_buffer|.
void AudioCallbackTrivial(void* sample_buffer, uint32_t buffer_size_in_bytes); void AudioCallbackTrivial(void* sample_buffer,
uint32_t buffer_size_in_bytes,
PP_TimeDelta latency);
// |AudioCallbackMethod| used by |TestAudioCallbackN()|. // |AudioCallbackMethod| used by |TestAudioCallbackN()|.
void AudioCallbackTest(void* sample_buffer, uint32_t buffer_size_in_bytes); void AudioCallbackTest(void* sample_buffer,
uint32_t buffer_size_in_bytes,
PP_TimeDelta latency);
PP_Resource CreateAudioConfig(PP_AudioSampleRate sample_rate,
uint32_t requested_sample_frame_count);
// Used by |TestAudioCallbackN()|. // Used by |TestAudioCallbackN()|.
NestedEvent audio_callback_event_; NestedEvent audio_callback_event_;
bool test_done_; bool test_done_;
bool callback_fired_;
// Raw C-level interfaces, set in |Init()|; do not modify them elsewhere. // Raw C-level interfaces, set in |Init()|; do not modify them elsewhere.
const PPB_Audio* audio_interface_; const PPB_Audio_1_1* audio_interface_;
const PPB_Audio_1_0* audio_interface_1_0_;
const PPB_AudioConfig* audio_config_interface_; const PPB_AudioConfig* audio_config_interface_;
const PPB_Core* core_interface_; const PPB_Core* core_interface_;
}; };
......
...@@ -45,6 +45,7 @@ UNPROXIED_API(PPB_AudioConfig) ...@@ -45,6 +45,7 @@ UNPROXIED_API(PPB_AudioConfig)
// interface string. // interface string.
// Note: Core is special and is registered manually. // Note: Core is special and is registered manually.
PROXIED_IFACE(PPB_Audio, PPB_AUDIO_INTERFACE_1_0, PPB_Audio_1_0) PROXIED_IFACE(PPB_Audio, PPB_AUDIO_INTERFACE_1_0, PPB_Audio_1_0)
PROXIED_IFACE(PPB_Audio, PPB_AUDIO_INTERFACE_1_1, PPB_Audio_1_1)
PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_0, PPB_FileRef_1_0) PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_0, PPB_FileRef_1_0)
PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_1, PPB_FileRef_1_1) PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_1, PPB_FileRef_1_1)
PROXIED_IFACE(NoAPIName, PPB_FILESYSTEM_INTERFACE_1_0, PPB_FileSystem_1_0) PROXIED_IFACE(NoAPIName, PPB_FILESYSTEM_INTERFACE_1_0, PPB_FileSystem_1_0)
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// From ppb_audio.idl modified Thu Dec 20 13:10:26 2012.
#include "ppapi/c/pp_errors.h" #include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_audio.h" #include "ppapi/c/ppb_audio.h"
#include "ppapi/shared_impl/tracked_callback.h" #include "ppapi/shared_impl/tracked_callback.h"
...@@ -18,6 +16,20 @@ namespace thunk { ...@@ -18,6 +16,20 @@ namespace thunk {
namespace { namespace {
PP_Resource Create_1_0(PP_Instance instance,
PP_Resource config,
PPB_Audio_Callback_1_0 audio_callback,
void* user_data) {
VLOG(4) << "PPB_Audio::Create()";
EnterResourceCreation enter(instance);
if (enter.failed())
return 0;
return enter.functions()->CreateAudio1_0(instance,
config,
audio_callback,
user_data);
}
PP_Resource Create(PP_Instance instance, PP_Resource Create(PP_Instance instance,
PP_Resource config, PP_Resource config,
PPB_Audio_Callback audio_callback, PPB_Audio_Callback audio_callback,
...@@ -63,6 +75,14 @@ PP_Bool StopPlayback(PP_Resource audio) { ...@@ -63,6 +75,14 @@ PP_Bool StopPlayback(PP_Resource audio) {
} }
const PPB_Audio_1_0 g_ppb_audio_thunk_1_0 = { const PPB_Audio_1_0 g_ppb_audio_thunk_1_0 = {
&Create_1_0,
&IsAudio,
&GetCurrentConfig,
&StartPlayback,
&StopPlayback
};
const PPB_Audio_1_1 g_ppb_audio_thunk_1_1 = {
&Create, &Create,
&IsAudio, &IsAudio,
&GetCurrentConfig, &GetCurrentConfig,
...@@ -76,5 +96,9 @@ const PPB_Audio_1_0* GetPPB_Audio_1_0_Thunk() { ...@@ -76,5 +96,9 @@ const PPB_Audio_1_0* GetPPB_Audio_1_0_Thunk() {
return &g_ppb_audio_thunk_1_0; return &g_ppb_audio_thunk_1_0;
} }
const PPB_Audio_1_1* GetPPB_Audio_1_1_Thunk() {
return &g_ppb_audio_thunk_1_1;
}
} // namespace thunk } // namespace thunk
} // namespace ppapi } // namespace ppapi
...@@ -108,6 +108,10 @@ class ResourceCreationAPI { ...@@ -108,6 +108,10 @@ class ResourceCreationAPI {
const PP_FloatPoint* wheel_ticks, const PP_FloatPoint* wheel_ticks,
PP_Bool scroll_by_page) = 0; PP_Bool scroll_by_page) = 0;
virtual PP_Resource CreateAudio1_0(PP_Instance instance,
PP_Resource config_id,
PPB_Audio_Callback_1_0 audio_callback,
void* user_data) = 0;
virtual PP_Resource CreateAudio(PP_Instance instance, virtual PP_Resource CreateAudio(PP_Instance instance,
PP_Resource config_id, PP_Resource config_id,
PPB_Audio_Callback audio_callback, PPB_Audio_Callback audio_callback,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment