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

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

Issue 23691038: Switch LiveAudio to source provider solution. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased and fixed some unittests Created 7 years, 3 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 "content/renderer/media/media_stream_dependency_factory.h" 5 #include "content/renderer/media/media_stream_dependency_factory.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 // WebRTC logging. It's a Google specific key, hence the "goog" prefix. 54 // WebRTC logging. It's a Google specific key, hence the "goog" prefix.
55 const char kWebRtcLoggingConstraint[] = "googLog"; 55 const char kWebRtcLoggingConstraint[] = "googLog";
56 56
57 // Constant constraint keys which disables all audio constraints. 57 // Constant constraint keys which disables all audio constraints.
58 // Only used in combination with WebAudio sources. 58 // Only used in combination with WebAudio sources.
59 struct { 59 struct {
60 const char* key; 60 const char* key;
61 const char* value; 61 const char* value;
62 } const kWebAudioConstraints[] = { 62 } const kWebAudioConstraints[] = {
63 {webrtc::MediaConstraintsInterface::kEchoCancellation, 63 {webrtc::MediaConstraintsInterface::kEchoCancellation,
64 webrtc::MediaConstraintsInterface::kValueTrue}, 64 webrtc::MediaConstraintsInterface::kValueFalse},
tommi (sloooow) - chröme 2013/09/06 11:20:30 please cc bemasc. It does seem though that if all
no longer working on chromium 2013/09/10 12:43:15 Removed the changed now, I want to completely remo
tommi (sloooow) - chröme 2013/09/10 16:00:38 sgtm
65 {webrtc::MediaConstraintsInterface::kAutoGainControl, 65 {webrtc::MediaConstraintsInterface::kAutoGainControl,
66 webrtc::MediaConstraintsInterface::kValueTrue}, 66 webrtc::MediaConstraintsInterface::kValueFalse},
67 {webrtc::MediaConstraintsInterface::kNoiseSuppression, 67 {webrtc::MediaConstraintsInterface::kNoiseSuppression,
68 webrtc::MediaConstraintsInterface::kValueTrue}, 68 webrtc::MediaConstraintsInterface::kValueFalse},
69 {webrtc::MediaConstraintsInterface::kHighpassFilter, 69 {webrtc::MediaConstraintsInterface::kHighpassFilter,
70 webrtc::MediaConstraintsInterface::kValueTrue}, 70 webrtc::MediaConstraintsInterface::kValueFalse},
71 }; 71 };
72 72
73 void ApplyFixedWebAudioConstraints(RTCMediaConstraints* constraints) { 73 void ApplyFixedWebAudioConstraints(RTCMediaConstraints* constraints) {
74 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kWebAudioConstraints); ++i) { 74 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kWebAudioConstraints); ++i) {
75 constraints->AddMandatory(kWebAudioConstraints[i].key, 75 constraints->AddMandatory(kWebAudioConstraints[i].key,
76 kWebAudioConstraints[i].value, false); 76 kWebAudioConstraints[i].value, false);
77 } 77 }
78 } 78 }
79 79
80 class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface { 80 class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 WebKit::WebMediaStream* web_stream, 365 WebKit::WebMediaStream* web_stream,
366 const MediaStreamExtraData::StreamStopCallback& stream_stop) { 366 const MediaStreamExtraData::StreamStopCallback& stream_stop) {
367 CreateNativeLocalMediaStream(web_stream); 367 CreateNativeLocalMediaStream(web_stream);
368 368
369 MediaStreamExtraData* extra_data = 369 MediaStreamExtraData* extra_data =
370 static_cast<MediaStreamExtraData*>(web_stream->extraData()); 370 static_cast<MediaStreamExtraData*>(web_stream->extraData());
371 extra_data->SetLocalStreamStopCallback(stream_stop); 371 extra_data->SetLocalStreamStopCallback(stream_stop);
372 } 372 }
373 373
374 bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack( 374 bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack(
375 const WebKit::WebMediaStream& stream, 375 const WebKit::WebMediaStream& stream,
376 const WebKit::WebMediaStreamTrack& track) { 376 const WebKit::WebMediaStreamTrack& track) {
377 MediaStreamExtraData* extra_data = 377 MediaStreamExtraData* extra_data =
378 static_cast<MediaStreamExtraData*>(stream.extraData()); 378 static_cast<MediaStreamExtraData*>(stream.extraData());
379 webrtc::MediaStreamInterface* native_stream = extra_data->stream().get(); 379 webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
380 DCHECK(native_stream); 380 DCHECK(native_stream);
381 381
382 WebKit::WebMediaStreamSource source = track.source(); 382 WebKit::WebMediaStreamSource source = track.source();
383 MediaStreamSourceExtraData* source_data = 383 MediaStreamSourceExtraData* source_data =
384 static_cast<MediaStreamSourceExtraData*>(source.extraData()); 384 static_cast<MediaStreamSourceExtraData*>(source.extraData());
385 385
386
386 // In the future the constraints will belong to the track itself, but 387 // In the future the constraints will belong to the track itself, but
387 // right now they're on the source, so we fetch them from there. 388 // right now they're on the source, so we fetch them from there.
388 RTCMediaConstraints track_constraints(source.constraints()); 389 RTCMediaConstraints track_constraints(source.constraints());
389 390
390 scoped_refptr<WebRtcAudioCapturer> capturer; 391 scoped_refptr<WebAudioCapturerSource> webaudio_source;
391 if (!source_data) { 392 if (!source_data) {
392 if (source.requiresAudioConsumer()) { 393 if (source.requiresAudioConsumer()) {
393 // We're adding a WebAudio MediaStream. 394 // We're adding a WebAudio MediaStream.
394 // Create a specific capturer for each WebAudio consumer. 395 // Create a specific capturer for each WebAudio consumer.
395 capturer = CreateWebAudioSource(&source, &track_constraints); 396 webaudio_source = CreateWebAudioSource(&source, &track_constraints);
396 source_data = 397 source_data =
397 static_cast<MediaStreamSourceExtraData*>(source.extraData()); 398 static_cast<MediaStreamSourceExtraData*>(source.extraData());
398 } else { 399 } else {
399 // TODO(perkj): Implement support for sources from 400 // TODO(perkj): Implement support for sources from
400 // remote MediaStreams. 401 // remote MediaStreams.
401 NOTIMPLEMENTED(); 402 NOTIMPLEMENTED();
402 return false; 403 return false;
403 } 404 }
404 } 405 }
405 406
406 WebKit::WebMediaStreamSource::Type type = track.source().type(); 407 WebKit::WebMediaStreamSource::Type type = track.source().type();
407 DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio || 408 DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio ||
408 type == WebKit::WebMediaStreamSource::TypeVideo); 409 type == WebKit::WebMediaStreamSource::TypeVideo);
409 410
410 std::string track_id = UTF16ToUTF8(track.id()); 411 std::string track_id = UTF16ToUTF8(track.id());
411 if (source.type() == WebKit::WebMediaStreamSource::TypeAudio) { 412 if (source.type() == WebKit::WebMediaStreamSource::TypeAudio) {
412 if (!capturer.get() && GetWebRtcAudioDevice()) 413 scoped_refptr<WebRtcAudioCapturer> capturer;
414 if (GetWebRtcAudioDevice())
413 capturer = GetWebRtcAudioDevice()->GetDefaultCapturer(); 415 capturer = GetWebRtcAudioDevice()->GetDefaultCapturer();
414 416
415 scoped_refptr<webrtc::AudioTrackInterface> audio_track( 417 scoped_refptr<webrtc::AudioTrackInterface> audio_track(
416 CreateLocalAudioTrack(track_id, 418 CreateLocalAudioTrack(track_id,
417 capturer, 419 capturer,
420 webaudio_source.get(),
418 source_data->local_audio_source(), 421 source_data->local_audio_source(),
419 &track_constraints)); 422 &track_constraints));
420 audio_track->set_enabled(track.isEnabled()); 423 audio_track->set_enabled(track.isEnabled());
424 if (capturer.get()) {
425 WebKit::WebMediaStreamTrack writable_track = track;
426 writable_track.setSourceProvider(capturer->AudioSourceProvider());
427 }
421 return native_stream->AddTrack(audio_track.get()); 428 return native_stream->AddTrack(audio_track.get());
422 } else { 429 } else {
423 DCHECK(source.type() == WebKit::WebMediaStreamSource::TypeVideo); 430 DCHECK(source.type() == WebKit::WebMediaStreamSource::TypeVideo);
424 scoped_refptr<webrtc::VideoTrackInterface> video_track( 431 scoped_refptr<webrtc::VideoTrackInterface> video_track(
425 CreateLocalVideoTrack(track_id, source_data->video_source())); 432 CreateLocalVideoTrack(track_id, source_data->video_source()));
426 video_track->set_enabled(track.isEnabled()); 433 video_track->set_enabled(track.isEnabled());
427 return native_stream->AddTrack(video_track.get()); 434 return native_stream->AddTrack(video_track.get());
428 } 435 }
429 } 436 }
430 437
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 MediaStreamExtraData* extra_data = 475 MediaStreamExtraData* extra_data =
469 static_cast<MediaStreamExtraData*>(stream.extraData()); 476 static_cast<MediaStreamExtraData*>(stream.extraData());
470 webrtc::MediaStreamInterface* native_stream = extra_data->stream().get(); 477 webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
471 DCHECK(native_stream); 478 DCHECK(native_stream);
472 479
473 WebKit::WebMediaStreamSource::Type type = track.source().type(); 480 WebKit::WebMediaStreamSource::Type type = track.source().type();
474 DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio || 481 DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio ||
475 type == WebKit::WebMediaStreamSource::TypeVideo); 482 type == WebKit::WebMediaStreamSource::TypeVideo);
476 483
477 std::string track_id = UTF16ToUTF8(track.id()); 484 std::string track_id = UTF16ToUTF8(track.id());
478 return type == WebKit::WebMediaStreamSource::TypeAudio ? 485 if (type == WebKit::WebMediaStreamSource::TypeAudio) {
479 native_stream->RemoveTrack(native_stream->FindAudioTrack(track_id)) : 486 // Remove the source provider as the track is going away.
480 native_stream->RemoveTrack(native_stream->FindVideoTrack(track_id)); 487 WebKit::WebMediaStreamTrack writable_track = track;
488 writable_track.setSourceProvider(NULL);
489 return native_stream->RemoveTrack(native_stream->FindAudioTrack(track_id));
490 }
491
492 return native_stream->RemoveTrack(native_stream->FindVideoTrack(track_id));
tommi (sloooow) - chröme 2013/09/06 11:20:30 can you add a DCHECK_EQ(type, WebKit::WebMediaStre
no longer working on chromium 2013/09/10 12:43:15 Done.
481 } 493 }
482 494
483 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory() { 495 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory() {
484 DVLOG(1) << "MediaStreamDependencyFactory::CreatePeerConnectionFactory()"; 496 DVLOG(1) << "MediaStreamDependencyFactory::CreatePeerConnectionFactory()";
485 if (!pc_factory_.get()) { 497 if (!pc_factory_.get()) {
486 DCHECK(!audio_device_.get()); 498 DCHECK(!audio_device_.get());
487 audio_device_ = new WebRtcAudioDeviceImpl(); 499 audio_device_ = new WebRtcAudioDeviceImpl();
488 500
489 scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory; 501 scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
490 scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory; 502 scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 const webrtc::MediaConstraintsInterface* constraints) { 599 const webrtc::MediaConstraintsInterface* constraints) {
588 RtcVideoCapturer* capturer = new RtcVideoCapturer( 600 RtcVideoCapturer* capturer = new RtcVideoCapturer(
589 video_session_id, vc_manager_.get(), is_screencast); 601 video_session_id, vc_manager_.get(), is_screencast);
590 602
591 // The video source takes ownership of |capturer|. 603 // The video source takes ownership of |capturer|.
592 scoped_refptr<webrtc::VideoSourceInterface> source = 604 scoped_refptr<webrtc::VideoSourceInterface> source =
593 pc_factory_->CreateVideoSource(capturer, constraints).get(); 605 pc_factory_->CreateVideoSource(capturer, constraints).get();
594 return source; 606 return source;
595 } 607 }
596 608
597 scoped_refptr<WebRtcAudioCapturer> 609 scoped_refptr<WebAudioCapturerSource>
598 MediaStreamDependencyFactory::CreateWebAudioSource( 610 MediaStreamDependencyFactory::CreateWebAudioSource(
599 WebKit::WebMediaStreamSource* source, 611 WebKit::WebMediaStreamSource* source,
600 RTCMediaConstraints* constraints) { 612 RTCMediaConstraints* constraints) {
601 DVLOG(1) << "MediaStreamDependencyFactory::CreateWebAudioSource()"; 613 DVLOG(1) << "MediaStreamDependencyFactory::CreateWebAudioSource()";
602 DCHECK(GetWebRtcAudioDevice()); 614 DCHECK(GetWebRtcAudioDevice());
603 615
604 // Set up the source and ensure that WebAudio is driving things instead of
605 // a microphone. For WebAudio, we always create a new capturer without
606 // calling initialize(), WebAudio will re-configure the capturer later on.
607 // Pass -1 as the |render_view_id| and an empty device struct to tell the
608 // capturer not to start the default source.
609 scoped_refptr<WebRtcAudioCapturer> capturer(
610 MaybeCreateAudioCapturer(-1, StreamDeviceInfo()));
tommi (sloooow) - chröme 2013/09/06 11:20:30 nice to get rid of this :)
611 DCHECK(capturer.get());
612
613 scoped_refptr<WebAudioCapturerSource> 616 scoped_refptr<WebAudioCapturerSource>
614 webaudio_capturer_source(new WebAudioCapturerSource(capturer.get())); 617 webaudio_capturer_source(new WebAudioCapturerSource());
615 MediaStreamSourceExtraData* source_data = 618 MediaStreamSourceExtraData* source_data =
616 new content::MediaStreamSourceExtraData(webaudio_capturer_source.get()); 619 new content::MediaStreamSourceExtraData();
617 620
618 // Create a LocalAudioSource object which holds audio options. 621 // Create a LocalAudioSource object which holds audio options.
619 // Use audio constraints where all values are true, i.e., enable 622 // Use audio constraints where all values are true, i.e., enable
620 // echo cancellation, automatic gain control, noise suppression and 623 // echo cancellation, automatic gain control, noise suppression and
621 // high-pass filter. SetLocalAudioSource() affects core audio parts in 624 // high-pass filter. SetLocalAudioSource() affects core audio parts in
622 // third_party/Libjingle. 625 // third_party/Libjingle.
623 ApplyFixedWebAudioConstraints(constraints); 626 ApplyFixedWebAudioConstraints(constraints);
624 source_data->SetLocalAudioSource(CreateLocalAudioSource(constraints).get()); 627 source_data->SetLocalAudioSource(CreateLocalAudioSource(constraints).get());
625 source->setExtraData(source_data); 628 source->setExtraData(source_data);
626 629
627 // Replace the default source with WebAudio as source instead. 630 // Replace the default source with WebAudio as source instead.
628 source->addAudioConsumer(webaudio_capturer_source.get()); 631 source->addAudioConsumer(webaudio_capturer_source.get());
629 632
630 return capturer; 633 return webaudio_capturer_source;
631 } 634 }
632 635
633 scoped_refptr<webrtc::VideoTrackInterface> 636 scoped_refptr<webrtc::VideoTrackInterface>
634 MediaStreamDependencyFactory::CreateLocalVideoTrack( 637 MediaStreamDependencyFactory::CreateLocalVideoTrack(
635 const std::string& id, 638 const std::string& id,
636 webrtc::VideoSourceInterface* source) { 639 webrtc::VideoSourceInterface* source) {
637 return pc_factory_->CreateVideoTrack(id, source).get(); 640 return pc_factory_->CreateVideoTrack(id, source).get();
638 } 641 }
639 642
640 scoped_refptr<webrtc::VideoTrackInterface> 643 scoped_refptr<webrtc::VideoTrackInterface>
641 MediaStreamDependencyFactory::CreateLocalVideoTrack( 644 MediaStreamDependencyFactory::CreateLocalVideoTrack(
642 const std::string& id, cricket::VideoCapturer* capturer) { 645 const std::string& id, cricket::VideoCapturer* capturer) {
643 if (!capturer) { 646 if (!capturer) {
644 LOG(ERROR) << "CreateLocalVideoTrack called with null VideoCapturer."; 647 LOG(ERROR) << "CreateLocalVideoTrack called with null VideoCapturer.";
645 return NULL; 648 return NULL;
646 } 649 }
647 650
648 // Create video source from the |capturer|. 651 // Create video source from the |capturer|.
649 scoped_refptr<webrtc::VideoSourceInterface> source = 652 scoped_refptr<webrtc::VideoSourceInterface> source =
650 pc_factory_->CreateVideoSource(capturer, NULL).get(); 653 pc_factory_->CreateVideoSource(capturer, NULL).get();
651 654
652 // Create native track from the source. 655 // Create native track from the source.
653 return pc_factory_->CreateVideoTrack(id, source.get()).get(); 656 return pc_factory_->CreateVideoTrack(id, source.get()).get();
654 } 657 }
655 658
656 scoped_refptr<webrtc::AudioTrackInterface> 659 scoped_refptr<webrtc::AudioTrackInterface>
657 MediaStreamDependencyFactory::CreateLocalAudioTrack( 660 MediaStreamDependencyFactory::CreateLocalAudioTrack(
658 const std::string& id, 661 const std::string& id,
659 const scoped_refptr<WebRtcAudioCapturer>& capturer, 662 const scoped_refptr<WebRtcAudioCapturer>& capturer,
660 webrtc::AudioSourceInterface* source, 663 WebAudioCapturerSource* webaudio_source,
664 webrtc::AudioSourceInterface* track_source,
661 const webrtc::MediaConstraintsInterface* constraints) { 665 const webrtc::MediaConstraintsInterface* constraints) {
662 // TODO(xians): Merge |source| to the capturer(). We can't do this today 666 // TODO(xians): Merge |source| to the capturer(). We can't do this today
663 // because only one capturer() is supported while one |source| is created 667 // because only one capturer() is supported while one |source| is created
664 // for each audio track. 668 // for each audio track.
665 scoped_refptr<WebRtcLocalAudioTrack> audio_track( 669 scoped_refptr<WebRtcLocalAudioTrack> audio_track(
666 WebRtcLocalAudioTrack::Create(id, capturer, source, constraints)); 670 WebRtcLocalAudioTrack::Create(id, capturer, webaudio_source,
671 track_source, constraints));
672
667 // Add the WebRtcAudioDevice as the sink to the local audio track. 673 // Add the WebRtcAudioDevice as the sink to the local audio track.
668 audio_track->AddSink(GetWebRtcAudioDevice()); 674 audio_track->AddSink(GetWebRtcAudioDevice());
669 // Start the audio track. This will hook the |audio_track| to the capturer 675 // Start the audio track. This will hook the |audio_track| to the capturer
670 // as the sink of the audio, and only start the source of the capturer if 676 // as the sink of the audio, and only start the source of the capturer if
671 // it is the first audio track connecting to the capturer. 677 // it is the first audio track connecting to the capturer.
672 audio_track->Start(); 678 audio_track->Start();
673 return audio_track; 679 return audio_track;
674 } 680 }
675 681
676 webrtc::SessionDescriptionInterface* 682 webrtc::SessionDescriptionInterface*
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 } else { 799 } else {
794 NOTREACHED() << "Worker thread not running."; 800 NOTREACHED() << "Worker thread not running.";
795 } 801 }
796 } 802 }
797 } 803 }
798 804
799 scoped_refptr<WebRtcAudioCapturer> 805 scoped_refptr<WebRtcAudioCapturer>
800 MediaStreamDependencyFactory::MaybeCreateAudioCapturer( 806 MediaStreamDependencyFactory::MaybeCreateAudioCapturer(
801 int render_view_id, 807 int render_view_id,
802 const StreamDeviceInfo& device_info) { 808 const StreamDeviceInfo& device_info) {
803 scoped_refptr<WebRtcAudioCapturer> capturer; 809 if (render_view_id < 0)
tommi (sloooow) - chröme 2013/09/06 11:20:30 Can we now simply DCHECK that render_view_id is >=
no longer working on chromium 2013/09/10 12:43:15 I think the answer might depend on if we support g
tommi (sloooow) - chröme 2013/09/10 16:00:38 sgtm
804 if (render_view_id != -1) { 810 return NULL;
805 // From a normal getUserMedia, re-use the existing default capturer. 811
806 capturer = GetWebRtcAudioDevice()->GetDefaultCapturer(); 812 scoped_refptr<WebRtcAudioCapturer> capturer =
807 } 813 GetWebRtcAudioDevice()->GetDefaultCapturer();
814
808 // If the default capturer does not exist or |render_view_id| == -1, create 815 // If the default capturer does not exist or |render_view_id| == -1, create
809 // a new capturer. 816 // a new capturer.
810 bool is_new_capturer = false; 817 bool is_new_capturer = false;
811 if (!capturer.get()) { 818 if (!capturer.get()) {
812 capturer = WebRtcAudioCapturer::CreateCapturer(); 819 capturer = WebRtcAudioCapturer::CreateCapturer();
813 is_new_capturer = true; 820 is_new_capturer = true;
814 } 821 }
815 822
816 if (!capturer->Initialize( 823 if (!capturer->Initialize(
817 render_view_id, 824 render_view_id,
818 static_cast<media::ChannelLayout>(device_info.device.channel_layout), 825 static_cast<media::ChannelLayout>(device_info.device.channel_layout),
819 device_info.device.sample_rate, device_info.session_id, 826 device_info.device.sample_rate, device_info.session_id,
820 device_info.device.id)) { 827 device_info.device.id)) {
821 return NULL; 828 return NULL;
822 } 829 }
823 830
824 // Add the capturer to the WebRtcAudioDeviceImpl if it is a new capturer. 831 // Add the capturer to the WebRtcAudioDeviceImpl if it is a new capturer.
825 if (is_new_capturer) 832 if (is_new_capturer)
826 GetWebRtcAudioDevice()->AddAudioCapturer(capturer); 833 GetWebRtcAudioDevice()->AddAudioCapturer(capturer);
827 834
828 return capturer; 835 return capturer;
829 } 836 }
830 837
831 } // namespace content 838 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698