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); |