Roll ffmpeg 2fa2c9a:202208
[chromium-blink-merge.git] / media / audio / clockless_audio_sink.cc
blob88e25b8af8db6c70912b11dca429d54f20c21e9e
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"
8 #include "base/time/time.h"
9 #include "media/base/audio_renderer_sink.h"
11 namespace media {
13 // Internal to ClocklessAudioSink. Class is used to call Render() on a seperate
14 // thread, running as fast as it can read the data.
15 class ClocklessAudioSinkThread : public base::DelegateSimpleThread::Delegate {
16 public:
17 explicit ClocklessAudioSinkThread(const AudioParameters& params,
18 AudioRendererSink::RenderCallback* callback)
19 : callback_(callback),
20 audio_bus_(AudioBus::Create(params)),
21 stop_event_(new base::WaitableEvent(false, false)) {}
23 void Start() {
24 stop_event_->Reset();
25 thread_.reset(new base::DelegateSimpleThread(this, "ClocklessAudioSink"));
26 thread_->Start();
29 // Generate a signal to stop calling Render().
30 base::TimeDelta Stop() {
31 stop_event_->Signal();
32 thread_->Join();
33 return playback_time_;
36 private:
37 // Call Render() repeatedly, keeping track of the rendering time.
38 void Run() override {
39 base::TimeTicks start;
40 while (!stop_event_->IsSignaled()) {
41 int frames_received = callback_->Render(audio_bus_.get(), 0);
42 if (frames_received <= 0) {
43 // No data received, so let other threads run to provide data.
44 base::PlatformThread::YieldCurrentThread();
45 } else if (start.is_null()) {
46 // First time we processed some audio, so record the starting time.
47 start = base::TimeTicks::HighResNow();
48 } else {
49 // Keep track of the last time data was rendered.
50 playback_time_ = base::TimeTicks::HighResNow() - start;
55 AudioRendererSink::RenderCallback* callback_;
56 scoped_ptr<AudioBus> audio_bus_;
57 scoped_ptr<base::WaitableEvent> stop_event_;
58 scoped_ptr<base::DelegateSimpleThread> thread_;
59 base::TimeDelta playback_time_;
62 ClocklessAudioSink::ClocklessAudioSink()
63 : initialized_(false),
64 playing_(false) {}
66 ClocklessAudioSink::~ClocklessAudioSink() {}
68 void ClocklessAudioSink::Initialize(const AudioParameters& params,
69 RenderCallback* callback) {
70 DCHECK(!initialized_);
71 thread_.reset(new ClocklessAudioSinkThread(params, callback));
72 initialized_ = true;
75 void ClocklessAudioSink::Start() {
76 DCHECK(initialized_);
77 DCHECK(!playing_);
80 void ClocklessAudioSink::Stop() {
81 if (initialized_)
82 Pause();
85 void ClocklessAudioSink::Play() {
86 DCHECK(initialized_);
88 if (playing_)
89 return;
91 playing_ = true;
92 thread_->Start();
95 void ClocklessAudioSink::Pause() {
96 DCHECK(initialized_);
98 if (!playing_)
99 return;
101 playing_ = false;
102 playback_time_ = thread_->Stop();
105 bool ClocklessAudioSink::SetVolume(double volume) {
106 // Audio is always muted.
107 return volume == 0.0;
110 } // namespace media