| 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 |