Changing settings of a MediaStreamTrack clone should not alter the settings of the...
[WebKit-https.git] / Source / WebCore / platform / mediastream / MediaStreamTrackPrivate.cpp
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
45 namespace WebCore {
46
47 Ref<MediaStreamTrackPrivate> MediaStreamTrackPrivate::create(Ref<const Logger>&& logger, Ref<RealtimeMediaSource>&& source)
48 {
49     return create(WTFMove(logger), WTFMove(source), createCanonicalUUIDString());
50 }
51
52 Ref<MediaStreamTrackPrivate> MediaStreamTrackPrivate::create(Ref<const Logger>&& logger, Ref<RealtimeMediaSource>&& source, String&& id)
53 {
54     return adoptRef(*new MediaStreamTrackPrivate(WTFMove(logger), WTFMove(source), WTFMove(id)));
55 }
56
57 MediaStreamTrackPrivate::MediaStreamTrackPrivate(Ref<const Logger>&& logger, Ref<RealtimeMediaSource>&& source, String&& id)
58     : m_source(WTFMove(source))
59     , m_id(WTFMove(id))
60     , m_logger(WTFMove(logger))
61 #if !RELEASE_LOG_DISABLED
62     , m_logIdentifier(uniqueLogIdentifier())
63 #endif
64 {
65     UNUSED_PARAM(logger);
66 #if !RELEASE_LOG_DISABLED
67     m_source->setLogger(m_logger.copyRef(), m_logIdentifier);
68 #endif
69     m_source->addObserver(*this);
70 }
71
72 MediaStreamTrackPrivate::~MediaStreamTrackPrivate()
73 {
74     m_source->removeObserver(*this);
75 }
76
77 void MediaStreamTrackPrivate::forEachObserver(const WTF::Function<void(Observer&)>& apply) const
78 {
79     Vector<Observer*> observersCopy;
80     {
81         auto locker = holdLock(m_observersLock);
82         observersCopy = copyToVector(m_observers);
83     }
84     for (auto* observer : observersCopy) {
85         auto locker = holdLock(m_observersLock);
86         // Make sure the observer has not been destroyed.
87         if (!m_observers.contains(observer))
88             continue;
89         apply(*observer);
90     }
91 }
92
93 void MediaStreamTrackPrivate::addObserver(MediaStreamTrackPrivate::Observer& observer)
94 {
95     auto locker = holdLock(m_observersLock);
96     m_observers.add(&observer);
97 }
98
99 void MediaStreamTrackPrivate::removeObserver(MediaStreamTrackPrivate::Observer& observer)
100 {
101     auto locker = holdLock(m_observersLock);
102     m_observers.remove(&observer);
103 }
104
105 const String& MediaStreamTrackPrivate::label() const
106 {
107     return m_source->name();
108 }
109
110 void MediaStreamTrackPrivate::setContentHint(HintValue hintValue)
111 {
112     m_contentHint = hintValue;
113 }
114     
115 bool MediaStreamTrackPrivate::muted() const
116 {
117     return m_source->muted();
118 }
119
120 bool MediaStreamTrackPrivate::isCaptureTrack() const
121 {
122     return m_source->isCaptureSource();
123 }
124
125 void MediaStreamTrackPrivate::setEnabled(bool enabled)
126 {
127     if (m_isEnabled == enabled)
128         return;
129
130     // Always update the enabled state regardless of the track being ended.
131     m_isEnabled = enabled;
132
133     forEachObserver([this](auto& observer) {
134         observer.trackEnabledChanged(*this);
135     });
136 }
137
138 void MediaStreamTrackPrivate::endTrack()
139 {
140     if (m_isEnded)
141         return;
142
143     // Set m_isEnded to true before telling the source it can stop, so if this is the
144     // only track using the source and it does stop, we will only call each observer's
145     // trackEnded method once.
146     m_isEnded = true;
147     updateReadyState();
148
149     m_source->requestToEnd(*this);
150
151     forEachObserver([this](auto& observer) {
152         observer.trackEnded(*this);
153     });
154 }
155
156 Ref<MediaStreamTrackPrivate> MediaStreamTrackPrivate::clone()
157 {
158     auto clonedMediaStreamTrackPrivate = create(m_logger.copyRef(), m_source->clone());
159
160     clonedMediaStreamTrackPrivate->m_isEnabled = this->m_isEnabled;
161     clonedMediaStreamTrackPrivate->m_isEnded = this->m_isEnded;
162     clonedMediaStreamTrackPrivate->m_contentHint = this->m_contentHint;
163     clonedMediaStreamTrackPrivate->updateReadyState();
164
165     if (isProducingData())
166         clonedMediaStreamTrackPrivate->startProducingData();
167
168     return clonedMediaStreamTrackPrivate;
169 }
170
171 RealtimeMediaSource::Type MediaStreamTrackPrivate::type() const
172 {
173     return m_source->type();
174 }
175
176 const RealtimeMediaSourceSettings& MediaStreamTrackPrivate::settings() const
177 {
178     return m_source->settings();
179 }
180
181 const RealtimeMediaSourceCapabilities& MediaStreamTrackPrivate::capabilities() const
182 {
183     return m_source->capabilities();
184 }
185
186 void MediaStreamTrackPrivate::applyConstraints(const MediaConstraints& constraints, RealtimeMediaSource::ApplyConstraintsHandler&& completionHandler)
187 {
188     m_source->applyConstraints(constraints, WTFMove(completionHandler));
189 }
190
191 AudioSourceProvider* MediaStreamTrackPrivate::audioSourceProvider()
192 {
193 #if PLATFORM(COCOA)
194     if (!m_audioSourceProvider)
195         m_audioSourceProvider = WebAudioSourceProviderAVFObjC::create(*this);
196 #elif USE(LIBWEBRTC) && USE(GSTREAMER)
197     if (!m_audioSourceProvider)
198         m_audioSourceProvider = AudioSourceProviderGStreamer::create(*this);
199 #endif
200     return m_audioSourceProvider.get();
201 }
202
203 void MediaStreamTrackPrivate::sourceStarted()
204 {
205     forEachObserver([this](auto& observer) {
206         observer.trackStarted(*this);
207     });
208 }
209
210 void MediaStreamTrackPrivate::sourceStopped()
211 {
212     if (m_isEnded)
213         return;
214
215     m_isEnded = true;
216     updateReadyState();
217
218     forEachObserver([this](auto& observer) {
219         observer.trackEnded(*this);
220     });
221 }
222
223 void MediaStreamTrackPrivate::sourceMutedChanged()
224 {
225     forEachObserver([this](auto& observer) {
226         observer.trackMutedChanged(*this);
227     });
228 }
229
230 void MediaStreamTrackPrivate::sourceSettingsChanged()
231 {
232     forEachObserver([this](auto& observer) {
233         observer.trackSettingsChanged(*this);
234     });
235 }
236
237 bool MediaStreamTrackPrivate::preventSourceFromStopping()
238 {
239     // Do not allow the source to stop if we are still using it.
240     return !m_isEnded;
241 }
242
243 void MediaStreamTrackPrivate::videoSampleAvailable(MediaSample& mediaSample)
244 {
245     if (!m_haveProducedData) {
246         m_haveProducedData = true;
247         updateReadyState();
248     }
249
250     if (!enabled())
251         return;
252
253     mediaSample.setTrackID(id());
254     forEachObserver([&](auto& observer) {
255         observer.sampleBufferUpdated(*this, mediaSample);
256     });
257 }
258
259 // May get called on a background thread.
260 void MediaStreamTrackPrivate::audioSamplesAvailable(const MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount)
261 {
262     if (!m_haveProducedData) {
263         m_haveProducedData = true;
264         updateReadyState();
265     }
266
267     forEachObserver([&](auto& observer) {
268         observer.audioSamplesAvailable(*this, mediaTime, data, description, sampleCount);
269     });
270 }
271
272
273 void MediaStreamTrackPrivate::updateReadyState()
274 {
275     ReadyState state = ReadyState::None;
276
277     if (m_isEnded)
278         state = ReadyState::Ended;
279     else if (m_haveProducedData)
280         state = ReadyState::Live;
281
282     if (state == m_readyState)
283         return;
284
285     ALWAYS_LOG(LOGIDENTIFIER);
286
287     m_readyState = state;
288     forEachObserver([this](auto& observer) {
289         observer.readyStateChanged(*this);
290     });
291 }
292
293 #if !RELEASE_LOG_DISABLED
294 WTFLogChannel& MediaStreamTrackPrivate::logChannel() const
295 {
296     return LogWebRTC;
297 }
298 #endif
299
300 } // namespace WebCore
301
302 #endif // ENABLE(MEDIA_STREAM)