blob: aba44006bf9c06fde1805d02f020b96a12f1401a [file] [log] [blame]
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2014 The WebRTC project authors. All Rights Reserved.
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +00009 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/remote_audio_source.h"
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stddef.h>
Yves Gerey3e707812018-11-28 16:47:49 +010014#include <string>
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000015
Steve Anton64b626b2019-01-28 17:25:26 -080016#include "absl/algorithm/container.h"
Karl Wiberg918f50c2018-07-05 11:40:33 +020017#include "absl/memory/memory.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010018#include "api/scoped_refptr.h"
Ruslan Burakov493a6502019-02-27 15:32:48 +010019#include "pc/playout_latency.h"
20#include "pc/playout_latency_proxy.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "rtc_base/constructor_magic.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "rtc_base/location.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/logging.h"
Ruslan Burakov7ea46052019-02-16 02:07:05 +010025#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/thread.h"
Yves Gerey3e707812018-11-28 16:47:49 +010027#include "rtc_base/thread_checker.h"
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000028
29namespace webrtc {
30
Steve Antond3679212018-01-17 17:41:02 -080031// This proxy is passed to the underlying media engine to receive audio data as
32// they come in. The data will then be passed back up to the RemoteAudioSource
33// which will fan it out to all the sinks that have been added to it.
34class RemoteAudioSource::AudioDataProxy : public AudioSinkInterface {
Tommif888bb52015-12-12 01:37:01 +010035 public:
Steve Antond3679212018-01-17 17:41:02 -080036 explicit AudioDataProxy(RemoteAudioSource* source) : source_(source) {
37 RTC_DCHECK(source);
38 }
39 ~AudioDataProxy() override { source_->OnAudioChannelGone(); }
Tommif888bb52015-12-12 01:37:01 +010040
Steve Antond3679212018-01-17 17:41:02 -080041 // AudioSinkInterface implementation.
Tommif888bb52015-12-12 01:37:01 +010042 void OnData(const AudioSinkInterface::Data& audio) override {
Steve Antond3679212018-01-17 17:41:02 -080043 source_->OnData(audio);
Tommif888bb52015-12-12 01:37:01 +010044 }
45
Steve Antond3679212018-01-17 17:41:02 -080046 private:
Tommif888bb52015-12-12 01:37:01 +010047 const rtc::scoped_refptr<RemoteAudioSource> source_;
Steve Antond3679212018-01-17 17:41:02 -080048
49 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioDataProxy);
Tommif888bb52015-12-12 01:37:01 +010050};
51
Steve Antond3679212018-01-17 17:41:02 -080052RemoteAudioSource::RemoteAudioSource(rtc::Thread* worker_thread)
Tommif888bb52015-12-12 01:37:01 +010053 : main_thread_(rtc::Thread::Current()),
Steve Antond3679212018-01-17 17:41:02 -080054 worker_thread_(worker_thread),
Ruslan Burakov493a6502019-02-27 15:32:48 +010055 state_(MediaSourceInterface::kLive),
56 latency_(PlayoutLatencyProxy::Create(
57 main_thread_,
58 worker_thread_,
59 new rtc::RefCountedObject<PlayoutLatency>(worker_thread))) {
Tommif888bb52015-12-12 01:37:01 +010060 RTC_DCHECK(main_thread_);
Steve Antond3679212018-01-17 17:41:02 -080061 RTC_DCHECK(worker_thread_);
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000062}
63
64RemoteAudioSource::~RemoteAudioSource() {
Tommif888bb52015-12-12 01:37:01 +010065 RTC_DCHECK(main_thread_->IsCurrent());
66 RTC_DCHECK(audio_observers_.empty());
67 RTC_DCHECK(sinks_.empty());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000068}
69
Steve Antond3679212018-01-17 17:41:02 -080070void RemoteAudioSource::Start(cricket::VoiceMediaChannel* media_channel,
71 uint32_t ssrc) {
72 RTC_DCHECK_RUN_ON(main_thread_);
73 RTC_DCHECK(media_channel);
Ruslan Burakov7ea46052019-02-16 02:07:05 +010074
Steve Antond3679212018-01-17 17:41:02 -080075 // Register for callbacks immediately before AddSink so that we always get
76 // notified when a channel goes out of scope (signaled when "AudioDataProxy"
77 // is destroyed).
78 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
Karl Wiberg918f50c2018-07-05 11:40:33 +020079 media_channel->SetRawAudioSink(ssrc,
80 absl::make_unique<AudioDataProxy>(this));
Steve Antond3679212018-01-17 17:41:02 -080081 });
Ruslan Burakov7ea46052019-02-16 02:07:05 +010082
Ruslan Burakov493a6502019-02-27 15:32:48 +010083 // Apply latency to the audio stream if |SetLatency| was called before.
84 latency_->OnStart(media_channel, ssrc);
Steve Antond3679212018-01-17 17:41:02 -080085}
86
87void RemoteAudioSource::Stop(cricket::VoiceMediaChannel* media_channel,
88 uint32_t ssrc) {
89 RTC_DCHECK_RUN_ON(main_thread_);
90 RTC_DCHECK(media_channel);
Ruslan Burakov7ea46052019-02-16 02:07:05 +010091
Ruslan Burakov493a6502019-02-27 15:32:48 +010092 latency_->OnStop();
Ruslan Burakov7ea46052019-02-16 02:07:05 +010093
Steve Antond3679212018-01-17 17:41:02 -080094 worker_thread_->Invoke<void>(
95 RTC_FROM_HERE, [&] { media_channel->SetRawAudioSink(ssrc, nullptr); });
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000096}
97
Tommif888bb52015-12-12 01:37:01 +010098MediaSourceInterface::SourceState RemoteAudioSource::state() const {
99 RTC_DCHECK(main_thread_->IsCurrent());
100 return state_;
101}
102
tommi6eca7e32015-12-15 04:27:11 -0800103bool RemoteAudioSource::remote() const {
104 RTC_DCHECK(main_thread_->IsCurrent());
105 return true;
106}
107
Tommif888bb52015-12-12 01:37:01 +0100108void RemoteAudioSource::SetVolume(double volume) {
kwibergee89e782017-08-09 17:22:01 -0700109 RTC_DCHECK_GE(volume, 0);
110 RTC_DCHECK_LE(volume, 10);
Steve Antond3679212018-01-17 17:41:02 -0800111 for (auto* observer : audio_observers_) {
Tommif888bb52015-12-12 01:37:01 +0100112 observer->OnSetVolume(volume);
Steve Antond3679212018-01-17 17:41:02 -0800113 }
Tommif888bb52015-12-12 01:37:01 +0100114}
115
Ruslan Burakov7ea46052019-02-16 02:07:05 +0100116void RemoteAudioSource::SetLatency(double latency) {
Ruslan Burakov493a6502019-02-27 15:32:48 +0100117 latency_->SetLatency(latency);
Ruslan Burakov7ea46052019-02-16 02:07:05 +0100118}
119
120double RemoteAudioSource::GetLatency() const {
Ruslan Burakov493a6502019-02-27 15:32:48 +0100121 return latency_->GetLatency();
Ruslan Burakov7ea46052019-02-16 02:07:05 +0100122}
123
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000124void RemoteAudioSource::RegisterAudioObserver(AudioObserver* observer) {
Tommif888bb52015-12-12 01:37:01 +0100125 RTC_DCHECK(observer != NULL);
Steve Anton64b626b2019-01-28 17:25:26 -0800126 RTC_DCHECK(!absl::c_linear_search(audio_observers_, observer));
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000127 audio_observers_.push_back(observer);
128}
129
130void RemoteAudioSource::UnregisterAudioObserver(AudioObserver* observer) {
Tommif888bb52015-12-12 01:37:01 +0100131 RTC_DCHECK(observer != NULL);
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000132 audio_observers_.remove(observer);
133}
134
Tommif888bb52015-12-12 01:37:01 +0100135void RemoteAudioSource::AddSink(AudioTrackSinkInterface* sink) {
136 RTC_DCHECK(main_thread_->IsCurrent());
137 RTC_DCHECK(sink);
138
139 if (state_ != MediaSourceInterface::kLive) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100140 RTC_LOG(LS_ERROR) << "Can't register sink as the source isn't live.";
Tommif888bb52015-12-12 01:37:01 +0100141 return;
142 }
143
144 rtc::CritScope lock(&sink_lock_);
Steve Anton3d023842019-01-28 19:48:28 -0800145 RTC_DCHECK(!absl::c_linear_search(sinks_, sink));
Tommif888bb52015-12-12 01:37:01 +0100146 sinks_.push_back(sink);
147}
148
149void RemoteAudioSource::RemoveSink(AudioTrackSinkInterface* sink) {
150 RTC_DCHECK(main_thread_->IsCurrent());
151 RTC_DCHECK(sink);
152
153 rtc::CritScope lock(&sink_lock_);
154 sinks_.remove(sink);
155}
156
157void RemoteAudioSource::OnData(const AudioSinkInterface::Data& audio) {
158 // Called on the externally-owned audio callback thread, via/from webrtc.
159 rtc::CritScope lock(&sink_lock_);
160 for (auto* sink : sinks_) {
161 sink->OnData(audio.data, 16, audio.sample_rate, audio.channels,
162 audio.samples_per_channel);
163 }
164}
165
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700166void RemoteAudioSource::OnAudioChannelGone() {
167 // Called when the audio channel is deleted. It may be the worker thread
Tommif888bb52015-12-12 01:37:01 +0100168 // in libjingle or may be a different worker thread.
Steve Anton3b80aac2017-10-19 10:17:12 -0700169 // This object needs to live long enough for the cleanup logic in OnMessage to
170 // run, so take a reference to it as the data. Sometimes the message may not
171 // be processed (because the thread was destroyed shortly after this call),
172 // but that is fine because the thread destructor will take care of destroying
173 // the message data which will release the reference on RemoteAudioSource.
174 main_thread_->Post(RTC_FROM_HERE, this, 0,
175 new rtc::ScopedRefMessageData<RemoteAudioSource>(this));
Tommif888bb52015-12-12 01:37:01 +0100176}
177
178void RemoteAudioSource::OnMessage(rtc::Message* msg) {
179 RTC_DCHECK(main_thread_->IsCurrent());
180 sinks_.clear();
181 state_ = MediaSourceInterface::kEnded;
182 FireOnChanged();
Steve Anton3b80aac2017-10-19 10:17:12 -0700183 // Will possibly delete this RemoteAudioSource since it is reference counted
184 // in the message.
185 delete msg->pdata;
Tommif888bb52015-12-12 01:37:01 +0100186}
187
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000188} // namespace webrtc