| 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 // The actual worker thread implementation. It's very bare bones and much | 21 // The actual worker thread implementation. It's very bare bones and much |
| 22 // simpler than SimpleThread (no synchronization in Start, etc) and supports | 22 // simpler than SimpleThread (no synchronization in Start, etc) and supports |
| 23 // joining the thread handle asynchronously via a provided message loop even | 23 // joining the thread handle asynchronously via a provided message loop even |
| 24 // after the Thread object itself has been deleted. | 24 // after the Thread object itself has been deleted. |
| 25 class AudioDeviceThread::Thread | 25 class AudioDeviceThread::Thread |
| 26 : public PlatformThread::Delegate, | 26 : public PlatformThread::Delegate, |
| 27 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> { | 27 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> { |
| 28 public: | 28 public: |
| 29 Thread(AudioDeviceThread::Callback* callback, | 29 Thread(AudioDeviceThread::Callback* callback, |
| 30 base::SyncSocket::Handle socket, | 30 base::SyncSocket::Handle socket, |
| 31 const char* thread_name); | 31 const char* thread_name, |
| 32 bool synchronized_buffers); |
| 32 | 33 |
| 33 void Start(); | 34 void Start(); |
| 34 | 35 |
| 35 // Stops the thread. If |loop_for_join| is non-NULL, the function posts | 36 // Stops the thread. If |loop_for_join| is non-NULL, the function posts |
| 36 // a task to join (close) the thread handle later instead of waiting for | 37 // a task to join (close) the thread handle later instead of waiting for |
| 37 // the thread. If loop_for_join is NULL, then the function waits | 38 // the thread. If loop_for_join is NULL, then the function waits |
| 38 // synchronously for the thread to terminate. | 39 // synchronously for the thread to terminate. |
| 39 void Stop(base::MessageLoop* loop_for_join); | 40 void Stop(base::MessageLoop* loop_for_join); |
| 40 | 41 |
| 41 private: | 42 private: |
| 42 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; | 43 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; |
| 43 virtual ~Thread(); | 44 virtual ~Thread(); |
| 44 | 45 |
| 45 // Overrides from PlatformThread::Delegate. | 46 // Overrides from PlatformThread::Delegate. |
| 46 virtual void ThreadMain() OVERRIDE; | 47 virtual void ThreadMain() OVERRIDE; |
| 47 | 48 |
| 48 // Runs the loop that reads from the socket. | 49 // Runs the loop that reads from the socket. |
| 49 void Run(); | 50 void Run(); |
| 50 | 51 |
| 51 private: | 52 private: |
| 52 base::PlatformThreadHandle thread_; | 53 base::PlatformThreadHandle thread_; |
| 53 AudioDeviceThread::Callback* callback_; | 54 AudioDeviceThread::Callback* callback_; |
| 54 base::CancelableSyncSocket socket_; | 55 base::CancelableSyncSocket socket_; |
| 55 base::Lock callback_lock_; | 56 base::Lock callback_lock_; |
| 56 const char* thread_name_; | 57 const char* thread_name_; |
| 58 const bool synchronized_buffers_; |
| 57 | 59 |
| 58 DISALLOW_COPY_AND_ASSIGN(Thread); | 60 DISALLOW_COPY_AND_ASSIGN(Thread); |
| 59 }; | 61 }; |
| 60 | 62 |
| 61 // AudioDeviceThread implementation | 63 // AudioDeviceThread implementation |
| 62 | 64 |
| 63 AudioDeviceThread::AudioDeviceThread() { | 65 AudioDeviceThread::AudioDeviceThread() { |
| 64 } | 66 } |
| 65 | 67 |
| 66 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_.get()); } | 68 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_.get()); } |
| 67 | 69 |
| 68 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, | 70 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, |
| 69 base::SyncSocket::Handle socket, | 71 base::SyncSocket::Handle socket, |
| 70 const char* thread_name) { | 72 const char* thread_name, |
| 73 bool synchronized_buffers) { |
| 71 base::AutoLock auto_lock(thread_lock_); | 74 base::AutoLock auto_lock(thread_lock_); |
| 72 CHECK(thread_.get() == NULL); | 75 CHECK(!thread_); |
| 73 thread_ = new AudioDeviceThread::Thread(callback, socket, thread_name); | 76 thread_ = new AudioDeviceThread::Thread( |
| 77 callback, socket, thread_name, synchronized_buffers); |
| 74 thread_->Start(); | 78 thread_->Start(); |
| 75 } | 79 } |
| 76 | 80 |
| 77 void AudioDeviceThread::Stop(base::MessageLoop* loop_for_join) { | 81 void AudioDeviceThread::Stop(base::MessageLoop* loop_for_join) { |
| 78 base::AutoLock auto_lock(thread_lock_); | 82 base::AutoLock auto_lock(thread_lock_); |
| 79 if (thread_.get()) { | 83 if (thread_.get()) { |
| 80 thread_->Stop(loop_for_join); | 84 thread_->Stop(loop_for_join); |
| 81 thread_ = NULL; | 85 thread_ = NULL; |
| 82 } | 86 } |
| 83 } | 87 } |
| 84 | 88 |
| 85 bool AudioDeviceThread::IsStopped() { | 89 bool AudioDeviceThread::IsStopped() { |
| 86 base::AutoLock auto_lock(thread_lock_); | 90 base::AutoLock auto_lock(thread_lock_); |
| 87 return thread_.get() == NULL; | 91 return !thread_; |
| 88 } | 92 } |
| 89 | 93 |
| 90 // AudioDeviceThread::Thread implementation | 94 // AudioDeviceThread::Thread implementation |
| 91 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, | 95 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, |
| 92 base::SyncSocket::Handle socket, | 96 base::SyncSocket::Handle socket, |
| 93 const char* thread_name) | 97 const char* thread_name, |
| 98 bool synchronized_buffers) |
| 94 : thread_(), | 99 : thread_(), |
| 95 callback_(callback), | 100 callback_(callback), |
| 96 socket_(socket), | 101 socket_(socket), |
| 97 thread_name_(thread_name) { | 102 thread_name_(thread_name), |
| 103 synchronized_buffers_(synchronized_buffers) { |
| 98 } | 104 } |
| 99 | 105 |
| 100 AudioDeviceThread::Thread::~Thread() { | 106 AudioDeviceThread::Thread::~Thread() { |
| 101 DCHECK(thread_.is_null()); | 107 DCHECK(thread_.is_null()); |
| 102 } | 108 } |
| 103 | 109 |
| 104 void AudioDeviceThread::Thread::Start() { | 110 void AudioDeviceThread::Thread::Start() { |
| 105 base::AutoLock auto_lock(callback_lock_); | 111 base::AutoLock auto_lock(callback_lock_); |
| 106 DCHECK(thread_.is_null()); | 112 DCHECK(thread_.is_null()); |
| 107 // This reference will be released when the thread exists. | 113 // This reference will be released when the thread exists. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 } | 155 } |
| 150 | 156 |
| 151 Run(); | 157 Run(); |
| 152 | 158 |
| 153 // Release the reference for the thread. Note that after this, the Thread | 159 // Release the reference for the thread. Note that after this, the Thread |
| 154 // instance will most likely be deleted. | 160 // instance will most likely be deleted. |
| 155 Release(); | 161 Release(); |
| 156 } | 162 } |
| 157 | 163 |
| 158 void AudioDeviceThread::Thread::Run() { | 164 void AudioDeviceThread::Thread::Run() { |
| 165 uint32 buffer_index = 0; |
| 159 while (true) { | 166 while (true) { |
| 160 int pending_data = 0; | 167 int pending_data = 0; |
| 161 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data)); | 168 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data)); |
| 162 if (bytes_read != sizeof(pending_data)) { | 169 if (bytes_read != sizeof(pending_data)) { |
| 163 DCHECK_EQ(bytes_read, 0U); | 170 DCHECK_EQ(bytes_read, 0U); |
| 164 break; | 171 break; |
| 165 } | 172 } |
| 166 | 173 |
| 167 base::AutoLock auto_lock(callback_lock_); | 174 { |
| 168 if (callback_) | 175 base::AutoLock auto_lock(callback_lock_); |
| 169 callback_->Process(pending_data); | 176 if (callback_) |
| 177 callback_->Process(pending_data); |
| 178 } |
| 179 |
| 180 // Let the other end know which buffer we just filled. The buffer index is |
| 181 // used to ensure the other end is getting the buffer it expects. For more |
| 182 // details on how this works see AudioSyncReader::WaitUntilDataIsReady(). |
| 183 if (synchronized_buffers_) { |
| 184 ++buffer_index; |
| 185 size_t bytes_sent = socket_.Send(&buffer_index, sizeof(buffer_index)); |
| 186 if (bytes_sent != sizeof(buffer_index)) |
| 187 break; |
| 188 } |
| 170 } | 189 } |
| 171 } | 190 } |
| 172 | 191 |
| 173 // AudioDeviceThread::Callback implementation | 192 // AudioDeviceThread::Callback implementation |
| 174 | 193 |
| 175 AudioDeviceThread::Callback::Callback( | 194 AudioDeviceThread::Callback::Callback( |
| 176 const AudioParameters& audio_parameters, | 195 const AudioParameters& audio_parameters, |
| 177 base::SharedMemoryHandle memory, | 196 base::SharedMemoryHandle memory, |
| 178 int memory_length, | 197 int memory_length, |
| 179 int total_segments) | 198 int total_segments) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 193 } | 212 } |
| 194 | 213 |
| 195 AudioDeviceThread::Callback::~Callback() {} | 214 AudioDeviceThread::Callback::~Callback() {} |
| 196 | 215 |
| 197 void AudioDeviceThread::Callback::InitializeOnAudioThread() { | 216 void AudioDeviceThread::Callback::InitializeOnAudioThread() { |
| 198 MapSharedMemory(); | 217 MapSharedMemory(); |
| 199 CHECK(shared_memory_.memory()); | 218 CHECK(shared_memory_.memory()); |
| 200 } | 219 } |
| 201 | 220 |
| 202 } // namespace media. | 221 } // namespace media. |
| OLD | NEW |