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

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

Issue 11416350: Tab Audio Mirroring: WebContentsAudioInputStream is a new implementation which represents the lifet… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased. Created 7 years, 11 months 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
« no previous file with comments | « media/audio/virtual_audio_input_stream.h ('k') | media/audio/virtual_audio_output_stream.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "media/audio/virtual_audio_input_stream.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/message_loop_proxy.h"
12 #include "media/audio/virtual_audio_output_stream.h" 13 #include "media/audio/virtual_audio_output_stream.h"
13 14
14 namespace media { 15 namespace media {
15 16
16 // LoopbackAudioConverter works similar to AudioConverter and converts input 17 // LoopbackAudioConverter works similar to AudioConverter and converts input
17 // streams to different audio parameters. Then, the LoopbackAudioConverter can 18 // streams to different audio parameters. Then, the LoopbackAudioConverter can
18 // be used as an input to another AudioConverter. This allows us to 19 // be used as an input to another AudioConverter. This allows us to
19 // use converted audio from AudioOutputStreams as input to an AudioConverter. 20 // use converted audio from AudioOutputStreams as input to an AudioConverter.
20 // For example, this allows converting multiple streams into a common format and 21 // 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). 22 // using the converted audio as input to another AudioConverter (i.e. a mixer).
(...skipping 18 matching lines...) Expand all
40 base::TimeDelta buffer_delay) OVERRIDE { 41 base::TimeDelta buffer_delay) OVERRIDE {
41 audio_converter_.Convert(audio_bus); 42 audio_converter_.Convert(audio_bus);
42 return 1.0; 43 return 1.0;
43 } 44 }
44 45
45 AudioConverter audio_converter_; 46 AudioConverter audio_converter_;
46 47
47 DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter); 48 DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter);
48 }; 49 };
49 50
50 VirtualAudioInputStream* VirtualAudioInputStream::MakeStream(
51 AudioManagerBase* manager, const AudioParameters& params,
52 base::MessageLoopProxy* message_loop) {
53 return new VirtualAudioInputStream(manager, params, message_loop);
54 }
55
56 VirtualAudioInputStream::VirtualAudioInputStream( 51 VirtualAudioInputStream::VirtualAudioInputStream(
57 AudioManagerBase* manager, const AudioParameters& params, 52 const AudioParameters& params, base::MessageLoopProxy* message_loop,
58 base::MessageLoopProxy* message_loop) 53 const AfterCloseCallback& after_close_cb)
59 : audio_manager_(manager), 54 : message_loop_(message_loop),
60 message_loop_(message_loop), 55 after_close_cb_(after_close_cb),
61 callback_(NULL), 56 callback_(NULL),
62 buffer_duration_(base::TimeDelta::FromMicroseconds( 57 buffer_duration_(base::TimeDelta::FromMicroseconds(
63 params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond / 58 params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
64 static_cast<float>(params.sample_rate()))), 59 static_cast<float>(params.sample_rate()))),
65 buffer_(new uint8[params.GetBytesPerBuffer()]), 60 buffer_(new uint8[params.GetBytesPerBuffer()]),
66 params_(params), 61 params_(params),
67 audio_bus_(AudioBus::Create(params_)), 62 audio_bus_(AudioBus::Create(params_)),
68 mixer_(params_, params_, false), 63 mixer_(params_, params_, false),
69 num_attached_outputs_streams_(0) { 64 num_attached_output_streams_(0) {
65 DCHECK(params_.IsValid());
66 DCHECK(message_loop_);
70 } 67 }
71 68
72 VirtualAudioInputStream::~VirtualAudioInputStream() { 69 VirtualAudioInputStream::~VirtualAudioInputStream() {
73 for (AudioConvertersMap::iterator it = converters_.begin(); 70 for (AudioConvertersMap::iterator it = converters_.begin();
74 it != converters_.end(); ++it) 71 it != converters_.end(); ++it)
75 delete it->second; 72 delete it->second;
76 73
77 DCHECK_EQ(0, num_attached_outputs_streams_); 74 DCHECK_EQ(0, num_attached_output_streams_);
78 } 75 }
79 76
80 bool VirtualAudioInputStream::Open() { 77 bool VirtualAudioInputStream::Open() {
78 DCHECK(message_loop_->BelongsToCurrentThread());
81 memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); 79 memset(buffer_.get(), 0, params_.GetBytesPerBuffer());
82 return true; 80 return true;
83 } 81 }
84 82
85 void VirtualAudioInputStream::Start(AudioInputCallback* callback) { 83 void VirtualAudioInputStream::Start(AudioInputCallback* callback) {
86 DCHECK(message_loop_->BelongsToCurrentThread()); 84 DCHECK(message_loop_->BelongsToCurrentThread());
87 callback_ = callback; 85 callback_ = callback;
88 next_read_time_ = base::Time::Now(); 86 next_read_time_ = base::Time::Now();
89 on_more_data_cb_.Reset(base::Bind(&VirtualAudioInputStream::ReadAudio, 87 on_more_data_cb_.Reset(base::Bind(&VirtualAudioInputStream::ReadAudio,
90 base::Unretained(this))); 88 base::Unretained(this)));
91 audio_manager_->GetMessageLoop()->PostTask(FROM_HERE, 89 message_loop_->PostTask(FROM_HERE, on_more_data_cb_.callback());
92 on_more_data_cb_.callback());
93 } 90 }
94 91
95 void VirtualAudioInputStream::Stop() { 92 void VirtualAudioInputStream::Stop() {
96 DCHECK(message_loop_->BelongsToCurrentThread()); 93 DCHECK(message_loop_->BelongsToCurrentThread());
97 on_more_data_cb_.Cancel(); 94 on_more_data_cb_.Cancel();
98 } 95 }
99 96
100 void VirtualAudioInputStream::AddOutputStream( 97 void VirtualAudioInputStream::AddOutputStream(
101 VirtualAudioOutputStream* stream, const AudioParameters& output_params) { 98 VirtualAudioOutputStream* stream, const AudioParameters& output_params) {
102 DCHECK(message_loop_->BelongsToCurrentThread()); 99 DCHECK(message_loop_->BelongsToCurrentThread());
103 100
104 AudioConvertersMap::iterator converter = converters_.find(output_params); 101 AudioConvertersMap::iterator converter = converters_.find(output_params);
105 if (converter == converters_.end()) { 102 if (converter == converters_.end()) {
106 std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert( 103 std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert(
107 std::make_pair(output_params, 104 std::make_pair(output_params,
108 new LoopbackAudioConverter(output_params, params_))); 105 new LoopbackAudioConverter(output_params, params_)));
109 converter = result.first; 106 converter = result.first;
110 107
111 // Add to main mixer if we just added a new AudioTransform. 108 // Add to main mixer if we just added a new AudioTransform.
112 mixer_.AddInput(converter->second); 109 mixer_.AddInput(converter->second);
113 } 110 }
114 converter->second->AddInput(stream); 111 converter->second->AddInput(stream);
115 ++num_attached_outputs_streams_; 112 ++num_attached_output_streams_;
116 } 113 }
117 114
118 void VirtualAudioInputStream::RemoveOutputStream( 115 void VirtualAudioInputStream::RemoveOutputStream(
119 VirtualAudioOutputStream* stream, const AudioParameters& output_params) { 116 VirtualAudioOutputStream* stream, const AudioParameters& output_params) {
120 DCHECK(message_loop_->BelongsToCurrentThread()); 117 DCHECK(message_loop_->BelongsToCurrentThread());
121 118
122 DCHECK(converters_.find(output_params) != converters_.end()); 119 DCHECK(converters_.find(output_params) != converters_.end());
123 converters_[output_params]->RemoveInput(stream); 120 converters_[output_params]->RemoveInput(stream);
124 121
125 --num_attached_outputs_streams_; 122 --num_attached_output_streams_;
123 DCHECK_LE(0, num_attached_output_streams_);
126 } 124 }
127 125
128 void VirtualAudioInputStream::ReadAudio() { 126 void VirtualAudioInputStream::ReadAudio() {
129 DCHECK(message_loop_->BelongsToCurrentThread()); 127 DCHECK(message_loop_->BelongsToCurrentThread());
130 DCHECK(callback_); 128 DCHECK(callback_);
131 129
132 mixer_.Convert(audio_bus_.get()); 130 mixer_.Convert(audio_bus_.get());
133 audio_bus_->ToInterleaved(params_.frames_per_buffer(), 131 audio_bus_->ToInterleaved(params_.frames_per_buffer(),
134 params_.bits_per_sample() / 8, 132 params_.bits_per_sample() / 8,
135 buffer_.get()); 133 buffer_.get());
(...skipping 16 matching lines...) Expand all
152 next_read_time_ = now; 150 next_read_time_ = now;
153 } 151 }
154 152
155 message_loop_->PostDelayedTask(FROM_HERE, 153 message_loop_->PostDelayedTask(FROM_HERE,
156 on_more_data_cb_.callback(), 154 on_more_data_cb_.callback(),
157 delay); 155 delay);
158 } 156 }
159 157
160 void VirtualAudioInputStream::Close() { 158 void VirtualAudioInputStream::Close() {
161 DCHECK(message_loop_->BelongsToCurrentThread()); 159 DCHECK(message_loop_->BelongsToCurrentThread());
160
162 if (callback_) { 161 if (callback_) {
163 DCHECK(on_more_data_cb_.IsCancelled()); 162 DCHECK(on_more_data_cb_.IsCancelled());
164 callback_->OnClose(this); 163 callback_->OnClose(this);
165 callback_ = NULL; 164 callback_ = NULL;
166 } 165 }
167 audio_manager_->ReleaseInputStream(this); 166
167 // If a non-null AfterCloseCallback was provided to the constructor, invoke it
168 // here. The callback is moved to a stack-local first since |this| could be
169 // destroyed during Run().
170 if (!after_close_cb_.is_null()) {
171 const AfterCloseCallback cb = after_close_cb_;
172 after_close_cb_.Reset();
173 cb.Run(this);
174 }
168 } 175 }
169 176
170 double VirtualAudioInputStream::GetMaxVolume() { 177 double VirtualAudioInputStream::GetMaxVolume() {
171 return 1.0; 178 return 1.0;
172 } 179 }
173 180
174 void VirtualAudioInputStream::SetVolume(double volume) {} 181 void VirtualAudioInputStream::SetVolume(double volume) {}
175 182
176 double VirtualAudioInputStream::GetVolume() { 183 double VirtualAudioInputStream::GetVolume() {
177 return 1.0; 184 return 1.0;
178 } 185 }
179 186
180 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} 187 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {}
181 188
182 bool VirtualAudioInputStream::GetAutomaticGainControl() { 189 bool VirtualAudioInputStream::GetAutomaticGainControl() {
183 return false; 190 return false;
184 } 191 }
185 192
186 } // namespace media 193 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/virtual_audio_input_stream.h ('k') | media/audio/virtual_audio_output_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698