OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2014 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * 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. | |
9 */ | |
10 | |
11 #include "webrtc/api/remoteaudiosource.h" | |
12 | |
13 #include <algorithm> | |
14 #include <functional> | |
15 #include <memory> | |
16 #include <utility> | |
17 | |
18 #include "webrtc/base/checks.h" | |
19 #include "webrtc/base/constructormagic.h" | |
20 #include "webrtc/base/logging.h" | |
21 #include "webrtc/base/thread.h" | |
22 | |
23 namespace webrtc { | |
24 | |
25 class RemoteAudioSource::MessageHandler : public rtc::MessageHandler { | |
26 public: | |
27 explicit MessageHandler(RemoteAudioSource* source) : source_(source) {} | |
28 | |
29 private: | |
30 ~MessageHandler() override {} | |
31 | |
32 void OnMessage(rtc::Message* msg) override { | |
33 source_->OnMessage(msg); | |
34 delete this; | |
35 } | |
36 | |
37 const rtc::scoped_refptr<RemoteAudioSource> source_; | |
38 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MessageHandler); | |
39 }; | |
40 | |
41 class RemoteAudioSource::Sink : public AudioSinkInterface { | |
42 public: | |
43 explicit Sink(RemoteAudioSource* source) : source_(source) {} | |
44 ~Sink() override { source_->OnAudioChannelGone(); } | |
45 | |
46 private: | |
47 void OnData(const AudioSinkInterface::Data& audio) override { | |
48 if (source_) | |
49 source_->OnData(audio); | |
50 } | |
51 | |
52 const rtc::scoped_refptr<RemoteAudioSource> source_; | |
53 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sink); | |
54 }; | |
55 | |
56 rtc::scoped_refptr<RemoteAudioSource> RemoteAudioSource::Create( | |
57 uint32_t ssrc, | |
58 cricket::VoiceChannel* channel) { | |
59 rtc::scoped_refptr<RemoteAudioSource> ret( | |
60 new rtc::RefCountedObject<RemoteAudioSource>()); | |
61 ret->Initialize(ssrc, channel); | |
62 return ret; | |
63 } | |
64 | |
65 RemoteAudioSource::RemoteAudioSource() | |
66 : main_thread_(rtc::Thread::Current()), | |
67 state_(MediaSourceInterface::kLive) { | |
68 RTC_DCHECK(main_thread_); | |
69 } | |
70 | |
71 RemoteAudioSource::~RemoteAudioSource() { | |
72 RTC_DCHECK(main_thread_->IsCurrent()); | |
73 RTC_DCHECK(audio_observers_.empty()); | |
74 RTC_DCHECK(sinks_.empty()); | |
75 } | |
76 | |
77 void RemoteAudioSource::Initialize(uint32_t ssrc, | |
78 cricket::VoiceChannel* channel) { | |
79 RTC_DCHECK(main_thread_->IsCurrent()); | |
80 // To make sure we always get notified when the channel goes out of scope, | |
81 // we register for callbacks here and not on demand in AddSink. | |
82 if (channel) { // May be null in tests. | |
83 channel->SetRawAudioSink( | |
84 ssrc, std::unique_ptr<AudioSinkInterface>(new Sink(this))); | |
85 } | |
86 } | |
87 | |
88 MediaSourceInterface::SourceState RemoteAudioSource::state() const { | |
89 RTC_DCHECK(main_thread_->IsCurrent()); | |
90 return state_; | |
91 } | |
92 | |
93 bool RemoteAudioSource::remote() const { | |
94 RTC_DCHECK(main_thread_->IsCurrent()); | |
95 return true; | |
96 } | |
97 | |
98 void RemoteAudioSource::SetVolume(double volume) { | |
99 RTC_DCHECK(volume >= 0 && volume <= 10); | |
100 for (auto* observer : audio_observers_) | |
101 observer->OnSetVolume(volume); | |
102 } | |
103 | |
104 void RemoteAudioSource::RegisterAudioObserver(AudioObserver* observer) { | |
105 RTC_DCHECK(observer != NULL); | |
106 RTC_DCHECK(std::find(audio_observers_.begin(), audio_observers_.end(), | |
107 observer) == audio_observers_.end()); | |
108 audio_observers_.push_back(observer); | |
109 } | |
110 | |
111 void RemoteAudioSource::UnregisterAudioObserver(AudioObserver* observer) { | |
112 RTC_DCHECK(observer != NULL); | |
113 audio_observers_.remove(observer); | |
114 } | |
115 | |
116 void RemoteAudioSource::AddSink(AudioTrackSinkInterface* sink) { | |
117 RTC_DCHECK(main_thread_->IsCurrent()); | |
118 RTC_DCHECK(sink); | |
119 | |
120 if (state_ != MediaSourceInterface::kLive) { | |
121 LOG(LS_ERROR) << "Can't register sink as the source isn't live."; | |
122 return; | |
123 } | |
124 | |
125 rtc::CritScope lock(&sink_lock_); | |
126 RTC_DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end()); | |
127 sinks_.push_back(sink); | |
128 } | |
129 | |
130 void RemoteAudioSource::RemoveSink(AudioTrackSinkInterface* sink) { | |
131 RTC_DCHECK(main_thread_->IsCurrent()); | |
132 RTC_DCHECK(sink); | |
133 | |
134 rtc::CritScope lock(&sink_lock_); | |
135 sinks_.remove(sink); | |
136 } | |
137 | |
138 void RemoteAudioSource::OnData(const AudioSinkInterface::Data& audio) { | |
139 // Called on the externally-owned audio callback thread, via/from webrtc. | |
140 rtc::CritScope lock(&sink_lock_); | |
141 for (auto* sink : sinks_) { | |
142 sink->OnData(audio.data, 16, audio.sample_rate, audio.channels, | |
143 audio.samples_per_channel); | |
144 } | |
145 } | |
146 | |
147 void RemoteAudioSource::OnAudioChannelGone() { | |
148 // Called when the audio channel is deleted. It may be the worker thread | |
149 // in libjingle or may be a different worker thread. | |
150 main_thread_->Post(RTC_FROM_HERE, new MessageHandler(this)); | |
151 } | |
152 | |
153 void RemoteAudioSource::OnMessage(rtc::Message* msg) { | |
154 RTC_DCHECK(main_thread_->IsCurrent()); | |
155 sinks_.clear(); | |
156 state_ = MediaSourceInterface::kEnded; | |
157 FireOnChanged(); | |
158 } | |
159 | |
160 } // namespace webrtc | |
OLD | NEW |