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 |