1/*
2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "MockMediaPlayerMediaSource.h"
28
29#if ENABLE(MEDIA_SOURCE)
30
31#include "MediaPlayer.h"
32#include "MediaSourcePrivateClient.h"
33#include "MockMediaSourcePrivate.h"
34#include <wtf/MainThread.h>
35#include <wtf/NeverDestroyed.h>
36#include <wtf/text/WTFString.h>
37
38namespace WebCore {
39
40// MediaPlayer Enigne Support
41void MockMediaPlayerMediaSource::registerMediaEngine(MediaEngineRegistrar registrar)
42{
43 registrar([] (MediaPlayer* player) { return std::make_unique<MockMediaPlayerMediaSource>(player); }, getSupportedTypes,
44 supportsType, 0, 0, 0, 0);
45}
46
47// FIXME: What does the word "cache" mean here?
48static const HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeCache()
49{
50 static const auto cache = makeNeverDestroyed(HashSet<String, ASCIICaseInsensitiveHash> {
51 "video/mock",
52 "audio/mock",
53 });
54 return cache;
55}
56
57void MockMediaPlayerMediaSource::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& supportedTypes)
58{
59 supportedTypes = mimeTypeCache();
60}
61
62MediaPlayer::SupportsType MockMediaPlayerMediaSource::supportsType(const MediaEngineSupportParameters& parameters)
63{
64 if (!parameters.isMediaSource)
65 return MediaPlayer::IsNotSupported;
66
67 auto containerType = parameters.type.containerType();
68 if (containerType.isEmpty() || !mimeTypeCache().contains(containerType))
69 return MediaPlayer::IsNotSupported;
70
71 auto codecs = parameters.type.parameter(ContentType::codecsParameter());
72 if (codecs.isEmpty())
73 return MediaPlayer::MayBeSupported;
74
75 if (codecs == "mock" || codecs == "kcom")
76 return MediaPlayer::IsSupported;
77
78 return MediaPlayer::MayBeSupported;
79}
80
81MockMediaPlayerMediaSource::MockMediaPlayerMediaSource(MediaPlayer* player)
82 : m_player(player)
83 , m_currentTime(MediaTime::zeroTime())
84 , m_readyState(MediaPlayer::HaveNothing)
85 , m_networkState(MediaPlayer::Empty)
86 , m_playing(false)
87 , m_seekCompleted(true)
88{
89}
90
91MockMediaPlayerMediaSource::~MockMediaPlayerMediaSource() = default;
92
93void MockMediaPlayerMediaSource::load(const String&)
94{
95 ASSERT_NOT_REACHED();
96}
97
98void MockMediaPlayerMediaSource::load(const String&, MediaSourcePrivateClient* source)
99{
100 m_mediaSourcePrivate = MockMediaSourcePrivate::create(*this, *source);
101}
102
103void MockMediaPlayerMediaSource::cancelLoad()
104{
105}
106
107void MockMediaPlayerMediaSource::play()
108{
109 m_playing = 1;
110 callOnMainThread([this] {
111 advanceCurrentTime();
112 });
113}
114
115void MockMediaPlayerMediaSource::pause()
116{
117 m_playing = 0;
118}
119
120FloatSize MockMediaPlayerMediaSource::naturalSize() const
121{
122 return FloatSize();
123}
124
125bool MockMediaPlayerMediaSource::hasVideo() const
126{
127 return m_mediaSourcePrivate ? m_mediaSourcePrivate->hasVideo() : false;
128}
129
130bool MockMediaPlayerMediaSource::hasAudio() const
131{
132 return m_mediaSourcePrivate ? m_mediaSourcePrivate->hasAudio() : false;
133}
134
135void MockMediaPlayerMediaSource::setVisible(bool)
136{
137}
138
139bool MockMediaPlayerMediaSource::seeking() const
140{
141 return !m_seekCompleted;
142}
143
144bool MockMediaPlayerMediaSource::paused() const
145{
146 return !m_playing;
147}
148
149MediaPlayer::NetworkState MockMediaPlayerMediaSource::networkState() const
150{
151 return m_networkState;
152}
153
154MediaPlayer::ReadyState MockMediaPlayerMediaSource::readyState() const
155{
156 return m_readyState;
157}
158
159MediaTime MockMediaPlayerMediaSource::maxMediaTimeSeekable() const
160{
161 return m_duration;
162}
163
164std::unique_ptr<PlatformTimeRanges> MockMediaPlayerMediaSource::buffered() const
165{
166 if (m_mediaSourcePrivate)
167 return m_mediaSourcePrivate->buffered();
168
169 return std::make_unique<PlatformTimeRanges>();
170}
171
172bool MockMediaPlayerMediaSource::didLoadingProgress() const
173{
174 return false;
175}
176
177void MockMediaPlayerMediaSource::setSize(const IntSize&)
178{
179}
180
181void MockMediaPlayerMediaSource::paint(GraphicsContext&, const FloatRect&)
182{
183}
184
185MediaTime MockMediaPlayerMediaSource::currentMediaTime() const
186{
187 return m_currentTime;
188}
189
190MediaTime MockMediaPlayerMediaSource::durationMediaTime() const
191{
192 return m_mediaSourcePrivate ? m_mediaSourcePrivate->duration() : MediaTime::zeroTime();
193}
194
195void MockMediaPlayerMediaSource::seekWithTolerance(const MediaTime& time, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance)
196{
197 if (!negativeTolerance && !positiveTolerance) {
198 m_currentTime = time;
199 m_mediaSourcePrivate->seekToTime(time);
200 } else
201 m_currentTime = m_mediaSourcePrivate->seekToTime(time, negativeTolerance, positiveTolerance);
202
203 if (m_seekCompleted) {
204 m_player->timeChanged();
205
206 if (m_playing)
207 callOnMainThread([this] {
208 advanceCurrentTime();
209 });
210 }
211}
212
213void MockMediaPlayerMediaSource::advanceCurrentTime()
214{
215 if (!m_mediaSourcePrivate)
216 return;
217
218 auto buffered = m_mediaSourcePrivate->buffered();
219 size_t pos = buffered->find(m_currentTime);
220 if (pos == notFound)
221 return;
222
223 bool ignoreError;
224 m_currentTime = std::min(m_duration, buffered->end(pos, ignoreError));
225 m_player->timeChanged();
226}
227
228void MockMediaPlayerMediaSource::updateDuration(const MediaTime& duration)
229{
230 if (m_duration == duration)
231 return;
232
233 m_duration = duration;
234 m_player->durationChanged();
235}
236
237void MockMediaPlayerMediaSource::setReadyState(MediaPlayer::ReadyState readyState)
238{
239 if (readyState == m_readyState)
240 return;
241
242 m_readyState = readyState;
243 m_player->readyStateChanged();
244}
245
246void MockMediaPlayerMediaSource::setNetworkState(MediaPlayer::NetworkState networkState)
247{
248 if (networkState == m_networkState)
249 return;
250
251 m_networkState = networkState;
252 m_player->networkStateChanged();
253}
254
255void MockMediaPlayerMediaSource::waitForSeekCompleted()
256{
257 m_seekCompleted = false;
258}
259
260void MockMediaPlayerMediaSource::seekCompleted()
261{
262 if (m_seekCompleted)
263 return;
264 m_seekCompleted = true;
265
266 m_player->timeChanged();
267
268 if (m_playing)
269 callOnMainThread([this] {
270 advanceCurrentTime();
271 });
272}
273
274Optional<VideoPlaybackQualityMetrics> MockMediaPlayerMediaSource::videoPlaybackQualityMetrics()
275{
276 return m_mediaSourcePrivate ? m_mediaSourcePrivate->videoPlaybackQualityMetrics() : WTF::nullopt;
277}
278
279}
280
281#endif
282