| 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 "chrome/renderer/media/audio_renderer_impl.h" | 5 #include "chrome/renderer/media/audio_renderer_impl.h" | 
| 6 | 6 | 
| 7 #include <math.h> | 7 #include <math.h> | 
| 8 | 8 | 
| 9 #include "chrome/common/render_messages_params.h" | 9 #include "chrome/common/render_messages_params.h" | 
| 10 #include "chrome/renderer/audio_message_filter.h" | 10 #include "chrome/renderer/audio_message_filter.h" | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 64   // Calculate the number of bytes per second using information of the stream. | 64   // Calculate the number of bytes per second using information of the stream. | 
| 65   bytes_per_second_ = params_.sample_rate * params_.channels * | 65   bytes_per_second_ = params_.sample_rate * params_.channels * | 
| 66       params_.bits_per_sample / 8; | 66       params_.bits_per_sample / 8; | 
| 67 | 67 | 
| 68   io_loop_->PostTask(FROM_HERE, | 68   io_loop_->PostTask(FROM_HERE, | 
| 69       NewRunnableMethod(this, &AudioRendererImpl::CreateStreamTask, params_)); | 69       NewRunnableMethod(this, &AudioRendererImpl::CreateStreamTask, params_)); | 
| 70   return true; | 70   return true; | 
| 71 } | 71 } | 
| 72 | 72 | 
| 73 void AudioRendererImpl::OnStop() { | 73 void AudioRendererImpl::OnStop() { | 
| 74   AutoLock auto_lock(lock_); | 74   base::AutoLock auto_lock(lock_); | 
| 75   if (stopped_) | 75   if (stopped_) | 
| 76     return; | 76     return; | 
| 77   stopped_ = true; | 77   stopped_ = true; | 
| 78 | 78 | 
| 79   // We should never touch |io_loop_| after being stopped, so post our final | 79   // We should never touch |io_loop_| after being stopped, so post our final | 
| 80   // task to clean up. | 80   // task to clean up. | 
| 81   io_loop_->PostTask(FROM_HERE, | 81   io_loop_->PostTask(FROM_HERE, | 
| 82       NewRunnableMethod(this, &AudioRendererImpl::DestroyTask)); | 82       NewRunnableMethod(this, &AudioRendererImpl::DestroyTask)); | 
| 83 } | 83 } | 
| 84 | 84 | 
| 85 void AudioRendererImpl::ConsumeAudioSamples( | 85 void AudioRendererImpl::ConsumeAudioSamples( | 
| 86     scoped_refptr<media::Buffer> buffer_in) { | 86     scoped_refptr<media::Buffer> buffer_in) { | 
| 87   AutoLock auto_lock(lock_); | 87   base::AutoLock auto_lock(lock_); | 
| 88   if (stopped_) | 88   if (stopped_) | 
| 89     return; | 89     return; | 
| 90 | 90 | 
| 91   // TODO(hclam): handle end of stream here. | 91   // TODO(hclam): handle end of stream here. | 
| 92 | 92 | 
| 93   // Use the base class to queue the buffer. | 93   // Use the base class to queue the buffer. | 
| 94   AudioRendererBase::ConsumeAudioSamples(buffer_in); | 94   AudioRendererBase::ConsumeAudioSamples(buffer_in); | 
| 95 | 95 | 
| 96   // Post a task to render thread to notify a packet reception. | 96   // Post a task to render thread to notify a packet reception. | 
| 97   io_loop_->PostTask(FROM_HERE, | 97   io_loop_->PostTask(FROM_HERE, | 
| 98       NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); | 98       NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); | 
| 99 } | 99 } | 
| 100 | 100 | 
| 101 void AudioRendererImpl::SetPlaybackRate(float rate) { | 101 void AudioRendererImpl::SetPlaybackRate(float rate) { | 
| 102   DCHECK(rate >= 0.0f); | 102   DCHECK(rate >= 0.0f); | 
| 103 | 103 | 
| 104   AutoLock auto_lock(lock_); | 104   base::AutoLock auto_lock(lock_); | 
| 105   // Handle the case where we stopped due to |io_loop_| dying. | 105   // Handle the case where we stopped due to |io_loop_| dying. | 
| 106   if (stopped_) { | 106   if (stopped_) { | 
| 107     AudioRendererBase::SetPlaybackRate(rate); | 107     AudioRendererBase::SetPlaybackRate(rate); | 
| 108     return; | 108     return; | 
| 109   } | 109   } | 
| 110 | 110 | 
| 111   // We have two cases here: | 111   // We have two cases here: | 
| 112   // Play: GetPlaybackRate() == 0.0 && rate != 0.0 | 112   // Play: GetPlaybackRate() == 0.0 && rate != 0.0 | 
| 113   // Pause: GetPlaybackRate() != 0.0 && rate == 0.0 | 113   // Pause: GetPlaybackRate() != 0.0 && rate == 0.0 | 
| 114   if (GetPlaybackRate() == 0.0f && rate != 0.0f) { | 114   if (GetPlaybackRate() == 0.0f && rate != 0.0f) { | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 125   // the previous packet request may be stalled by a pause. | 125   // the previous packet request may be stalled by a pause. | 
| 126   if (rate > 0.0f) { | 126   if (rate > 0.0f) { | 
| 127     io_loop_->PostTask( | 127     io_loop_->PostTask( | 
| 128         FROM_HERE, | 128         FROM_HERE, | 
| 129         NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); | 129         NewRunnableMethod(this, &AudioRendererImpl::NotifyPacketReadyTask)); | 
| 130   } | 130   } | 
| 131 } | 131 } | 
| 132 | 132 | 
| 133 void AudioRendererImpl::Pause(media::FilterCallback* callback) { | 133 void AudioRendererImpl::Pause(media::FilterCallback* callback) { | 
| 134   AudioRendererBase::Pause(callback); | 134   AudioRendererBase::Pause(callback); | 
| 135   AutoLock auto_lock(lock_); | 135   base::AutoLock auto_lock(lock_); | 
| 136   if (stopped_) | 136   if (stopped_) | 
| 137     return; | 137     return; | 
| 138 | 138 | 
| 139   io_loop_->PostTask(FROM_HERE, | 139   io_loop_->PostTask(FROM_HERE, | 
| 140       NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); | 140       NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); | 
| 141 } | 141 } | 
| 142 | 142 | 
| 143 void AudioRendererImpl::Seek(base::TimeDelta time, | 143 void AudioRendererImpl::Seek(base::TimeDelta time, | 
| 144                              media::FilterCallback* callback) { | 144                              media::FilterCallback* callback) { | 
| 145   AudioRendererBase::Seek(time, callback); | 145   AudioRendererBase::Seek(time, callback); | 
| 146   AutoLock auto_lock(lock_); | 146   base::AutoLock auto_lock(lock_); | 
| 147   if (stopped_) | 147   if (stopped_) | 
| 148     return; | 148     return; | 
| 149 | 149 | 
| 150   io_loop_->PostTask(FROM_HERE, | 150   io_loop_->PostTask(FROM_HERE, | 
| 151       NewRunnableMethod(this, &AudioRendererImpl::SeekTask)); | 151       NewRunnableMethod(this, &AudioRendererImpl::SeekTask)); | 
| 152 } | 152 } | 
| 153 | 153 | 
| 154 | 154 | 
| 155 void AudioRendererImpl::Play(media::FilterCallback* callback) { | 155 void AudioRendererImpl::Play(media::FilterCallback* callback) { | 
| 156   AudioRendererBase::Play(callback); | 156   AudioRendererBase::Play(callback); | 
| 157   AutoLock auto_lock(lock_); | 157   base::AutoLock auto_lock(lock_); | 
| 158   if (stopped_) | 158   if (stopped_) | 
| 159     return; | 159     return; | 
| 160 | 160 | 
| 161   if (GetPlaybackRate() != 0.0f) { | 161   if (GetPlaybackRate() != 0.0f) { | 
| 162     io_loop_->PostTask(FROM_HERE, | 162     io_loop_->PostTask(FROM_HERE, | 
| 163                        NewRunnableMethod(this, &AudioRendererImpl::PlayTask)); | 163                        NewRunnableMethod(this, &AudioRendererImpl::PlayTask)); | 
| 164   } else { | 164   } else { | 
| 165     io_loop_->PostTask(FROM_HERE, | 165     io_loop_->PostTask(FROM_HERE, | 
| 166                        NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); | 166                        NewRunnableMethod(this, &AudioRendererImpl::PauseTask)); | 
| 167   } | 167   } | 
| 168 } | 168 } | 
| 169 | 169 | 
| 170 void AudioRendererImpl::SetVolume(float volume) { | 170 void AudioRendererImpl::SetVolume(float volume) { | 
| 171   AutoLock auto_lock(lock_); | 171   base::AutoLock auto_lock(lock_); | 
| 172   if (stopped_) | 172   if (stopped_) | 
| 173     return; | 173     return; | 
| 174   io_loop_->PostTask(FROM_HERE, | 174   io_loop_->PostTask(FROM_HERE, | 
| 175       NewRunnableMethod( | 175       NewRunnableMethod( | 
| 176           this, &AudioRendererImpl::SetVolumeTask, volume)); | 176           this, &AudioRendererImpl::SetVolumeTask, volume)); | 
| 177 } | 177 } | 
| 178 | 178 | 
| 179 void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle, | 179 void AudioRendererImpl::OnCreated(base::SharedMemoryHandle handle, | 
| 180                                   uint32 length) { | 180                                   uint32 length) { | 
| 181   DCHECK(MessageLoop::current() == io_loop_); | 181   DCHECK(MessageLoop::current() == io_loop_); | 
| 182 | 182 | 
| 183   AutoLock auto_lock(lock_); | 183   base::AutoLock auto_lock(lock_); | 
| 184   if (stopped_) | 184   if (stopped_) | 
| 185     return; | 185     return; | 
| 186 | 186 | 
| 187   shared_memory_.reset(new base::SharedMemory(handle, false)); | 187   shared_memory_.reset(new base::SharedMemory(handle, false)); | 
| 188   shared_memory_->Map(length); | 188   shared_memory_->Map(length); | 
| 189   shared_memory_size_ = length; | 189   shared_memory_size_ = length; | 
| 190 } | 190 } | 
| 191 | 191 | 
| 192 void AudioRendererImpl::OnLowLatencyCreated(base::SharedMemoryHandle, | 192 void AudioRendererImpl::OnLowLatencyCreated(base::SharedMemoryHandle, | 
| 193                                             base::SyncSocket::Handle, uint32) { | 193                                             base::SyncSocket::Handle, uint32) { | 
| 194   // AudioRenderer should not have a low-latency audio channel. | 194   // AudioRenderer should not have a low-latency audio channel. | 
| 195   NOTREACHED(); | 195   NOTREACHED(); | 
| 196 } | 196 } | 
| 197 | 197 | 
| 198 void AudioRendererImpl::OnRequestPacket(AudioBuffersState buffers_state) { | 198 void AudioRendererImpl::OnRequestPacket(AudioBuffersState buffers_state) { | 
| 199   DCHECK(MessageLoop::current() == io_loop_); | 199   DCHECK(MessageLoop::current() == io_loop_); | 
| 200 | 200 | 
| 201   { | 201   { | 
| 202     AutoLock auto_lock(lock_); | 202     base::AutoLock auto_lock(lock_); | 
| 203     DCHECK(!pending_request_); | 203     DCHECK(!pending_request_); | 
| 204     pending_request_ = true; | 204     pending_request_ = true; | 
| 205     request_buffers_state_ = buffers_state; | 205     request_buffers_state_ = buffers_state; | 
| 206   } | 206   } | 
| 207 | 207 | 
| 208   // Try to fill in the fulfill the packet request. | 208   // Try to fill in the fulfill the packet request. | 
| 209   NotifyPacketReadyTask(); | 209   NotifyPacketReadyTask(); | 
| 210 } | 210 } | 
| 211 | 211 | 
| 212 void AudioRendererImpl::OnStateChanged( | 212 void AudioRendererImpl::OnStateChanged( | 
| 213     const ViewMsg_AudioStreamState_Params& state) { | 213     const ViewMsg_AudioStreamState_Params& state) { | 
| 214   DCHECK(MessageLoop::current() == io_loop_); | 214   DCHECK(MessageLoop::current() == io_loop_); | 
| 215 | 215 | 
| 216   AutoLock auto_lock(lock_); | 216   base::AutoLock auto_lock(lock_); | 
| 217   if (stopped_) | 217   if (stopped_) | 
| 218     return; | 218     return; | 
| 219 | 219 | 
| 220   switch (state.state) { | 220   switch (state.state) { | 
| 221     case ViewMsg_AudioStreamState_Params::kError: | 221     case ViewMsg_AudioStreamState_Params::kError: | 
| 222       // We receive this error if we counter an hardware error on the browser | 222       // We receive this error if we counter an hardware error on the browser | 
| 223       // side. We can proceed with ignoring the audio stream. | 223       // side. We can proceed with ignoring the audio stream. | 
| 224       // TODO(hclam): We need more handling of these kind of error. For example | 224       // 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 | 225       // 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. | 226       // nicely and report to demuxer that the whole audio stream is discarded. | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 237 } | 237 } | 
| 238 | 238 | 
| 239 void AudioRendererImpl::OnVolume(double volume) { | 239 void AudioRendererImpl::OnVolume(double volume) { | 
| 240   // TODO(hclam): decide whether we need to report the current volume to | 240   // TODO(hclam): decide whether we need to report the current volume to | 
| 241   // pipeline. | 241   // pipeline. | 
| 242 } | 242 } | 
| 243 | 243 | 
| 244 void AudioRendererImpl::CreateStreamTask(AudioParameters audio_params) { | 244 void AudioRendererImpl::CreateStreamTask(AudioParameters audio_params) { | 
| 245   DCHECK(MessageLoop::current() == io_loop_); | 245   DCHECK(MessageLoop::current() == io_loop_); | 
| 246 | 246 | 
| 247   AutoLock auto_lock(lock_); | 247   base::AutoLock auto_lock(lock_); | 
| 248   if (stopped_) | 248   if (stopped_) | 
| 249     return; | 249     return; | 
| 250 | 250 | 
| 251   // Make sure we don't call create more than once. | 251   // Make sure we don't call create more than once. | 
| 252   DCHECK_EQ(0, stream_id_); | 252   DCHECK_EQ(0, stream_id_); | 
| 253   stream_id_ = filter_->AddDelegate(this); | 253   stream_id_ = filter_->AddDelegate(this); | 
| 254   io_loop_->AddDestructionObserver(this); | 254   io_loop_->AddDestructionObserver(this); | 
| 255 | 255 | 
| 256   ViewHostMsg_Audio_CreateStream_Params params; | 256   ViewHostMsg_Audio_CreateStream_Params params; | 
| 257   params.params = audio_params; | 257   params.params = audio_params; | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 290   DCHECK_NE(0, stream_id_); | 290   DCHECK_NE(0, stream_id_); | 
| 291   filter_->RemoveDelegate(stream_id_); | 291   filter_->RemoveDelegate(stream_id_); | 
| 292   filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); | 292   filter_->Send(new ViewHostMsg_CloseAudioStream(0, stream_id_)); | 
| 293   io_loop_->RemoveDestructionObserver(this); | 293   io_loop_->RemoveDestructionObserver(this); | 
| 294   stream_id_ = 0; | 294   stream_id_ = 0; | 
| 295 } | 295 } | 
| 296 | 296 | 
| 297 void AudioRendererImpl::SetVolumeTask(double volume) { | 297 void AudioRendererImpl::SetVolumeTask(double volume) { | 
| 298   DCHECK(MessageLoop::current() == io_loop_); | 298   DCHECK(MessageLoop::current() == io_loop_); | 
| 299 | 299 | 
| 300   AutoLock auto_lock(lock_); | 300   base::AutoLock auto_lock(lock_); | 
| 301   if (stopped_) | 301   if (stopped_) | 
| 302     return; | 302     return; | 
| 303   filter_->Send(new ViewHostMsg_SetAudioVolume(0, stream_id_, volume)); | 303   filter_->Send(new ViewHostMsg_SetAudioVolume(0, stream_id_, volume)); | 
| 304 } | 304 } | 
| 305 | 305 | 
| 306 void AudioRendererImpl::NotifyPacketReadyTask() { | 306 void AudioRendererImpl::NotifyPacketReadyTask() { | 
| 307   DCHECK(MessageLoop::current() == io_loop_); | 307   DCHECK(MessageLoop::current() == io_loop_); | 
| 308 | 308 | 
| 309   AutoLock auto_lock(lock_); | 309   base::AutoLock auto_lock(lock_); | 
| 310   if (stopped_) | 310   if (stopped_) | 
| 311     return; | 311     return; | 
| 312   if (pending_request_ && GetPlaybackRate() > 0.0f) { | 312   if (pending_request_ && GetPlaybackRate() > 0.0f) { | 
| 313     DCHECK(shared_memory_.get()); | 313     DCHECK(shared_memory_.get()); | 
| 314 | 314 | 
| 315     // Adjust the playback delay. | 315     // Adjust the playback delay. | 
| 316     base::Time current_time = base::Time::Now(); | 316     base::Time current_time = base::Time::Now(); | 
| 317 | 317 | 
| 318     base::TimeDelta request_delay = | 318     base::TimeDelta request_delay = | 
| 319         ConvertToDuration(request_buffers_state_.total_bytes()); | 319         ConvertToDuration(request_buffers_state_.total_bytes()); | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 345     // Then tell browser process we are done filling into the buffer. | 345     // Then tell browser process we are done filling into the buffer. | 
| 346     filter_->Send( | 346     filter_->Send( | 
| 347         new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled)); | 347         new ViewHostMsg_NotifyAudioPacketReady(0, stream_id_, filled)); | 
| 348   } | 348   } | 
| 349 } | 349 } | 
| 350 | 350 | 
| 351 void AudioRendererImpl::WillDestroyCurrentMessageLoop() { | 351 void AudioRendererImpl::WillDestroyCurrentMessageLoop() { | 
| 352   DCHECK(MessageLoop::current() == io_loop_); | 352   DCHECK(MessageLoop::current() == io_loop_); | 
| 353 | 353 | 
| 354   // We treat the IO loop going away the same as stopping. | 354   // We treat the IO loop going away the same as stopping. | 
| 355   AutoLock auto_lock(lock_); | 355   base::AutoLock auto_lock(lock_); | 
| 356   if (stopped_) | 356   if (stopped_) | 
| 357     return; | 357     return; | 
| 358 | 358 | 
| 359   stopped_ = true; | 359   stopped_ = true; | 
| 360   DestroyTask(); | 360   DestroyTask(); | 
| 361 } | 361 } | 
| OLD | NEW | 
|---|