Blink roll 172110:172126
[chromium-blink-merge.git] / ppapi / shared_impl / ppb_audio_shared.cc
blobc8c97d4096fb8fca4931670a0ad25f998b6051cf
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 "ppapi/shared_impl/ppapi_globals.h"
9 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
10 #include "ppapi/shared_impl/proxy_lock.h"
12 namespace ppapi {
14 #if defined(OS_NACL)
15 namespace {
16 // Because this is static, the function pointers will be NULL initially.
17 PP_ThreadFunctions thread_functions;
19 #endif // defined(OS_NACL)
21 AudioCallbackCombined::AudioCallbackCombined()
22 : callback_1_0_(NULL), callback_(NULL) {}
24 AudioCallbackCombined::AudioCallbackCombined(
25 PPB_Audio_Callback_1_0 callback_1_0)
26 : callback_1_0_(callback_1_0), callback_(NULL) {}
28 AudioCallbackCombined::AudioCallbackCombined(PPB_Audio_Callback callback)
29 : callback_1_0_(NULL), callback_(callback) {}
31 AudioCallbackCombined::~AudioCallbackCombined() {}
33 bool AudioCallbackCombined::IsValid() const {
34 return callback_1_0_ || callback_;
37 void AudioCallbackCombined::Run(void* sample_buffer,
38 uint32_t buffer_size_in_bytes,
39 PP_TimeDelta latency,
40 void* user_data) const {
41 if (callback_) {
42 callback_(sample_buffer, buffer_size_in_bytes, latency, user_data);
43 } else if (callback_1_0_) {
44 callback_1_0_(sample_buffer, buffer_size_in_bytes, user_data);
45 } else {
46 NOTREACHED();
50 PPB_Audio_Shared::PPB_Audio_Shared()
51 : playing_(false),
52 shared_memory_size_(0),
53 #if defined(OS_NACL)
54 thread_id_(0),
55 thread_active_(false),
56 #endif
57 user_data_(NULL),
58 client_buffer_size_bytes_(0),
59 bytes_per_second_(0),
60 buffer_index_(0) {
63 PPB_Audio_Shared::~PPB_Audio_Shared() {
64 // Shut down the socket to escape any hanging |Receive|s.
65 if (socket_.get())
66 socket_->Shutdown();
67 StopThread();
70 void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback,
71 void* user_data) {
72 callback_ = callback;
73 user_data_ = user_data;
76 void PPB_Audio_Shared::SetStartPlaybackState() {
77 DCHECK(!playing_);
78 #if !defined(OS_NACL)
79 DCHECK(!audio_thread_.get());
80 #else
81 DCHECK(!thread_active_);
82 #endif
83 // If the socket doesn't exist, that means that the plugin has started before
84 // the browser has had a chance to create all the shared memory info and
85 // notify us. This is a common case. In this case, we just set the playing_
86 // flag and the playback will automatically start when that data is available
87 // in SetStreamInfo.
88 playing_ = true;
89 StartThread();
92 void PPB_Audio_Shared::SetStopPlaybackState() {
93 DCHECK(playing_);
94 StopThread();
95 playing_ = false;
98 void PPB_Audio_Shared::SetStreamInfo(
99 PP_Instance instance,
100 base::SharedMemoryHandle shared_memory_handle,
101 size_t shared_memory_size,
102 base::SyncSocket::Handle socket_handle,
103 PP_AudioSampleRate sample_rate,
104 int sample_frame_count) {
105 socket_.reset(new base::CancelableSyncSocket(socket_handle));
106 shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false));
107 shared_memory_size_ = shared_memory_size;
108 bytes_per_second_ =
109 kAudioOutputChannels * (kBitsPerAudioOutputSample / 8) * sample_rate;
110 buffer_index_ = 0;
112 if (!shared_memory_->Map(shared_memory_size_)) {
113 PpapiGlobals::Get()->LogWithSource(
114 instance,
115 PP_LOGLEVEL_WARNING,
116 std::string(),
117 "Failed to map shared memory for PPB_Audio_Shared.");
118 } else {
119 audio_bus_ = media::AudioBus::WrapMemory(
120 kAudioOutputChannels, sample_frame_count, shared_memory_->memory());
121 // Setup integer audio buffer for user audio data.
122 client_buffer_size_bytes_ = audio_bus_->frames() * audio_bus_->channels() *
123 kBitsPerAudioOutputSample / 8;
124 client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]);
127 StartThread();
130 void PPB_Audio_Shared::StartThread() {
131 // Don't start the thread unless all our state is set up correctly.
132 if (!playing_ || !callback_.IsValid() || !socket_.get() ||
133 !shared_memory_->memory() || !audio_bus_.get() || !client_buffer_.get() ||
134 bytes_per_second_ == 0)
135 return;
136 // Clear contents of shm buffer before starting audio thread. This will
137 // prevent a burst of static if for some reason the audio thread doesn't
138 // start up quickly enough.
139 memset(shared_memory_->memory(), 0, shared_memory_size_);
140 memset(client_buffer_.get(), 0, client_buffer_size_bytes_);
141 #if !defined(OS_NACL)
142 DCHECK(!audio_thread_.get());
143 audio_thread_.reset(
144 new base::DelegateSimpleThread(this, "plugin_audio_thread"));
145 audio_thread_->Start();
146 #else
147 // Use NaCl's special API for IRT code that creates threads that call back
148 // into user code.
149 if (!IsThreadFunctionReady())
150 return;
152 DCHECK(!thread_active_);
153 int result = thread_functions.thread_create(&thread_id_, CallRun, this);
154 DCHECK_EQ(result, 0);
155 thread_active_ = true;
156 #endif
159 void PPB_Audio_Shared::StopThread() {
160 #if !defined(OS_NACL)
161 if (audio_thread_.get()) {
162 // In general, the audio thread should not do Pepper calls, but it might
163 // anyway (for example, our Audio test does CallOnMainThread). If it did
164 // a pepper call which acquires the lock (most of them do), and we try to
165 // shut down the thread and Join it while holding the lock, we would
166 // deadlock. So we give up the lock here so that the thread at least _can_
167 // make Pepper calls without causing deadlock.
168 CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join,
169 base::Unretained(audio_thread_.get())));
170 audio_thread_.reset();
172 #else
173 if (thread_active_) {
174 // See comment above about why we unlock here.
175 int result = CallWhileUnlocked(thread_functions.thread_join, thread_id_);
176 DCHECK_EQ(0, result);
177 thread_active_ = false;
179 #endif
182 // static
183 bool PPB_Audio_Shared::IsThreadFunctionReady() {
184 #if defined(OS_NACL)
185 if (thread_functions.thread_create == NULL ||
186 thread_functions.thread_join == NULL)
187 return false;
188 #endif
189 return true;
192 #if defined(OS_NACL)
193 // static
194 void PPB_Audio_Shared::SetThreadFunctions(
195 const struct PP_ThreadFunctions* functions) {
196 thread_functions = *functions;
199 // static
200 void PPB_Audio_Shared::CallRun(void* self) {
201 PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self);
202 audio->Run();
204 #endif
206 void PPB_Audio_Shared::Run() {
207 int pending_data = 0;
208 while (sizeof(pending_data) ==
209 socket_->Receive(&pending_data, sizeof(pending_data))) {
210 // |buffer_index_| must track the number of Receive() calls. See the Send()
211 // call below for why this is important.
212 ++buffer_index_;
213 if (pending_data < 0)
214 break;
216 PP_TimeDelta latency =
217 static_cast<double>(pending_data) / bytes_per_second_;
218 callback_.Run(
219 client_buffer_.get(), client_buffer_size_bytes_, latency, user_data_);
221 // Deinterleave the audio data into the shared memory as floats.
222 audio_bus_->FromInterleaved(client_buffer_.get(),
223 audio_bus_->frames(),
224 kBitsPerAudioOutputSample / 8);
226 // Let the other end know which buffer we just filled. The buffer index is
227 // used to ensure the other end is getting the buffer it expects. For more
228 // details on how this works see AudioSyncReader::WaitUntilDataIsReady().
229 size_t bytes_sent = socket_->Send(&buffer_index_, sizeof(buffer_index_));
230 if (bytes_sent != sizeof(buffer_index_))
231 break;
235 } // namespace ppapi