Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / media / audio / clockless_audio_sink.cc
blob60c839c124b210c682f9cf5fd724881075ff12bb
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/bind.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/threading/simple_thread.h"
12 namespace media {
14 // Internal to ClocklessAudioSink. Class is used to call Render() on a seperate
15 // thread, running as fast as it can read the data.
16 class ClocklessAudioSinkThread : public base::DelegateSimpleThread::Delegate {
17 public:
18 explicit ClocklessAudioSinkThread(const AudioParameters& params,
19 AudioRendererSink::RenderCallback* callback)
20 : callback_(callback),
21 audio_bus_(AudioBus::Create(params)),
22 stop_event_(new base::WaitableEvent(false, false)) {}
24 void Start() {
25 stop_event_->Reset();
26 thread_.reset(new base::DelegateSimpleThread(this, "ClocklessAudioSink"));
27 thread_->Start();
30 // Generate a signal to stop calling Render().
31 base::TimeDelta Stop() {
32 stop_event_->Signal();
33 thread_->Join();
34 return playback_time_;
37 private:
38 // Call Render() repeatedly, keeping track of the rendering time.
39 void Run() override {
40 base::TimeTicks start;
41 while (!stop_event_->IsSignaled()) {
42 int frames_received = callback_->Render(audio_bus_.get(), 0);
43 if (frames_received <= 0) {
44 // No data received, so let other threads run to provide data.
45 base::PlatformThread::YieldCurrentThread();
46 } else if (start.is_null()) {
47 // First time we processed some audio, so record the starting time.
48 start = base::TimeTicks::Now();
49 } else {
50 // Keep track of the last time data was rendered.
51 playback_time_ = base::TimeTicks::Now() - start;
56 AudioRendererSink::RenderCallback* callback_;
57 scoped_ptr<AudioBus> audio_bus_;
58 scoped_ptr<base::WaitableEvent> stop_event_;
59 scoped_ptr<base::DelegateSimpleThread> thread_;
60 base::TimeDelta playback_time_;
63 ClocklessAudioSink::ClocklessAudioSink()
64 : initialized_(false),
65 playing_(false) {}
67 ClocklessAudioSink::~ClocklessAudioSink() {}
69 void ClocklessAudioSink::Initialize(const AudioParameters& params,
70 RenderCallback* callback) {
71 DCHECK(!initialized_);
72 thread_.reset(new ClocklessAudioSinkThread(params, callback));
73 initialized_ = true;
76 void ClocklessAudioSink::Start() {
77 DCHECK(initialized_);
78 DCHECK(!playing_);
81 void ClocklessAudioSink::Stop() {
82 if (initialized_)
83 Pause();
86 void ClocklessAudioSink::Play() {
87 DCHECK(initialized_);
89 if (playing_)
90 return;
92 playing_ = true;
93 thread_->Start();
96 void ClocklessAudioSink::Pause() {
97 DCHECK(initialized_);
99 if (!playing_)
100 return;
102 playing_ = false;
103 playback_time_ = thread_->Stop();
106 bool ClocklessAudioSink::SetVolume(double volume) {
107 // Audio is always muted.
108 return volume == 0.0;
111 void ClocklessAudioSink::SwitchOutputDevice(
112 const std::string& device_id,
113 const GURL& security_origin,
114 const SwitchOutputDeviceCB& callback) {
115 callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_SUPPORTED);
118 } // namespace media