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
3 // found in the LICENSE file.
4
5 #include "media/audio/audio_device_thread.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/aligned_memory.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "media/base/audio_bus.h"
16
17 using base::PlatformThread;
18
19 namespace media {
20
21 // The actual worker thread implementation. It's very bare bones and much
22 // simpler than SimpleThread (no synchronization in Start, etc) and supports
23 // joining the thread handle asynchronously via a provided message loop even
24 // after the Thread object itself has been deleted.
25 class AudioDeviceThread::Thread
26 : public PlatformThread::Delegate,
27 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> {
28 public:
29 Thread(AudioDeviceThread::Callback* callback,
30 base::SyncSocket::Handle socket,
31 const char* thread_name,
32 bool synchronized_buffers);
33
34 void Start();
35
36 // 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 // the thread. If loop_for_join is NULL, then the function waits
39 // synchronously for the thread to terminate.
40 void Stop(base::MessageLoop* loop_for_join);
41
42 private:
43 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>;
44 virtual ~Thread();
45
46 // Overrides from PlatformThread::Delegate.
47 virtual void ThreadMain() OVERRIDE;
48
49 // Runs the loop that reads from the socket.
50 void Run();
51
52 private:
53 base::PlatformThreadHandle thread_;
54 AudioDeviceThread::Callback* callback_;
55 base::CancelableSyncSocket socket_;
56 base::Lock callback_lock_;
57 const char* thread_name_;
58 const bool synchronized_buffers_;
59
60 DISALLOW_COPY_AND_ASSIGN(Thread);
61 };
62
63 // AudioDeviceThread implementation
64
AudioDeviceThread()65 AudioDeviceThread::AudioDeviceThread() {
66 }
67
~AudioDeviceThread()68 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_.get()); }
69
Start(AudioDeviceThread::Callback * callback,base::SyncSocket::Handle socket,const char * thread_name,bool synchronized_buffers)70 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback,
71 base::SyncSocket::Handle socket,
72 const char* thread_name,
73 bool synchronized_buffers) {
74 base::AutoLock auto_lock(thread_lock_);
75 CHECK(!thread_.get());
76 thread_ = new AudioDeviceThread::Thread(
77 callback, socket, thread_name, synchronized_buffers);
78 thread_->Start();
79 }
80
Stop(base::MessageLoop * loop_for_join)81 void AudioDeviceThread::Stop(base::MessageLoop* loop_for_join) {
82 base::AutoLock auto_lock(thread_lock_);
83 if (thread_.get()) {
84 thread_->Stop(loop_for_join);
85 thread_ = NULL;
86 }
87 }
88
IsStopped()89 bool AudioDeviceThread::IsStopped() {
90 base::AutoLock auto_lock(thread_lock_);
91 return !thread_.get();
92 }
93
94 // AudioDeviceThread::Thread implementation
Thread(AudioDeviceThread::Callback * callback,base::SyncSocket::Handle socket,const char * thread_name,bool synchronized_buffers)95 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback,
96 base::SyncSocket::Handle socket,
97 const char* thread_name,
98 bool synchronized_buffers)
99 : thread_(),
100 callback_(callback),
101 socket_(socket),
102 thread_name_(thread_name),
103 synchronized_buffers_(synchronized_buffers) {
104 }
105
~Thread()106 AudioDeviceThread::Thread::~Thread() {
107 DCHECK(thread_.is_null());
108 }
109
Start()110 void AudioDeviceThread::Thread::Start() {
111 base::AutoLock auto_lock(callback_lock_);
112 DCHECK(thread_.is_null());
113 // This reference will be released when the thread exists.
114 AddRef();
115
116 PlatformThread::CreateWithPriority(0, this, &thread_,
117 base::kThreadPriority_RealtimeAudio);
118 CHECK(!thread_.is_null());
119 }
120
Stop(base::MessageLoop * loop_for_join)121 void AudioDeviceThread::Thread::Stop(base::MessageLoop* loop_for_join) {
122 socket_.Shutdown();
123
124 base::PlatformThreadHandle thread = base::PlatformThreadHandle();
125
126 { // NOLINT
127 base::AutoLock auto_lock(callback_lock_);
128 callback_ = NULL;
129 std::swap(thread, thread_);
130 }
131
132 if (!thread.is_null()) {
133 if (loop_for_join) {
134 loop_for_join->PostTask(FROM_HERE,
135 base::Bind(&base::PlatformThread::Join, thread));
136 } else {
137 base::PlatformThread::Join(thread);
138 }
139 }
140 }
141
ThreadMain()142 void AudioDeviceThread::Thread::ThreadMain() {
143 PlatformThread::SetName(thread_name_);
144
145 // Singleton access is safe from this thread as long as callback is non-NULL.
146 // The callback is the only point where the thread calls out to 'unknown' code
147 // that might touch singletons and the lifetime of the callback is controlled
148 // by another thread on which singleton access is OK as well.
149 base::ThreadRestrictions::SetSingletonAllowed(true);
150
151 { // NOLINT
152 base::AutoLock auto_lock(callback_lock_);
153 if (callback_)
154 callback_->InitializeOnAudioThread();
155 }
156
157 Run();
158
159 // Release the reference for the thread. Note that after this, the Thread
160 // instance will most likely be deleted.
161 Release();
162 }
163
Run()164 void AudioDeviceThread::Thread::Run() {
165 uint32 buffer_index = 0;
166 while (true) {
167 int pending_data = 0;
168 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data));
169 if (bytes_read != sizeof(pending_data))
170 break;
171
172 {
173 base::AutoLock auto_lock(callback_lock_);
174 if (callback_)
175 callback_->Process(pending_data);
176 }
177
178 // Let the other end know which buffer we just filled. The buffer index is
179 // used to ensure the other end is getting the buffer it expects. For more
180 // details on how this works see AudioSyncReader::WaitUntilDataIsReady().
181 if (synchronized_buffers_) {
182 ++buffer_index;
183 size_t bytes_sent = socket_.Send(&buffer_index, sizeof(buffer_index));
184 if (bytes_sent != sizeof(buffer_index))
185 break;
186 }
187 }
188 }
189
190 // AudioDeviceThread::Callback implementation
191
Callback(const AudioParameters & audio_parameters,base::SharedMemoryHandle memory,int memory_length,int total_segments)192 AudioDeviceThread::Callback::Callback(
193 const AudioParameters& audio_parameters,
194 base::SharedMemoryHandle memory,
195 int memory_length,
196 int total_segments)
197 : audio_parameters_(audio_parameters),
198 samples_per_ms_(audio_parameters.sample_rate() / 1000),
199 bytes_per_ms_(audio_parameters.channels() *
200 (audio_parameters_.bits_per_sample() / 8) *
201 samples_per_ms_),
202 shared_memory_(memory, false),
203 memory_length_(memory_length),
204 total_segments_(total_segments) {
205 CHECK_NE(bytes_per_ms_, 0); // Catch division by zero early.
206 CHECK_NE(samples_per_ms_, 0);
207 CHECK_GT(total_segments_, 0);
208 CHECK_EQ(memory_length_ % total_segments_, 0);
209 segment_length_ = memory_length_ / total_segments_;
210 }
211
~Callback()212 AudioDeviceThread::Callback::~Callback() {}
213
InitializeOnAudioThread()214 void AudioDeviceThread::Callback::InitializeOnAudioThread() {
215 MapSharedMemory();
216 CHECK(shared_memory_.memory());
217 }
218
219 } // namespace media.
220