1/*
2 * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
3 * Copyright (C) 2015 Ericsson AB. All rights reserved.
4 * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "MediaStreamTrackPrivate.h"
30
31#if ENABLE(MEDIA_STREAM)
32
33#include "GraphicsContext.h"
34#include "IntRect.h"
35#include <wtf/UUID.h>
36
37#if PLATFORM(COCOA)
38#include "WebAudioSourceProviderAVFObjC.h"
39#elif ENABLE(WEB_AUDIO) && ENABLE(MEDIA_STREAM) && USE(LIBWEBRTC) && USE(GSTREAMER)
40#include "AudioSourceProviderGStreamer.h"
41#else
42#include "WebAudioSourceProvider.h"
43#endif
44
45namespace WebCore {
46
47Ref<MediaStreamTrackPrivate> MediaStreamTrackPrivate::create(Ref<RealtimeMediaSource>&& source)
48{
49 return create(WTFMove(source), createCanonicalUUIDString());
50}
51
52Ref<MediaStreamTrackPrivate> MediaStreamTrackPrivate::create(Ref<RealtimeMediaSource>&& source, String&& id)
53{
54 return adoptRef(*new MediaStreamTrackPrivate(WTFMove(source), WTFMove(id)));
55}
56
57MediaStreamTrackPrivate::MediaStreamTrackPrivate(Ref<RealtimeMediaSource>&& source, String&& id)
58 : m_source(WTFMove(source))
59 , m_id(WTFMove(id))
60{
61 m_source->addObserver(*this);
62}
63
64MediaStreamTrackPrivate::~MediaStreamTrackPrivate()
65{
66 m_source->removeObserver(*this);
67}
68
69void MediaStreamTrackPrivate::forEachObserver(const WTF::Function<void(Observer&)>& apply) const
70{
71 Vector<Observer*> observersCopy;
72 {
73 auto locker = holdLock(m_observersLock);
74 observersCopy = copyToVector(m_observers);
75 }
76 for (auto* observer : observersCopy) {
77 auto locker = holdLock(m_observersLock);
78 // Make sure the observer has not been destroyed.
79 if (!m_observers.contains(observer))
80 continue;
81 apply(*observer);
82 }
83}
84
85void MediaStreamTrackPrivate::addObserver(MediaStreamTrackPrivate::Observer& observer)
86{
87 auto locker = holdLock(m_observersLock);
88 m_observers.add(&observer);
89}
90
91void MediaStreamTrackPrivate::removeObserver(MediaStreamTrackPrivate::Observer& observer)
92{
93 auto locker = holdLock(m_observersLock);
94 m_observers.remove(&observer);
95}
96
97const String& MediaStreamTrackPrivate::label() const
98{
99 return m_source->name();
100}
101
102void MediaStreamTrackPrivate::setContentHint(HintValue hintValue)
103{
104 m_contentHint = hintValue;
105}
106
107bool MediaStreamTrackPrivate::muted() const
108{
109 return m_source->muted();
110}
111
112bool MediaStreamTrackPrivate::isCaptureTrack() const
113{
114 return m_source->isCaptureSource();
115}
116
117void MediaStreamTrackPrivate::setEnabled(bool enabled)
118{
119 if (m_isEnabled == enabled)
120 return;
121
122 // Always update the enabled state regardless of the track being ended.
123 m_isEnabled = enabled;
124
125 forEachObserver([this](auto& observer) {
126 observer.trackEnabledChanged(*this);
127 });
128}
129
130void MediaStreamTrackPrivate::endTrack()
131{
132 if (m_isEnded)
133 return;
134
135 // Set m_isEnded to true before telling the source it can stop, so if this is the
136 // only track using the source and it does stop, we will only call each observer's
137 // trackEnded method once.
138 m_isEnded = true;
139 updateReadyState();
140
141 m_source->requestToEnd(*this);
142
143 forEachObserver([this](auto& observer) {
144 observer.trackEnded(*this);
145 });
146}
147
148Ref<MediaStreamTrackPrivate> MediaStreamTrackPrivate::clone()
149{
150 auto clonedMediaStreamTrackPrivate = create(m_source.copyRef());
151 clonedMediaStreamTrackPrivate->m_isEnabled = this->m_isEnabled;
152 clonedMediaStreamTrackPrivate->m_isEnded = this->m_isEnded;
153 clonedMediaStreamTrackPrivate->m_contentHint = this->m_contentHint;
154 clonedMediaStreamTrackPrivate->updateReadyState();
155
156 return clonedMediaStreamTrackPrivate;
157}
158
159RealtimeMediaSource::Type MediaStreamTrackPrivate::type() const
160{
161 return m_source->type();
162}
163
164const RealtimeMediaSourceSettings& MediaStreamTrackPrivate::settings() const
165{
166 return m_source->settings();
167}
168
169const RealtimeMediaSourceCapabilities& MediaStreamTrackPrivate::capabilities() const
170{
171 return m_source->capabilities();
172}
173
174void MediaStreamTrackPrivate::applyConstraints(const MediaConstraints& constraints, RealtimeMediaSource::ApplyConstraintsHandler&& completionHandler)
175{
176 m_source->applyConstraints(constraints, WTFMove(completionHandler));
177}
178
179AudioSourceProvider* MediaStreamTrackPrivate::audioSourceProvider()
180{
181#if PLATFORM(COCOA)
182 if (!m_audioSourceProvider)
183 m_audioSourceProvider = WebAudioSourceProviderAVFObjC::create(*this);
184#elif USE(LIBWEBRTC) && USE(GSTREAMER)
185 if (!m_audioSourceProvider)
186 m_audioSourceProvider = AudioSourceProviderGStreamer::create(*this);
187#endif
188 return m_audioSourceProvider.get();
189}
190
191void MediaStreamTrackPrivate::sourceStarted()
192{
193 forEachObserver([this](auto& observer) {
194 observer.trackStarted(*this);
195 });
196}
197
198void MediaStreamTrackPrivate::sourceStopped()
199{
200 if (m_isEnded)
201 return;
202
203 m_isEnded = true;
204 updateReadyState();
205
206 forEachObserver([this](auto& observer) {
207 observer.trackEnded(*this);
208 });
209}
210
211void MediaStreamTrackPrivate::sourceMutedChanged()
212{
213 forEachObserver([this](auto& observer) {
214 observer.trackMutedChanged(*this);
215 });
216}
217
218void MediaStreamTrackPrivate::sourceSettingsChanged()
219{
220 forEachObserver([this](auto& observer) {
221 observer.trackSettingsChanged(*this);
222 });
223}
224
225bool MediaStreamTrackPrivate::preventSourceFromStopping()
226{
227 // Do not allow the source to stop if we are still using it.
228 return !m_isEnded;
229}
230
231void MediaStreamTrackPrivate::videoSampleAvailable(MediaSample& mediaSample)
232{
233 if (!m_haveProducedData) {
234 m_haveProducedData = true;
235 updateReadyState();
236 }
237
238 if (!enabled())
239 return;
240
241 mediaSample.setTrackID(id());
242 forEachObserver([&](auto& observer) {
243 observer.sampleBufferUpdated(*this, mediaSample);
244 });
245}
246
247// May get called on a background thread.
248void MediaStreamTrackPrivate::audioSamplesAvailable(const MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount)
249{
250 if (!m_haveProducedData) {
251 m_haveProducedData = true;
252 updateReadyState();
253 }
254
255 forEachObserver([&](auto& observer) {
256 observer.audioSamplesAvailable(*this, mediaTime, data, description, sampleCount);
257 });
258}
259
260
261void MediaStreamTrackPrivate::updateReadyState()
262{
263 ReadyState state = ReadyState::None;
264
265 if (m_isEnded)
266 state = ReadyState::Ended;
267 else if (m_haveProducedData)
268 state = ReadyState::Live;
269
270 if (state == m_readyState)
271 return;
272
273 ALWAYS_LOG(LOGIDENTIFIER);
274
275 m_readyState = state;
276 forEachObserver([this](auto& observer) {
277 observer.readyStateChanged(*this);
278 });
279}
280
281#if !RELEASE_LOG_DISABLED
282void MediaStreamTrackPrivate::setLogger(const Logger& newLogger, const void* newLogIdentifier)
283{
284 m_logger = &newLogger;
285 m_logIdentifier = newLogIdentifier;
286 ALWAYS_LOG(LOGIDENTIFIER);
287 m_source->setLogger(newLogger, newLogIdentifier);
288}
289
290WTFLogChannel& MediaStreamTrackPrivate::logChannel() const
291{
292 return LogWebRTC;
293}
294#endif
295
296} // namespace WebCore
297
298#endif // ENABLE(MEDIA_STREAM)
299