| 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 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 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 read_index) |
| 67 : read_index_(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, 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 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 read_index_(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 (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 DCHECK(shared_memory_.memory() != NULL); | 214 for (size_t id = 0; id < shared_memory_.size(); ++id) |
| 215 DCHECK(shared_memory_[id]->memory() != NULL); |
| 197 } | 216 } |
| 198 | 217 |
| 199 } // namespace media. | 218 } // namespace media. |
| OLD | NEW |