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

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

Issue 8477037: Simplify AudioRendererImpl by using AudioDevice. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/time.h" 10 #include "base/time.h"
11 #include "content/common/child_process.h" 11 #include "content/common/child_process.h"
12 #include "content/common/media/audio_messages.h" 12 #include "content/common/media/audio_messages.h"
13 #include "content/common/view_messages.h" 13 #include "content/common/view_messages.h"
14 #include "content/renderer/render_thread_impl.h" 14 #include "content/renderer/render_thread_impl.h"
15 #include "media/audio/audio_util.h" 15 #include "media/audio/audio_util.h"
16 16
17 AudioDevice::AudioDevice()
18 : buffer_size_(0),
19 channels_(0),
20 bits_per_sample_(16),
21 sample_rate_(0),
22 latency_format_(AudioParameters::AUDIO_PCM_LOW_LATENCY),
23 callback_(0),
24 audio_delay_milliseconds_(0),
25 volume_(1.0),
26 stream_id_(0) {
27 filter_ = RenderThreadImpl::current()->audio_message_filter();
28 }
29
17 AudioDevice::AudioDevice(size_t buffer_size, 30 AudioDevice::AudioDevice(size_t buffer_size,
18 int channels, 31 int channels,
19 double sample_rate, 32 double sample_rate,
20 RenderCallback* callback) 33 RenderCallback* callback)
21 : buffer_size_(buffer_size), 34 : buffer_size_(buffer_size),
22 channels_(channels), 35 channels_(channels),
23 bits_per_sample_(16), 36 bits_per_sample_(16),
24 sample_rate_(sample_rate), 37 sample_rate_(sample_rate),
25 callback_(callback), 38 callback_(callback),
26 audio_delay_milliseconds_(0), 39 audio_delay_milliseconds_(0),
27 volume_(1.0), 40 volume_(1.0),
28 stream_id_(0) { 41 stream_id_(0) {
29 filter_ = RenderThreadImpl::current()->audio_message_filter(); 42 filter_ = RenderThreadImpl::current()->audio_message_filter();
43 Initialize(buffer_size,
44 channels,
45 sample_rate,
46 AudioParameters::AUDIO_PCM_LOW_LATENCY,
47 callback);
48 }
49
50 void AudioDevice::Initialize(size_t buffer_size,
51 int channels,
52 double sample_rate,
53 AudioParameters::Format latency_format,
54 RenderCallback* callback) {
55 CHECK_EQ(0, stream_id_) <<
56 "AudioDevice::Initialize() must be called before Start()";
57
58 buffer_size_ = buffer_size;
59 channels_ = channels;
60 sample_rate_ = sample_rate;
61 latency_format_ = latency_format;
62 callback_ = callback;
63
64 // Cleanup from any previous initialization.
65 for (size_t i = 0; i < audio_data_.size(); ++i)
66 delete [] audio_data_[i];
67
30 audio_data_.reserve(channels); 68 audio_data_.reserve(channels);
31 for (int i = 0; i < channels; ++i) { 69 for (int i = 0; i < channels; ++i) {
32 float* channel_data = new float[buffer_size]; 70 float* channel_data = new float[buffer_size];
33 audio_data_.push_back(channel_data); 71 audio_data_.push_back(channel_data);
34 } 72 }
35 } 73 }
36 74
75 bool AudioDevice::IsInitialized() {
76 return audio_data_.size() > 0;
77 }
78
37 AudioDevice::~AudioDevice() { 79 AudioDevice::~AudioDevice() {
38 // The current design requires that the user calls Stop() before deleting 80 // The current design requires that the user calls Stop() before deleting
39 // this class. 81 // this class.
40 CHECK_EQ(0, stream_id_); 82 CHECK_EQ(0, stream_id_);
41 for (int i = 0; i < channels_; ++i) 83 for (int i = 0; i < channels_; ++i)
42 delete [] audio_data_[i]; 84 delete [] audio_data_[i];
43 } 85 }
44 86
45 void AudioDevice::Start() { 87 void AudioDevice::Start() {
46 AudioParameters params; 88 AudioParameters params;
47 params.format = AudioParameters::AUDIO_PCM_LOW_LATENCY; 89 params.format = latency_format_;
48 params.channels = channels_; 90 params.channels = channels_;
49 params.sample_rate = static_cast<int>(sample_rate_); 91 params.sample_rate = static_cast<int>(sample_rate_);
50 params.bits_per_sample = bits_per_sample_; 92 params.bits_per_sample = bits_per_sample_;
51 params.samples_per_packet = buffer_size_; 93 params.samples_per_packet = buffer_size_;
52 94
53 ChildProcess::current()->io_message_loop()->PostTask( 95 ChildProcess::current()->io_message_loop()->PostTask(
54 FROM_HERE, 96 FROM_HERE,
55 base::Bind(&AudioDevice::InitializeOnIOThread, this, params)); 97 base::Bind(&AudioDevice::InitializeOnIOThread, this, params));
56 } 98 }
57 99
(...skipping 19 matching lines...) Expand all
77 audio_thread_.reset(NULL); 119 audio_thread_.reset(NULL);
78 } 120 }
79 } else { 121 } else {
80 LOG(ERROR) << "Failed to shut down audio output on IO thread"; 122 LOG(ERROR) << "Failed to shut down audio output on IO thread";
81 return false; 123 return false;
82 } 124 }
83 125
84 return true; 126 return true;
85 } 127 }
86 128
129 void AudioDevice::Play() {
130 ChildProcess::current()->io_message_loop()->PostTask(
131 FROM_HERE,
132 base::Bind(&AudioDevice::PlayOnIOThread, this));
133 }
134
135 void AudioDevice::Pause(bool flush) {
136 ChildProcess::current()->io_message_loop()->PostTask(
137 FROM_HERE,
138 base::Bind(&AudioDevice::PauseOnIOThread, this, flush));
139 }
140
87 bool AudioDevice::SetVolume(double volume) { 141 bool AudioDevice::SetVolume(double volume) {
88 if (volume < 0 || volume > 1.0) 142 if (volume < 0 || volume > 1.0)
89 return false; 143 return false;
90 144
91 ChildProcess::current()->io_message_loop()->PostTask( 145 ChildProcess::current()->io_message_loop()->PostTask(
92 FROM_HERE, 146 FROM_HERE,
93 base::Bind(&AudioDevice::SetVolumeOnIOThread, this, volume)); 147 base::Bind(&AudioDevice::SetVolumeOnIOThread, this, volume));
94 148
95 volume_ = volume; 149 volume_ = volume;
96 150
97 return true; 151 return true;
98 } 152 }
99 153
100 void AudioDevice::GetVolume(double* volume) { 154 void AudioDevice::GetVolume(double* volume) {
101 // Return a locally cached version of the current scaling factor. 155 // Return a locally cached version of the current scaling factor.
102 *volume = volume_; 156 *volume = volume_;
103 } 157 }
104 158
105 void AudioDevice::InitializeOnIOThread(const AudioParameters& params) { 159 void AudioDevice::InitializeOnIOThread(const AudioParameters& params) {
106 // Make sure we don't call Start() more than once. 160 // Make sure we don't create the stream more than once.
107 DCHECK_EQ(0, stream_id_); 161 DCHECK_EQ(0, stream_id_);
108 if (stream_id_) 162 if (stream_id_)
109 return; 163 return;
110 164
111 stream_id_ = filter_->AddDelegate(this); 165 stream_id_ = filter_->AddDelegate(this);
112 Send(new AudioHostMsg_CreateStream(stream_id_, params, true)); 166 Send(new AudioHostMsg_CreateStream(stream_id_, params, true));
113 } 167 }
114 168
115 void AudioDevice::StartOnIOThread() { 169 void AudioDevice::PlayOnIOThread() {
116 if (stream_id_) 170 if (stream_id_)
117 Send(new AudioHostMsg_PlayStream(stream_id_)); 171 Send(new AudioHostMsg_PlayStream(stream_id_));
118 } 172 }
119 173
174 void AudioDevice::PauseOnIOThread(bool flush) {
175 if (stream_id_) {
176 Send(new AudioHostMsg_PauseStream(stream_id_));
177 if (flush)
178 Send(new AudioHostMsg_FlushStream(stream_id_));
179 }
180 }
181
120 void AudioDevice::ShutDownOnIOThread(base::WaitableEvent* completion) { 182 void AudioDevice::ShutDownOnIOThread(base::WaitableEvent* completion) {
121 // Make sure we don't call shutdown more than once. 183 // Make sure we don't call shutdown more than once.
122 if (!stream_id_) { 184 if (!stream_id_) {
123 completion->Signal(); 185 completion->Signal();
124 return; 186 return;
125 } 187 }
126 188
127 filter_->RemoveDelegate(stream_id_); 189 filter_->RemoveDelegate(stream_id_);
128 Send(new AudioHostMsg_CloseStream(stream_id_)); 190 Send(new AudioHostMsg_CloseStream(stream_id_));
129 stream_id_ = 0; 191 stream_id_ = 0;
130 192
131 completion->Signal(); 193 completion->Signal();
132 } 194 }
133 195
134 void AudioDevice::SetVolumeOnIOThread(double volume) { 196 void AudioDevice::SetVolumeOnIOThread(double volume) {
135 if (stream_id_) 197 if (stream_id_)
136 Send(new AudioHostMsg_SetVolume(stream_id_, volume)); 198 Send(new AudioHostMsg_SetVolume(stream_id_, volume));
137 } 199 }
138 200
139 void AudioDevice::OnRequestPacket(AudioBuffersState buffers_state) { 201 void AudioDevice::OnRequestPacket(AudioBuffersState buffers_state) {
140 // This method does not apply to the low-latency system. 202 // This method does not apply to the low-latency system.
141 NOTIMPLEMENTED();
142 } 203 }
143 204
144 void AudioDevice::OnStateChanged(AudioStreamState state) { 205 void AudioDevice::OnStateChanged(AudioStreamState state) {
145 if (state == kAudioStreamError) { 206 if (state == kAudioStreamError) {
146 DLOG(WARNING) << "AudioDevice::OnStateChanged(kError)"; 207 DLOG(WARNING) << "AudioDevice::OnStateChanged(kError)";
147 } 208 }
148 NOTIMPLEMENTED();
149 } 209 }
150 210
151 void AudioDevice::OnCreated( 211 void AudioDevice::OnCreated(
152 base::SharedMemoryHandle handle, uint32 length) { 212 base::SharedMemoryHandle handle, uint32 length) {
153 // Not needed in this simple implementation. 213 // Not needed in this simple implementation.
154 NOTIMPLEMENTED();
155 } 214 }
156 215
157 void AudioDevice::OnLowLatencyCreated( 216 void AudioDevice::OnLowLatencyCreated(
158 base::SharedMemoryHandle handle, 217 base::SharedMemoryHandle handle,
159 base::SyncSocket::Handle socket_handle, 218 base::SyncSocket::Handle socket_handle,
160 uint32 length) { 219 uint32 length) {
161 DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop()); 220 DCHECK(MessageLoop::current() == ChildProcess::current()->io_message_loop());
162 #if defined(OS_WIN) 221 #if defined(OS_WIN)
163 DCHECK(handle); 222 DCHECK(handle);
164 DCHECK(socket_handle); 223 DCHECK(socket_handle);
(...skipping 19 matching lines...) Expand all
184 socket_.reset(new base::SyncSocket(socket_handle)); 243 socket_.reset(new base::SyncSocket(socket_handle));
185 // Allow the client to pre-populate the buffer. 244 // Allow the client to pre-populate the buffer.
186 FireRenderCallback(); 245 FireRenderCallback();
187 246
188 audio_thread_.reset( 247 audio_thread_.reset(
189 new base::DelegateSimpleThread(this, "renderer_audio_thread")); 248 new base::DelegateSimpleThread(this, "renderer_audio_thread"));
190 audio_thread_->Start(); 249 audio_thread_->Start();
191 250
192 MessageLoop::current()->PostTask( 251 MessageLoop::current()->PostTask(
193 FROM_HERE, 252 FROM_HERE,
194 base::Bind(&AudioDevice::StartOnIOThread, this)); 253 base::Bind(&AudioDevice::PlayOnIOThread, this));
195 } 254 }
196 255
197 void AudioDevice::OnVolume(double volume) { 256 void AudioDevice::OnVolume(double volume) {
198 NOTIMPLEMENTED(); 257 NOTIMPLEMENTED();
199 } 258 }
200 259
201 void AudioDevice::Send(IPC::Message* message) { 260 void AudioDevice::Send(IPC::Message* message) {
202 filter_->Send(message); 261 filter_->Send(message);
203 } 262 }
204 263
205 // Our audio thread runs here. 264 // Our audio thread runs here.
206 void AudioDevice::Run() { 265 void AudioDevice::Run() {
207 audio_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio); 266 audio_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio);
208 267
209 int pending_data; 268 int pending_data;
210 const int samples_per_ms = static_cast<int>(sample_rate_) / 1000; 269 const int samples_per_ms = static_cast<int>(sample_rate_) / 1000;
211 const int bytes_per_ms = channels_ * (bits_per_sample_ / 8) * samples_per_ms; 270 const int bytes_per_ms = channels_ * (bits_per_sample_ / 8) * samples_per_ms;
212 271
213 while ((sizeof(pending_data) == socket_->Receive(&pending_data, 272 while (sizeof(pending_data) ==
214 sizeof(pending_data))) && 273 socket_->Receive(&pending_data, sizeof(pending_data))) {
215 (pending_data >= 0)) {
216
217 // Convert the number of pending bytes in the render buffer 274 // Convert the number of pending bytes in the render buffer
218 // into milliseconds. 275 // into milliseconds.
219 audio_delay_milliseconds_ = pending_data / bytes_per_ms; 276 audio_delay_milliseconds_ = pending_data / bytes_per_ms;
220 FireRenderCallback(); 277 FireRenderCallback();
221 } 278 }
222 } 279 }
223 280
224 void AudioDevice::FireRenderCallback() { 281 void AudioDevice::FireRenderCallback() {
225 TRACE_EVENT0("audio", "AudioDevice::FireRenderCallback"); 282 TRACE_EVENT0("audio", "AudioDevice::FireRenderCallback");
226 283
(...skipping 20 matching lines...) Expand all
247 304
248 size_t AudioDevice::GetAudioHardwareBufferSize() { 305 size_t AudioDevice::GetAudioHardwareBufferSize() {
249 // Uses cached value if possible. 306 // Uses cached value if possible.
250 static size_t buffer_size = 0; 307 static size_t buffer_size = 0;
251 308
252 if (!buffer_size) 309 if (!buffer_size)
253 buffer_size = media::GetAudioHardwareBufferSize(); 310 buffer_size = media::GetAudioHardwareBufferSize();
254 311
255 return buffer_size; 312 return buffer_size;
256 } 313 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698