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

Side by Side Diff: content/renderer/media/media_stream_audio_processor.cc

Issue 594233002: Strip away the keyboard mic channel if no audio processing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@change_stream_layout_to_kmic
Patch Set: Rebase Created 6 years, 2 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
« no previous file with comments | « no previous file | content/renderer/media/media_stream_audio_processor_unittest.cc » ('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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/renderer/media/media_stream_audio_processor.h" 5 #include "content/renderer/media/media_stream_audio_processor.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #if defined(OS_MACOSX) 9 #if defined(OS_MACOSX)
10 #include "base/metrics/field_trial.h" 10 #include "base/metrics/field_trial.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 case media::CHANNEL_LAYOUT_STEREO: 42 case media::CHANNEL_LAYOUT_STEREO:
43 return AudioProcessing::kStereo; 43 return AudioProcessing::kStereo;
44 case media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC: 44 case media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC:
45 return AudioProcessing::kStereoAndKeyboard; 45 return AudioProcessing::kStereoAndKeyboard;
46 default: 46 default:
47 NOTREACHED() << "Layout not supported: " << media_layout; 47 NOTREACHED() << "Layout not supported: " << media_layout;
48 return AudioProcessing::kMono; 48 return AudioProcessing::kMono;
49 } 49 }
50 } 50 }
51 51
52 // This is only used for playout data where only max two channels is supported.
52 AudioProcessing::ChannelLayout ChannelsToLayout(int num_channels) { 53 AudioProcessing::ChannelLayout ChannelsToLayout(int num_channels) {
53 switch (num_channels) { 54 switch (num_channels) {
54 case 1: 55 case 1:
55 return AudioProcessing::kMono; 56 return AudioProcessing::kMono;
56 case 2: 57 case 2:
57 return AudioProcessing::kStereo; 58 return AudioProcessing::kStereo;
58 default: 59 default:
59 NOTREACHED() << "Channels not supported: " << num_channels; 60 NOTREACHED() << "Channels not supported: " << num_channels;
60 return AudioProcessing::kMono; 61 return AudioProcessing::kMono;
61 } 62 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 } 107 }
107 108
108 private: 109 private:
109 base::ThreadChecker thread_checker_; 110 base::ThreadChecker thread_checker_;
110 scoped_ptr<media::AudioBus> bus_; 111 scoped_ptr<media::AudioBus> bus_;
111 scoped_ptr<float*[]> channel_ptrs_; 112 scoped_ptr<float*[]> channel_ptrs_;
112 }; 113 };
113 114
114 // Wraps AudioFifo to provide a cleaner interface to MediaStreamAudioProcessor. 115 // Wraps AudioFifo to provide a cleaner interface to MediaStreamAudioProcessor.
115 // It avoids the FIFO when the source and destination frames match. All methods 116 // It avoids the FIFO when the source and destination frames match. All methods
116 // are called on one of the capture or render audio threads exclusively. 117 // are called on one of the capture or render audio threads exclusively. If
118 // |source_channels| is larger than |destination_channels|, only the first
119 // |destination_channels| are kept from the source.
117 class MediaStreamAudioFifo { 120 class MediaStreamAudioFifo {
118 public: 121 public:
119 MediaStreamAudioFifo(int channels, int source_frames, 122 MediaStreamAudioFifo(int source_channels,
123 int destination_channels,
124 int source_frames,
120 int destination_frames) 125 int destination_frames)
121 : source_frames_(source_frames), 126 : source_channels_(source_channels),
122 destination_(new MediaStreamAudioBus(channels, destination_frames)), 127 source_frames_(source_frames),
128 destination_(
129 new MediaStreamAudioBus(destination_channels, destination_frames)),
123 data_available_(false) { 130 data_available_(false) {
131 DCHECK_GE(source_channels, destination_channels);
132
133 if (source_channels > destination_channels) {
134 audio_source_intermediate_ =
135 media::AudioBus::CreateWrapper(destination_channels);
136 }
137
124 if (source_frames != destination_frames) { 138 if (source_frames != destination_frames) {
125 // Since we require every Push to be followed by as many Consumes as 139 // Since we require every Push to be followed by as many Consumes as
126 // possible, twice the larger of the two is a (probably) loose upper bound 140 // possible, twice the larger of the two is a (probably) loose upper bound
127 // on the FIFO size. 141 // on the FIFO size.
128 const int fifo_frames = 2 * std::max(source_frames, destination_frames); 142 const int fifo_frames = 2 * std::max(source_frames, destination_frames);
129 fifo_.reset(new media::AudioFifo(channels, fifo_frames)); 143 fifo_.reset(new media::AudioFifo(destination_channels, fifo_frames));
130 } 144 }
131 145
132 // May be created in the main render thread and used in the audio threads. 146 // May be created in the main render thread and used in the audio threads.
133 thread_checker_.DetachFromThread(); 147 thread_checker_.DetachFromThread();
134 } 148 }
135 149
136 void Push(const media::AudioBus* source) { 150 void Push(const media::AudioBus* source) {
137 DCHECK(thread_checker_.CalledOnValidThread()); 151 DCHECK(thread_checker_.CalledOnValidThread());
138 DCHECK_EQ(source->channels(), destination_->bus()->channels()); 152 DCHECK_EQ(source->channels(), source_channels_);
139 DCHECK_EQ(source->frames(), source_frames_); 153 DCHECK_EQ(source->frames(), source_frames_);
140 154
155 const media::AudioBus* source_to_push = source;
156
157 if (audio_source_intermediate_) {
158 for (int i = 0; i < destination_->bus()->channels(); ++i) {
159 audio_source_intermediate_->SetChannelData(
160 i,
161 const_cast<float*>(source->channel(i)));
162 }
163 audio_source_intermediate_->set_frames(source->frames());
164 source_to_push = audio_source_intermediate_.get();
165 }
166
141 if (fifo_) { 167 if (fifo_) {
142 fifo_->Push(source); 168 fifo_->Push(source_to_push);
143 } else { 169 } else {
144 source->CopyTo(destination_->bus()); 170 source_to_push->CopyTo(destination_->bus());
145 data_available_ = true; 171 data_available_ = true;
146 } 172 }
147 } 173 }
148 174
149 // Returns true if there are destination_frames() of data available to be 175 // Returns true if there are destination_frames() of data available to be
150 // consumed, and otherwise false. 176 // consumed, and otherwise false.
151 bool Consume(MediaStreamAudioBus** destination) { 177 bool Consume(MediaStreamAudioBus** destination) {
152 DCHECK(thread_checker_.CalledOnValidThread()); 178 DCHECK(thread_checker_.CalledOnValidThread());
153 179
154 if (fifo_) { 180 if (fifo_) {
155 if (fifo_->frames() < destination_->bus()->frames()) 181 if (fifo_->frames() < destination_->bus()->frames())
156 return false; 182 return false;
157 183
158 fifo_->Consume(destination_->bus(), 0, destination_->bus()->frames()); 184 fifo_->Consume(destination_->bus(), 0, destination_->bus()->frames());
159 } else { 185 } else {
160 if (!data_available_) 186 if (!data_available_)
161 return false; 187 return false;
162 188
163 // The data was already copied to |destination_| in this case. 189 // The data was already copied to |destination_| in this case.
164 data_available_ = false; 190 data_available_ = false;
165 } 191 }
166 192
167 *destination = destination_.get(); 193 *destination = destination_.get();
168 return true; 194 return true;
169 } 195 }
170 196
171 private: 197 private:
172 base::ThreadChecker thread_checker_; 198 base::ThreadChecker thread_checker_;
199 const int source_channels_; // For a DCHECK.
173 const int source_frames_; // For a DCHECK. 200 const int source_frames_; // For a DCHECK.
201 scoped_ptr<media::AudioBus> audio_source_intermediate_;
174 scoped_ptr<MediaStreamAudioBus> destination_; 202 scoped_ptr<MediaStreamAudioBus> destination_;
175 scoped_ptr<media::AudioFifo> fifo_; 203 scoped_ptr<media::AudioFifo> fifo_;
176 // Only used when the FIFO is disabled; 204 // Only used when the FIFO is disabled;
177 bool data_available_; 205 bool data_available_;
178 }; 206 };
179 207
180 bool MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() { 208 bool MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() {
181 return !CommandLine::ForCurrentProcess()->HasSwitch( 209 return !CommandLine::ForCurrentProcess()->HasSwitch(
182 switches::kDisableAudioTrackProcessing); 210 switches::kDisableAudioTrackProcessing);
183 } 211 }
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 DCHECK(input_format.IsValid()); 486 DCHECK(input_format.IsValid());
459 input_format_ = input_format; 487 input_format_ = input_format;
460 488
461 // TODO(ajm): For now, we assume fixed parameters for the output when audio 489 // TODO(ajm): For now, we assume fixed parameters for the output when audio
462 // processing is enabled, to match the previous behavior. We should either 490 // processing is enabled, to match the previous behavior. We should either
463 // use the input parameters (in which case, audio processing will convert 491 // use the input parameters (in which case, audio processing will convert
464 // at output) or ideally, have a backchannel from the sink to know what 492 // at output) or ideally, have a backchannel from the sink to know what
465 // format it would prefer. 493 // format it would prefer.
466 const int output_sample_rate = audio_processing_ ? 494 const int output_sample_rate = audio_processing_ ?
467 kAudioProcessingSampleRate : input_format.sample_rate(); 495 kAudioProcessingSampleRate : input_format.sample_rate();
468 const media::ChannelLayout output_channel_layout = audio_processing_ ? 496 media::ChannelLayout output_channel_layout = audio_processing_ ?
469 media::GuessChannelLayout(kAudioProcessingNumberOfChannels) : 497 media::GuessChannelLayout(kAudioProcessingNumberOfChannels) :
470 input_format.channel_layout(); 498 input_format.channel_layout();
471 499
500 // The output channels from the fifo is normally the same as input.
501 int fifo_output_channels = input_format.channels();
502
503 // Special case for if we have a keyboard mic channel on the input and no
504 // audio processing is used. We will then have the fifo strip away that
505 // channel. So we use stereo as output layout, and also change the output
506 // channels for the fifo.
507 if (input_format.channel_layout() ==
508 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC &&
509 !audio_processing_) {
510 output_channel_layout = media::CHANNEL_LAYOUT_STEREO;
511 fifo_output_channels = ChannelLayoutToChannelCount(output_channel_layout);
512 }
513
472 // webrtc::AudioProcessing requires a 10 ms chunk size. We use this native 514 // webrtc::AudioProcessing requires a 10 ms chunk size. We use this native
473 // size when processing is enabled. When disabled we use the same size as 515 // size when processing is enabled. When disabled we use the same size as
474 // the source if less than 10 ms. 516 // the source if less than 10 ms.
475 // 517 //
476 // TODO(ajm): This conditional buffer size appears to be assuming knowledge of 518 // TODO(ajm): This conditional buffer size appears to be assuming knowledge of
477 // the sink based on the source parameters. PeerConnection sinks seem to want 519 // the sink based on the source parameters. PeerConnection sinks seem to want
478 // 10 ms chunks regardless, while WebAudio sinks want less, and we're assuming 520 // 10 ms chunks regardless, while WebAudio sinks want less, and we're assuming
479 // we can identify WebAudio sinks by the input chunk size. Less fragile would 521 // we can identify WebAudio sinks by the input chunk size. Less fragile would
480 // be to have the sink actually tell us how much it wants (as in the above 522 // be to have the sink actually tell us how much it wants (as in the above
481 // TODO). 523 // TODO).
482 int processing_frames = input_format.sample_rate() / 100; 524 int processing_frames = input_format.sample_rate() / 100;
483 int output_frames = output_sample_rate / 100; 525 int output_frames = output_sample_rate / 100;
484 if (!audio_processing_ && input_format.frames_per_buffer() < output_frames) { 526 if (!audio_processing_ && input_format.frames_per_buffer() < output_frames) {
485 processing_frames = input_format.frames_per_buffer(); 527 processing_frames = input_format.frames_per_buffer();
486 output_frames = processing_frames; 528 output_frames = processing_frames;
487 } 529 }
488 530
489 output_format_ = media::AudioParameters( 531 output_format_ = media::AudioParameters(
490 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 532 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
491 output_channel_layout, 533 output_channel_layout,
492 output_sample_rate, 534 output_sample_rate,
493 16, 535 16,
494 output_frames); 536 output_frames);
495 537
496 capture_fifo_.reset( 538 capture_fifo_.reset(
497 new MediaStreamAudioFifo(input_format.channels(), 539 new MediaStreamAudioFifo(input_format.channels(),
540 fifo_output_channels,
498 input_format.frames_per_buffer(), 541 input_format.frames_per_buffer(),
499 processing_frames)); 542 processing_frames));
500 543
501 if (audio_processing_) { 544 if (audio_processing_) {
502 output_bus_.reset(new MediaStreamAudioBus(output_format_.channels(), 545 output_bus_.reset(new MediaStreamAudioBus(output_format_.channels(),
503 output_frames)); 546 output_frames));
504 } 547 }
505 output_data_.reset(new int16[output_format_.GetBytesPerBuffer() / 548 output_data_.reset(new int16[output_format_.GetBytesPerBuffer() /
506 sizeof(int16)]); 549 sizeof(int16)]);
507 } 550 }
(...skipping 12 matching lines...) Expand all
520 render_format_ = media::AudioParameters( 563 render_format_ = media::AudioParameters(
521 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 564 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
522 media::GuessChannelLayout(number_of_channels), 565 media::GuessChannelLayout(number_of_channels),
523 sample_rate, 566 sample_rate,
524 16, 567 16,
525 frames_per_buffer); 568 frames_per_buffer);
526 569
527 const int analysis_frames = sample_rate / 100; // 10 ms chunks. 570 const int analysis_frames = sample_rate / 100; // 10 ms chunks.
528 render_fifo_.reset( 571 render_fifo_.reset(
529 new MediaStreamAudioFifo(number_of_channels, 572 new MediaStreamAudioFifo(number_of_channels,
573 number_of_channels,
530 frames_per_buffer, 574 frames_per_buffer,
531 analysis_frames)); 575 analysis_frames));
532 } 576 }
533 577
534 int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs, 578 int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
535 int process_frames, 579 int process_frames,
536 base::TimeDelta capture_delay, 580 base::TimeDelta capture_delay,
537 int volume, 581 int volume,
538 bool key_pressed, 582 bool key_pressed,
539 float* const* output_ptrs) { 583 float* const* output_ptrs) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 vad->stream_has_voice()); 623 vad->stream_has_voice());
580 base::subtle::Release_Store(&typing_detected_, detected); 624 base::subtle::Release_Store(&typing_detected_, detected);
581 } 625 }
582 626
583 // Return 0 if the volume hasn't been changed, and otherwise the new volume. 627 // Return 0 if the volume hasn't been changed, and otherwise the new volume.
584 return (agc->stream_analog_level() == volume) ? 628 return (agc->stream_analog_level() == volume) ?
585 0 : agc->stream_analog_level(); 629 0 : agc->stream_analog_level();
586 } 630 }
587 631
588 } // namespace content 632 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/renderer/media/media_stream_audio_processor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698