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.
5 #include "media/audio/audio_device_thread.h"
10 #include "base/logging.h"
11 #include "base/memory/aligned_memory.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/threading/platform_thread.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "media/base/audio_bus.h"
18 using base::PlatformThread
;
22 // The actual worker thread implementation. It's very bare bones and much
23 // simpler than SimpleThread (no synchronization in Start, etc) and supports
24 // joining the thread handle asynchronously via a provided message loop even
25 // after the Thread object itself has been deleted.
26 class AudioDeviceThread::Thread
27 : public PlatformThread::Delegate
,
28 public base::RefCountedThreadSafe
<AudioDeviceThread::Thread
> {
30 Thread(AudioDeviceThread::Callback
* callback
,
31 base::SyncSocket::Handle socket
,
32 const char* thread_name
,
33 bool synchronized_buffers
);
37 // 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 // the thread. If loop_for_join is NULL, then the function waits
40 // synchronously for the thread to terminate.
41 void Stop(base::MessageLoop
* loop_for_join
);
44 friend class base::RefCountedThreadSafe
<AudioDeviceThread::Thread
>;
47 // Overrides from PlatformThread::Delegate.
48 virtual void ThreadMain() OVERRIDE
;
50 // Runs the loop that reads from the socket.
54 base::PlatformThreadHandle thread_
;
55 AudioDeviceThread::Callback
* callback_
;
56 base::CancelableSyncSocket socket_
;
57 base::Lock callback_lock_
;
58 const char* thread_name_
;
59 const bool synchronized_buffers_
;
61 DISALLOW_COPY_AND_ASSIGN(Thread
);
64 // AudioDeviceThread implementation
66 AudioDeviceThread::AudioDeviceThread() {
69 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_
.get()); }
71 void AudioDeviceThread::Start(AudioDeviceThread::Callback
* callback
,
72 base::SyncSocket::Handle socket
,
73 const char* thread_name
,
74 bool synchronized_buffers
) {
75 base::AutoLock
auto_lock(thread_lock_
);
76 CHECK(!thread_
.get());
77 thread_
= new AudioDeviceThread::Thread(
78 callback
, socket
, thread_name
, synchronized_buffers
);
82 void AudioDeviceThread::Stop(base::MessageLoop
* loop_for_join
) {
83 base::AutoLock
auto_lock(thread_lock_
);
85 thread_
->Stop(loop_for_join
);
90 bool AudioDeviceThread::IsStopped() {
91 base::AutoLock
auto_lock(thread_lock_
);
92 return !thread_
.get();
95 // AudioDeviceThread::Thread implementation
96 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback
* callback
,
97 base::SyncSocket::Handle socket
,
98 const char* thread_name
,
99 bool synchronized_buffers
)
103 thread_name_(thread_name
),
104 synchronized_buffers_(synchronized_buffers
) {
107 AudioDeviceThread::Thread::~Thread() {
108 DCHECK(thread_
.is_null());
111 void AudioDeviceThread::Thread::Start() {
112 base::AutoLock
auto_lock(callback_lock_
);
113 DCHECK(thread_
.is_null());
114 // This reference will be released when the thread exists.
117 PlatformThread::CreateWithPriority(0, this, &thread_
,
118 base::kThreadPriority_RealtimeAudio
);
119 CHECK(!thread_
.is_null());
122 void AudioDeviceThread::Thread::Stop(base::MessageLoop
* loop_for_join
) {
125 base::PlatformThreadHandle thread
= base::PlatformThreadHandle();
128 base::AutoLock
auto_lock(callback_lock_
);
130 std::swap(thread
, thread_
);
133 if (!thread
.is_null()) {
135 loop_for_join
->PostTask(FROM_HERE
,
136 base::Bind(&base::PlatformThread::Join
, thread
));
138 base::PlatformThread::Join(thread
);
143 void AudioDeviceThread::Thread::ThreadMain() {
144 PlatformThread::SetName(thread_name_
);
146 // Singleton access is safe from this thread as long as callback is non-NULL.
147 // The callback is the only point where the thread calls out to 'unknown' code
148 // that might touch singletons and the lifetime of the callback is controlled
149 // by another thread on which singleton access is OK as well.
150 base::ThreadRestrictions::SetSingletonAllowed(true);
153 base::AutoLock
auto_lock(callback_lock_
);
155 callback_
->InitializeOnAudioThread();
160 // Release the reference for the thread. Note that after this, the Thread
161 // instance will most likely be deleted.
165 void AudioDeviceThread::Thread::Run() {
166 uint32 buffer_index
= 0;
168 uint32 pending_data
= 0;
169 size_t bytes_read
= socket_
.Receive(&pending_data
, sizeof(pending_data
));
170 if (bytes_read
!= sizeof(pending_data
))
174 base::AutoLock
auto_lock(callback_lock_
);
176 // TODO(acolwell): Update downstream code to use a uint32.
177 // Under normal operation saturation should never occur here
178 // and even if it does, it would only cause a temporary loss
179 // of A/V sync which is much better than crashing or halting
181 callback_
->Process(base::saturated_cast
<uint32
>(pending_data
));
185 // Let the other end know which buffer we just filled. The buffer index is
186 // used to ensure the other end is getting the buffer it expects. For more
187 // details on how this works see AudioSyncReader::WaitUntilDataIsReady().
188 if (synchronized_buffers_
) {
190 size_t bytes_sent
= socket_
.Send(&buffer_index
, sizeof(buffer_index
));
191 if (bytes_sent
!= sizeof(buffer_index
))
197 // AudioDeviceThread::Callback implementation
199 AudioDeviceThread::Callback::Callback(
200 const AudioParameters
& audio_parameters
,
201 base::SharedMemoryHandle memory
,
204 : audio_parameters_(audio_parameters
),
205 samples_per_ms_(audio_parameters
.sample_rate() / 1000),
206 bytes_per_ms_(audio_parameters
.channels() *
207 (audio_parameters_
.bits_per_sample() / 8) *
209 shared_memory_(memory
, false),
210 memory_length_(memory_length
),
211 total_segments_(total_segments
) {
212 CHECK_NE(bytes_per_ms_
, 0); // Catch division by zero early.
213 CHECK_NE(samples_per_ms_
, 0);
214 CHECK_GT(total_segments_
, 0);
215 CHECK_EQ(memory_length_
% total_segments_
, 0);
216 segment_length_
= memory_length_
/ total_segments_
;
219 AudioDeviceThread::Callback::~Callback() {}
221 void AudioDeviceThread::Callback::InitializeOnAudioThread() {
223 CHECK(shared_memory_
.memory());
226 } // namespace media.