1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/shared_impl/ppb_audio_shared.h"
7 #include "base/logging.h"
8 #include "media/audio/shared_memory_util.h"
9 #include "ppapi/shared_impl/ppapi_globals.h"
10 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
11 #include "ppapi/shared_impl/proxy_lock.h"
17 // Because this is static, the function pointers will be NULL initially.
18 PP_ThreadFunctions thread_functions
;
20 #endif // defined(OS_NACL)
22 AudioCallbackCombined::AudioCallbackCombined() : callback_1_0_(NULL
),
26 AudioCallbackCombined::AudioCallbackCombined(
27 PPB_Audio_Callback_1_0 callback_1_0
)
28 : callback_1_0_(callback_1_0
),
32 AudioCallbackCombined::AudioCallbackCombined(PPB_Audio_Callback callback
)
33 : callback_1_0_(NULL
),
37 AudioCallbackCombined::~AudioCallbackCombined() {
40 bool AudioCallbackCombined::IsValid() const {
41 return callback_1_0_
|| callback_
;
44 void AudioCallbackCombined::Run(void* sample_buffer
,
45 uint32_t buffer_size_in_bytes
,
47 void* user_data
) const {
49 callback_(sample_buffer
, buffer_size_in_bytes
, latency
, user_data
);
50 } else if (callback_1_0_
) {
51 callback_1_0_(sample_buffer
, buffer_size_in_bytes
, user_data
);
57 PPB_Audio_Shared::PPB_Audio_Shared()
59 shared_memory_size_(0),
62 thread_active_(false),
65 client_buffer_size_bytes_(0),
66 bytes_per_second_(0) {
69 PPB_Audio_Shared::~PPB_Audio_Shared() {
70 // Shut down the socket to escape any hanging |Receive|s.
76 void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined
& callback
,
79 user_data_
= user_data
;
82 void PPB_Audio_Shared::SetStartPlaybackState() {
85 DCHECK(!audio_thread_
.get());
87 DCHECK(!thread_active_
);
89 // If the socket doesn't exist, that means that the plugin has started before
90 // the browser has had a chance to create all the shared memory info and
91 // notify us. This is a common case. In this case, we just set the playing_
92 // flag and the playback will automatically start when that data is available
98 void PPB_Audio_Shared::SetStopPlaybackState() {
104 void PPB_Audio_Shared::SetStreamInfo(
105 PP_Instance instance
,
106 base::SharedMemoryHandle shared_memory_handle
,
107 size_t shared_memory_size
,
108 base::SyncSocket::Handle socket_handle
,
109 PP_AudioSampleRate sample_rate
,
110 int sample_frame_count
) {
111 socket_
.reset(new base::CancelableSyncSocket(socket_handle
));
112 shared_memory_
.reset(new base::SharedMemory(shared_memory_handle
, false));
113 shared_memory_size_
= shared_memory_size
;
114 bytes_per_second_
= kAudioOutputChannels
* (kBitsPerAudioOutputSample
/ 8) *
117 if (!shared_memory_
->Map(
118 media::TotalSharedMemorySizeInBytes(shared_memory_size_
))) {
119 PpapiGlobals::Get()->LogWithSource(
123 "Failed to map shared memory for PPB_Audio_Shared.");
125 audio_bus_
= media::AudioBus::WrapMemory(
126 kAudioOutputChannels
, sample_frame_count
, shared_memory_
->memory());
127 // Setup integer audio buffer for user audio data.
128 client_buffer_size_bytes_
=
129 audio_bus_
->frames() * audio_bus_
->channels() *
130 kBitsPerAudioOutputSample
/ 8;
131 client_buffer_
.reset(new uint8_t[client_buffer_size_bytes_
]);
137 void PPB_Audio_Shared::StartThread() {
138 // Don't start the thread unless all our state is set up correctly.
139 if (!playing_
|| !callback_
.IsValid() || !socket_
.get() ||
140 !shared_memory_
->memory() || !audio_bus_
.get() || !client_buffer_
.get() ||
141 bytes_per_second_
== 0)
143 // Clear contents of shm buffer before starting audio thread. This will
144 // prevent a burst of static if for some reason the audio thread doesn't
145 // start up quickly enough.
146 memset(shared_memory_
->memory(), 0, shared_memory_size_
);
147 memset(client_buffer_
.get(), 0, client_buffer_size_bytes_
);
148 #if !defined(OS_NACL)
149 DCHECK(!audio_thread_
.get());
150 audio_thread_
.reset(new base::DelegateSimpleThread(
151 this, "plugin_audio_thread"));
152 audio_thread_
->Start();
154 // Use NaCl's special API for IRT code that creates threads that call back
156 if (NULL
== thread_functions
.thread_create
||
157 NULL
== thread_functions
.thread_join
)
160 int result
= thread_functions
.thread_create(&thread_id_
, CallRun
, this);
161 DCHECK_EQ(result
, 0);
162 thread_active_
= true;
166 void PPB_Audio_Shared::StopThread() {
167 #if !defined(OS_NACL)
168 if (audio_thread_
.get()) {
169 // In general, the audio thread should not do Pepper calls, but it might
170 // anyway (for example, our Audio test does CallOnMainThread). If it did
171 // a pepper call which acquires the lock (most of them do), and we try to
172 // shut down the thread and Join it while holding the lock, we would
173 // deadlock. So we give up the lock here so that the thread at least _can_
174 // make Pepper calls without causing deadlock.
175 CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join
,
176 base::Unretained(audio_thread_
.get())));
177 audio_thread_
.reset();
180 if (thread_active_
) {
181 // See comment above about why we unlock here.
182 int result
= CallWhileUnlocked(thread_functions
.thread_join
, thread_id_
);
183 DCHECK_EQ(0, result
);
184 thread_active_
= false;
191 void PPB_Audio_Shared::SetThreadFunctions(
192 const struct PP_ThreadFunctions
* functions
) {
193 DCHECK(thread_functions
.thread_create
== NULL
);
194 DCHECK(thread_functions
.thread_join
== NULL
);
195 thread_functions
= *functions
;
199 void PPB_Audio_Shared::CallRun(void* self
) {
200 PPB_Audio_Shared
* audio
= static_cast<PPB_Audio_Shared
*>(self
);
205 void PPB_Audio_Shared::Run() {
207 const int bytes_per_frame
=
208 sizeof(*audio_bus_
->channel(0)) * audio_bus_
->channels();
210 while (sizeof(pending_data
) ==
211 socket_
->Receive(&pending_data
, sizeof(pending_data
)) &&
212 pending_data
!= media::kPauseMark
) {
213 PP_TimeDelta latency
=
214 static_cast<double>(pending_data
) / bytes_per_second_
;
215 callback_
.Run(client_buffer_
.get(), client_buffer_size_bytes_
, latency
,
218 // Deinterleave the audio data into the shared memory as float.
219 audio_bus_
->FromInterleaved(
220 client_buffer_
.get(), audio_bus_
->frames(),
221 kBitsPerAudioOutputSample
/ 8);
223 // Let the host know we are done.
224 // TODO(dalecurtis): Technically this is not the exact size. Due to channel
225 // padding for alignment, there may be more data available than this. We're
226 // relying on AudioSyncReader::Read() to parse this with that in mind.
227 // Rename these methods to Set/GetActualFrameCount().
228 media::SetActualDataSizeInBytes(
229 shared_memory_
.get(), shared_memory_size_
,
230 audio_bus_
->frames() * bytes_per_frame
);