OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/audio/virtual_audio_input_stream.h" | 5 #ifndef MEDIA_BASE_LOOPBACK_AUDIO_CONVERTER_H_ |
| 6 #define MEDIA_BASE_LOOPBACK_AUDIO_CONVERTER_H_ |
6 | 7 |
7 #include <algorithm> | 8 #include "base/macros.h" |
8 #include <utility> | 9 #include "media/base/audio_converter.h" |
9 | |
10 #include "base/bind.h" | |
11 #include "base/single_thread_task_runner.h" | |
12 #include "media/audio/virtual_audio_output_stream.h" | |
13 | 10 |
14 namespace media { | 11 namespace media { |
15 | 12 |
16 // LoopbackAudioConverter works similar to AudioConverter and converts input | 13 // LoopbackAudioConverter works similar to AudioConverter and converts input |
17 // streams to different audio parameters. Then, the LoopbackAudioConverter can | 14 // streams to different audio parameters. Then, the LoopbackAudioConverter can |
18 // be used as an input to another AudioConverter. This allows us to | 15 // be used as an input to another AudioConverter. This allows us to |
19 // use converted audio from AudioOutputStreams as input to an AudioConverter. | 16 // use converted audio from AudioOutputStreams as input to an AudioConverter. |
20 // For example, this allows converting multiple streams into a common format and | 17 // For example, this allows converting multiple streams into a common format and |
21 // using the converted audio as input to another AudioConverter (i.e. a mixer). | 18 // using the converted audio as input to another AudioConverter (i.e. a mixer). |
22 class LoopbackAudioConverter : public AudioConverter::InputCallback { | 19 class LoopbackAudioConverter : public AudioConverter::InputCallback { |
23 public: | 20 public: |
24 LoopbackAudioConverter(const AudioParameters& input_params, | 21 LoopbackAudioConverter(const AudioParameters& input_params, |
25 const AudioParameters& output_params) | 22 const AudioParameters& output_params, |
26 : audio_converter_(input_params, output_params, false) {} | 23 bool disable_fifo); |
27 | 24 |
28 ~LoopbackAudioConverter() override {} | 25 ~LoopbackAudioConverter() override; |
29 | 26 |
30 void AddInput(AudioConverter::InputCallback* input) { | 27 void AddInput(AudioConverter::InputCallback* input) { |
31 audio_converter_.AddInput(input); | 28 audio_converter_.AddInput(input); |
32 } | 29 } |
33 | 30 |
34 void RemoveInput(AudioConverter::InputCallback* input) { | 31 void RemoveInput(AudioConverter::InputCallback* input) { |
35 audio_converter_.RemoveInput(input); | 32 audio_converter_.RemoveInput(input); |
36 } | 33 } |
37 | 34 |
| 35 bool empty() { return audio_converter_.empty(); } |
| 36 |
38 private: | 37 private: |
39 double ProvideInput(AudioBus* audio_bus, | 38 double ProvideInput(AudioBus* audio_bus, |
40 base::TimeDelta buffer_delay) override { | 39 base::TimeDelta buffer_delay) override; |
41 audio_converter_.ConvertWithDelay(buffer_delay, audio_bus); | |
42 return 1.0; | |
43 } | |
44 | 40 |
45 AudioConverter audio_converter_; | 41 AudioConverter audio_converter_; |
46 | 42 |
47 DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter); | 43 DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter); |
48 }; | 44 }; |
49 | 45 |
50 VirtualAudioInputStream::VirtualAudioInputStream( | 46 } // namespace media |
51 const AudioParameters& params, | |
52 const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner, | |
53 const AfterCloseCallback& after_close_cb) | |
54 : worker_task_runner_(worker_task_runner), | |
55 after_close_cb_(after_close_cb), | |
56 callback_(NULL), | |
57 buffer_(new uint8[params.GetBytesPerBuffer()]), | |
58 params_(params), | |
59 mixer_(params_, params_, false), | |
60 num_attached_output_streams_(0), | |
61 fake_worker_(worker_task_runner_, params_), | |
62 audio_bus_(AudioBus::Create(params)) { | |
63 DCHECK(params_.IsValid()); | |
64 DCHECK(worker_task_runner_.get()); | |
65 | 47 |
66 // VAIS can be constructed on any thread, but will DCHECK that all | 48 #endif // MEDIA_BASE_LOOPBACK_AUDIO_CONVERTER_H_ |
67 // AudioInputStream methods are called from the same thread. | |
68 thread_checker_.DetachFromThread(); | |
69 } | |
70 | |
71 VirtualAudioInputStream::~VirtualAudioInputStream() { | |
72 DCHECK(!callback_); | |
73 | |
74 // Sanity-check: Contract for Add/RemoveOutputStream() requires that all | |
75 // output streams be removed before VirtualAudioInputStream is destroyed. | |
76 DCHECK_EQ(0, num_attached_output_streams_); | |
77 | |
78 for (AudioConvertersMap::iterator it = converters_.begin(); | |
79 it != converters_.end(); ++it) { | |
80 delete it->second; | |
81 } | |
82 } | |
83 | |
84 bool VirtualAudioInputStream::Open() { | |
85 DCHECK(thread_checker_.CalledOnValidThread()); | |
86 memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); | |
87 return true; | |
88 } | |
89 | |
90 void VirtualAudioInputStream::Start(AudioInputCallback* callback) { | |
91 DCHECK(thread_checker_.CalledOnValidThread()); | |
92 callback_ = callback; | |
93 fake_worker_.Start(base::Bind( | |
94 &VirtualAudioInputStream::PumpAudio, base::Unretained(this))); | |
95 } | |
96 | |
97 void VirtualAudioInputStream::Stop() { | |
98 DCHECK(thread_checker_.CalledOnValidThread()); | |
99 fake_worker_.Stop(); | |
100 callback_ = NULL; | |
101 } | |
102 | |
103 void VirtualAudioInputStream::AddOutputStream( | |
104 VirtualAudioOutputStream* stream, const AudioParameters& output_params) { | |
105 DCHECK(thread_checker_.CalledOnValidThread()); | |
106 | |
107 base::AutoLock scoped_lock(converter_network_lock_); | |
108 | |
109 AudioConvertersMap::iterator converter = converters_.find(output_params); | |
110 if (converter == converters_.end()) { | |
111 std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert( | |
112 std::make_pair(output_params, | |
113 new LoopbackAudioConverter(output_params, params_))); | |
114 converter = result.first; | |
115 | |
116 // Add to main mixer if we just added a new AudioTransform. | |
117 mixer_.AddInput(converter->second); | |
118 } | |
119 converter->second->AddInput(stream); | |
120 ++num_attached_output_streams_; | |
121 } | |
122 | |
123 void VirtualAudioInputStream::RemoveOutputStream( | |
124 VirtualAudioOutputStream* stream, const AudioParameters& output_params) { | |
125 DCHECK(thread_checker_.CalledOnValidThread()); | |
126 | |
127 base::AutoLock scoped_lock(converter_network_lock_); | |
128 | |
129 DCHECK(converters_.find(output_params) != converters_.end()); | |
130 converters_[output_params]->RemoveInput(stream); | |
131 | |
132 --num_attached_output_streams_; | |
133 DCHECK_LE(0, num_attached_output_streams_); | |
134 } | |
135 | |
136 void VirtualAudioInputStream::PumpAudio() { | |
137 DCHECK(worker_task_runner_->BelongsToCurrentThread()); | |
138 | |
139 { | |
140 base::AutoLock scoped_lock(converter_network_lock_); | |
141 // Because the audio is being looped-back, the delay until it will be played | |
142 // out is zero. | |
143 mixer_.ConvertWithDelay(base::TimeDelta(), audio_bus_.get()); | |
144 } | |
145 // Because the audio is being looped-back, the delay since since it was | |
146 // recorded is zero. | |
147 callback_->OnData(this, audio_bus_.get(), 0, 1.0); | |
148 } | |
149 | |
150 void VirtualAudioInputStream::Close() { | |
151 DCHECK(thread_checker_.CalledOnValidThread()); | |
152 | |
153 Stop(); // Make sure callback_ is no longer being used. | |
154 | |
155 // If a non-null AfterCloseCallback was provided to the constructor, invoke it | |
156 // here. The callback is moved to a stack-local first since |this| could be | |
157 // destroyed during Run(). | |
158 if (!after_close_cb_.is_null()) { | |
159 const AfterCloseCallback cb = after_close_cb_; | |
160 after_close_cb_.Reset(); | |
161 cb.Run(this); | |
162 } | |
163 } | |
164 | |
165 double VirtualAudioInputStream::GetMaxVolume() { | |
166 return 1.0; | |
167 } | |
168 | |
169 void VirtualAudioInputStream::SetVolume(double volume) {} | |
170 | |
171 double VirtualAudioInputStream::GetVolume() { | |
172 return 1.0; | |
173 } | |
174 | |
175 bool VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) { | |
176 return false; | |
177 } | |
178 | |
179 bool VirtualAudioInputStream::GetAutomaticGainControl() { | |
180 return false; | |
181 } | |
182 | |
183 bool VirtualAudioInputStream::IsMuted() { | |
184 return false; | |
185 } | |
186 | |
187 } // namespace media | |
OLD | NEW |