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 | |
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 callback_delay_(static_cast<float>(params.frames_per_buffer()) | |
miu
2012/11/26 21:14:55
Consider changing this to:
callback_delay_(base
justinlin
2012/11/27 22:26:12
Done. Thanks
| |
43 / params.sample_rate() | |
44 * base::Time::kMillisecondsPerSecond), | |
45 buffer_(new uint8[params.GetBytesPerBuffer()]), | |
46 params_(params), | |
47 audio_bus_(AudioBus::Create(params_)), | |
48 mixer_(params_, params_, false) { | |
49 } | |
50 | |
51 VirtualAudioInputStream::~VirtualAudioInputStream() { | |
52 for (AudioConvertersMap::iterator it = converters_.begin(); | |
53 it != converters_.end(); ++it) { | |
54 delete it->second; | |
55 } | |
56 } | |
57 | |
58 bool VirtualAudioInputStream::Open() { | |
59 memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); | |
60 return true; | |
61 } | |
62 | |
63 void VirtualAudioInputStream::Start(AudioInputCallback* callback) { | |
64 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
65 callback_ = callback; | |
66 on_more_data_cb_.Reset(base::Bind( | |
67 &VirtualAudioInputStream::DoCallback, base::Unretained(this))); | |
68 audio_manager_->GetMessageLoop()->PostTask( | |
69 FROM_HERE, on_more_data_cb_.callback()); | |
70 } | |
71 | |
72 void VirtualAudioInputStream::Stop() { | |
73 on_more_data_cb_.Cancel(); | |
74 } | |
75 | |
76 void VirtualAudioInputStream::AddOutputStream( | |
77 VirtualAudioOutputStream* stream, const AudioParameters& params) { | |
78 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
79 output_params_.insert(std::make_pair(stream, params)); | |
80 | |
81 LoopbackAudioConverter*& converter = converters_[params]; | |
82 if (!converter) { | |
83 converter = new LoopbackAudioConverter(params, params_); | |
84 // Add to main mixer if we just added a new AudioTransform. | |
85 mixer_.AddInput(converter); | |
86 } | |
87 converter->AddInput(stream); | |
88 } | |
89 | |
90 void VirtualAudioInputStream::RemoveOutputStream( | |
91 VirtualAudioOutputStream* stream) { | |
92 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
93 DCHECK(output_params_.find(stream) != output_params_.end()); | |
94 const AudioParameters& params = output_params_[stream]; | |
95 | |
96 DCHECK(converters_.find(params) != converters_.end()); | |
97 converters_[params]->RemoveInput(stream); | |
98 // TODO(justinlin): Do we need to delete the AudioConverter and remove it from | |
99 // the mixer when there's no more input streams? | |
100 | |
101 output_params_.erase(stream); | |
102 } | |
103 | |
104 void VirtualAudioInputStream::DoCallback() { | |
105 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
106 DCHECK(callback_); | |
107 | |
108 mixer_.Convert(audio_bus_.get()); | |
109 audio_bus_->ToInterleaved(params_.frames_per_buffer(), | |
110 params_.bits_per_sample() / 8, | |
111 buffer_.get()); | |
112 | |
113 callback_->OnData(this, buffer_.get(), params_.GetBytesPerBuffer(), | |
114 params_.GetBytesPerBuffer(), 1.0); | |
115 | |
116 // TODO(justinlin): DO_NOT_SUBMIT, try out Yuri's idea for scheduling next | |
miu
2012/11/26 21:14:55
I think you meant to include the timestamp-based s
justinlin
2012/11/27 22:26:12
Done.
| |
117 // time. | |
118 | |
119 MessageLoop::current()->PostDelayedTask( | |
no longer working on chromium
2012/11/27 12:36:15
you should cache the message loop for the polling
justinlin
2012/11/27 22:26:12
Hmm.. is it safe to schedule into that message loo
| |
120 FROM_HERE, on_more_data_cb_.callback(), | |
121 base::TimeDelta::FromMilliseconds(callback_delay_)); | |
122 } | |
123 | |
124 void VirtualAudioInputStream::Close() { | |
125 DCHECK(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); | |
126 if (callback_) { | |
127 DCHECK(on_more_data_cb_.IsCancelled()); | |
128 callback_->OnClose(this); | |
129 callback_ = NULL; | |
130 } | |
131 audio_manager_->ReleaseInputStream(this); | |
132 } | |
133 | |
134 double VirtualAudioInputStream::GetMaxVolume() { | |
135 return 1.0; | |
136 } | |
137 | |
138 void VirtualAudioInputStream::SetVolume(double volume) {} | |
139 | |
140 double VirtualAudioInputStream::GetVolume() { | |
141 return 1.0; | |
142 } | |
143 | |
144 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} | |
145 | |
146 bool VirtualAudioInputStream::GetAutomaticGainControl() { | |
147 return false; | |
148 } | |
149 | |
150 LoopbackAudioConverter::LoopbackAudioConverter( | |
151 const AudioParameters& input_params, const AudioParameters& output_params) | |
152 : AudioConverter(input_params, output_params, false) { | |
153 } | |
154 | |
155 double LoopbackAudioConverter::ProvideInput( | |
156 AudioBus* audio_bus, base::TimeDelta buffer_delay) { | |
157 Convert(audio_bus); | |
158 return 1.0; | |
159 } | |
160 | |
161 } // namespace media | |
OLD | NEW |