Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / media / audio / clockless_audio_sink.cc
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.
4
5 #include "media/audio/clockless_audio_sink.h"
6
7 #include "base/threading/simple_thread.h"
8 #include "base/time/time.h"
9 #include "media/base/audio_renderer_sink.h"
10
11 namespace media {
12
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)) {}
22
23   void Start() {
24     stop_event_->Reset();
25     thread_.reset(new base::DelegateSimpleThread(this, "ClocklessAudioSink"));
26     thread_->Start();
27   }
28
29   // Generate a signal to stop calling Render().
30   base::TimeDelta Stop() {
31     stop_event_->Signal();
32     thread_->Join();
33     return playback_time_;
34   }
35
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;
51        }
52      }
53    }
54
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_;
60 };
61
62 ClocklessAudioSink::ClocklessAudioSink()
63     : initialized_(false),
64       playing_(false) {}
65
66 ClocklessAudioSink::~ClocklessAudioSink() {}
67
68 void ClocklessAudioSink::Initialize(const AudioParameters& params,
69                                     RenderCallback* callback) {
70   DCHECK(!initialized_);
71   thread_.reset(new ClocklessAudioSinkThread(params, callback));
72   initialized_ = true;
73 }
74
75 void ClocklessAudioSink::Start() {
76   DCHECK(initialized_);
77   DCHECK(!playing_);
78 }
79
80 void ClocklessAudioSink::Stop() {
81   if (initialized_)
82     Pause();
83 }
84
85 void ClocklessAudioSink::Play() {
86   DCHECK(initialized_);
87
88   if (playing_)
89     return;
90
91   playing_ = true;
92   thread_->Start();
93 }
94
95 void ClocklessAudioSink::Pause() {
96   DCHECK(initialized_);
97
98   if (!playing_)
99     return;
100
101   playing_ = false;
102   playback_time_ = thread_->Stop();
103 }
104
105 bool ClocklessAudioSink::SetVolume(double volume) {
106   // Audio is always muted.
107   return volume == 0.0;
108 }
109
110 }  // namespace media