Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: media/audio/virtual_audio_input_stream.cc

Issue 11298006: Browser-wide audio mirroring for TabCapture API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review comments, some unit tests, move attach/detach into virtual audio output stream Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698