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/threading/platform_thread.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "media/base/audio_bus.h"
17 using base::PlatformThread
;
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
> {
29 Thread(AudioDeviceThread::Callback
* callback
,
30 base::SyncSocket::Handle socket
,
31 const char* thread_name
,
32 bool synchronized_buffers
);
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
);
43 friend class base::RefCountedThreadSafe
<AudioDeviceThread::Thread
>;
46 // Overrides from PlatformThread::Delegate.
47 virtual void ThreadMain() OVERRIDE
;
49 // Runs the loop that reads from the socket.
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_
;
60 DISALLOW_COPY_AND_ASSIGN(Thread
);
63 // AudioDeviceThread implementation
65 AudioDeviceThread::AudioDeviceThread() {
68 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_
.get()); }
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_
);
76 thread_
= new AudioDeviceThread::Thread(
77 callback
, socket
, thread_name
, synchronized_buffers
);
81 void AudioDeviceThread::Stop(base::MessageLoop
* loop_for_join
) {
82 base::AutoLock
auto_lock(thread_lock_
);
84 thread_
->Stop(loop_for_join
);
89 bool AudioDeviceThread::IsStopped() {
90 base::AutoLock
auto_lock(thread_lock_
);
94 // AudioDeviceThread::Thread implementation
95 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback
* callback
,
96 base::SyncSocket::Handle socket
,
97 const char* thread_name
,
98 bool synchronized_buffers
)
102 thread_name_(thread_name
),
103 synchronized_buffers_(synchronized_buffers
) {
106 AudioDeviceThread::Thread::~Thread() {
107 DCHECK(thread_
.is_null());
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.
116 PlatformThread::CreateWithPriority(0, this, &thread_
,
117 base::kThreadPriority_RealtimeAudio
);
118 CHECK(!thread_
.is_null());
121 void AudioDeviceThread::Thread::Stop(base::MessageLoop
* loop_for_join
) {
124 base::PlatformThreadHandle thread
= base::PlatformThreadHandle();
127 base::AutoLock
auto_lock(callback_lock_
);
129 std::swap(thread
, thread_
);
132 if (!thread
.is_null()) {
134 loop_for_join
->PostTask(FROM_HERE
,
135 base::Bind(&base::PlatformThread::Join
, thread
));
137 base::PlatformThread::Join(thread
);
142 void AudioDeviceThread::Thread::ThreadMain() {
143 PlatformThread::SetName(thread_name_
);
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);
152 base::AutoLock
auto_lock(callback_lock_
);
154 callback_
->InitializeOnAudioThread();
159 // Release the reference for the thread. Note that after this, the Thread
160 // instance will most likely be deleted.
164 void AudioDeviceThread::Thread::Run() {
165 uint32 buffer_index
= 0;
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 DCHECK_EQ(bytes_read
, 0U);
175 base::AutoLock
auto_lock(callback_lock_
);
177 callback_
->Process(pending_data
);
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_
) {
185 size_t bytes_sent
= socket_
.Send(&buffer_index
, sizeof(buffer_index
));
186 if (bytes_sent
!= sizeof(buffer_index
))
192 // AudioDeviceThread::Callback implementation
194 AudioDeviceThread::Callback::Callback(
195 const AudioParameters
& audio_parameters
,
196 base::SharedMemoryHandle memory
,
199 : audio_parameters_(audio_parameters
),
200 samples_per_ms_(audio_parameters
.sample_rate() / 1000),
201 bytes_per_ms_(audio_parameters
.channels() *
202 (audio_parameters_
.bits_per_sample() / 8) *
204 shared_memory_(memory
, false),
205 memory_length_(memory_length
),
206 total_segments_(total_segments
) {
207 CHECK_NE(bytes_per_ms_
, 0); // Catch division by zero early.
208 CHECK_NE(samples_per_ms_
, 0);
209 CHECK_GT(total_segments_
, 0);
210 CHECK_EQ(memory_length_
% total_segments_
, 0);
211 segment_length_
= memory_length_
/ total_segments_
;
214 AudioDeviceThread::Callback::~Callback() {}
216 void AudioDeviceThread::Callback::InitializeOnAudioThread() {
218 CHECK(shared_memory_
.memory());
221 } // namespace media.