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 // Low-latency audio rendering unit utilizing audio output stream provided | 5 // Low-latency audio rendering unit utilizing audio output stream provided |
6 // by browser process through IPC. | 6 // by browser process through IPC. |
7 // | 7 // |
8 // Relationship of classes. | 8 // Relationship of classes. |
9 // | 9 // |
10 // AudioOutputController AudioDevice | 10 // AudioOutputController AudioDevice |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
59 // - Pause() is asynchronous/non-blocking. | 59 // - Pause() is asynchronous/non-blocking. |
60 // - The user must call Stop() before deleting the class instance. | 60 // - The user must call Stop() before deleting the class instance. |
61 | 61 |
62 #ifndef CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_H_ | 62 #ifndef CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_H_ |
63 #define CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_H_ | 63 #define CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_H_ |
64 #pragma once | 64 #pragma once |
65 | 65 |
66 #include <vector> | 66 #include <vector> |
67 | 67 |
68 #include "base/basictypes.h" | 68 #include "base/basictypes.h" |
69 #include "base/bind.h" | |
69 #include "base/memory/scoped_ptr.h" | 70 #include "base/memory/scoped_ptr.h" |
71 #include "base/message_loop.h" | |
70 #include "base/shared_memory.h" | 72 #include "base/shared_memory.h" |
71 #include "base/synchronization/lock.h" | 73 #include "base/synchronization/lock.h" |
72 #include "base/threading/simple_thread.h" | 74 #include "base/threading/simple_thread.h" |
73 #include "content/common/content_export.h" | 75 #include "content/common/content_export.h" |
74 #include "content/renderer/media/audio_message_filter.h" | 76 #include "content/renderer/media/audio_message_filter.h" |
75 #include "media/audio/audio_parameters.h" | 77 #include "media/audio/audio_parameters.h" |
76 #include "media/base/audio_renderer_sink.h" | 78 #include "media/base/audio_renderer_sink.h" |
77 | 79 |
78 namespace base { | 80 // A common base class for AudioDevice and AudioInputDevice that manages |
scherkus (not reviewing)
2012/02/04 00:27:46
seeing as this is common code perhaps move to sepa
tommi (sloooow) - chröme
2012/02/06 13:38:56
Done.
| |
79 class WaitableEvent; | 81 // the IO message loop pointer and monitors it for destruction. |
80 } | 82 // When the loop goes away, we automatically stop any running streams. |
83 template <class T> | |
84 class AudioDeviceIOLoopObserver | |
85 : public MessageLoop::DestructionObserver { | |
86 public: | |
87 explicit AudioDeviceIOLoopObserver(MessageLoop* io_loop) | |
88 : io_loop_(io_loop->message_loop_proxy()) { | |
89 // Watch the IO loop and make sure that we stop the audio thread before we | |
90 // lose the IO thread. | |
91 ObserveIOLoopDestruction(true, NULL); | |
92 } | |
93 | |
94 ~AudioDeviceIOLoopObserver() { | |
scherkus (not reviewing)
2012/02/04 00:27:46
virtual
tommi (sloooow) - chröme
2012/02/06 13:38:56
Done.
| |
95 ObserveIOLoopDestruction(false, NULL); | |
96 } | |
97 | |
98 protected: | |
99 // Accessor to the IO loop that's used by the derived class. | |
100 base::MessageLoopProxy* loop() { return io_loop_; } | |
scherkus (not reviewing)
2012/02/04 00:27:46
nit: what about io_message_loop()?
Audio{Input}De
tommi (sloooow) - chröme
2012/02/06 13:38:56
I changed it to message_loop() in the end. The re
| |
101 | |
102 private: | |
103 // MessageLoop::DestructionObserver implementation. | |
104 // Called on the IO thread when the thread is going away. | |
105 virtual void WillDestroyCurrentMessageLoop() OVERRIDE { | |
106 DCHECK(io_loop_->BelongsToCurrentThread()); | |
107 // The IO thread is terminating. We must stop the audio thread before the | |
108 // IO thread goes away. | |
109 static_cast<T*>(this)->ShutDownOnIOThread(NULL); | |
scherkus (not reviewing)
2012/02/04 00:27:46
ISTM the only reason this class is templated is fo
tommi (sloooow) - chröme
2012/02/06 13:38:56
Done.
| |
110 } | |
111 | |
112 // Call from the IO thread to add or remove ourselves from the list of | |
113 // destruction observers for the IO message loop. | |
114 void ObserveIOLoopDestruction(bool enable, base::WaitableEvent* done) { | |
scherkus (not reviewing)
2012/02/04 00:27:46
nit: what about splitting this method into AddDest
tommi (sloooow) - chröme
2012/02/06 13:38:56
The function is still as it was because it does ba
| |
115 if (io_loop_->BelongsToCurrentThread()) { | |
116 MessageLoop* loop = MessageLoop::current(); | |
117 if (enable) { | |
118 loop->AddDestructionObserver(this); | |
119 } else { | |
120 loop->RemoveDestructionObserver(this); | |
121 } | |
122 } else { | |
123 base::WaitableEvent event(false, false); | |
124 if (io_loop_->PostTask(FROM_HERE, | |
125 base::Bind( | |
126 &AudioDeviceIOLoopObserver<T>::ObserveIOLoopDestruction, | |
127 base::Unretained(this), enable, &event))) { | |
128 event.Wait(); | |
129 } else { | |
130 // The IO thread has already terminated, so no need to wait. | |
131 } | |
132 } | |
133 | |
134 if (done) | |
135 done->Signal(); | |
136 } | |
137 | |
138 // A pointer to the IO thread's message loop. That's here we do control the | |
139 // stream from. It is possible during shutdown that the IO thread has gone | |
140 // away before the user of the AudioDevice instance has called Stop(). | |
141 // So, we need to be prepared to stop and take down the audio thread if | |
142 // the IO thread ever goes away while we're still playing. | |
143 // So, when this pointer is NULL, the IO thread has gone away and all methods | |
144 // that post to it, must check for this first. | |
145 scoped_refptr<base::MessageLoopProxy> io_loop_; | |
146 }; | |
scherkus (not reviewing)
2012/02/04 00:27:46
DISALLOW_ etc
tommi (sloooow) - chröme
2012/02/06 13:38:56
Done.
| |
81 | 147 |
82 class CONTENT_EXPORT AudioDevice | 148 class CONTENT_EXPORT AudioDevice |
83 : NON_EXPORTED_BASE(public media::AudioRendererSink), | 149 : NON_EXPORTED_BASE(public media::AudioRendererSink), |
84 public AudioMessageFilter::Delegate, | 150 public AudioMessageFilter::Delegate, |
85 public base::DelegateSimpleThread::Delegate { | 151 public base::DelegateSimpleThread::Delegate, |
152 public AudioDeviceIOLoopObserver<AudioDevice> { | |
86 public: | 153 public: |
87 // Methods called on main render thread ------------------------------------- | 154 // Methods called on main render thread ------------------------------------- |
88 | 155 |
89 // Minimal constructor where Initialize() must be called later. | 156 // Minimal constructor where Initialize() must be called later. |
90 AudioDevice(); | 157 AudioDevice(); |
91 | 158 |
92 AudioDevice(size_t buffer_size, | 159 AudioDevice(size_t buffer_size, |
93 int channels, | 160 int channels, |
94 double sample_rate, | 161 double sample_rate, |
95 RenderCallback* callback); | 162 RenderCallback* callback); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
147 friend class base::RefCountedThreadSafe<AudioDevice>; | 214 friend class base::RefCountedThreadSafe<AudioDevice>; |
148 virtual ~AudioDevice(); | 215 virtual ~AudioDevice(); |
149 | 216 |
150 // Methods called on IO thread ---------------------------------------------- | 217 // Methods called on IO thread ---------------------------------------------- |
151 // The following methods are tasks posted on the IO thread that needs to | 218 // The following methods are tasks posted on the IO thread that needs to |
152 // be executed on that thread. They interact with AudioMessageFilter and | 219 // be executed on that thread. They interact with AudioMessageFilter and |
153 // sends IPC messages on that thread. | 220 // sends IPC messages on that thread. |
154 void InitializeOnIOThread(const AudioParameters& params); | 221 void InitializeOnIOThread(const AudioParameters& params); |
155 void PlayOnIOThread(); | 222 void PlayOnIOThread(); |
156 void PauseOnIOThread(bool flush); | 223 void PauseOnIOThread(bool flush); |
224 // Allow AudioDeviceIOLoopObserver to call ShutDownOnIOThread. | |
225 friend class AudioDeviceIOLoopObserver<AudioDevice>; | |
157 void ShutDownOnIOThread(base::WaitableEvent* signal); | 226 void ShutDownOnIOThread(base::WaitableEvent* signal); |
158 void SetVolumeOnIOThread(double volume); | 227 void SetVolumeOnIOThread(double volume); |
159 | 228 |
160 void Send(IPC::Message* message); | 229 void Send(IPC::Message* message); |
161 | 230 |
162 // Method called on the audio thread ---------------------------------------- | 231 // Method called on the audio thread ---------------------------------------- |
163 // Calls the client's callback for rendering audio. | 232 // Calls the client's callback for rendering audio. |
164 // Returns actual number of filled frames that callback returned. This length | 233 // Returns actual number of filled frames that callback returned. This length |
165 // is passed to host at the end of the shared memory (i.e. buffer). In case of | 234 // is passed to host at the end of the shared memory (i.e. buffer). In case of |
166 // continuous stream host just ignores it and assumes buffer is always filled | 235 // continuous stream host just ignores it and assumes buffer is always filled |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 // These variables must only be set on the IO thread while the audio_thread_ | 290 // These variables must only be set on the IO thread while the audio_thread_ |
222 // is not running. | 291 // is not running. |
223 base::SharedMemoryHandle shared_memory_handle_; | 292 base::SharedMemoryHandle shared_memory_handle_; |
224 scoped_ptr<base::CancelableSyncSocket> audio_socket_; | 293 scoped_ptr<base::CancelableSyncSocket> audio_socket_; |
225 int memory_length_; | 294 int memory_length_; |
226 | 295 |
227 DISALLOW_COPY_AND_ASSIGN(AudioDevice); | 296 DISALLOW_COPY_AND_ASSIGN(AudioDevice); |
228 }; | 297 }; |
229 | 298 |
230 #endif // CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_H_ | 299 #endif // CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_H_ |
OLD | NEW |