Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Side by Side Diff: content/renderer/media/audio_device_thread.cc

Issue 10834033: Move AudioDevice and AudioInputDevice to media. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "content/renderer/media/audio_device_thread.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop.h"
10 #include "base/threading/platform_thread.h"
11 #include "base/threading/thread_restrictions.h"
12 #include "media/audio/audio_util.h"
13
14 using base::PlatformThread;
15
16 // The actual worker thread implementation. It's very bare bones and much
17 // simpler than SimpleThread (no synchronization in Start, etc) and supports
18 // joining the thread handle asynchronously via a provided message loop even
19 // after the Thread object itself has been deleted.
20 class AudioDeviceThread::Thread
21 : public PlatformThread::Delegate,
22 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> {
23 public:
24 Thread(AudioDeviceThread::Callback* callback,
25 base::SyncSocket::Handle socket,
26 const char* thread_name);
27
28 void Start();
29
30 // Stops the thread. If |loop_for_join| is non-NULL, the function posts
31 // a task to join (close) the thread handle later instead of waiting for
32 // the thread. If loop_for_join is NULL, then the function waits
33 // synchronously for the thread to terminate.
34 void Stop(MessageLoop* loop_for_join);
35
36 private:
37 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>;
38 virtual ~Thread();
39
40 // Overrides from PlatformThread::Delegate.
41 virtual void ThreadMain() OVERRIDE;
42
43 // Runs the loop that reads from the socket.
44 void Run();
45
46 private:
47 base::PlatformThreadHandle thread_;
48 AudioDeviceThread::Callback* callback_;
49 base::CancelableSyncSocket socket_;
50 base::Lock callback_lock_;
51 const char* thread_name_;
52
53 DISALLOW_COPY_AND_ASSIGN(Thread);
54 };
55
56 // AudioDeviceThread implementation
57
58 AudioDeviceThread::AudioDeviceThread() {
59 }
60
61 AudioDeviceThread::~AudioDeviceThread() {
62 DCHECK(!thread_);
63 }
64
65 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback,
66 base::SyncSocket::Handle socket,
67 const char* thread_name) {
68 base::AutoLock auto_lock(thread_lock_);
69 CHECK(thread_ == NULL);
70 thread_ = new AudioDeviceThread::Thread(callback, socket, thread_name);
71 thread_->Start();
72 }
73
74 void AudioDeviceThread::Stop(MessageLoop* loop_for_join) {
75 base::AutoLock auto_lock(thread_lock_);
76 if (thread_) {
77 thread_->Stop(loop_for_join);
78 thread_ = NULL;
79 }
80 }
81
82 bool AudioDeviceThread::IsStopped() {
83 base::AutoLock auto_lock(thread_lock_);
84 return thread_ == NULL;
85 }
86
87 // AudioDeviceThread::Thread implementation
88 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback,
89 base::SyncSocket::Handle socket,
90 const char* thread_name)
91 : thread_(base::kNullThreadHandle),
92 callback_(callback),
93 socket_(socket),
94 thread_name_(thread_name) {
95 }
96
97 AudioDeviceThread::Thread::~Thread() {
98 DCHECK_EQ(thread_, base::kNullThreadHandle) << "Stop wasn't called";
99 }
100
101 void AudioDeviceThread::Thread::Start() {
102 base::AutoLock auto_lock(callback_lock_);
103 DCHECK_EQ(thread_, base::kNullThreadHandle);
104 // This reference will be released when the thread exists.
105 AddRef();
106
107 PlatformThread::CreateWithPriority(0, this, &thread_,
108 base::kThreadPriority_RealtimeAudio);
109 CHECK(thread_ != base::kNullThreadHandle);
110 }
111
112 void AudioDeviceThread::Thread::Stop(MessageLoop* loop_for_join) {
113 socket_.Shutdown();
114
115 base::PlatformThreadHandle thread = base::kNullThreadHandle;
116
117 { // NOLINT
118 base::AutoLock auto_lock(callback_lock_);
119 callback_ = NULL;
120 std::swap(thread, thread_);
121 }
122
123 if (thread != base::kNullThreadHandle) {
124 if (loop_for_join) {
125 loop_for_join->PostTask(FROM_HERE,
126 base::Bind(&base::PlatformThread::Join, thread));
127 } else {
128 base::PlatformThread::Join(thread);
129 }
130 }
131 }
132
133 void AudioDeviceThread::Thread::ThreadMain() {
134 PlatformThread::SetName(thread_name_);
135
136 // Singleton access is safe from this thread as long as callback is non-NULL.
137 // The callback is the only point where the thread calls out to 'unknown' code
138 // that might touch singletons and the lifetime of the callback is controlled
139 // by another thread on which singleton access is OK as well.
140 base::ThreadRestrictions::SetSingletonAllowed(true);
141
142 { // NOLINT
143 base::AutoLock auto_lock(callback_lock_);
144 if (callback_)
145 callback_->InitializeOnAudioThread();
146 }
147
148 Run();
149
150 // Release the reference for the thread. Note that after this, the Thread
151 // instance will most likely be deleted.
152 Release();
153 }
154
155 void AudioDeviceThread::Thread::Run() {
156 while (true) {
157 int pending_data = 0;
158 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data));
159 if (bytes_read != sizeof(pending_data)) {
160 DCHECK_EQ(bytes_read, 0U);
161 break;
162 }
163
164 base::AutoLock auto_lock(callback_lock_);
165 if (callback_)
166 callback_->Process(pending_data);
167 }
168 }
169
170 // AudioDeviceThread::Callback implementation
171
172 AudioDeviceThread::Callback::Callback(
173 const media::AudioParameters& audio_parameters,
174 base::SharedMemoryHandle memory, int memory_length)
175 : audio_parameters_(audio_parameters),
176 samples_per_ms_(audio_parameters.sample_rate() / 1000),
177 bytes_per_ms_(audio_parameters.channels() *
178 (audio_parameters_.bits_per_sample() / 8) *
179 samples_per_ms_),
180 shared_memory_(memory, false),
181 memory_length_(memory_length) {
182 CHECK_NE(bytes_per_ms_, 0); // Catch division by zero early.
183 CHECK_NE(samples_per_ms_, 0);
184 }
185
186 AudioDeviceThread::Callback::~Callback() {
187 for (size_t i = 0; i < audio_data_.size(); ++i)
188 delete [] audio_data_[i];
189 }
190
191 void AudioDeviceThread::Callback::InitializeOnAudioThread() {
192 DCHECK(audio_data_.empty());
193
194 MapSharedMemory();
195 DCHECK(shared_memory_.memory() != NULL);
196
197 audio_data_.reserve(audio_parameters_.channels());
198 for (int i = 0; i < audio_parameters_.channels(); ++i) {
199 float* channel_data = new float[audio_parameters_.frames_per_buffer()];
200 audio_data_.push_back(channel_data);
201 }
202 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698