| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_renderer_impl.h" | 5 #include "content/renderer/media/audio_renderer_impl.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include "chrome/common/render_messages.h" | |
| 10 #include "chrome/common/render_messages_params.h" | |
| 11 #include "chrome/renderer/render_thread.h" | 9 #include "chrome/renderer/render_thread.h" |
| 10 #include "content/common/audio_messages.h" |
| 12 #include "content/renderer/render_view.h" | 11 #include "content/renderer/render_view.h" |
| 13 #include "media/base/filter_host.h" | 12 #include "media/base/filter_host.h" |
| 14 | 13 |
| 15 namespace { | 14 namespace { |
| 16 | 15 |
| 17 // We will try to fill 200 ms worth of audio samples in each packet. A round | 16 // We will try to fill 200 ms worth of audio samples in each packet. A round |
| 18 // trip latency for IPC messages are typically 10 ms, this should give us | 17 // trip latency for IPC messages are typically 10 ms, this should give us |
| 19 // plenty of time to avoid clicks. | 18 // plenty of time to avoid clicks. |
| 20 const int kMillisecondsPerPacket = 200; | 19 const int kMillisecondsPerPacket = 200; |
| 21 | 20 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 base::AutoLock auto_lock(lock_); | 201 base::AutoLock auto_lock(lock_); |
| 203 DCHECK(!pending_request_); | 202 DCHECK(!pending_request_); |
| 204 pending_request_ = true; | 203 pending_request_ = true; |
| 205 request_buffers_state_ = buffers_state; | 204 request_buffers_state_ = buffers_state; |
| 206 } | 205 } |
| 207 | 206 |
| 208 // Try to fill in the fulfill the packet request. | 207 // Try to fill in the fulfill the packet request. |
| 209 NotifyPacketReadyTask(); | 208 NotifyPacketReadyTask(); |
| 210 } | 209 } |
| 211 | 210 |
| 212 void AudioRendererImpl::OnStateChanged( | 211 void AudioRendererImpl::OnStateChanged(AudioStreamState state) { |
| 213 const ViewMsg_AudioStreamState_Params& state) { | |
| 214 DCHECK(MessageLoop::current() == io_loop_); | 212 DCHECK(MessageLoop::current() == io_loop_); |
| 215 | 213 |
| 216 base::AutoLock auto_lock(lock_); | 214 base::AutoLock auto_lock(lock_); |
| 217 if (stopped_) | 215 if (stopped_) |
| 218 return; | 216 return; |
| 219 | 217 |
| 220 switch (state.state) { | 218 switch (state) { |
| 221 case ViewMsg_AudioStreamState_Params::kError: | 219 case kAudioStreamError: |
| 222 // We receive this error if we counter an hardware error on the browser | 220 // We receive this error if we counter an hardware error on the browser |
| 223 // side. We can proceed with ignoring the audio stream. | 221 // side. We can proceed with ignoring the audio stream. |
| 224 // TODO(hclam): We need more handling of these kind of error. For example | 222 // TODO(hclam): We need more handling of these kind of error. For example |
| 225 // re-try creating the audio output stream on the browser side or fail | 223 // re-try creating the audio output stream on the browser side or fail |
| 226 // nicely and report to demuxer that the whole audio stream is discarded. | 224 // nicely and report to demuxer that the whole audio stream is discarded. |
| 227 host()->DisableAudioRenderer(); | 225 host()->DisableAudioRenderer(); |
| 228 break; | 226 break; |
| 229 // TODO(hclam): handle these events. | 227 // TODO(hclam): handle these events. |
| 230 case ViewMsg_AudioStreamState_Params::kPlaying: | 228 case kAudioStreamPlaying: |
| 231 case ViewMsg_AudioStreamState_Params::kPaused: | 229 case kAudioStreamPaused: |
| 232 break; | 230 break; |
| 233 default: | 231 default: |
| 234 NOTREACHED(); | 232 NOTREACHED(); |
| 235 break; | 233 break; |
| 236 } | 234 } |
| 237 } | 235 } |
| 238 | 236 |
| 239 void AudioRendererImpl::OnVolume(double volume) { | 237 void AudioRendererImpl::OnVolume(double volume) { |
| 240 // TODO(hclam): decide whether we need to report the current volume to | 238 // TODO(hclam): decide whether we need to report the current volume to |
| 241 // pipeline. | 239 // pipeline. |
| 242 } | 240 } |
| 243 | 241 |
| 244 void AudioRendererImpl::CreateStreamTask(const AudioParameters& audio_params) { | 242 void AudioRendererImpl::CreateStreamTask(const AudioParameters& audio_params) { |
| 245 DCHECK(MessageLoop::current() == io_loop_); | 243 DCHECK(MessageLoop::current() == io_loop_); |
| 246 | 244 |
| 247 base::AutoLock auto_lock(lock_); | 245 base::AutoLock auto_lock(lock_); |
| 248 if (stopped_) | 246 if (stopped_) |
| 249 return; | 247 return; |
| 250 | 248 |
| 251 // Make sure we don't call create more than once. | 249 // Make sure we don't call create more than once. |
| 252 DCHECK_EQ(0, stream_id_); | 250 DCHECK_EQ(0, stream_id_); |
| 253 stream_id_ = filter_->AddDelegate(this); | 251 stream_id_ = filter_->AddDelegate(this); |
| 254 io_loop_->AddDestructionObserver(this); | 252 io_loop_->AddDestructionObserver(this); |
| 255 | 253 |
| 256 ViewHostMsg_Audio_CreateStream_Params params; | 254 AudioParameters params_to_send(audio_params); |
| 257 params.params = audio_params; | 255 // Let the browser choose packet size. |
| 256 params_to_send.samples_per_packet = 0; |
| 258 | 257 |
| 259 // Let the browser choose packet size. | 258 filter_->Send(new AudioHostMsg_CreateStream( |
| 260 params.params.samples_per_packet = 0; | 259 0, stream_id_, params_to_send, false)); |
| 261 | |
| 262 filter_->Send(new ViewHostMsg_CreateAudioStream(0, stream_id_, params, | |
| 263 false)); | |
| 264 } | 260 } |
| 265 | 261 |
| 266 void AudioRendererImpl::PlayTask() { | 262 void AudioRendererImpl::PlayTask() { |
| 267 DCHECK(MessageLoop::current() == io_loop_); | 263 DCHECK(MessageLoop::current() == io_loop_); |
| 268 | 264 |
| 269 filter_->Send(new ViewHostMsg_PlayAudioStream(0, stream_id_)); | 265 filter_->Send(new AudioHostMsg_PlayStream(0, stream_id_)); |
| 270 } | 266 } |
| 271 | 267 |
| 272 void AudioRendererImpl::PauseTask() { | 268 void AudioRendererImpl::PauseTask() { |
| 273 DCHECK(MessageLoop::current() == io_loop_); | 269 DCHECK(MessageLoop::current() == io_loop_); |
| 274 | 270 |
| 275 filter_->Send(new ViewHostMsg_PauseAudioStream(0, stream_id_)); | 271 filter_->Send(new AudioHostMsg_PauseStream(0, stream_id_)); |
| 276 } | 272 } |
| 277 | 273 |
| 278 void AudioRendererImpl::SeekTask() { | 274 void AudioRendererImpl::SeekTask() { |
| 279 DCHECK(MessageLoop::current() == io_loop_); | 275 DCHECK(MessageLoop::current() == io_loop_); |
| 280 | 276 |
| 281 // We have to pause the audio stream before we can flush. | 277 // We have to pause the audio stream before we can flush. |
| 282 filter_->Send(new ViewHostMsg_PauseAudioStream(0, stream_id_)); | 278 filter_->Send(new AudioHostMsg_PauseStream(0, stream_id_)); |
| 283 filter_->Send(new ViewHostMsg_FlushAudioStream(0, stream_id_)); | 279 filter_->Send(new AudioHostMsg_FlushStream(0, stream_id_)); |
| 284 } | 280 } |
| 285 | 281 |
| 286 void AudioRendererImpl::DestroyTask() { | 282 void AudioRendererImpl::DestroyTask() { |
| 287 DCHECK(MessageLoop::current() == io_loop_); | 283 DCHECK(MessageLoop::current() == io_loop_); |
| 288 | 284 |
| 289 // Make sure we don't call destroy more than once. | 285 // Make sure we don't call destroy more than once. |
| 290 DCHECK_NE(0, stream_id_); | 286 DCHECK_NE(0, stream_id_); |
| 291 filter_->RemoveDelegate(stream_id_); | 287 filter_->RemoveDelegate(stream_id_); |
| 292 filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); | 288 filter_->Send(new AudioHostMsg_CloseStream(0, stream_id_)); |
| 293 io_loop_->RemoveDestructionObserver(this); | 289 io_loop_->RemoveDestructionObserver(this); |
| 294 stream_id_ = 0; | 290 stream_id_ = 0; |
| 295 } | 291 } |
| 296 | 292 |
| 297 void AudioRendererImpl::SetVolumeTask(double volume) { | 293 void AudioRendererImpl::SetVolumeTask(double volume) { |
| 298 DCHECK(MessageLoop::current() == io_loop_); | 294 DCHECK(MessageLoop::current() == io_loop_); |
| 299 | 295 |
| 300 base::AutoLock auto_lock(lock_); | 296 base::AutoLock auto_lock(lock_); |
| 301 if (stopped_) | 297 if (stopped_) |
| 302 return; | 298 return; |
| 303 filter_->Send(new ViewHostMsg_SetAudioVolume(0, stream_id_, volume)); | 299 filter_->Send(new AudioHostMsg_SetVolume(0, stream_id_, volume)); |
| 304 } | 300 } |
| 305 | 301 |
| 306 void AudioRendererImpl::NotifyPacketReadyTask() { | 302 void AudioRendererImpl::NotifyPacketReadyTask() { |
| 307 DCHECK(MessageLoop::current() == io_loop_); | 303 DCHECK(MessageLoop::current() == io_loop_); |
| 308 | 304 |
| 309 base::AutoLock auto_lock(lock_); | 305 base::AutoLock auto_lock(lock_); |
| 310 if (stopped_) | 306 if (stopped_) |
| 311 return; | 307 return; |
| 312 if (pending_request_ && GetPlaybackRate() > 0.0f) { | 308 if (pending_request_ && GetPlaybackRate() > 0.0f) { |
| 313 DCHECK(shared_memory_.get()); | 309 DCHECK(shared_memory_.get()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 336 request_delay = base::TimeDelta::FromMicroseconds( | 332 request_delay = base::TimeDelta::FromMicroseconds( |
| 337 static_cast<int64>(ceil(request_delay.InMicroseconds() * | 333 static_cast<int64>(ceil(request_delay.InMicroseconds() * |
| 338 GetPlaybackRate()))); | 334 GetPlaybackRate()))); |
| 339 } | 335 } |
| 340 | 336 |
| 341 uint32 filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()), | 337 uint32 filled = FillBuffer(static_cast<uint8*>(shared_memory_->memory()), |
| 342 shared_memory_size_, request_delay, | 338 shared_memory_size_, request_delay, |
| 343 request_buffers_state_.pending_bytes == 0); | 339 request_buffers_state_.pending_bytes == 0); |
| 344 pending_request_ = false; | 340 pending_request_ = false; |
| 345 // Then tell browser process we are done filling into the buffer. | 341 // Then tell browser process we are done filling into the buffer. |
| 346 filter_->Send( | 342 filter_->Send(new AudioHostMsg_NotifyPacketReady(0, stream_id_, filled)); |
| 347 new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled)); | |
| 348 } | 343 } |
| 349 } | 344 } |
| 350 | 345 |
| 351 void AudioRendererImpl::WillDestroyCurrentMessageLoop() { | 346 void AudioRendererImpl::WillDestroyCurrentMessageLoop() { |
| 352 DCHECK(MessageLoop::current() == io_loop_); | 347 DCHECK(MessageLoop::current() == io_loop_); |
| 353 | 348 |
| 354 // We treat the IO loop going away the same as stopping. | 349 // We treat the IO loop going away the same as stopping. |
| 355 base::AutoLock auto_lock(lock_); | 350 base::AutoLock auto_lock(lock_); |
| 356 if (stopped_) | 351 if (stopped_) |
| 357 return; | 352 return; |
| 358 | 353 |
| 359 stopped_ = true; | 354 stopped_ = true; |
| 360 DestroyTask(); | 355 DestroyTask(); |
| 361 } | 356 } |
| OLD | NEW |