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

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

Issue 334743006: Support multiple files for AEC dump. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Code review (sky). Created 6 years, 6 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 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/webrtc_audio_device_impl.h" 5 #include "content/renderer/media/webrtc_audio_device_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "base/win/windows_version.h" 10 #include "base/win/windows_version.h"
11 #include "content/renderer/media/media_stream_audio_processor.h" 11 #include "content/renderer/media/media_stream_audio_processor.h"
12 #include "content/renderer/media/webrtc_audio_capturer.h" 12 #include "content/renderer/media/webrtc_audio_capturer.h"
13 #include "content/renderer/media/webrtc_audio_renderer.h" 13 #include "content/renderer/media/webrtc_audio_renderer.h"
14 #include "content/renderer/render_thread_impl.h" 14 #include "content/renderer/render_thread_impl.h"
15 #include "media/audio/audio_parameters.h" 15 #include "media/audio/audio_parameters.h"
16 #include "media/audio/sample_rates.h" 16 #include "media/audio/sample_rates.h"
17 17
18 using media::AudioParameters; 18 using media::AudioParameters;
19 using media::ChannelLayout; 19 using media::ChannelLayout;
20 20
21 namespace {
22 int g_capturer_id_counter = 0;
no longer working on chromium 2014/06/16 18:30:55 why? can't it be a member instead?
Henrik Grunell 2014/06/17 20:21:41 Right, it can. Done.
23 }
24
21 namespace content { 25 namespace content {
22 26
23 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() 27 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
24 : ref_count_(0), 28 : ref_count_(0),
25 audio_transport_callback_(NULL), 29 audio_transport_callback_(NULL),
26 input_delay_ms_(0), 30 input_delay_ms_(0),
27 output_delay_ms_(0), 31 output_delay_ms_(0),
28 initialized_(false), 32 initialized_(false),
29 playing_(false), 33 playing_(false),
30 recording_(false), 34 recording_(false),
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 DCHECK(thread_checker_.CalledOnValidThread()); 224 DCHECK(thread_checker_.CalledOnValidThread());
221 DCHECK_EQ(audio_transport_callback_ == NULL, audio_callback != NULL); 225 DCHECK_EQ(audio_transport_callback_ == NULL, audio_callback != NULL);
222 audio_transport_callback_ = audio_callback; 226 audio_transport_callback_ = audio_callback;
223 return 0; 227 return 0;
224 } 228 }
225 229
226 int32_t WebRtcAudioDeviceImpl::Init() { 230 int32_t WebRtcAudioDeviceImpl::Init() {
227 DVLOG(1) << "WebRtcAudioDeviceImpl::Init()"; 231 DVLOG(1) << "WebRtcAudioDeviceImpl::Init()";
228 DCHECK(thread_checker_.CalledOnValidThread()); 232 DCHECK(thread_checker_.CalledOnValidThread());
229 233
234 if (MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) {
no longer working on chromium 2014/06/16 18:30:55 WebRtcAudioDeviceImpl is not the right place for a
Henrik Grunell 2014/06/17 20:21:41 After discussing offline I understand that this is
235 aec_dump_message_filter_ = AecDumpMessageFilter::Get();
236 DCHECK(aec_dump_message_filter_);
no longer working on chromium 2014/06/16 18:30:55 you don't need this DCHECK(), the following line w
Henrik Grunell 2014/06/17 20:21:41 Done.
237 aec_dump_message_filter_->SetObserver(this);
238 for (CapturerMap::const_iterator iter = capturers_.begin();
239 iter != capturers_.end(); ++iter) {
240 RegisterAecDumpForId(iter->first);
no longer working on chromium 2014/06/16 18:30:55 indentation.
Henrik Grunell 2014/06/17 20:21:41 Done.
241 }
242 }
243
230 // We need to return a success to continue the initialization of WebRtc VoE 244 // We need to return a success to continue the initialization of WebRtc VoE
231 // because failure on the capturer_ initialization should not prevent WebRTC 245 // because failure on the capturer_ initialization should not prevent WebRTC
232 // from working. See issue http://crbug.com/144421 for details. 246 // from working. See issue http://crbug.com/144421 for details.
233 initialized_ = true; 247 initialized_ = true;
234 248
235 return 0; 249 return 0;
236 } 250 }
237 251
238 int32_t WebRtcAudioDeviceImpl::Terminate() { 252 int32_t WebRtcAudioDeviceImpl::Terminate() {
239 DVLOG(1) << "WebRtcAudioDeviceImpl::Terminate()"; 253 DVLOG(1) << "WebRtcAudioDeviceImpl::Terminate()";
240 DCHECK(thread_checker_.CalledOnValidThread()); 254 DCHECK(thread_checker_.CalledOnValidThread());
241 255
242 // Calling Terminate() multiple times in a row is OK. 256 // Calling Terminate() multiple times in a row is OK.
243 if (!initialized_) 257 if (!initialized_)
244 return 0; 258 return 0;
245 259
246 StopRecording(); 260 StopRecording();
247 StopPlayout(); 261 StopPlayout();
248 262
249 DCHECK(!renderer_.get() || !renderer_->IsStarted()) 263 DCHECK(!renderer_.get() || !renderer_->IsStarted())
250 << "The shared audio renderer shouldn't be running"; 264 << "The shared audio renderer shouldn't be running";
251 265
266 if (aec_dump_message_filter_) {
267 aec_dump_message_filter_->SetObserver(NULL);
no longer working on chromium 2014/06/16 18:30:55 if you have more than 1 tab using webrtc, this Set
Henrik Grunell 2014/06/17 20:21:41 This is changed now. MSAP is a delegate instead.
268 aec_dump_message_filter_ = NULL;
269 }
270
252 DisableAecDump(); 271 DisableAecDump();
253 272
254 // Stop all the capturers to ensure no further OnData() and 273 // Stop all the capturers to ensure no further OnData() and
255 // RemoveAudioCapturer() callback. 274 // RemoveAudioCapturer() callback.
256 // Cache the capturers in a local list since WebRtcAudioCapturer::Stop() 275 // Cache the capturers in a local list since WebRtcAudioCapturer::Stop()
257 // will trigger RemoveAudioCapturer() callback. 276 // will trigger RemoveAudioCapturer() callback.
258 CapturerList capturers; 277 CapturerMap capturers;
259 capturers.swap(capturers_); 278 capturers.swap(capturers_);
260 for (CapturerList::const_iterator iter = capturers.begin(); 279 for (CapturerMap::const_iterator iter = capturers.begin();
261 iter != capturers.end(); ++iter) { 280 iter != capturers.end(); ++iter) {
262 (*iter)->Stop(); 281 iter->second->Stop();
263 } 282 }
264 283
265 initialized_ = false; 284 initialized_ = false;
266 return 0; 285 return 0;
267 } 286 }
268 287
269 bool WebRtcAudioDeviceImpl::Initialized() const { 288 bool WebRtcAudioDeviceImpl::Initialized() const {
270 return initialized_; 289 return initialized_;
271 } 290 }
272 291
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 capturer->source_audio_parameters().sample_rate()); 462 capturer->source_audio_parameters().sample_rate());
444 return 0; 463 return 0;
445 } 464 }
446 465
447 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( 466 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate(
448 uint32_t* sample_rate) const { 467 uint32_t* sample_rate) const {
449 *sample_rate = renderer_ ? renderer_->sample_rate() : 0; 468 *sample_rate = renderer_ ? renderer_->sample_rate() : 0;
450 return 0; 469 return 0;
451 } 470 }
452 471
472 void WebRtcAudioDeviceImpl::OnAecDumpFile(
473 int id,
474 const IPC::PlatformFileForTransit& file_handle) {
475 DCHECK(thread_checker_.CalledOnValidThread());
476 base::File file = IPC::PlatformFileForTransitToFile(file_handle);
477 DCHECK(file.IsValid());
478
479 CapturerMap::iterator iter = capturers_.find(id);
480 if (iter != capturers_.end()) {
481 iter->second->StartAecDump(file.Pass());
482 } else {
483 // The capturer has been removed.
484 file.Close();
485 }
486 }
487
488 void WebRtcAudioDeviceImpl::OnDisableAecDump() {
489 DCHECK(thread_checker_.CalledOnValidThread());
490 DisableAecDump();
491 }
492
493 void WebRtcAudioDeviceImpl::OnIpcClosed() {
494 DCHECK(thread_checker_.CalledOnValidThread());
495 aec_dump_message_filter_ = NULL;
496 }
497
453 bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { 498 bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) {
454 DCHECK(thread_checker_.CalledOnValidThread()); 499 DCHECK(thread_checker_.CalledOnValidThread());
455 DCHECK(renderer); 500 DCHECK(renderer);
456 501
457 base::AutoLock auto_lock(lock_); 502 base::AutoLock auto_lock(lock_);
458 if (renderer_.get()) 503 if (renderer_.get())
459 return false; 504 return false;
460 505
461 if (!renderer->Initialize(this)) 506 if (!renderer->Initialize(this))
462 return false; 507 return false;
463 508
464 renderer_ = renderer; 509 renderer_ = renderer;
465 return true; 510 return true;
466 } 511 }
467 512
468 void WebRtcAudioDeviceImpl::AddAudioCapturer( 513 void WebRtcAudioDeviceImpl::AddAudioCapturer(
469 const scoped_refptr<WebRtcAudioCapturer>& capturer) { 514 const scoped_refptr<WebRtcAudioCapturer>& capturer) {
470 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; 515 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
471 DCHECK(thread_checker_.CalledOnValidThread()); 516 DCHECK(thread_checker_.CalledOnValidThread());
472 DCHECK(capturer.get()); 517 DCHECK(capturer.get());
473 DCHECK(!capturer->device_id().empty()); 518 DCHECK(!capturer->device_id().empty());
519
520 int id = g_capturer_id_counter++;
Tom Sepez 2014/06/16 17:33:18 why is it OK to increment this outside the lock?
Henrik Grunell 2014/06/17 20:21:41 This has been removed, ids are handled in the mess
474 { 521 {
475 base::AutoLock auto_lock(lock_); 522 base::AutoLock auto_lock(lock_);
476 DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) == 523 DCHECK(capturers_.find(id) == capturers_.end());
477 capturers_.end()); 524 for (CapturerMap::const_iterator iter = capturers_.begin();
478 capturers_.push_back(capturer); 525 iter != capturers_.end(); ++iter) {
526 DCHECK(capturer != iter->second);
527 }
528 capturers_[id] = capturer;
479 } 529 }
480 530 RegisterAecDumpForId(id);
481 // Start the Aec dump if the Aec dump has been enabled and has not been
482 // started.
483 if (aec_dump_file_.IsValid())
484 MaybeStartAecDump();
485 } 531 }
486 532
487 void WebRtcAudioDeviceImpl::RemoveAudioCapturer( 533 void WebRtcAudioDeviceImpl::RemoveAudioCapturer(
488 const scoped_refptr<WebRtcAudioCapturer>& capturer) { 534 const scoped_refptr<WebRtcAudioCapturer>& capturer) {
489 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; 535 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
490 DCHECK(thread_checker_.CalledOnValidThread()); 536 DCHECK(thread_checker_.CalledOnValidThread());
491 DCHECK(capturer.get()); 537 DCHECK(capturer.get());
492 base::AutoLock auto_lock(lock_); 538
493 capturers_.remove(capturer); 539 int id = -1;
540 {
541 base::AutoLock auto_lock(lock_);
542 for (CapturerMap::iterator iter = capturers_.begin();
543 iter != capturers_.end(); ++iter) {
544 if (iter->second == capturer) {
545 id = iter->first;
546 capturers_.erase(iter);
547 break;
548 }
549 }
550 }
551 DCHECK_GE(id, 0);
552
553 if (aec_dump_message_filter_) {
554 aec_dump_message_filter_->io_message_loop()->PostTask(
555 FROM_HERE,
556 base::Bind(
557 &AecDumpMessageFilter::UnregisterAecDumpConsumer,
558 aec_dump_message_filter_,
559 id));
560 }
494 } 561 }
495 562
496 scoped_refptr<WebRtcAudioCapturer> 563 scoped_refptr<WebRtcAudioCapturer>
497 WebRtcAudioDeviceImpl::GetDefaultCapturer() const { 564 WebRtcAudioDeviceImpl::GetDefaultCapturer() const {
498 base::AutoLock auto_lock(lock_); 565 base::AutoLock auto_lock(lock_);
499 // Use the last |capturer| which is from the latest getUserMedia call as 566 // Use the last |capturer| which is from the latest getUserMedia call as
500 // the default capture device. 567 // the default capture device. The last capturer will have the largest key,
501 return capturers_.empty() ? NULL : capturers_.back(); 568 // so it will be last entry in the map.
569 return capturers_.empty() ? NULL : capturers_.rbegin()->second;
502 } 570 }
503 571
504 void WebRtcAudioDeviceImpl::AddPlayoutSink( 572 void WebRtcAudioDeviceImpl::AddPlayoutSink(
505 WebRtcPlayoutDataSource::Sink* sink) { 573 WebRtcPlayoutDataSource::Sink* sink) {
506 DCHECK(thread_checker_.CalledOnValidThread()); 574 DCHECK(thread_checker_.CalledOnValidThread());
507 DCHECK(sink); 575 DCHECK(sink);
508 base::AutoLock auto_lock(lock_); 576 base::AutoLock auto_lock(lock_);
509 DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) == 577 DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) ==
510 playout_sinks_.end()); 578 playout_sinks_.end());
511 playout_sinks_.push_back(sink); 579 playout_sinks_.push_back(sink);
(...skipping 14 matching lines...) Expand all
526 DCHECK(thread_checker_.CalledOnValidThread()); 594 DCHECK(thread_checker_.CalledOnValidThread());
527 // If there is no capturer or there are more than one open capture devices, 595 // If there is no capturer or there are more than one open capture devices,
528 // return false. 596 // return false.
529 if (capturers_.empty() || capturers_.size() > 1) 597 if (capturers_.empty() || capturers_.size() > 1)
530 return false; 598 return false;
531 599
532 return GetDefaultCapturer()->GetPairedOutputParameters( 600 return GetDefaultCapturer()->GetPairedOutputParameters(
533 session_id, output_sample_rate, output_frames_per_buffer); 601 session_id, output_sample_rate, output_frames_per_buffer);
534 } 602 }
535 603
536 void WebRtcAudioDeviceImpl::EnableAecDump(base::File aec_dump_file) { 604 void WebRtcAudioDeviceImpl::RegisterAecDumpForId(int id) {
537 DCHECK(thread_checker_.CalledOnValidThread()); 605 DCHECK(thread_checker_.CalledOnValidThread());
538 DCHECK(aec_dump_file.IsValid()); 606 if (aec_dump_message_filter_) {
539 607 aec_dump_message_filter_->io_message_loop()->PostTask(
540 // Close the previous AEC dump file description if it has not been consumed. 608 FROM_HERE,
541 // This can happen if no getUserMedia has been made yet. 609 base::Bind(
542 // TODO(xians): DCHECK(!aec_dump_file_.IsValid()) after the browser 610 &AecDumpMessageFilter::RegisterAecDumpConsumer,
543 // guarantees it won't call EnableAecDump() more than once in a row. 611 aec_dump_message_filter_,
544 if (aec_dump_file_.IsValid()) 612 id));
545 aec_dump_file_.Close(); 613 }
546
547 aec_dump_file_ = aec_dump_file.Pass();
548 MaybeStartAecDump();
549 } 614 }
550 615
551 void WebRtcAudioDeviceImpl::DisableAecDump() { 616 void WebRtcAudioDeviceImpl::DisableAecDump() {
552 DCHECK(thread_checker_.CalledOnValidThread()); 617 DCHECK(thread_checker_.CalledOnValidThread());
553 // Simply invalidate the |aec_dump_file_| if we have not pass the ownership 618 for (CapturerMap::const_iterator iter = capturers_.begin();
554 // to WebRtc.
555 if (aec_dump_file_.IsValid()) {
556 aec_dump_file_.Close();
557 return;
558 }
559
560 // We might have call StartAecDump() on one of the capturer. Loop
561 // through all the capturers and call StopAecDump() on each of them.
562 for (CapturerList::const_iterator iter = capturers_.begin();
563 iter != capturers_.end(); ++iter) { 619 iter != capturers_.end(); ++iter) {
564 (*iter)->StopAecDump(); 620 iter->second->StopAecDump();
565 } 621 }
566 } 622 }
567 623
568 void WebRtcAudioDeviceImpl::MaybeStartAecDump() {
569 DCHECK(thread_checker_.CalledOnValidThread());
570 DCHECK(aec_dump_file_.IsValid());
571
572 // Start the Aec dump on the current default capturer.
573 scoped_refptr<WebRtcAudioCapturer> default_capturer(GetDefaultCapturer());
574 if (!default_capturer)
575 return;
576
577 default_capturer->StartAecDump(aec_dump_file_.Pass());
578 }
579
580 } // namespace content 624 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698