OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/audio_device_thread.h" | 5 #include "content/renderer/media/audio_device_thread.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/synchronization/lock.h" | |
11 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
12 #include "base/threading/thread_restrictions.h" | 11 #include "base/threading/thread_restrictions.h" |
13 #include "media/audio/audio_util.h" | 12 #include "media/audio/audio_util.h" |
14 | 13 |
15 using base::PlatformThread; | 14 using base::PlatformThread; |
16 | 15 |
17 // The actual worker thread implementation. It's very bare bones and much | 16 // The actual worker thread implementation. It's very bare bones and much |
18 // simpler than SimpleThread (no synchronization in Start, etc) and supports | 17 // simpler than SimpleThread (no synchronization in Start, etc) and supports |
19 // joining the thread handle asynchronously via a provided message loop even | 18 // joining the thread handle asynchronously via a provided message loop even |
20 // after the Thread object itself has been deleted. | 19 // after the Thread object itself has been deleted. |
21 class AudioDeviceThread::Thread | 20 class AudioDeviceThread::Thread |
22 : public PlatformThread::Delegate, | 21 : public PlatformThread::Delegate, |
23 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> { | 22 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> { |
24 public: | 23 public: |
25 Thread(AudioDeviceThread::Callback* callback, | 24 Thread(AudioDeviceThread::Callback* callback, |
26 base::SyncSocket::Handle socket, | 25 base::SyncSocket::Handle socket, |
27 const char* thread_name); | 26 const char* thread_name); |
28 | 27 |
29 void Start(); | 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. |
30 void Stop(MessageLoop* loop_for_join); | 34 void Stop(MessageLoop* loop_for_join); |
31 | 35 |
32 private: | 36 private: |
33 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; | 37 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; |
34 virtual ~Thread(); | 38 virtual ~Thread(); |
35 | 39 |
36 // Overrides from PlatformThread::Delegate. | 40 // Overrides from PlatformThread::Delegate. |
37 virtual void ThreadMain() OVERRIDE; | 41 virtual void ThreadMain() OVERRIDE; |
38 | 42 |
39 // Runs the loop that reads from the socket. | 43 // Runs the loop that reads from the socket. |
(...skipping 14 matching lines...) Expand all Loading... |
54 AudioDeviceThread::AudioDeviceThread() { | 58 AudioDeviceThread::AudioDeviceThread() { |
55 } | 59 } |
56 | 60 |
57 AudioDeviceThread::~AudioDeviceThread() { | 61 AudioDeviceThread::~AudioDeviceThread() { |
58 DCHECK(!thread_); | 62 DCHECK(!thread_); |
59 } | 63 } |
60 | 64 |
61 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, | 65 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, |
62 base::SyncSocket::Handle socket, | 66 base::SyncSocket::Handle socket, |
63 const char* thread_name) { | 67 const char* thread_name) { |
| 68 base::AutoLock auto_lock(thread_lock_); |
64 CHECK(thread_ == NULL); | 69 CHECK(thread_ == NULL); |
65 thread_ = new AudioDeviceThread::Thread(callback, socket, thread_name); | 70 thread_ = new AudioDeviceThread::Thread(callback, socket, thread_name); |
66 thread_->Start(); | 71 thread_->Start(); |
67 } | 72 } |
68 | 73 |
69 void AudioDeviceThread::Stop(MessageLoop* loop_for_join) { | 74 void AudioDeviceThread::Stop(MessageLoop* loop_for_join) { |
| 75 base::AutoLock auto_lock(thread_lock_); |
70 if (thread_) { | 76 if (thread_) { |
71 if (!loop_for_join) { | |
72 loop_for_join = MessageLoop::current(); | |
73 CHECK(loop_for_join); | |
74 } | |
75 thread_->Stop(loop_for_join); | 77 thread_->Stop(loop_for_join); |
76 thread_ = NULL; | 78 thread_ = NULL; |
77 } | 79 } |
78 } | 80 } |
79 | 81 |
| 82 bool AudioDeviceThread::IsStopped() { |
| 83 base::AutoLock auto_lock(thread_lock_); |
| 84 return thread_ == NULL; |
| 85 } |
| 86 |
80 // AudioDeviceThread::Thread implementation | 87 // AudioDeviceThread::Thread implementation |
81 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, | 88 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, |
82 base::SyncSocket::Handle socket, | 89 base::SyncSocket::Handle socket, |
83 const char* thread_name) | 90 const char* thread_name) |
84 : thread_(base::kNullThreadHandle), | 91 : thread_(base::kNullThreadHandle), |
85 callback_(callback), | 92 callback_(callback), |
86 socket_(socket), | 93 socket_(socket), |
87 thread_name_(thread_name) { | 94 thread_name_(thread_name) { |
88 } | 95 } |
89 | 96 |
(...skipping 16 matching lines...) Expand all Loading... |
106 | 113 |
107 base::PlatformThreadHandle thread = base::kNullThreadHandle; | 114 base::PlatformThreadHandle thread = base::kNullThreadHandle; |
108 | 115 |
109 { // NOLINT | 116 { // NOLINT |
110 base::AutoLock auto_lock(callback_lock_); | 117 base::AutoLock auto_lock(callback_lock_); |
111 callback_ = NULL; | 118 callback_ = NULL; |
112 std::swap(thread, thread_); | 119 std::swap(thread, thread_); |
113 } | 120 } |
114 | 121 |
115 if (thread != base::kNullThreadHandle) { | 122 if (thread != base::kNullThreadHandle) { |
116 loop_for_join->PostTask(FROM_HERE, | 123 if (loop_for_join) { |
117 base::Bind(&base::PlatformThread::Join, thread)); | 124 loop_for_join->PostTask(FROM_HERE, |
| 125 base::Bind(&base::PlatformThread::Join, thread)); |
| 126 } else { |
| 127 base::PlatformThread::Join(thread); |
| 128 } |
118 } | 129 } |
119 } | 130 } |
120 | 131 |
121 void AudioDeviceThread::Thread::ThreadMain() { | 132 void AudioDeviceThread::Thread::ThreadMain() { |
122 PlatformThread::SetName(thread_name_); | 133 PlatformThread::SetName(thread_name_); |
123 | 134 |
124 // Singleton access is safe from this thread as long as callback is non-NULL. | 135 // Singleton access is safe from this thread as long as callback is non-NULL. |
125 // The callback is the only point where the thread calls out to 'unknown' code | 136 // The callback is the only point where the thread calls out to 'unknown' code |
126 // that might touch singletons and the lifetime of the callback is controlled | 137 // that might touch singletons and the lifetime of the callback is controlled |
127 // by another thread on which singleton access is OK as well. | 138 // by another thread on which singleton access is OK as well. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 MapSharedMemory(); | 193 MapSharedMemory(); |
183 DCHECK(shared_memory_.memory() != NULL); | 194 DCHECK(shared_memory_.memory() != NULL); |
184 | 195 |
185 audio_data_.reserve(audio_parameters_.channels); | 196 audio_data_.reserve(audio_parameters_.channels); |
186 for (int i = 0; i < audio_parameters_.channels; ++i) { | 197 for (int i = 0; i < audio_parameters_.channels; ++i) { |
187 float* channel_data = new float[audio_parameters_.samples_per_packet]; | 198 float* channel_data = new float[audio_parameters_.samples_per_packet]; |
188 audio_data_.push_back(channel_data); | 199 audio_data_.push_back(channel_data); |
189 } | 200 } |
190 } | 201 } |
191 | 202 |
OLD | NEW |