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