[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / platform / graphics / holepunch / MediaPlayerPrivateHolePunch.cpp
1 /*
2  * Copyright (C) 2019 Igalia S.L
3  * Copyright (C) 2019 Metrological Group B.V.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * aint with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "MediaPlayerPrivateHolePunch.h"
23
24 #if USE(EXTERNAL_HOLEPUNCH)
25 #include "MediaPlayer.h"
26 #include "TextureMapperPlatformLayerBuffer.h"
27 #include "TextureMapperPlatformLayerProxy.h"
28
29 namespace WebCore {
30
31 static const FloatSize s_holePunchDefaultFrameSize(1280, 720);
32
33 MediaPlayerPrivateHolePunch::MediaPlayerPrivateHolePunch(MediaPlayer* player)
34     : m_player(player)
35     , m_readyTimer(RunLoop::main(), this, &MediaPlayerPrivateHolePunch::notifyReadyState)
36 #if USE(NICOSIA)
37     , m_nicosiaLayer(Nicosia::ContentLayer::create(Nicosia::ContentLayerTextureMapperImpl::createFactory(*this)))
38 #else
39     , m_platformLayerProxy(adoptRef(new TextureMapperPlatformLayerProxy()))
40 #endif
41 {
42     pushNextHolePunchBuffer();
43
44     // Delay the configuration of the HTMLMediaElement, as during this stage this is not
45     // the MediaPlayer private yet and calls from HTMLMediaElement won't reach this.
46     m_readyTimer.startOneShot(0_s);
47 }
48
49 MediaPlayerPrivateHolePunch::~MediaPlayerPrivateHolePunch()
50 {
51 #if USE(NICOSIA)
52     downcast<Nicosia::ContentLayerTextureMapperImpl>(m_nicosiaLayer->impl()).invalidateClient();
53 #endif
54 }
55
56 PlatformLayer* MediaPlayerPrivateHolePunch::platformLayer() const
57 {
58 #if USE(NICOSIA)
59     return m_nicosiaLayer.ptr();
60 #else
61     return const_cast<MediaPlayerPrivateHolePunch*>(this);
62 #endif
63 }
64
65 FloatSize MediaPlayerPrivateHolePunch::naturalSize() const
66 {
67     // When using the holepuch we may not be able to get the video frames size, so we can't use
68     // it. But we need to report some non empty naturalSize for the player's GraphicsLayer
69     // to be properly created.
70     return s_holePunchDefaultFrameSize;
71 }
72
73 void MediaPlayerPrivateHolePunch::pushNextHolePunchBuffer()
74 {
75     auto proxyOperation =
76         [this](TextureMapperPlatformLayerProxy& proxy)
77         {
78             LockHolder holder(proxy.lock());
79             std::unique_ptr<TextureMapperPlatformLayerBuffer> layerBuffer = makeUnique<TextureMapperPlatformLayerBuffer>(0, m_size, TextureMapperGL::ShouldNotBlend, GL_DONT_CARE);
80             proxy.pushNextBuffer(WTFMove(layerBuffer));
81         };
82
83 #if USE(NICOSIA)
84     proxyOperation(downcast<Nicosia::ContentLayerTextureMapperImpl>(m_nicosiaLayer->impl()).proxy());
85 #else
86     proxyOperation(*m_platformLayerProxy);
87 #endif
88 }
89
90 void MediaPlayerPrivateHolePunch::swapBuffersIfNeeded()
91 {
92     pushNextHolePunchBuffer();
93 }
94
95 #if !USE(NICOSIA)
96 RefPtr<TextureMapperPlatformLayerProxy> MediaPlayerPrivateHolePunch::proxy() const
97 {
98     return m_platformLayerProxy.copyRef();
99 }
100 #endif
101
102 static HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeCache()
103 {
104     static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> cache;
105     static bool typeListInitialized = false;
106
107     if (typeListInitialized)
108         return cache;
109
110     const char* mimeTypes[] = {
111         "video/holepunch"
112     };
113
114     for (unsigned i = 0; i < (sizeof(mimeTypes) / sizeof(*mimeTypes)); ++i)
115         cache.get().add(String(mimeTypes[i]));
116
117     typeListInitialized = true;
118
119     return cache;
120 }
121
122 void MediaPlayerPrivateHolePunch::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types)
123 {
124     types = mimeTypeCache();
125 }
126
127 MediaPlayer::SupportsType MediaPlayerPrivateHolePunch::supportsType(const MediaEngineSupportParameters& parameters)
128 {
129     auto containerType = parameters.type.containerType();
130
131     // Spec says we should not return "probably" if the codecs string is empty.
132     if (!containerType.isEmpty() && mimeTypeCache().contains(containerType)) {
133         if (parameters.type.codecs().isEmpty())
134             return MediaPlayer::MayBeSupported;
135
136         return MediaPlayer::IsSupported;
137     }
138
139     return MediaPlayer::IsNotSupported;
140 }
141
142 void MediaPlayerPrivateHolePunch::registerMediaEngine(MediaEngineRegistrar registrar)
143 {
144     registrar([](MediaPlayer* player) { return makeUnique<MediaPlayerPrivateHolePunch>(player); },
145         getSupportedTypes, supportsType, nullptr, nullptr, nullptr, nullptr);
146 }
147
148 void MediaPlayerPrivateHolePunch::notifyReadyState()
149 {
150     // Notify the ready state so the GraphicsLayer gets created.
151     m_player->readyStateChanged();
152 }
153 }
154 #endif // USE(EXTERNAL_HOLEPUNCH)