- add sources.
[platform/framework/web/crosswalk.git] / src / media / audio / audio_device_thread.cc
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
65 AudioDeviceThread::AudioDeviceThread() {
66 }
67
68 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_.get()); }
69
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_);
76   thread_ = new AudioDeviceThread::Thread(
77       callback, socket, thread_name, synchronized_buffers);
78   thread_->Start();
79 }
80
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
89 bool AudioDeviceThread::IsStopped() {
90   base::AutoLock auto_lock(thread_lock_);
91   return !thread_;
92 }
93
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)
99     : thread_(),
100       callback_(callback),
101       socket_(socket),
102       thread_name_(thread_name),
103       synchronized_buffers_(synchronized_buffers) {
104 }
105
106 AudioDeviceThread::Thread::~Thread() {
107   DCHECK(thread_.is_null());
108 }
109
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
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
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
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       DCHECK_EQ(bytes_read, 0U);
171       break;
172     }
173
174     {
175       base::AutoLock auto_lock(callback_lock_);
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     }
189   }
190 }
191
192 // AudioDeviceThread::Callback implementation
193
194 AudioDeviceThread::Callback::Callback(
195     const AudioParameters& audio_parameters,
196     base::SharedMemoryHandle memory,
197     int memory_length,
198     int total_segments)
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) *
203                     samples_per_ms_),
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_;
212 }
213
214 AudioDeviceThread::Callback::~Callback() {}
215
216 void AudioDeviceThread::Callback::InitializeOnAudioThread() {
217   MapSharedMemory();
218   CHECK(shared_memory_.memory());
219 }
220
221 }  // namespace media.