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