Chromium Code Reviews| Index: content/renderer/media/audio_renderer_impl.cc |
| =================================================================== |
| --- content/renderer/media/audio_renderer_impl.cc (revision 120523) |
| +++ content/renderer/media/audio_renderer_impl.cc (working copy) |
| @@ -16,6 +16,8 @@ |
| #include "media/audio/audio_util.h" |
| #include "media/base/filter_host.h" |
| +using base::subtle::AtomicWord; |
| + |
| // We define GetBufferSizeForSampleRate() instead of using |
| // GetAudioHardwareBufferSize() in audio_util because we're using |
| // the AUDIO_PCM_LINEAR flag, instead of AUDIO_PCM_LOW_LATENCY, |
| @@ -41,7 +43,10 @@ |
| bytes_per_second_(0), |
| stopped_(false), |
| sink_(sink), |
| - is_initialized_(false) { |
| + is_initialized_(false), |
| + ended_event_scheduled_(false), |
| + io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), |
| + stream_id_(0) { |
| } |
| AudioRendererImpl::~AudioRendererImpl() { |
| @@ -174,17 +179,21 @@ |
| void AudioRendererImpl::DoPlay() { |
| earliest_end_time_ = base::Time::Now(); |
| + ended_event_scheduled_ = false; |
| DCHECK(sink_.get()); |
| sink_->Play(); |
| } |
| void AudioRendererImpl::DoPause() { |
| + ++stream_id_; |
| DCHECK(sink_.get()); |
| sink_->Pause(false); |
| } |
| void AudioRendererImpl::DoSeek() { |
| earliest_end_time_ = base::Time::Now(); |
| + ended_event_scheduled_ = false; |
| + ++stream_id_; |
| // Pause and flush the stream when we seek to a new location. |
| DCHECK(sink_.get()); |
| @@ -197,7 +206,7 @@ |
| if (stopped_ || GetPlaybackRate() == 0.0f) { |
| // Output silence if stopped. |
| for (size_t i = 0; i < audio_data.size(); ++i) |
| - memset(audio_data[i], 0, sizeof(float) * number_of_frames); |
| + memset(audio_data[i], 0, sizeof(audio_data[i][0]) * number_of_frames); |
| return 0; |
| } |
| @@ -239,7 +248,7 @@ |
| int frames_to_zero = number_of_frames - filled_frames; |
| memset(audio_data[channel_index] + filled_frames, |
| 0, |
| - sizeof(float) * frames_to_zero); |
| + sizeof(audio_data[channel_index][0]) * frames_to_zero); |
| } |
| } |
| return filled_frames; |
| @@ -249,8 +258,28 @@ |
| host()->DisableAudioRenderer(); |
| } |
| +int64 AudioRendererImpl::OnRenderEndOfStreamDelay() { |
| + return (earliest_end_time_ - base::Time::Now()).InMilliseconds(); |
| +} |
| + |
| void AudioRendererImpl::OnRenderEndOfStream() { |
| - // TODO(enal): schedule callback instead of polling. |
| - if (base::Time::Now() >= earliest_end_time_) |
| + if (!ended_event_scheduled_) { |
| + ended_event_scheduled_ = true; |
| + int64 delay_ms = OnRenderEndOfStreamDelay(); |
| + if (delay_ms <= 0) { |
| + DoSignalEndOfStream(stream_id_); |
| + } else { |
| + io_message_loop_proxy_->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&AudioRendererImpl::DoSignalEndOfStream, this, stream_id_), |
| + delay_ms); |
|
scherkus (not reviewing)
2012/02/08 02:10:40
PostDelayedTask() now supports base::TimeDelta and
enal1
2012/02/08 02:43:22
Not MessageLoopProxy::PostDelayedTask(). It is for
scherkus (not reviewing)
2012/02/09 04:52:50
Looks like MLProxy slipped through the cracks!
htt
|
| + } |
| + } |
| +} |
| + |
| +void AudioRendererImpl::DoSignalEndOfStream(AtomicWord stream_id) { |
| + // There is no way to cancel delayed task if we paused or seeked after task |
| + // was scheduled, use stream id to catch such case. |
| + if (stream_id == stream_id_) |
| SignalEndOfStream(); |
| } |