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

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

Issue 10790121: First step towards moving AudioDevice from content/ to media/audio. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove unnecessary #include Created 8 years, 5 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
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.h" 5 #include "content/renderer/media/audio_device.h"
6 6
7 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/threading/thread_restrictions.h" 9 #include "base/threading/thread_restrictions.h"
10 #include "base/time.h" 10 #include "base/time.h"
11 #include "content/common/media/audio_messages.h"
12 #include "content/common/view_messages.h"
13 #include "media/audio/audio_output_controller.h" 11 #include "media/audio/audio_output_controller.h"
14 #include "media/audio/audio_util.h" 12 #include "media/audio/audio_util.h"
15 13
16 using media::AudioRendererSink; 14 using media::AudioRendererSink;
17 15
18 // Takes care of invoking the render callback on the audio thread. 16 // Takes care of invoking the render callback on the audio thread.
19 // An instance of this class is created for each capture stream in 17 // An instance of this class is created for each capture stream in
20 // OnStreamCreated(). 18 // OnStreamCreated().
21 class AudioDevice::AudioThreadCallback 19 class AudioDevice::AudioThreadCallback
22 : public AudioDeviceThread::Callback { 20 : public AudioDeviceThread::Callback {
23 public: 21 public:
24 AudioThreadCallback(const media::AudioParameters& audio_parameters, 22 AudioThreadCallback(const media::AudioParameters& audio_parameters,
25 base::SharedMemoryHandle memory, 23 base::SharedMemoryHandle memory,
26 int memory_length, 24 int memory_length,
27 AudioRendererSink::RenderCallback* render_callback); 25 AudioRendererSink::RenderCallback* render_callback);
28 virtual ~AudioThreadCallback(); 26 virtual ~AudioThreadCallback();
29 27
30 virtual void MapSharedMemory() OVERRIDE; 28 virtual void MapSharedMemory() OVERRIDE;
31 29
32 // Called whenever we receive notifications about pending data. 30 // Called whenever we receive notifications about pending data.
33 virtual void Process(int pending_data) OVERRIDE; 31 virtual void Process(int pending_data) OVERRIDE;
34 32
35 private: 33 private:
36 AudioRendererSink::RenderCallback* render_callback_; 34 AudioRendererSink::RenderCallback* render_callback_;
37 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); 35 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
38 }; 36 };
39 37
40 AudioDevice::AudioDevice( 38 AudioDevice::AudioDevice(
39 media::AudioDeviceIPC* ipc,
41 const scoped_refptr<base::MessageLoopProxy>& io_loop) 40 const scoped_refptr<base::MessageLoopProxy>& io_loop)
42 : ScopedLoopObserver(io_loop), 41 : ScopedLoopObserver(io_loop),
43 callback_(NULL), 42 callback_(NULL),
43 ipc_(ipc),
44 stream_id_(0), 44 stream_id_(0),
45 play_on_start_(true), 45 play_on_start_(true),
46 is_started_(false) { 46 is_started_(false) {
47 // Use the filter instance already created on the main render thread. 47 CHECK(ipc_);
48 CHECK(AudioMessageFilter::Get()) << "Invalid audio message filter.";
49 filter_ = AudioMessageFilter::Get();
50 } 48 }
51 49
52 void AudioDevice::Initialize(const media::AudioParameters& params, 50 void AudioDevice::Initialize(const media::AudioParameters& params,
53 RenderCallback* callback) { 51 RenderCallback* callback) {
54 CHECK_EQ(0, stream_id_) << 52 CHECK_EQ(0, stream_id_) <<
55 "AudioDevice::Initialize() must be called before Start()"; 53 "AudioDevice::Initialize() must be called before Start()";
56 54
57 CHECK(!callback_); // Calling Initialize() twice? 55 CHECK(!callback_); // Calling Initialize() twice?
58 56
59 audio_parameters_ = params; 57 audio_parameters_ = params;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 return true; 103 return true;
106 } 104 }
107 105
108 void AudioDevice::CreateStreamOnIOThread(const media::AudioParameters& params) { 106 void AudioDevice::CreateStreamOnIOThread(const media::AudioParameters& params) {
109 DCHECK(message_loop()->BelongsToCurrentThread()); 107 DCHECK(message_loop()->BelongsToCurrentThread());
110 // Make sure we don't create the stream more than once. 108 // Make sure we don't create the stream more than once.
111 DCHECK_EQ(0, stream_id_); 109 DCHECK_EQ(0, stream_id_);
112 if (stream_id_) 110 if (stream_id_)
113 return; 111 return;
114 112
115 stream_id_ = filter_->AddDelegate(this); 113 stream_id_ = ipc_->AddDelegate(this);
116 Send(new AudioHostMsg_CreateStream(stream_id_, params)); 114 ipc_->CreateStream(stream_id_, params);
117 } 115 }
118 116
119 void AudioDevice::PlayOnIOThread() { 117 void AudioDevice::PlayOnIOThread() {
120 DCHECK(message_loop()->BelongsToCurrentThread()); 118 DCHECK(message_loop()->BelongsToCurrentThread());
121 if (stream_id_ && is_started_) 119 if (stream_id_ && is_started_)
122 Send(new AudioHostMsg_PlayStream(stream_id_)); 120 ipc_->PlayStream(stream_id_);
123 else 121 else
124 play_on_start_ = true; 122 play_on_start_ = true;
125 } 123 }
126 124
127 void AudioDevice::PauseOnIOThread(bool flush) { 125 void AudioDevice::PauseOnIOThread(bool flush) {
128 DCHECK(message_loop()->BelongsToCurrentThread()); 126 DCHECK(message_loop()->BelongsToCurrentThread());
129 if (stream_id_ && is_started_) { 127 if (stream_id_ && is_started_) {
130 Send(new AudioHostMsg_PauseStream(stream_id_)); 128 ipc_->PauseStream(stream_id_);
131 if (flush) 129 if (flush)
132 Send(new AudioHostMsg_FlushStream(stream_id_)); 130 ipc_->FlushStream(stream_id_);
133 } else { 131 } else {
134 // Note that |flush| isn't relevant here since this is the case where 132 // Note that |flush| isn't relevant here since this is the case where
135 // the stream is first starting. 133 // the stream is first starting.
136 play_on_start_ = false; 134 play_on_start_ = false;
137 } 135 }
138 } 136 }
139 137
140 void AudioDevice::ShutDownOnIOThread() { 138 void AudioDevice::ShutDownOnIOThread() {
141 DCHECK(message_loop()->BelongsToCurrentThread()); 139 DCHECK(message_loop()->BelongsToCurrentThread());
142 140
143 // Make sure we don't call shutdown more than once. 141 // Make sure we don't call shutdown more than once.
144 if (stream_id_) { 142 if (stream_id_) {
145 is_started_ = false; 143 is_started_ = false;
146 144
147 filter_->RemoveDelegate(stream_id_); 145 ipc_->RemoveDelegate(stream_id_);
148 Send(new AudioHostMsg_CloseStream(stream_id_)); 146 ipc_->CloseStream(stream_id_);
149 stream_id_ = 0; 147 stream_id_ = 0;
150 } 148 }
151 149
152 // We can run into an issue where ShutDownOnIOThread is called right after 150 // We can run into an issue where ShutDownOnIOThread is called right after
153 // OnStreamCreated is called in cases where Start/Stop are called before we 151 // OnStreamCreated is called in cases where Start/Stop are called before we
154 // get the OnStreamCreated callback. To handle that corner case, we call 152 // get the OnStreamCreated callback. To handle that corner case, we call
155 // Stop(). In most cases, the thread will already be stopped. 153 // Stop(). In most cases, the thread will already be stopped.
156 // Another situation is when the IO thread goes away before Stop() is called 154 // Another situation is when the IO thread goes away before Stop() is called
157 // in which case, we cannot use the message loop to close the thread handle 155 // in which case, we cannot use the message loop to close the thread handle
158 // and can't not rely on the main thread existing either. 156 // and can't not rely on the main thread existing either.
159 base::ThreadRestrictions::ScopedAllowIO allow_io; 157 base::ThreadRestrictions::ScopedAllowIO allow_io;
160 audio_thread_.Stop(NULL); 158 audio_thread_.Stop(NULL);
161 audio_callback_.reset(); 159 audio_callback_.reset();
162 } 160 }
163 161
164 void AudioDevice::SetVolumeOnIOThread(double volume) { 162 void AudioDevice::SetVolumeOnIOThread(double volume) {
165 DCHECK(message_loop()->BelongsToCurrentThread()); 163 DCHECK(message_loop()->BelongsToCurrentThread());
166 if (stream_id_) 164 if (stream_id_)
167 Send(new AudioHostMsg_SetVolume(stream_id_, volume)); 165 ipc_->SetVolume(stream_id_, volume);
168 } 166 }
169 167
170 void AudioDevice::OnStateChanged(AudioStreamState state) { 168 void AudioDevice::OnStateChanged(media::AudioStreamState state) {
171 DCHECK(message_loop()->BelongsToCurrentThread()); 169 DCHECK(message_loop()->BelongsToCurrentThread());
172 170
173 // Do nothing if the stream has been closed. 171 // Do nothing if the stream has been closed.
174 if (!stream_id_) 172 if (!stream_id_)
175 return; 173 return;
176 174
177 if (state == kAudioStreamError) { 175 if (state == media::kAudioStreamError) {
178 DLOG(WARNING) << "AudioDevice::OnStateChanged(kError)"; 176 DLOG(WARNING) << "AudioDevice::OnStateChanged(kError)";
179 // Don't dereference the callback object if the audio thread 177 // Don't dereference the callback object if the audio thread
180 // is stopped or stopping. That could mean that the callback 178 // is stopped or stopping. That could mean that the callback
181 // object has been deleted. 179 // object has been deleted.
182 // TODO(tommi): Add an explicit contract for clearing the callback 180 // TODO(tommi): Add an explicit contract for clearing the callback
183 // object. Possibly require calling Initialize again or provide 181 // object. Possibly require calling Initialize again or provide
184 // a callback object via Start() and clear it in Stop(). 182 // a callback object via Start() and clear it in Stop().
185 if (!audio_thread_.IsStopped()) 183 if (!audio_thread_.IsStopped())
186 callback_->OnRenderError(); 184 callback_->OnRenderError();
187 } 185 }
(...skipping 29 matching lines...) Expand all
217 handle, length, callback_)); 215 handle, length, callback_));
218 audio_thread_.Start(audio_callback_.get(), socket_handle, "AudioDevice"); 216 audio_thread_.Start(audio_callback_.get(), socket_handle, "AudioDevice");
219 217
220 // We handle the case where Play() and/or Pause() may have been called 218 // We handle the case where Play() and/or Pause() may have been called
221 // multiple times before OnStreamCreated() gets called. 219 // multiple times before OnStreamCreated() gets called.
222 is_started_ = true; 220 is_started_ = true;
223 if (play_on_start_) 221 if (play_on_start_)
224 PlayOnIOThread(); 222 PlayOnIOThread();
225 } 223 }
226 224
227 void AudioDevice::Send(IPC::Message* message) {
228 filter_->Send(message);
229 }
230
231 void AudioDevice::WillDestroyCurrentMessageLoop() { 225 void AudioDevice::WillDestroyCurrentMessageLoop() {
232 LOG(ERROR) << "IO loop going away before the audio device has been stopped"; 226 LOG(ERROR) << "IO loop going away before the audio device has been stopped";
233 ShutDownOnIOThread(); 227 ShutDownOnIOThread();
234 } 228 }
235 229
236 // AudioDevice::AudioThreadCallback 230 // AudioDevice::AudioThreadCallback
237 231
238 AudioDevice::AudioThreadCallback::AudioThreadCallback( 232 AudioDevice::AudioThreadCallback::AudioThreadCallback(
239 const media::AudioParameters& audio_parameters, 233 const media::AudioParameters& audio_parameters,
240 base::SharedMemoryHandle memory, 234 base::SharedMemoryHandle memory,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 // Interleave, scale, and clip to int. 266 // Interleave, scale, and clip to int.
273 // TODO(crogers/vrk): Figure out a way to avoid the float -> int -> float 267 // TODO(crogers/vrk): Figure out a way to avoid the float -> int -> float
274 // conversions that happen in the <audio> and WebRTC scenarios. 268 // conversions that happen in the <audio> and WebRTC scenarios.
275 media::InterleaveFloatToInt(audio_data_, shared_memory_.memory(), 269 media::InterleaveFloatToInt(audio_data_, shared_memory_.memory(),
276 num_frames, audio_parameters_.bits_per_sample() / 8); 270 num_frames, audio_parameters_.bits_per_sample() / 8);
277 271
278 // Let the host know we are done. 272 // Let the host know we are done.
279 media::SetActualDataSizeInBytes(&shared_memory_, memory_length_, 273 media::SetActualDataSizeInBytes(&shared_memory_, memory_length_,
280 num_frames * audio_parameters_.GetBytesPerFrame()); 274 num_frames * audio_parameters_.GetBytesPerFrame());
281 } 275 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698