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 10 matching lines...) Expand all Loading... |
21 | 21 |
22 // The actual worker thread implementation. It's very bare bones and much | 22 // The actual worker thread implementation. It's very bare bones and much |
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 bool need_read_index, |
31 base::SyncSocket::Handle socket, | 32 base::SyncSocket::Handle socket, |
32 const char* thread_name); | 33 const char* thread_name); |
33 | 34 |
34 void Start(); | 35 void Start(); |
35 | 36 |
36 // Stops the thread. If |loop_for_join| is non-NULL, the function posts | 37 // Stops the thread. If |loop_for_join| is non-NULL, the function posts |
37 // a task to join (close) the thread handle later instead of waiting for | 38 // a task to join (close) the thread handle later instead of waiting for |
38 // the thread. If loop_for_join is NULL, then the function waits | 39 // the thread. If loop_for_join is NULL, then the function waits |
39 // synchronously for the thread to terminate. | 40 // synchronously for the thread to terminate. |
40 void Stop(MessageLoop* loop_for_join); | 41 void Stop(MessageLoop* loop_for_join); |
41 | 42 |
42 private: | 43 private: |
43 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; | 44 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; |
44 virtual ~Thread(); | 45 virtual ~Thread(); |
45 | 46 |
46 // Overrides from PlatformThread::Delegate. | 47 // Overrides from PlatformThread::Delegate. |
47 virtual void ThreadMain() OVERRIDE; | 48 virtual void ThreadMain() OVERRIDE; |
48 | 49 |
49 // Runs the loop that reads from the socket. | 50 // Runs the loop that reads from the socket. |
50 void Run(); | 51 void Run(); |
51 | 52 |
52 private: | 53 private: |
53 base::PlatformThreadHandle thread_; | 54 base::PlatformThreadHandle thread_; |
54 AudioDeviceThread::Callback* callback_; | 55 AudioDeviceThread::Callback* callback_; |
| 56 bool need_read_index_; |
55 base::CancelableSyncSocket socket_; | 57 base::CancelableSyncSocket socket_; |
56 base::Lock callback_lock_; | 58 base::Lock callback_lock_; |
57 const char* thread_name_; | 59 const char* thread_name_; |
58 | 60 |
59 DISALLOW_COPY_AND_ASSIGN(Thread); | 61 DISALLOW_COPY_AND_ASSIGN(Thread); |
60 }; | 62 }; |
61 | 63 |
62 // AudioDeviceThread implementation | 64 // AudioDeviceThread implementation |
63 | 65 |
64 AudioDeviceThread::AudioDeviceThread() { | 66 AudioDeviceThread::AudioDeviceThread(bool need_read_index) |
| 67 : need_read_index_(need_read_index) { |
65 } | 68 } |
66 | 69 |
67 AudioDeviceThread::~AudioDeviceThread() { | 70 AudioDeviceThread::~AudioDeviceThread() { |
68 DCHECK(!thread_); | 71 DCHECK(!thread_); |
69 } | 72 } |
70 | 73 |
71 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, | 74 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, |
72 base::SyncSocket::Handle socket, | 75 base::SyncSocket::Handle socket, |
73 const char* thread_name) { | 76 const char* thread_name) { |
74 base::AutoLock auto_lock(thread_lock_); | 77 base::AutoLock auto_lock(thread_lock_); |
75 CHECK(thread_ == NULL); | 78 CHECK(thread_ == NULL); |
76 thread_ = new AudioDeviceThread::Thread(callback, socket, thread_name); | 79 thread_ = new AudioDeviceThread::Thread( |
| 80 callback, need_read_index_, socket, thread_name); |
77 thread_->Start(); | 81 thread_->Start(); |
78 } | 82 } |
79 | 83 |
80 void AudioDeviceThread::Stop(MessageLoop* loop_for_join) { | 84 void AudioDeviceThread::Stop(MessageLoop* loop_for_join) { |
81 base::AutoLock auto_lock(thread_lock_); | 85 base::AutoLock auto_lock(thread_lock_); |
82 if (thread_) { | 86 if (thread_) { |
83 thread_->Stop(loop_for_join); | 87 thread_->Stop(loop_for_join); |
84 thread_ = NULL; | 88 thread_ = NULL; |
85 } | 89 } |
86 } | 90 } |
87 | 91 |
88 bool AudioDeviceThread::IsStopped() { | 92 bool AudioDeviceThread::IsStopped() { |
89 base::AutoLock auto_lock(thread_lock_); | 93 base::AutoLock auto_lock(thread_lock_); |
90 return thread_ == NULL; | 94 return thread_ == NULL; |
91 } | 95 } |
92 | 96 |
93 // AudioDeviceThread::Thread implementation | 97 // AudioDeviceThread::Thread implementation |
94 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, | 98 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, |
| 99 bool need_read_index, |
95 base::SyncSocket::Handle socket, | 100 base::SyncSocket::Handle socket, |
96 const char* thread_name) | 101 const char* thread_name) |
97 : thread_(base::kNullThreadHandle), | 102 : thread_(base::kNullThreadHandle), |
98 callback_(callback), | 103 callback_(callback), |
| 104 need_read_index_(need_read_index), |
99 socket_(socket), | 105 socket_(socket), |
100 thread_name_(thread_name) { | 106 thread_name_(thread_name) { |
101 } | 107 } |
102 | 108 |
103 AudioDeviceThread::Thread::~Thread() { | 109 AudioDeviceThread::Thread::~Thread() { |
104 DCHECK_EQ(thread_, base::kNullThreadHandle) << "Stop wasn't called"; | 110 DCHECK_EQ(thread_, base::kNullThreadHandle) << "Stop wasn't called"; |
105 } | 111 } |
106 | 112 |
107 void AudioDeviceThread::Thread::Start() { | 113 void AudioDeviceThread::Thread::Start() { |
108 base::AutoLock auto_lock(callback_lock_); | 114 base::AutoLock auto_lock(callback_lock_); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 Run(); | 160 Run(); |
155 | 161 |
156 // Release the reference for the thread. Note that after this, the Thread | 162 // Release the reference for the thread. Note that after this, the Thread |
157 // instance will most likely be deleted. | 163 // instance will most likely be deleted. |
158 Release(); | 164 Release(); |
159 } | 165 } |
160 | 166 |
161 void AudioDeviceThread::Thread::Run() { | 167 void AudioDeviceThread::Thread::Run() { |
162 while (true) { | 168 while (true) { |
163 int pending_data = 0; | 169 int pending_data = 0; |
| 170 int pending_id = 0; |
164 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data)); | 171 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data)); |
165 if (bytes_read != sizeof(pending_data)) { | 172 if (bytes_read != sizeof(pending_data)) { |
166 DCHECK_EQ(bytes_read, 0U); | 173 DCHECK_EQ(bytes_read, 0U); |
167 break; | 174 break; |
168 } | 175 } |
169 | 176 |
| 177 if (need_read_index_) { |
| 178 size_t bytes_read = socket_.Receive(&pending_id, sizeof(pending_id)); |
| 179 if (bytes_read != sizeof(pending_id)) { |
| 180 DCHECK_EQ(bytes_read, 0U); |
| 181 break; |
| 182 } |
| 183 } |
| 184 |
170 base::AutoLock auto_lock(callback_lock_); | 185 base::AutoLock auto_lock(callback_lock_); |
171 if (callback_) | 186 if (callback_) |
172 callback_->Process(pending_data); | 187 callback_->Process(pending_data, pending_id); |
173 } | 188 } |
174 } | 189 } |
175 | 190 |
176 // AudioDeviceThread::Callback implementation | 191 // AudioDeviceThread::Callback implementation |
177 | 192 |
178 AudioDeviceThread::Callback::Callback( | 193 AudioDeviceThread::Callback::Callback( |
179 const AudioParameters& audio_parameters, | 194 const AudioParameters& audio_parameters, |
180 base::SharedMemoryHandle memory, int memory_length) | 195 SharedMemoryHandleVector& memory, |
| 196 int memory_length) |
181 : audio_parameters_(audio_parameters), | 197 : audio_parameters_(audio_parameters), |
182 samples_per_ms_(audio_parameters.sample_rate() / 1000), | 198 samples_per_ms_(audio_parameters.sample_rate() / 1000), |
183 bytes_per_ms_(audio_parameters.channels() * | 199 bytes_per_ms_(audio_parameters.channels() * |
184 (audio_parameters_.bits_per_sample() / 8) * | 200 (audio_parameters_.bits_per_sample() / 8) * |
185 samples_per_ms_), | 201 samples_per_ms_), |
186 shared_memory_(memory, false), | |
187 memory_length_(memory_length) { | 202 memory_length_(memory_length) { |
188 CHECK_NE(bytes_per_ms_, 0); // Catch division by zero early. | 203 CHECK_NE(bytes_per_ms_, 0); // Catch division by zero early. |
189 CHECK_NE(samples_per_ms_, 0); | 204 CHECK_NE(samples_per_ms_, 0); |
| 205 shared_memory_.resize(memory.size()); |
| 206 for (size_t id = 0; id < shared_memory_.size(); ++id) |
| 207 shared_memory_[id] = new base::SharedMemory(memory[id], false); |
190 } | 208 } |
191 | 209 |
192 AudioDeviceThread::Callback::~Callback() {} | 210 AudioDeviceThread::Callback::~Callback() {} |
193 | 211 |
194 void AudioDeviceThread::Callback::InitializeOnAudioThread() { | 212 void AudioDeviceThread::Callback::InitializeOnAudioThread() { |
195 MapSharedMemory(); | 213 MapSharedMemory(); |
196 CHECK(shared_memory_.memory()); | 214 for (size_t id = 0; id < shared_memory_.size(); ++id) |
| 215 CHECK(shared_memory_[id]->memory()); |
197 } | 216 } |
198 | 217 |
199 } // namespace media. | 218 } // namespace media. |
OLD | NEW |