ServiceWorker: Introduce ServiceWorkerDiskCacheMigrator
[chromium-blink-merge.git] / media / audio / clockless_audio_sink.cc
blob44e9adb4451f0c609e5db94f77a7b87c6e860f64
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/audio/clockless_audio_sink.h"
7 #include "base/threading/simple_thread.h"
9 namespace media {
11 // Internal to ClocklessAudioSink. Class is used to call Render() on a seperate
12 // thread, running as fast as it can read the data.
13 class ClocklessAudioSinkThread : public base::DelegateSimpleThread::Delegate {
14 public:
15 explicit ClocklessAudioSinkThread(const AudioParameters& params,
16 AudioRendererSink::RenderCallback* callback)
17 : callback_(callback),
18 audio_bus_(AudioBus::Create(params)),
19 stop_event_(new base::WaitableEvent(false, false)) {}
21 void Start() {
22 stop_event_->Reset();
23 thread_.reset(new base::DelegateSimpleThread(this, "ClocklessAudioSink"));
24 thread_->Start();
27 // Generate a signal to stop calling Render().
28 base::TimeDelta Stop() {
29 stop_event_->Signal();
30 thread_->Join();
31 return playback_time_;
34 private:
35 // Call Render() repeatedly, keeping track of the rendering time.
36 void Run() override {
37 base::TimeTicks start;
38 while (!stop_event_->IsSignaled()) {
39 int frames_received = callback_->Render(audio_bus_.get(), 0);
40 if (frames_received <= 0) {
41 // No data received, so let other threads run to provide data.
42 base::PlatformThread::YieldCurrentThread();
43 } else if (start.is_null()) {
44 // First time we processed some audio, so record the starting time.
45 start = base::TimeTicks::Now();
46 } else {
47 // Keep track of the last time data was rendered.
48 playback_time_ = base::TimeTicks::Now() - start;
53 AudioRendererSink::RenderCallback* callback_;
54 scoped_ptr<AudioBus> audio_bus_;
55 scoped_ptr<base::WaitableEvent> stop_event_;
56 scoped_ptr<base::DelegateSimpleThread> thread_;
57 base::TimeDelta playback_time_;
60 ClocklessAudioSink::ClocklessAudioSink()
61 : initialized_(false),
62 playing_(false) {}
64 ClocklessAudioSink::~ClocklessAudioSink() {}
66 void ClocklessAudioSink::Initialize(const AudioParameters& params,
67 RenderCallback* callback) {
68 DCHECK(!initialized_);
69 thread_.reset(new ClocklessAudioSinkThread(params, callback));
70 initialized_ = true;
73 void ClocklessAudioSink::Start() {
74 DCHECK(initialized_);
75 DCHECK(!playing_);
78 void ClocklessAudioSink::Stop() {
79 if (initialized_)
80 Pause();
83 void ClocklessAudioSink::Play() {
84 DCHECK(initialized_);
86 if (playing_)
87 return;
89 playing_ = true;
90 thread_->Start();
93 void ClocklessAudioSink::Pause() {
94 DCHECK(initialized_);
96 if (!playing_)
97 return;
99 playing_ = false;
100 playback_time_ = thread_->Stop();
103 bool ClocklessAudioSink::SetVolume(double volume) {
104 // Audio is always muted.
105 return volume == 0.0;
108 } // namespace media