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

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: Replace RunAfterClosed() scheme with 'after close callback' passed to ctor. 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
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_ms_(base::TimeDelta::FromMilliseconds( 57 buffer_duration_(base::TimeDelta::FromMicroseconds(
63 params.frames_per_buffer() * base::Time::kMillisecondsPerSecond / 58 params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
64 static_cast<float>(params.sample_rate()))), 59 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 on_more_data_cb_.Reset(base::Bind(&VirtualAudioInputStream::ReadAudio, 86 on_more_data_cb_.Reset(base::Bind(&VirtualAudioInputStream::ReadAudio,
89 base::Unretained(this))); 87 base::Unretained(this)));
90 audio_manager_->GetMessageLoop()->PostTask(FROM_HERE, 88 message_loop_->PostTask(FROM_HERE, on_more_data_cb_.callback());
91 on_more_data_cb_.callback());
92 } 89 }
93 90
94 void VirtualAudioInputStream::Stop() { 91 void VirtualAudioInputStream::Stop() {
95 DCHECK(message_loop_->BelongsToCurrentThread()); 92 DCHECK(message_loop_->BelongsToCurrentThread());
96 on_more_data_cb_.Cancel(); 93 on_more_data_cb_.Cancel();
97 } 94 }
98 95
99 void VirtualAudioInputStream::AddOutputStream( 96 void VirtualAudioInputStream::AddOutputStream(
100 VirtualAudioOutputStream* stream, const AudioParameters& output_params) { 97 VirtualAudioOutputStream* stream, const AudioParameters& output_params) {
101 DCHECK(message_loop_->BelongsToCurrentThread()); 98 DCHECK(message_loop_->BelongsToCurrentThread());
102 99
103 AudioConvertersMap::iterator converter = converters_.find(output_params); 100 AudioConvertersMap::iterator converter = converters_.find(output_params);
104 if (converter == converters_.end()) { 101 if (converter == converters_.end()) {
105 std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert( 102 std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert(
106 std::make_pair(output_params, 103 std::make_pair(output_params,
107 new LoopbackAudioConverter(output_params, params_))); 104 new LoopbackAudioConverter(output_params, params_)));
108 converter = result.first; 105 converter = result.first;
109 106
110 // Add to main mixer if we just added a new AudioTransform. 107 // Add to main mixer if we just added a new AudioTransform.
111 mixer_.AddInput(converter->second); 108 mixer_.AddInput(converter->second);
112 } 109 }
113 converter->second->AddInput(stream); 110 converter->second->AddInput(stream);
114 ++num_attached_outputs_streams_; 111 ++num_attached_output_streams_;
115 } 112 }
116 113
117 void VirtualAudioInputStream::RemoveOutputStream( 114 void VirtualAudioInputStream::RemoveOutputStream(
118 VirtualAudioOutputStream* stream, const AudioParameters& output_params) { 115 VirtualAudioOutputStream* stream, const AudioParameters& output_params) {
119 DCHECK(message_loop_->BelongsToCurrentThread()); 116 DCHECK(message_loop_->BelongsToCurrentThread());
120 117
121 DCHECK(converters_.find(output_params) != converters_.end()); 118 DCHECK(converters_.find(output_params) != converters_.end());
122 converters_[output_params]->RemoveInput(stream); 119 converters_[output_params]->RemoveInput(stream);
123 120
124 --num_attached_outputs_streams_; 121 --num_attached_output_streams_;
122 DCHECK_LE(0, num_attached_output_streams_);
125 } 123 }
126 124
127 void VirtualAudioInputStream::ReadAudio() { 125 void VirtualAudioInputStream::ReadAudio() {
128 DCHECK(message_loop_->BelongsToCurrentThread()); 126 DCHECK(message_loop_->BelongsToCurrentThread());
129 DCHECK(callback_); 127 DCHECK(callback_);
130 128
131 mixer_.Convert(audio_bus_.get()); 129 mixer_.Convert(audio_bus_.get());
132 audio_bus_->ToInterleaved(params_.frames_per_buffer(), 130 audio_bus_->ToInterleaved(params_.frames_per_buffer(),
133 params_.bits_per_sample() / 8, 131 params_.bits_per_sample() / 8,
134 buffer_.get()); 132 buffer_.get());
135 133
136 callback_->OnData(this, 134 callback_->OnData(this,
137 buffer_.get(), 135 buffer_.get(),
138 params_.GetBytesPerBuffer(), 136 params_.GetBytesPerBuffer(),
139 params_.GetBytesPerBuffer(), 137 params_.GetBytesPerBuffer(),
140 1.0); 138 1.0);
141 139
142 message_loop_->PostDelayedTask(FROM_HERE, 140 message_loop_->PostDelayedTask(FROM_HERE,
143 on_more_data_cb_.callback(), 141 on_more_data_cb_.callback(),
144 buffer_duration_ms_); 142 buffer_duration_);
145 } 143 }
146 144
147 void VirtualAudioInputStream::Close() { 145 void VirtualAudioInputStream::Close() {
148 DCHECK(message_loop_->BelongsToCurrentThread()); 146 DCHECK(message_loop_->BelongsToCurrentThread());
149 if (callback_) { 147 if (callback_) {
150 DCHECK(on_more_data_cb_.IsCancelled()); 148 DCHECK(on_more_data_cb_.IsCancelled());
151 callback_->OnClose(this); 149 callback_->OnClose(this);
152 callback_ = NULL; 150 callback_ = NULL;
153 } 151 }
154 audio_manager_->ReleaseInputStream(this); 152 if (!after_close_cb_.is_null()) {
153 const AfterCloseCallback cb = after_close_cb_;
DaleCurtis 2013/01/17 01:15:52 Are you doing this to prevent Close() from being c
miu 2013/01/17 05:33:55 Two things going on here: 1. The callback can del
154 after_close_cb_.Reset();
155 cb.Run(this);
156 }
155 } 157 }
156 158
157 double VirtualAudioInputStream::GetMaxVolume() { 159 double VirtualAudioInputStream::GetMaxVolume() {
158 return 1.0; 160 return 1.0;
159 } 161 }
160 162
161 void VirtualAudioInputStream::SetVolume(double volume) {} 163 void VirtualAudioInputStream::SetVolume(double volume) {}
162 164
163 double VirtualAudioInputStream::GetVolume() { 165 double VirtualAudioInputStream::GetVolume() {
164 return 1.0; 166 return 1.0;
165 } 167 }
166 168
167 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {} 169 void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {}
168 170
169 bool VirtualAudioInputStream::GetAutomaticGainControl() { 171 bool VirtualAudioInputStream::GetAutomaticGainControl() {
170 return false; 172 return false;
171 } 173 }
172 174
173 } // namespace media 175 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698