OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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/virtual_audio_input_stream.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/message_loop.h" | |
11 #include "media/audio/virtual_audio_output_stream.h" | |
12 | |
13 namespace media { | |
14 | |
15 // AudioConverter that can also be used an as InputCallback. This allows this | |
16 // audio conversion from input to output params to be used as an input stream to | |
Alpha Left Google
2012/11/28 01:04:47
This sentence is too long and hard to parse, can y
justinlin
2012/11/28 14:30:31
Done.
| |
17 // other AudioConverters. | |
18 class LoopbackAudioConverter | |
19 : public AudioConverter, | |
20 public AudioConverter::InputCallback { | |
21 public: | |
22 LoopbackAudioConverter(const AudioParameters& input_params, | |
23 const AudioParameters& output_params); | |
24 virtual ~LoopbackAudioConverter() {} | |
25 | |
26 private: | |
27 virtual double ProvideInput( | |
28 AudioBus* audio_bus, base::TimeDelta buffer_delay) OVERRIDE; | |
29 | |
30 DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter); | |
31 }; | |
32 | |
33 VirtualAudioInputStream* VirtualAudioInputStream::MakeStream( | |
34 AudioManagerBase* manager, const AudioParameters& params) { | |
35 return new VirtualAudioInputStream(manager, params); | |
36 } | |
37 | |
38 VirtualAudioInputStream::VirtualAudioInputStream(AudioManagerBase* manager, | |
39 const AudioParameters& params) | |
40 : audio_manager_(manager), | |
41 callback_(NULL), | |
42 buffer_duration_ms_(params.frames_per_buffer() | |
43 * base::Time::kMillisecondsPerSecond | |
44 / params.sample_rate()), | |
45 buffer_(new uint8[params.GetBytesPerBuffer()]), | |
46 params_(params), | |
47 audio_bus_(AudioBus::Create(params_)), | |
48 mixer_(params_, params_, false), | |
49 num_attached_outputs_streams_(0) { | |
50 } | |
51 | |
52 VirtualAudioInputStream::~VirtualAudioInputStream() { | |
53 for (AudioConvertersMap::iterator it = converters_.begin(); | |
54 it != converters_.end(); ++it) { | |
55 delete it->second; | |
56 } | |
57 DCHECK_EQ(0, num_attached_outputs_streams_); | |
58 } | |
59 | |
60 bool VirtualAudioInputStream::Open() { | |
61 memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); | |
62 return true; | |
63 } | |
64 | |
65 void VirtualAudioInputStream::Start(AudioInputCallback* callback) { | |
66 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
67 callback_ = callback; | |
68 on_more_data_cb_.Reset(base::Bind( | |
69 &VirtualAudioInputStream::DoCallback, base::Unretained(this))); | |
70 next_read_time_ = base::Time::Now(); | |
71 audio_manager_->GetMessageLoop()->PostTask( | |
72 FROM_HERE, on_more_data_cb_.callback()); | |
73 } | |
74 | |
75 void VirtualAudioInputStream::Stop() { | |
76 on_more_data_cb_.Cancel(); | |
77 } | |
78 | |
79 void VirtualAudioInputStream::AddOutputStream( | |
80 VirtualAudioOutputStream* stream, const AudioParameters& params) { | |
81 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
82 output_params_.insert(std::make_pair(stream, params)); | |
83 | |
84 LoopbackAudioConverter*& converter = converters_[params]; | |
Alpha Left Google
2012/11/28 01:04:47
*& is strange, can you do converters_.find() inste
justinlin
2012/11/28 14:30:31
Done.
| |
85 if (!converter) { | |
86 converter = new LoopbackAudioConverter(params, params_); | |
87 // Add to main mixer if we just added a new AudioTransform. | |
88 mixer_.AddInput(converter); | |
89 } | |
90 converter->AddInput(stream); | |
91 ++num_attached_outputs_streams_; | |
92 } | |
93 | |
94 void VirtualAudioInputStream::RemoveOutputStream( | |
95 VirtualAudioOutputStream* stream) { | |
96 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
97 DCHECK(output_params_.find(stream) != output_params_.end()); | |
98 const AudioParameters& params = output_params_[stream]; | |
99 | |
100 DCHECK(converters_.find(params) != converters_.end()); | |
101 converters_[params]->RemoveInput(stream); | |
102 // TODO(justinlin): Do we need to delete the AudioConverter and remove it from | |
103 // the mixer when there's no more input streams? | |
104 | |
105 output_params_.erase(stream); | |
106 --num_attached_outputs_streams_; | |
107 } | |
108 | |
109 void VirtualAudioInputStream::DoCallback() { | |
110 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
111 DCHECK(callback_); | |
112 | |
113 mixer_.Convert(audio_bus_.get()); | |
114 audio_bus_->ToInterleaved(params_.frames_per_buffer(), | |
115 params_.bits_per_sample() / 8, | |
116 buffer_.get()); | |
117 | |
118 callback_->OnData(this, buffer_.get(), params_.GetBytesPerBuffer(), | |
119 params_.GetBytesPerBuffer(), 1.0); | |
120 | |
121 next_read_time_ += base::TimeDelta::FromMilliseconds(buffer_duration_ms_); | |
122 base::TimeDelta delay = next_read_time_ - base::Time::Now(); | |
123 // Try to catchup if we fall behind. | |
124 if (delay < base::TimeDelta()) | |
125 delay = base::TimeDelta(); | |
126 | |
127 MessageLoop* message_loop = MessageLoop::current(); | |
128 if (message_loop) | |
Alpha Left Google
2012/11/28 01:04:47
{} since the statement below has 2 lines.
justinlin
2012/11/28 14:30:31
Done.
| |
129 message_loop->PostDelayedTask( | |
130 FROM_HERE, on_more_data_cb_.callback(), delay); | |
131 } | |
132 | |
133 void VirtualAudioInputStream::Close() { | |
134 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
135 if (callback_) { | |
136 DCHECK(on_more_data_cb_.IsCancelled()); | |
137 callback_->OnClose(this); | |
138 callback_ = NULL; | |
139 } | |
140 audio_manager_->ReleaseInputStream(this); | |
141 } | |
142 | |
143 double VirtualAudioInputStream::GetMaxVolume() { | |
144 return 1.0; | |
145 } | |
146 | |
147 void VirtualAudioInputStream::SetVolume(double volume) {} | |
148 | |
149 double VirtualAudioInputStream::GetVolume() { | |
150 return 1.0; | |
151 } | |
152 | |
153 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} | |
154 | |
155 bool VirtualAudioInputStream::GetAutomaticGainControl() { | |
156 return false; | |
157 } | |
158 | |
159 LoopbackAudioConverter::LoopbackAudioConverter( | |
Alpha Left Google
2012/11/28 01:04:47
Implement these methods inline in the definition o
justinlin
2012/11/28 14:30:31
Done.
| |
160 const AudioParameters& input_params, const AudioParameters& output_params) | |
161 : AudioConverter(input_params, output_params, false) { | |
162 } | |
163 | |
164 double LoopbackAudioConverter::ProvideInput( | |
165 AudioBus* audio_bus, base::TimeDelta buffer_delay) { | |
166 Convert(audio_bus); | |
167 return 1.0; | |
168 } | |
169 | |
170 } // namespace media | |
OLD | NEW |