| /* |
| * Copyright (C) 2012 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * 3. Neither the name of Google Inc. nor the names of its contributors |
| * may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h" |
| #include "third_party/blink/renderer/platform/wtf/assertions.h" |
| |
| namespace blink { |
| |
| MediaStreamSource* MediaStreamSource::Create(const String& id, |
| StreamType type, |
| const String& name, |
| bool remote, |
| ReadyState ready_state, |
| bool requires_consumer) { |
| return new MediaStreamSource(id, type, name, remote, ready_state, |
| requires_consumer); |
| } |
| |
| MediaStreamSource::MediaStreamSource(const String& id, |
| StreamType type, |
| const String& name, |
| bool remote, |
| ReadyState ready_state, |
| bool requires_consumer) |
| : id_(id), |
| type_(type), |
| name_(name), |
| remote_(remote), |
| ready_state_(ready_state), |
| requires_consumer_(requires_consumer) {} |
| |
| void MediaStreamSource::SetGroupId(const String& group_id) { |
| group_id_ = group_id; |
| } |
| |
| void MediaStreamSource::SetReadyState(ReadyState ready_state) { |
| if (ready_state_ != kReadyStateEnded && ready_state_ != ready_state) { |
| ready_state_ = ready_state; |
| |
| // Observers may dispatch events which create and add new Observers; |
| // take a snapshot so as to safely iterate. |
| HeapVector<Member<Observer>> observers; |
| CopyToVector(observers_, observers); |
| for (auto observer : observers) |
| observer->SourceChangedState(); |
| |
| // setReadyState() will be invoked via the MediaStreamComponent::dispose() |
| // prefinalizer, allocating |observers|. Which means that |observers| will |
| // live until the next GC (but be unreferenced by other heap objects), |
| // _but_ it will potentially contain references to Observers that were |
| // GCed after the MediaStreamComponent prefinalizer had completed. |
| // |
| // So, if the next GC is a conservative one _and_ it happens to find |
| // a reference to |observers| when scanning the stack, we're in trouble |
| // as it contains references to now-dead objects. |
| // |
| // Work around this by explicitly clearing the vector backing store. |
| // |
| // TODO(sof): consider adding run-time checks that disallows this kind |
| // of dead object revivification by default. |
| for (size_t i = 0; i < observers.size(); ++i) |
| observers[i] = nullptr; |
| } |
| } |
| |
| void MediaStreamSource::AddObserver(MediaStreamSource::Observer* observer) { |
| observers_.insert(observer); |
| } |
| |
| void MediaStreamSource::SetAudioProcessingProperties(bool echo_cancellation, |
| bool auto_gain_control, |
| bool noise_supression) { |
| echo_cancellation_ = echo_cancellation; |
| auto_gain_control_ = auto_gain_control; |
| noise_supression_ = noise_supression; |
| } |
| |
| void MediaStreamSource::AddAudioConsumer(AudioDestinationConsumer* consumer) { |
| DCHECK(requires_consumer_); |
| MutexLocker locker(audio_consumers_lock_); |
| audio_consumers_.insert(consumer); |
| } |
| |
| bool MediaStreamSource::RemoveAudioConsumer( |
| AudioDestinationConsumer* consumer) { |
| DCHECK(requires_consumer_); |
| MutexLocker locker(audio_consumers_lock_); |
| auto it = audio_consumers_.find(consumer); |
| if (it == audio_consumers_.end()) |
| return false; |
| audio_consumers_.erase(it); |
| return true; |
| } |
| |
| void MediaStreamSource::GetSettings(WebMediaStreamTrack::Settings& settings) { |
| settings.device_id = Id(); |
| settings.group_id = GroupId(); |
| |
| if (echo_cancellation_) |
| settings.echo_cancellation = *echo_cancellation_; |
| if (auto_gain_control_) |
| settings.auto_gain_control = *auto_gain_control_; |
| if (noise_supression_) |
| settings.noise_supression = *noise_supression_; |
| } |
| |
| void MediaStreamSource::SetAudioFormat(size_t number_of_channels, |
| float sample_rate) { |
| DCHECK(requires_consumer_); |
| MutexLocker locker(audio_consumers_lock_); |
| for (AudioDestinationConsumer* consumer : audio_consumers_) |
| consumer->SetFormat(number_of_channels, sample_rate); |
| } |
| |
| void MediaStreamSource::ConsumeAudio(AudioBus* bus, size_t number_of_frames) { |
| DCHECK(requires_consumer_); |
| MutexLocker locker(audio_consumers_lock_); |
| for (AudioDestinationConsumer* consumer : audio_consumers_) |
| consumer->ConsumeAudio(bus, number_of_frames); |
| } |
| |
| void MediaStreamSource::Trace(blink::Visitor* visitor) { |
| visitor->Trace(observers_); |
| } |
| |
| STATIC_ASSERT_ENUM(WebMediaStreamSource::kTypeAudio, |
| MediaStreamSource::kTypeAudio); |
| STATIC_ASSERT_ENUM(WebMediaStreamSource::kTypeVideo, |
| MediaStreamSource::kTypeVideo); |
| STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateLive, |
| MediaStreamSource::kReadyStateLive); |
| STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateMuted, |
| MediaStreamSource::kReadyStateMuted); |
| STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateEnded, |
| MediaStreamSource::kReadyStateEnded); |
| |
| } // namespace blink |