Chromium Code Reviews| Index: talk/media/webrtc/webrtcvoiceengine.cc |
| diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc |
| index 0b5bed1623753545b2087a6c61f595ea52fcf7f4..296685cc4ac2e4c30106bb92ca96f00713b91d96 100644 |
| --- a/talk/media/webrtc/webrtcvoiceengine.cc |
| +++ b/talk/media/webrtc/webrtcvoiceengine.cc |
| @@ -1225,6 +1225,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
| ~WebRtcAudioReceiveStream() { |
| RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| call_->DestroyAudioReceiveStream(stream_); |
| + RTC_DCHECK(!audio_callback_.get()); |
| } |
| void RecreateAudioReceiveStream( |
| @@ -1248,6 +1249,23 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
| return config_.voe_channel_id; |
| } |
| + void SetRawAudioSink(webrtc::VoEExternalMedia* external_media, |
| + AudioRenderer::Sink* sink) { |
| + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| + if (sink) { |
| + RTC_DCHECK(!audio_callback_.get()); |
| + audio_callback_.reset(new AudioCallback(sink)); |
| + int err = external_media->RegisterExternalMediaProcessing( |
|
the sun
2015/12/10 12:36:32
Add an API on AudioReceiveStream instead: SetRawAu
|
| + channel(), webrtc::kPlaybackPerChannel, *audio_callback_.get()); |
| + if (err != 0) |
| + audio_callback_.reset(); |
| + } else if (audio_callback_) { |
| + external_media->DeRegisterExternalMediaProcessing( |
| + channel(), webrtc::kPlaybackPerChannel); |
| + audio_callback_.reset(); |
| + } |
| + } |
| + |
| private: |
| void RecreateAudioReceiveStream(bool use_combined_bwe, |
| const std::vector<webrtc::RtpExtension>& extensions) { |
| @@ -1263,12 +1281,40 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
| RTC_CHECK(stream_); |
| } |
| + class AudioCallback : public webrtc::VoEMediaProcess { |
| + public: |
| + explicit AudioCallback(AudioRenderer::Sink* sink) : sink_(sink) {} |
| + ~AudioCallback() { |
| + RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| + sink_->OnClose(); |
| + } |
| + |
| + private: |
| + // VoEMediaProcess implementation. |
| + void Process(int channel, |
| + webrtc::ProcessingTypes type, |
| + int16_t audio_10ms[], |
| + size_t length, |
| + int sampling_freq, |
| + bool is_stereo) override { |
| + // Called on the audio thread from webrtc. This can be a ProcessThread |
| + // belonging to WebRTC or an externally owned thread. |
| + sink_->OnData(&audio_10ms[0], 16, sampling_freq, is_stereo ? 2 : 1, |
| + length); |
| + } |
| + |
| + rtc::ThreadChecker thread_checker_; |
| + AudioRenderer::Sink* const sink_; |
| + RTC_DISALLOW_COPY_AND_ASSIGN(AudioCallback); |
| + }; |
| + |
| rtc::ThreadChecker worker_thread_checker_; |
| webrtc::Call* call_ = nullptr; |
| webrtc::AudioReceiveStream::Config config_; |
| // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if |
| // configuration changes. |
| webrtc::AudioReceiveStream* stream_ = nullptr; |
| + rtc::scoped_ptr<AudioCallback> audio_callback_; |
| RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream); |
| }; |
| @@ -2032,6 +2078,7 @@ bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { |
| // Clean up and delete the receive stream+channel. |
| LOG(LS_INFO) << "Removing audio receive stream " << ssrc |
| << " with VoiceEngine channel #" << channel << "."; |
| + it->second->SetRawAudioSink(engine()->voe()->external_media(), nullptr); |
| delete it->second; |
| recv_streams_.erase(it); |
| return DeleteVoEChannel(channel); |
| @@ -2408,6 +2455,17 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { |
| return true; |
| } |
| +void WebRtcVoiceMediaChannel::SetRawAudioSink(uint32_t ssrc, |
| + AudioRenderer::Sink* sink) { |
| + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| + const auto it = recv_streams_.find(ssrc); |
| + if (it == recv_streams_.end()) { |
| + LOG(LS_WARNING) << "SetRawAudioSink: no recv stream" << ssrc; |
| + return; |
| + } |
| + it->second->SetRawAudioSink(engine()->voe()->external_media(), sink); |
| +} |
| + |
| int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) { |
| unsigned int ulevel = 0; |
| int ret = engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel); |