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

Side by Side Diff: content/renderer/media/audio_device.h

Issue 9104043: Monitor the IO message loop in the AudioDevice classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 10 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
« no previous file with comments | « no previous file | content/renderer/media/audio_device.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 AudioDeviceIOLoopObserver()
88 : io_loop_(
89 ChildProcess::current()->io_message_loop()->message_loop_proxy()) {
90 // Watch the IO loop and make sure that we stop the audio thread before we
91 // lose the IO thread.
92 ObserveIOLoopDestruction(true, NULL);
93 }
94
95 ~AudioDeviceIOLoopObserver() {
96 ObserveIOLoopDestruction(false, NULL);
97 }
98
99 protected:
100 // Accessor to the IO loop that's used by the derived class.
101 base::MessageLoopProxy* loop() { return io_loop_; }
102
103 private:
104 // MessageLoop::DestructionObserver implementation.
105 // Called on the IO thread when the thread is going away.
106 virtual void WillDestroyCurrentMessageLoop() OVERRIDE {
107 DCHECK(io_loop_->BelongsToCurrentThread());
108 // The IO thread is terminating. We must stop the audio thread before the
109 // IO thread goes away.
110 static_cast<T*>(this)->ShutDownOnIOThread(NULL);
111 }
112
113 // Call from the IO thread to add or remove ourselves from the list of
114 // destruction observers for the IO message loop.
115 void ObserveIOLoopDestruction(bool enable, base::WaitableEvent* done) {
116 if (io_loop_->BelongsToCurrentThread()) {
117 MessageLoop* loop = MessageLoop::current();
118 enable ? loop->AddDestructionObserver(this) :
enal1 2012/01/31 17:23:54 Why not regular if statement?
tommi (sloooow) - chröme 2012/02/01 14:50:49 Done.
119 loop->RemoveDestructionObserver(this);
120 } else {
121 base::WaitableEvent event(false, false);
122 if (io_loop_->PostTask(FROM_HERE,
enal1 2012/01/31 17:23:54 Are you sure we can post anything on IO loop if lo
tommi (sloooow) - chröme 2012/02/01 14:50:49 It's OK if the loop is being deleted and PostTask
123 base::Bind(
124 &AudioDeviceIOLoopObserver<T>::ObserveIOLoopDestruction,
125 base::Unretained(this), enable, &event))) {
126 event.Wait();
127 } else {
128 // The IO thread has already terminated, so no need to wait.
129 }
130 }
131
132 if (done)
133 done->Signal();
134 }
135
136 // A pointer to the IO thread's message loop. That's here we do control the
137 // stream from. It is possible during shutdown that the IO thread has gone
138 // away before the user of the AudioDevice instance has called Stop().
139 // So, we need to be prepared to stop and take down the audio thread if
140 // the IO thread ever goes away while we're still playing.
141 // So, when this pointer is NULL, the IO thread has gone away and all methods
142 // that post to it, must check for this first.
enal1 2012/01/31 17:23:54 I don't see how this pointer can become NULL. It i
tommi (sloooow) - chröme 2012/02/01 14:50:49 It cannot become NULL - did you see any checks for
143 scoped_refptr<base::MessageLoopProxy> io_loop_;
144 };
81 145
82 class CONTENT_EXPORT AudioDevice 146 class CONTENT_EXPORT AudioDevice
83 : NON_EXPORTED_BASE(public media::AudioRendererSink), 147 : NON_EXPORTED_BASE(public media::AudioRendererSink),
84 public AudioMessageFilter::Delegate, 148 public AudioMessageFilter::Delegate,
85 public base::DelegateSimpleThread::Delegate { 149 public base::DelegateSimpleThread::Delegate,
150 public AudioDeviceIOLoopObserver<AudioDevice> {
86 public: 151 public:
87 // Methods called on main render thread ------------------------------------- 152 // Methods called on main render thread -------------------------------------
88 153
89 // Minimal constructor where Initialize() must be called later. 154 // Minimal constructor where Initialize() must be called later.
90 AudioDevice(); 155 AudioDevice();
91 156
92 AudioDevice(size_t buffer_size, 157 AudioDevice(size_t buffer_size,
93 int channels, 158 int channels,
94 double sample_rate, 159 double sample_rate,
95 RenderCallback* callback); 160 RenderCallback* callback);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 friend class base::RefCountedThreadSafe<AudioDevice>; 212 friend class base::RefCountedThreadSafe<AudioDevice>;
148 virtual ~AudioDevice(); 213 virtual ~AudioDevice();
149 214
150 // Methods called on IO thread ---------------------------------------------- 215 // Methods called on IO thread ----------------------------------------------
151 // The following methods are tasks posted on the IO thread that needs to 216 // The following methods are tasks posted on the IO thread that needs to
152 // be executed on that thread. They interact with AudioMessageFilter and 217 // be executed on that thread. They interact with AudioMessageFilter and
153 // sends IPC messages on that thread. 218 // sends IPC messages on that thread.
154 void InitializeOnIOThread(const AudioParameters& params); 219 void InitializeOnIOThread(const AudioParameters& params);
155 void PlayOnIOThread(); 220 void PlayOnIOThread();
156 void PauseOnIOThread(bool flush); 221 void PauseOnIOThread(bool flush);
222 // Allow AudioDeviceIOLoopObserver to call ShutDownOnIOThread.
223 friend class AudioDeviceIOLoopObserver<AudioDevice>;
157 void ShutDownOnIOThread(base::WaitableEvent* signal); 224 void ShutDownOnIOThread(base::WaitableEvent* signal);
158 void SetVolumeOnIOThread(double volume); 225 void SetVolumeOnIOThread(double volume);
159 226
160 void Send(IPC::Message* message); 227 void Send(IPC::Message* message);
161 228
162 // Method called on the audio thread ---------------------------------------- 229 // Method called on the audio thread ----------------------------------------
163 // Calls the client's callback for rendering audio. 230 // Calls the client's callback for rendering audio.
164 // Returns actual number of filled frames that callback returned. This length 231 // 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 232 // 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 233 // continuous stream host just ignores it and assumes buffer is always filled
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 // These variables must only be set on the IO thread while the audio_thread_ 288 // These variables must only be set on the IO thread while the audio_thread_
222 // is not running. 289 // is not running.
223 base::SharedMemoryHandle shared_memory_handle_; 290 base::SharedMemoryHandle shared_memory_handle_;
224 scoped_ptr<base::CancelableSyncSocket> audio_socket_; 291 scoped_ptr<base::CancelableSyncSocket> audio_socket_;
225 int memory_length_; 292 int memory_length_;
226 293
227 DISALLOW_COPY_AND_ASSIGN(AudioDevice); 294 DISALLOW_COPY_AND_ASSIGN(AudioDevice);
228 }; 295 };
229 296
230 #endif // CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_H_ 297 #endif // CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_H_
OLDNEW
« no previous file with comments | « no previous file | content/renderer/media/audio_device.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698