Chromium Code Reviews| 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 |