fake_audio_consumer.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 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/fake_audio_consumer.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/logging.h"
10#include "base/message_loop.h"
11#include "base/message_loop_proxy.h"
12#include "media/base/audio_bus.h"
13
14namespace media {
15
16FakeAudioConsumer::FakeAudioConsumer(
17    const scoped_refptr<base::MessageLoopProxy>& message_loop,
18    const AudioParameters& params)
19    : message_loop_(message_loop),
20      audio_bus_(AudioBus::Create(params)),
21      buffer_duration_(base::TimeDelta::FromMicroseconds(
22          params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
23          static_cast<float>(params.sample_rate()))) {
24  audio_bus_->Zero();
25}
26
27FakeAudioConsumer::~FakeAudioConsumer() {
28  DCHECK(read_cb_.is_null());
29}
30
31void FakeAudioConsumer::Start(const ReadCB& read_cb)  {
32  DCHECK(message_loop_->BelongsToCurrentThread());
33  DCHECK(read_cb_.is_null());
34  DCHECK(!read_cb.is_null());
35  read_cb_ = read_cb;
36  next_read_time_ = base::Time::Now();
37  read_task_cb_.Reset(base::Bind(
38      &FakeAudioConsumer::DoRead, base::Unretained(this)));
39  message_loop_->PostTask(FROM_HERE, read_task_cb_.callback());
40}
41
42void FakeAudioConsumer::Stop() {
43  DCHECK(message_loop_->BelongsToCurrentThread());
44  read_cb_.Reset();
45  read_task_cb_.Cancel();
46}
47
48void FakeAudioConsumer::DoRead() {
49  DCHECK(message_loop_->BelongsToCurrentThread());
50  DCHECK(!read_cb_.is_null());
51
52  read_cb_.Run(audio_bus_.get());
53
54  // Need to account for time spent here due to the cost of |read_cb_| as well
55  // as the imprecision of PostDelayedTask().
56  base::Time now = base::Time::Now();
57  base::TimeDelta delay = next_read_time_ + buffer_duration_ - now;
58
59  // If we're behind, find the next nearest ontime interval.
60  if (delay < base::TimeDelta())
61    delay += buffer_duration_ * (-delay / buffer_duration_ + 1);
62  next_read_time_ = now + delay;
63
64  message_loop_->PostDelayedTask(FROM_HERE, read_task_cb_.callback(), delay);
65}
66
67}  // namespace media
68