OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/shared_impl/ppb_audio_shared.h" | 5 #include "ppapi/shared_impl/ppb_audio_shared.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "ppapi/nacl_irt/irt_ppapi.h" | |
8 #include "ppapi/shared_impl/ppapi_globals.h" | 9 #include "ppapi/shared_impl/ppapi_globals.h" |
9 #include "ppapi/shared_impl/ppb_audio_config_shared.h" | 10 #include "ppapi/shared_impl/ppb_audio_config_shared.h" |
10 #include "ppapi/shared_impl/proxy_lock.h" | 11 #include "ppapi/shared_impl/proxy_lock.h" |
11 | 12 |
12 namespace ppapi { | 13 namespace ppapi { |
13 | 14 |
14 #if defined(OS_NACL) | |
15 namespace { | 15 namespace { |
16 bool thread_functions_set = false; | |
16 // Because this is static, the function pointers will be NULL initially. | 17 // Because this is static, the function pointers will be NULL initially. |
17 PP_ThreadFunctions thread_functions; | 18 PP_ThreadFunctions thread_functions; |
18 } | 19 } |
19 #endif // defined(OS_NACL) | |
20 | 20 |
21 AudioCallbackCombined::AudioCallbackCombined() | 21 AudioCallbackCombined::AudioCallbackCombined() |
22 : callback_1_0_(NULL), callback_(NULL) {} | 22 : callback_1_0_(NULL), callback_(NULL) {} |
23 | 23 |
24 AudioCallbackCombined::AudioCallbackCombined( | 24 AudioCallbackCombined::AudioCallbackCombined( |
25 PPB_Audio_Callback_1_0 callback_1_0) | 25 PPB_Audio_Callback_1_0 callback_1_0) |
26 : callback_1_0_(callback_1_0), callback_(NULL) {} | 26 : callback_1_0_(callback_1_0), callback_(NULL) {} |
27 | 27 |
28 AudioCallbackCombined::AudioCallbackCombined(PPB_Audio_Callback callback) | 28 AudioCallbackCombined::AudioCallbackCombined(PPB_Audio_Callback callback) |
29 : callback_1_0_(NULL), callback_(callback) {} | 29 : callback_1_0_(NULL), callback_(callback) {} |
(...skipping 13 matching lines...) Expand all Loading... | |
43 } else if (callback_1_0_) { | 43 } else if (callback_1_0_) { |
44 callback_1_0_(sample_buffer, buffer_size_in_bytes, user_data); | 44 callback_1_0_(sample_buffer, buffer_size_in_bytes, user_data); |
45 } else { | 45 } else { |
46 NOTREACHED(); | 46 NOTREACHED(); |
47 } | 47 } |
48 } | 48 } |
49 | 49 |
50 PPB_Audio_Shared::PPB_Audio_Shared() | 50 PPB_Audio_Shared::PPB_Audio_Shared() |
51 : playing_(false), | 51 : playing_(false), |
52 shared_memory_size_(0), | 52 shared_memory_size_(0), |
53 #if defined(OS_NACL) | |
54 thread_id_(0), | 53 thread_id_(0), |
55 thread_active_(false), | 54 thread_active_(false), |
56 #endif | |
57 user_data_(NULL), | 55 user_data_(NULL), |
58 client_buffer_size_bytes_(0), | 56 client_buffer_size_bytes_(0), |
59 bytes_per_second_(0), | 57 bytes_per_second_(0), |
60 buffer_index_(0) { | 58 buffer_index_(0) { |
61 } | 59 } |
62 | 60 |
63 PPB_Audio_Shared::~PPB_Audio_Shared() { | 61 PPB_Audio_Shared::~PPB_Audio_Shared() { |
64 // Shut down the socket to escape any hanging |Receive|s. | 62 // Shut down the socket to escape any hanging |Receive|s. |
65 if (socket_.get()) | 63 if (socket_.get()) |
66 socket_->Shutdown(); | 64 socket_->Shutdown(); |
67 StopThread(); | 65 StopThread(); |
68 } | 66 } |
69 | 67 |
70 void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback, | 68 void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback, |
71 void* user_data) { | 69 void* user_data) { |
72 callback_ = callback; | 70 callback_ = callback; |
73 user_data_ = user_data; | 71 user_data_ = user_data; |
74 } | 72 } |
75 | 73 |
76 void PPB_Audio_Shared::SetStartPlaybackState() { | 74 void PPB_Audio_Shared::SetStartPlaybackState() { |
77 DCHECK(!playing_); | 75 DCHECK(!playing_); |
78 #if !defined(OS_NACL) | 76 #if !defined(OS_NACL) |
79 DCHECK(!audio_thread_.get()); | 77 DCHECK(!audio_thread_.get()); |
80 #else | 78 #endif |
81 DCHECK(!thread_active_); | 79 DCHECK(!thread_active_); |
82 #endif | |
83 // If the socket doesn't exist, that means that the plugin has started before | 80 // 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 | 81 // 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_ | 82 // 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 | 83 // flag and the playback will automatically start when that data is available |
87 // in SetStreamInfo. | 84 // in SetStreamInfo. |
88 playing_ = true; | 85 playing_ = true; |
89 StartThread(); | 86 StartThread(); |
90 } | 87 } |
91 | 88 |
92 void PPB_Audio_Shared::SetStopPlaybackState() { | 89 void PPB_Audio_Shared::SetStopPlaybackState() { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 // Don't start the thread unless all our state is set up correctly. | 128 // Don't start the thread unless all our state is set up correctly. |
132 if (!playing_ || !callback_.IsValid() || !socket_.get() || | 129 if (!playing_ || !callback_.IsValid() || !socket_.get() || |
133 !shared_memory_->memory() || !audio_bus_.get() || !client_buffer_.get() || | 130 !shared_memory_->memory() || !audio_bus_.get() || !client_buffer_.get() || |
134 bytes_per_second_ == 0) | 131 bytes_per_second_ == 0) |
135 return; | 132 return; |
136 // Clear contents of shm buffer before starting audio thread. This will | 133 // 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 | 134 // prevent a burst of static if for some reason the audio thread doesn't |
138 // start up quickly enough. | 135 // start up quickly enough. |
139 memset(shared_memory_->memory(), 0, shared_memory_size_); | 136 memset(shared_memory_->memory(), 0, shared_memory_size_); |
140 memset(client_buffer_.get(), 0, client_buffer_size_bytes_); | 137 memset(client_buffer_.get(), 0, client_buffer_size_bytes_); |
138 | |
139 if (thread_functions_set) { | |
Mark Seaborn
2014/03/20 23:23:30
PPB_Audio is meant to fail under NaCl (for both SF
hidehiko
2014/04/21 14:47:40
Done.
| |
140 // Use NaCl's special API for IRT code that creates threads that call back | |
141 // into user code. | |
142 if (NULL == thread_functions.thread_create || | |
143 NULL == thread_functions.thread_join) | |
144 return; | |
145 | |
146 int result = thread_functions.thread_create(&thread_id_, CallRun, this); | |
147 DCHECK_EQ(result, 0); | |
148 thread_active_ = true; | |
149 return; | |
150 } | |
151 | |
141 #if !defined(OS_NACL) | 152 #if !defined(OS_NACL) |
142 DCHECK(!audio_thread_.get()); | 153 DCHECK(!audio_thread_.get()); |
143 audio_thread_.reset( | 154 audio_thread_.reset( |
144 new base::DelegateSimpleThread(this, "plugin_audio_thread")); | 155 new base::DelegateSimpleThread(this, "plugin_audio_thread")); |
145 audio_thread_->Start(); | 156 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 (NULL == thread_functions.thread_create || | |
150 NULL == thread_functions.thread_join) | |
151 return; | |
152 | |
153 int result = thread_functions.thread_create(&thread_id_, CallRun, this); | |
154 DCHECK_EQ(result, 0); | |
155 thread_active_ = true; | |
156 #endif | 157 #endif |
157 } | 158 } |
158 | 159 |
159 void PPB_Audio_Shared::StopThread() { | 160 void PPB_Audio_Shared::StopThread() { |
160 #if !defined(OS_NACL) | 161 #if !defined(OS_NACL) |
161 if (audio_thread_.get()) { | 162 if (audio_thread_.get()) { |
162 // In general, the audio thread should not do Pepper calls, but it might | 163 // 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 // 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 // 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 // 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 // deadlock. So we give up the lock here so that the thread at least _can_ |
167 // make Pepper calls without causing deadlock. | 168 // make Pepper calls without causing deadlock. |
168 CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join, | 169 CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join, |
169 base::Unretained(audio_thread_.get()))); | 170 base::Unretained(audio_thread_.get()))); |
170 audio_thread_.reset(); | 171 audio_thread_.reset(); |
171 } | 172 } |
172 #else | 173 #endif |
173 if (thread_active_) { | 174 if (thread_active_) { |
174 // See comment above about why we unlock here. | 175 // See comment above about why we unlock here. |
175 int result = CallWhileUnlocked(thread_functions.thread_join, thread_id_); | 176 int result = CallWhileUnlocked(thread_functions.thread_join, thread_id_); |
176 DCHECK_EQ(0, result); | 177 DCHECK_EQ(0, result); |
177 thread_active_ = false; | 178 thread_active_ = false; |
178 } | 179 } |
179 #endif | |
180 } | 180 } |
181 | 181 |
182 #if defined(OS_NACL) | |
183 // static | 182 // static |
184 void PPB_Audio_Shared::SetThreadFunctions( | 183 void PPB_Audio_Shared::SetThreadFunctions( |
185 const struct PP_ThreadFunctions* functions) { | 184 const struct PP_ThreadFunctions* functions) { |
185 DCHECK(!thread_functions_set); | |
186 DCHECK(thread_functions.thread_create == NULL); | 186 DCHECK(thread_functions.thread_create == NULL); |
187 DCHECK(thread_functions.thread_join == NULL); | 187 DCHECK(thread_functions.thread_join == NULL); |
188 thread_functions_set = true; | |
188 thread_functions = *functions; | 189 thread_functions = *functions; |
189 } | 190 } |
190 | 191 |
191 // static | 192 // static |
192 void PPB_Audio_Shared::CallRun(void* self) { | 193 void PPB_Audio_Shared::CallRun(void* self) { |
193 PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self); | 194 PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self); |
194 audio->Run(); | 195 audio->Run(); |
195 } | 196 } |
196 #endif | |
197 | 197 |
198 void PPB_Audio_Shared::Run() { | 198 void PPB_Audio_Shared::Run() { |
199 int pending_data = 0; | 199 int pending_data = 0; |
200 while (sizeof(pending_data) == | 200 while (sizeof(pending_data) == |
201 socket_->Receive(&pending_data, sizeof(pending_data))) { | 201 socket_->Receive(&pending_data, sizeof(pending_data))) { |
202 // |buffer_index_| must track the number of Receive() calls. See the Send() | 202 // |buffer_index_| must track the number of Receive() calls. See the Send() |
203 // call below for why this is important. | 203 // call below for why this is important. |
204 ++buffer_index_; | 204 ++buffer_index_; |
205 if (pending_data < 0) | 205 if (pending_data < 0) |
206 break; | 206 break; |
(...skipping 11 matching lines...) Expand all Loading... | |
218 // Let the other end know which buffer we just filled. The buffer index is | 218 // Let the other end know which buffer we just filled. The buffer index is |
219 // used to ensure the other end is getting the buffer it expects. For more | 219 // used to ensure the other end is getting the buffer it expects. For more |
220 // details on how this works see AudioSyncReader::WaitUntilDataIsReady(). | 220 // details on how this works see AudioSyncReader::WaitUntilDataIsReady(). |
221 size_t bytes_sent = socket_->Send(&buffer_index_, sizeof(buffer_index_)); | 221 size_t bytes_sent = socket_->Send(&buffer_index_, sizeof(buffer_index_)); |
222 if (bytes_sent != sizeof(buffer_index_)) | 222 if (bytes_sent != sizeof(buffer_index_)) |
223 break; | 223 break; |
224 } | 224 } |
225 } | 225 } |
226 | 226 |
227 } // namespace ppapi | 227 } // namespace ppapi |
OLD | NEW |