summaryrefslogtreecommitdiff
path: root/chromium/media/audio/clockless_audio_sink.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/audio/clockless_audio_sink.cc')
-rw-r--r--chromium/media/audio/clockless_audio_sink.cc107
1 files changed, 107 insertions, 0 deletions
diff --git a/chromium/media/audio/clockless_audio_sink.cc b/chromium/media/audio/clockless_audio_sink.cc
new file mode 100644
index 00000000000..ff809d0541d
--- /dev/null
+++ b/chromium/media/audio/clockless_audio_sink.cc
@@ -0,0 +1,107 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/audio/clockless_audio_sink.h"
+
+#include "base/threading/simple_thread.h"
+#include "base/time/time.h"
+#include "media/base/audio_renderer_sink.h"
+
+namespace media {
+
+// Internal to ClocklessAudioSink. Class is used to call Render() on a seperate
+// thread, running as fast as it can read the data.
+class ClocklessAudioSinkThread : public base::DelegateSimpleThread::Delegate {
+ public:
+ explicit ClocklessAudioSinkThread(const AudioParameters& params,
+ AudioRendererSink::RenderCallback* callback)
+ : callback_(callback),
+ audio_bus_(AudioBus::Create(params)),
+ stop_event_(new base::WaitableEvent(false, false)) {}
+
+ void Start() {
+ stop_event_->Reset();
+ thread_.reset(new base::DelegateSimpleThread(this, "ClocklessAudioSink"));
+ thread_->Start();
+ }
+
+ // Generate a signal to stop calling Render().
+ base::TimeDelta Stop() {
+ stop_event_->Signal();
+ thread_->Join();
+ return playback_time_;
+ }
+
+ private:
+ // Call Render() repeatedly, keeping track of the rendering time.
+ virtual void Run() OVERRIDE {
+ base::TimeTicks start;
+ while (!stop_event_->IsSignaled()) {
+ int frames_received = callback_->Render(audio_bus_.get(), 0);
+ if (frames_received <= 0) {
+ // No data received, so let other threads run to provide data.
+ base::PlatformThread::YieldCurrentThread();
+ } else if (start.is_null()) {
+ // First time we processed some audio, so record the starting time.
+ start = base::TimeTicks::HighResNow();
+ } else {
+ // Keep track of the last time data was rendered.
+ playback_time_ = base::TimeTicks::HighResNow() - start;
+ }
+ }
+ }
+
+ AudioRendererSink::RenderCallback* callback_;
+ scoped_ptr<AudioBus> audio_bus_;
+ scoped_ptr<base::WaitableEvent> stop_event_;
+ scoped_ptr<base::DelegateSimpleThread> thread_;
+ base::TimeDelta playback_time_;
+};
+
+ClocklessAudioSink::ClocklessAudioSink()
+ : initialized_(false),
+ playing_(false) {}
+
+ClocklessAudioSink::~ClocklessAudioSink() {}
+
+void ClocklessAudioSink::Initialize(const AudioParameters& params,
+ RenderCallback* callback) {
+ DCHECK(!initialized_);
+ thread_.reset(new ClocklessAudioSinkThread(params, callback));
+ initialized_ = true;
+}
+
+void ClocklessAudioSink::Start() {
+ DCHECK(!playing_);
+}
+
+void ClocklessAudioSink::Stop() {
+ DCHECK(initialized_);
+
+ if (!playing_)
+ return;
+
+ playback_time_ = thread_->Stop();
+}
+
+void ClocklessAudioSink::Play() {
+ DCHECK(initialized_);
+
+ if (playing_)
+ return;
+
+ playing_ = true;
+ thread_->Start();
+}
+
+void ClocklessAudioSink::Pause() {
+ Stop();
+}
+
+bool ClocklessAudioSink::SetVolume(double volume) {
+ // Audio is always muted.
+ return volume == 0.0;
+}
+
+} // namespace media