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"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/threading/simple_thread.h"
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
{
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)) {}
26 thread_
.reset(new base::DelegateSimpleThread(this, "ClocklessAudioSink"));
30 // Generate a signal to stop calling Render().
31 base::TimeDelta
Stop() {
32 stop_event_
->Signal();
34 return playback_time_
;
38 // Call Render() repeatedly, keeping track of the rendering time.
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();
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),
67 ClocklessAudioSink::~ClocklessAudioSink() {}
69 void ClocklessAudioSink::Initialize(const AudioParameters
& params
,
70 RenderCallback
* callback
) {
71 DCHECK(!initialized_
);
72 thread_
.reset(new ClocklessAudioSinkThread(params
, callback
));
76 void ClocklessAudioSink::Start() {
81 void ClocklessAudioSink::Stop() {
86 void ClocklessAudioSink::Play() {
96 void ClocklessAudioSink::Pause() {
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
);