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 "media/audio/audio_device_thread.h" | 5 #include "media/audio/audio_device_thread.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 // simpler than SimpleThread (no synchronization in Start, etc) and supports | 23 // simpler than SimpleThread (no synchronization in Start, etc) and supports |
24 // joining the thread handle asynchronously via a provided message loop even | 24 // joining the thread handle asynchronously via a provided message loop even |
25 // after the Thread object itself has been deleted. | 25 // after the Thread object itself has been deleted. |
26 class AudioDeviceThread::Thread | 26 class AudioDeviceThread::Thread |
27 : public PlatformThread::Delegate, | 27 : public PlatformThread::Delegate, |
28 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> { | 28 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> { |
29 public: | 29 public: |
30 Thread(AudioDeviceThread::Callback* callback, | 30 Thread(AudioDeviceThread::Callback* callback, |
31 base::SyncSocket::Handle socket, | 31 base::SyncSocket::Handle socket, |
32 const char* thread_name, | 32 const char* thread_name, |
33 bool synchronized_buffers); | 33 bool synchronized_buffers, |
34 bool input); | |
34 | 35 |
35 void Start(); | 36 void Start(); |
36 | 37 |
37 // Stops the thread. If |loop_for_join| is non-NULL, the function posts | 38 // Stops the thread. If |loop_for_join| is non-NULL, the function posts |
38 // a task to join (close) the thread handle later instead of waiting for | 39 // a task to join (close) the thread handle later instead of waiting for |
39 // the thread. If loop_for_join is NULL, then the function waits | 40 // the thread. If loop_for_join is NULL, then the function waits |
40 // synchronously for the thread to terminate. | 41 // synchronously for the thread to terminate. |
41 void Stop(base::MessageLoop* loop_for_join); | 42 void Stop(base::MessageLoop* loop_for_join); |
42 | 43 |
43 private: | 44 private: |
44 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; | 45 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; |
45 ~Thread() override; | 46 ~Thread() override; |
46 | 47 |
47 // Overrides from PlatformThread::Delegate. | 48 // Overrides from PlatformThread::Delegate. |
48 void ThreadMain() override; | 49 void ThreadMain() override; |
49 | 50 |
50 // Runs the loop that reads from the socket. | 51 // Runs the loop that reads from the socket. |
51 void Run(); | 52 void Run(); |
52 | 53 |
53 private: | 54 private: |
54 base::PlatformThreadHandle thread_; | 55 base::PlatformThreadHandle thread_; |
55 AudioDeviceThread::Callback* callback_; | 56 AudioDeviceThread::Callback* callback_; |
56 base::CancelableSyncSocket socket_; | 57 base::CancelableSyncSocket socket_; |
57 base::Lock callback_lock_; | 58 base::Lock callback_lock_; |
58 const char* thread_name_; | 59 const char* thread_name_; |
59 const bool synchronized_buffers_; | 60 const bool synchronized_buffers_; |
61 const bool input_; | |
60 | 62 |
61 DISALLOW_COPY_AND_ASSIGN(Thread); | 63 DISALLOW_COPY_AND_ASSIGN(Thread); |
62 }; | 64 }; |
63 | 65 |
64 // AudioDeviceThread implementation | 66 // AudioDeviceThread implementation |
65 | 67 |
66 AudioDeviceThread::AudioDeviceThread() { | 68 AudioDeviceThread::AudioDeviceThread() { |
67 } | 69 } |
68 | 70 |
69 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_.get()); } | 71 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_.get()); } |
70 | 72 |
71 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, | 73 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, |
72 base::SyncSocket::Handle socket, | 74 base::SyncSocket::Handle socket, |
73 const char* thread_name, | 75 const char* thread_name, |
74 bool synchronized_buffers) { | 76 bool synchronized_buffers, |
77 bool input) { | |
75 base::AutoLock auto_lock(thread_lock_); | 78 base::AutoLock auto_lock(thread_lock_); |
76 CHECK(!thread_.get()); | 79 CHECK(!thread_.get()); |
77 thread_ = new AudioDeviceThread::Thread( | 80 thread_ = new AudioDeviceThread::Thread(callback, socket, thread_name, |
78 callback, socket, thread_name, synchronized_buffers); | 81 synchronized_buffers, input); |
79 thread_->Start(); | 82 thread_->Start(); |
80 } | 83 } |
81 | 84 |
82 void AudioDeviceThread::Stop(base::MessageLoop* loop_for_join) { | 85 void AudioDeviceThread::Stop(base::MessageLoop* loop_for_join) { |
83 base::AutoLock auto_lock(thread_lock_); | 86 base::AutoLock auto_lock(thread_lock_); |
84 if (thread_.get()) { | 87 if (thread_.get()) { |
85 thread_->Stop(loop_for_join); | 88 thread_->Stop(loop_for_join); |
86 thread_ = NULL; | 89 thread_ = NULL; |
87 } | 90 } |
88 } | 91 } |
89 | 92 |
90 bool AudioDeviceThread::IsStopped() { | 93 bool AudioDeviceThread::IsStopped() { |
91 base::AutoLock auto_lock(thread_lock_); | 94 base::AutoLock auto_lock(thread_lock_); |
92 return !thread_.get(); | 95 return !thread_.get(); |
93 } | 96 } |
94 | 97 |
95 // AudioDeviceThread::Thread implementation | 98 // AudioDeviceThread::Thread implementation |
96 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, | 99 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, |
97 base::SyncSocket::Handle socket, | 100 base::SyncSocket::Handle socket, |
98 const char* thread_name, | 101 const char* thread_name, |
99 bool synchronized_buffers) | 102 bool synchronized_buffers, |
103 bool input) | |
100 : thread_(), | 104 : thread_(), |
101 callback_(callback), | 105 callback_(callback), |
102 socket_(socket), | 106 socket_(socket), |
103 thread_name_(thread_name), | 107 thread_name_(thread_name), |
104 synchronized_buffers_(synchronized_buffers) { | 108 synchronized_buffers_(synchronized_buffers), |
105 } | 109 input_(input) {} |
106 | 110 |
107 AudioDeviceThread::Thread::~Thread() { | 111 AudioDeviceThread::Thread::~Thread() { |
108 DCHECK(thread_.is_null()); | 112 DCHECK(thread_.is_null()); |
109 } | 113 } |
110 | 114 |
111 void AudioDeviceThread::Thread::Start() { | 115 void AudioDeviceThread::Thread::Start() { |
112 base::AutoLock auto_lock(callback_lock_); | 116 base::AutoLock auto_lock(callback_lock_); |
113 DCHECK(thread_.is_null()); | 117 DCHECK(thread_.is_null()); |
114 // This reference will be released when the thread exists. | 118 // This reference will be released when the thread exists. |
115 AddRef(); | 119 AddRef(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 Run(); | 162 Run(); |
159 | 163 |
160 // Release the reference for the thread. Note that after this, the Thread | 164 // Release the reference for the thread. Note that after this, the Thread |
161 // instance will most likely be deleted. | 165 // instance will most likely be deleted. |
162 Release(); | 166 Release(); |
163 } | 167 } |
164 | 168 |
165 void AudioDeviceThread::Thread::Run() { | 169 void AudioDeviceThread::Thread::Run() { |
166 uint32 buffer_index = 0; | 170 uint32 buffer_index = 0; |
167 while (true) { | 171 while (true) { |
168 uint32 pending_data = 0; | 172 if (input_) { |
169 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data)); | 173 uint32_t pending_data = 0; |
170 if (bytes_read != sizeof(pending_data)) | 174 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data)); |
171 break; | 175 if (bytes_read != sizeof(pending_data)) |
176 break; | |
172 | 177 |
173 // kuint32max is a special signal which is returned after the browser | |
174 // stops the output device in response to a renderer side request. | |
175 // | |
176 // Avoid running Process() for the paused signal, we still need to update | |
177 // the buffer index if |synchronized_buffers_| is true though. | |
178 // | |
179 // See comments in AudioOutputController::DoPause() for details on why. | |
180 if (pending_data != kuint32max) { | |
181 base::AutoLock auto_lock(callback_lock_); | 178 base::AutoLock auto_lock(callback_lock_); |
182 if (callback_) | 179 if (callback_) |
183 callback_->Process(pending_data); | 180 callback_->Process(pending_data); |
181 } else { | |
182 uint64_t data = 0; | |
tommi (sloooow) - chröme
2015/12/01 13:34:25
if you don't want to use a struct, you can also us
DaleCurtis
2015/12/01 18:12:46
Long ago we were worried anything more than 4 byte
tommi (sloooow) - chröme
2015/12/01 19:03:31
Would it work to use the shared memory buffer inst
DaleCurtis
2015/12/01 20:06:48
That's what we do for input I believe.
Henrik Grunell
2015/12/03 17:01:06
Good to know. We can use the shared memory. Yes we
| |
183 size_t bytes_read = socket_.Receive(&data, sizeof(data)); | |
184 if (bytes_read != sizeof(data)) | |
185 break; | |
186 | |
187 uint32_t pending_data = static_cast<uint32_t>((data >> 32) & 0xffffffff); | |
188 uint32_t frames_skipped = static_cast<uint32_t>(data & 0xffffffff); | |
189 | |
190 base::AutoLock auto_lock(callback_lock_); | |
191 if (callback_) { | |
192 if (frames_skipped > 0) | |
193 callback_->FramesSkipped(frames_skipped); | |
194 | |
195 // kuint32max is a special signal which is returned after the browser | |
196 // stops the output device in response to a renderer side request. | |
197 // | |
198 // Avoid running Process() for the paused signal, we still need to | |
199 // update the buffer index if |synchronized_buffers_| is true though. | |
200 // | |
201 // See comments in AudioOutputController::DoPause() for details on why. | |
202 if (pending_data != kuint32max) | |
203 callback_->Process(pending_data); | |
204 } | |
184 } | 205 } |
185 | 206 |
186 // The usage of |synchronized_buffers_| differs between input and output | 207 // The usage of |synchronized_buffers_| differs between input and output |
187 // cases. | 208 // cases. |
188 // Input: | 209 // Input: |
189 // Let the other end know that we have read data, so that it can verify | 210 // Let the other end know that we have read data, so that it can verify |
190 // it doesn't overwrite any data before read. The |buffer_index| value is | 211 // it doesn't overwrite any data before read. The |buffer_index| value is |
191 // not used. For more details, see AudioInputSyncWriter::Write(). | 212 // not used. For more details, see AudioInputSyncWriter::Write(). |
192 // Output: | 213 // Output: |
193 // Let the other end know which buffer we just filled. The |buffer_index| is | 214 // Let the other end know which buffer we just filled. The |buffer_index| is |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 } | 246 } |
226 | 247 |
227 AudioDeviceThread::Callback::~Callback() {} | 248 AudioDeviceThread::Callback::~Callback() {} |
228 | 249 |
229 void AudioDeviceThread::Callback::InitializeOnAudioThread() { | 250 void AudioDeviceThread::Callback::InitializeOnAudioThread() { |
230 MapSharedMemory(); | 251 MapSharedMemory(); |
231 CHECK(shared_memory_.memory()); | 252 CHECK(shared_memory_.memory()); |
232 } | 253 } |
233 | 254 |
234 } // namespace media. | 255 } // namespace media. |
OLD | NEW |