Index: content/renderer/media/webrtc_local_audio_renderer.cc |
diff --git a/content/renderer/media/webrtc_local_audio_renderer.cc b/content/renderer/media/webrtc_local_audio_renderer.cc |
index 5fcd58997dabc488bac306ca35867a29dec046fc..ca03f839f53f563dab76ab3fb917794ab94f458c 100644 |
--- a/content/renderer/media/webrtc_local_audio_renderer.cc |
+++ b/content/renderer/media/webrtc_local_audio_renderer.cc |
@@ -16,7 +16,7 @@ |
#include "content/renderer/render_frame_impl.h" |
#include "media/audio/audio_output_device.h" |
#include "media/base/audio_bus.h" |
-#include "media/base/audio_fifo.h" |
+#include "media/base/audio_shifter.h" |
namespace content { |
@@ -36,21 +36,15 @@ int WebRtcLocalAudioRenderer::Render( |
TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::Render"); |
base::AutoLock auto_lock(thread_lock_); |
- if (!playing_ || !volume_ || !loopback_fifo_) { |
+ if (!playing_ || !volume_ || !audio_shifter_) { |
audio_bus->Zero(); |
return 0; |
} |
- // Provide data by reading from the FIFO if the FIFO contains enough |
- // to fulfill the request. |
- if (loopback_fifo_->frames() >= audio_bus->frames()) { |
- loopback_fifo_->Consume(audio_bus, 0, audio_bus->frames()); |
- } else { |
- audio_bus->Zero(); |
- // This warning is perfectly safe if it happens for the first audio |
- // frames. It should not happen in a steady-state mode. |
- DVLOG(2) << "loopback FIFO is not full enough yet"; |
- } |
+ audio_shifter_->Pull( |
+ audio_bus, |
+ base::TimeTicks::Now() - |
+ base::TimeDelta::FromMilliseconds(audio_delay_milliseconds)); |
return audio_bus->frames(); |
} |
@@ -68,24 +62,16 @@ void WebRtcLocalAudioRenderer::OnData(const media::AudioBus& audio_bus, |
TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::CaptureData"); |
base::AutoLock auto_lock(thread_lock_); |
- if (!playing_ || !volume_ || !loopback_fifo_) |
+ if (!playing_ || !volume_ || !audio_shifter_) |
return; |
- // Push captured audio to FIFO so it can be read by a local sink. |
- if ((loopback_fifo_->frames() + audio_bus.frames()) <= |
- loopback_fifo_->max_frames()) { |
- // TODO(miu): Make sure the Render() method accounts for time shifting |
- // appropriately, per the comments for the usage of the |
- // |estimated_capture_time| field found in media_stream_audio_sink.h. |
- // http://crbug.com/437064 |
- loopback_fifo_->Push(&audio_bus); |
- |
- const base::TimeTicks now = base::TimeTicks::Now(); |
- total_render_time_ += now - last_render_time_; |
- last_render_time_ = now; |
- } else { |
- DVLOG(1) << "FIFO is full"; |
- } |
+ scoped_ptr<media::AudioBus> audio_data( |
+ media::AudioBus::Create(audio_bus.channels(), audio_bus.frames())); |
+ audio_bus.CopyTo(audio_data.get()); |
+ audio_shifter_->Push(audio_data.Pass(), estimated_capture_time); |
+ const base::TimeTicks now = base::TimeTicks::Now(); |
+ total_render_time_ += now - last_render_time_; |
+ last_render_time_ = now; |
} |
void WebRtcLocalAudioRenderer::OnSetFormat( |
@@ -152,7 +138,7 @@ void WebRtcLocalAudioRenderer::Stop() { |
{ |
base::AutoLock auto_lock(thread_lock_); |
playing_ = false; |
- loopback_fifo_.reset(); |
+ audio_shifter_.reset(); |
} |
// Stop the output audio stream, i.e, stop asking for data to render. |
@@ -246,7 +232,7 @@ void WebRtcLocalAudioRenderer::MaybeStartSink() { |
{ |
// Clear up the old data in the FIFO. |
base::AutoLock auto_lock(thread_lock_); |
- loopback_fifo_->Clear(); |
+ audio_shifter_->Flush(); |
} |
if (!sink_params_.IsValid() || !playing_ || !volume_ || sink_started_) |
@@ -296,19 +282,19 @@ void WebRtcLocalAudioRenderer::ReconfigureSink( |
source_params_.effects() | implicit_ducking_effect); |
{ |
- // TODO(henrika): we could add a more dynamic solution here but I prefer |
- // a fixed size combined with bad audio at overflow. The alternative is |
- // that we start to build up latency and that can be more difficult to |
- // detect. Tests have shown that the FIFO never contains more than 2 or 3 |
- // audio frames but I have selected a max size of ten buffers just |
- // in case since these tests were performed on a 16 core, 64GB Win 7 |
- // machine. We could also add some sort of error notifier in this area if |
- // the FIFO overflows. |
- media::AudioFifo* const new_fifo = new media::AudioFifo( |
- params.channels(), 10 * params.frames_per_buffer()); |
+ // Note: The max buffer is fairly large, but will rarely be used. |
+ // Cast needs the buffer to hold at least one second of audio. |
+ // The clock accuracy is set to 20ms because clock accuracy is |
+ // ~15ms on windows. |
+ media::AudioShifter* const new_shifter = new media::AudioShifter( |
+ base::TimeDelta::FromSeconds(2), |
+ base::TimeDelta::FromMilliseconds(20), |
+ base::TimeDelta::FromSeconds(20), |
+ source_params_.sample_rate(), |
+ params.channels()); |
base::AutoLock auto_lock(thread_lock_); |
- loopback_fifo_.reset(new_fifo); |
+ audio_shifter_.reset(new_shifter); |
} |
if (!sink_.get()) |