clockless_audio_sink.cc revision 3551c9c881056c480085172ff9840cab31610854
13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file.
43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/audio/clockless_audio_sink.h"
63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/threading/simple_thread.h"
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/time/time.h"
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "media/base/audio_renderer_sink.h"
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace media {
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Internal to ClocklessAudioSink. Class is used to call Render() on a seperate
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// thread, running as fast as it can read the data.
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class ClocklessAudioSinkThread : public base::DelegateSimpleThread::Delegate {
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public:
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  explicit ClocklessAudioSinkThread(const AudioParameters& params,
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    AudioRendererSink::RenderCallback* callback)
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      : callback_(callback),
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        audio_bus_(AudioBus::Create(params)),
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        stop_event_(new base::WaitableEvent(false, false)) {}
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void Start() {
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    stop_event_->Reset();
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    thread_.reset(new base::DelegateSimpleThread(this, "ClocklessAudioSink"));
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    thread_->Start();
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Generate a signal to stop calling Render().
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::TimeDelta Stop() {
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    stop_event_->Signal();
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    thread_->Join();
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return playback_time_;
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private:
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   // Call Render() repeatedly, keeping track of the rendering time.
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   virtual void Run() OVERRIDE {
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)     base::TimeTicks start;
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)     while (!stop_event_->IsSignaled()) {
413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       int frames_received = callback_->Render(audio_bus_.get(), 0);
423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       if (frames_received <= 0) {
433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         // No data received, so let other threads run to provide data.
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         base::PlatformThread::YieldCurrentThread();
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       } else if (start.is_null()) {
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         // First time we processed some audio, so record the starting time.
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         start = base::TimeTicks::HighResNow();
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       } else {
493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         // Keep track of the last time data was rendered.
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)         playback_time_ = base::TimeTicks::HighResNow() - start;
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       }
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)     }
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   }
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AudioRendererSink::RenderCallback* callback_;
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<AudioBus> audio_bus_;
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<base::WaitableEvent> stop_event_;
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<base::DelegateSimpleThread> thread_;
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::TimeDelta playback_time_;
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)ClocklessAudioSink::ClocklessAudioSink()
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : initialized_(false),
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      playing_(false) {}
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)ClocklessAudioSink::~ClocklessAudioSink() {}
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ClocklessAudioSink::Initialize(const AudioParameters& params,
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                    RenderCallback* callback) {
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!initialized_);
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  thread_.reset(new ClocklessAudioSinkThread(params, callback));
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  initialized_ = true;
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ClocklessAudioSink::Start() {
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!playing_);
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ClocklessAudioSink::Stop() {
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(initialized_);
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!playing_)
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  playback_time_ = thread_->Stop();
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ClocklessAudioSink::Play() {
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(initialized_);
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (playing_)
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  playing_ = true;
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  thread_->Start();
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ClocklessAudioSink::Pause() {
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Stop();
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool ClocklessAudioSink::SetVolume(double volume) {
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Audio is always muted.
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return volume == 0.0;
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace media
108