[GStreamer] Add support to copy YUV video textures into images
[WebKit-https.git] / Source / WebCore / platform / graphics / gstreamer / MediaPlayerPrivateGStreamerBase.h
1 /*
2  * Copyright (C) 2007, 2009 Apple Inc.  All rights reserved.
3  * Copyright (C) 2007 Collabora Ltd. All rights reserved.
4  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5  * Copyright (C) 2009, 2010, 2015, 2016 Igalia S.L
6  * Copyright (C) 2015, 2016 Metrological Group B.V.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * aint with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #ifndef MediaPlayerPrivateGStreamerBase_h
25 #define MediaPlayerPrivateGStreamerBase_h
26 #if ENABLE(VIDEO) && USE(GSTREAMER)
27
28 #include "GStreamerCommon.h"
29 #include "GStreamerEMEUtilities.h"
30 #include "MainThreadNotifier.h"
31 #include "MediaPlayerPrivate.h"
32 #include "PlatformLayer.h"
33 #include <glib.h>
34 #include <gst/gst.h>
35 #include <wtf/Condition.h>
36 #include <wtf/Forward.h>
37 #include <wtf/RunLoop.h>
38 #include <wtf/WeakPtr.h>
39 #include <wtf/threads/BinarySemaphore.h>
40
41 #if USE(GSTREAMER_GL)
42 #if USE(LIBEPOXY)
43 // Include the <epoxy/gl.h> header before <gst/gl/gl.h>.
44 #include <epoxy/gl.h>
45
46 // Workaround build issue with RPi userland GLESv2 headers and libepoxy <https://webkit.org/b/185639>
47 #if !GST_CHECK_VERSION(1, 14, 0)
48 #include <gst/gl/gstglconfig.h>
49 #if defined(GST_GL_HAVE_WINDOW_DISPMANX) && GST_GL_HAVE_WINDOW_DISPMANX
50 #define __gl2_h_
51 #undef GST_GL_HAVE_GLSYNC
52 #define GST_GL_HAVE_GLSYNC 1
53 #endif
54 #endif // !GST_CHECK_VERSION(1, 14, 0)
55 #endif // USE(LIBEPOXY)
56
57 #define GST_USE_UNSTABLE_API
58 #include <gst/gl/gl.h>
59 #undef GST_USE_UNSTABLE_API
60 #endif
61
62 #if USE(TEXTURE_MAPPER_GL)
63 #include "TextureMapperGL.h"
64 #if USE(NICOSIA)
65 #include "NicosiaContentLayerTextureMapperImpl.h"
66 #else
67 #include "TextureMapperPlatformLayerProxyProvider.h"
68 #endif
69 #endif
70
71 typedef struct _GstStreamVolume GstStreamVolume;
72 typedef struct _GstVideoInfo GstVideoInfo;
73 typedef struct _GstGLContext GstGLContext;
74 typedef struct _GstGLDisplay GstGLDisplay;
75
76 namespace WebCore {
77
78 class BitmapTextureGL;
79 class GLContext;
80 class GraphicsContext;
81 class GraphicsContext3D;
82 class IntSize;
83 class IntRect;
84 class VideoTextureCopierGStreamer;
85
86 #if USE(TEXTURE_MAPPER_GL)
87 class TextureMapperPlatformLayerProxy;
88 #endif
89
90 void registerWebKitGStreamerElements();
91
92 // Use eager initialization for the WeakPtrFactory since we call makeWeakPtr() from another thread.
93 class MediaPlayerPrivateGStreamerBase : public MediaPlayerPrivateInterface, public CanMakeWeakPtr<MediaPlayerPrivateGStreamerBase, WeakPtrFactoryInitialization::Eager>
94 #if USE(TEXTURE_MAPPER_GL)
95 #if USE(NICOSIA)
96     , public Nicosia::ContentLayerTextureMapperImpl::Client
97 #else
98     , public PlatformLayer
99 #endif
100 #endif
101 {
102     WTF_MAKE_FAST_ALLOCATED;
103 public:
104     static void initializeDebugCategory();
105
106     virtual ~MediaPlayerPrivateGStreamerBase();
107
108     FloatSize naturalSize() const override;
109
110     void setVolume(float) override;
111     float volume() const override;
112
113 #if USE(GSTREAMER_GL)
114     bool ensureGstGLContext();
115     GstContext* requestGLContext(const char* contextType);
116 #endif
117     void setMuted(bool) override;
118     bool muted() const;
119
120     MediaPlayer::NetworkState networkState() const override;
121     MediaPlayer::ReadyState readyState() const override;
122
123     void setVisible(bool) override { }
124     void setSize(const IntSize&) override;
125
126     // Prefer MediaTime based methods over float based.
127     float duration() const override { return durationMediaTime().toFloat(); }
128     double durationDouble() const override { return durationMediaTime().toDouble(); }
129     MediaTime durationMediaTime() const override { return MediaTime::zeroTime(); }
130     float currentTime() const override { return currentMediaTime().toFloat(); }
131     double currentTimeDouble() const override { return currentMediaTime().toDouble(); }
132     MediaTime currentMediaTime() const override { return MediaTime::zeroTime(); }
133     void seek(float time) override { seek(MediaTime::createWithFloat(time)); }
134     void seekDouble(double time) override { seek(MediaTime::createWithDouble(time)); }
135     void seek(const MediaTime&) override { }
136     float maxTimeSeekable() const override { return maxMediaTimeSeekable().toFloat(); }
137     MediaTime maxMediaTimeSeekable() const override { return MediaTime::zeroTime(); }
138     double minTimeSeekable() const override { return minMediaTimeSeekable().toFloat(); }
139     MediaTime minMediaTimeSeekable() const override { return MediaTime::zeroTime(); }
140
141     void paint(GraphicsContext&, const FloatRect&) override;
142
143     bool hasSingleSecurityOrigin() const override { return true; }
144     virtual MediaTime maxTimeLoaded() const { return MediaTime::zeroTime(); }
145
146     bool supportsFullscreen() const override;
147
148     MediaPlayer::MovieLoadType movieLoadType() const override;
149     virtual bool isLiveStream() const = 0;
150
151     MediaPlayer* mediaPlayer() const { return m_player; }
152
153     unsigned decodedFrameCount() const override;
154     unsigned droppedFrameCount() const override;
155     unsigned audioDecodedByteCount() const override;
156     unsigned videoDecodedByteCount() const override;
157
158     void acceleratedRenderingStateChanged() override;
159
160 #if USE(TEXTURE_MAPPER_GL)
161     PlatformLayer* platformLayer() const override;
162 #if PLATFORM(WIN_CAIRO)
163     // FIXME: Accelerated rendering has not been implemented for WinCairo yet.
164     bool supportsAcceleratedRendering() const override { return false; }
165 #else
166     bool supportsAcceleratedRendering() const override { return true; }
167 #endif
168 #endif
169
170 #if ENABLE(ENCRYPTED_MEDIA)
171     void cdmInstanceAttached(CDMInstance&) override;
172     void cdmInstanceDetached(CDMInstance&) override;
173     void handleProtectionEvent(GstEvent*);
174     virtual void attemptToDecryptWithLocalInstance();
175     void attemptToDecryptWithInstance(CDMInstance&) final;
176     void initializationDataEncountered(InitData&&);
177     void setWaitingForKey(bool);
178     bool waitingForKey() const override;
179 #endif
180
181     static bool supportsKeySystem(const String& keySystem, const String& mimeType);
182     static MediaPlayer::SupportsType extendedSupportsType(const MediaEngineSupportParameters&, MediaPlayer::SupportsType);
183
184 #if USE(GSTREAMER_GL)
185     bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject, GC3Denum, GC3Dint, GC3Denum, GC3Denum, GC3Denum, bool, bool) override;
186     NativeImagePtr nativeImageForCurrentTime() override;
187 #endif
188
189     void setVideoSourceOrientation(ImageOrientation);
190     GstElement* pipeline() const { return m_pipeline.get(); }
191
192     virtual bool handleSyncMessage(GstMessage*);
193
194 protected:
195     MediaPlayerPrivateGStreamerBase(MediaPlayer*);
196     virtual GstElement* createVideoSink();
197
198 #if USE(GSTREAMER_HOLEPUNCH)
199     GstElement* createHolePunchVideoSink();
200     void pushNextHolePunchBuffer();
201     bool shouldIgnoreIntrinsicSize() final { return true; }
202 #endif
203
204 #if USE(GSTREAMER_GL)
205     static GstFlowReturn newSampleCallback(GstElement*, MediaPlayerPrivateGStreamerBase*);
206     static GstFlowReturn newPrerollCallback(GstElement*, MediaPlayerPrivateGStreamerBase*);
207     void flushCurrentBuffer();
208     GstElement* createGLAppSink();
209     GstElement* createVideoSinkGL();
210     GstGLContext* gstGLContext() const { return m_glContext.get(); }
211     GstGLDisplay* gstGLDisplay() const { return m_glDisplay.get(); }
212     void ensureGLVideoSinkContext();
213 #endif
214
215 #if USE(TEXTURE_MAPPER_GL)
216     void pushTextureToCompositor();
217 #if USE(NICOSIA)
218     void swapBuffersIfNeeded() override;
219 #else
220     RefPtr<TextureMapperPlatformLayerProxy> proxy() const override;
221     void swapBuffersIfNeeded() override;
222 #endif
223 #endif
224
225     GstElement* videoSink() const { return m_videoSink.get(); }
226
227     void setStreamVolumeElement(GstStreamVolume*);
228     virtual GstElement* createAudioSink() { return 0; }
229     virtual GstElement* audioSink() const { return 0; }
230
231     void setPipeline(GstElement*);
232
233     void triggerRepaint(GstSample*);
234     void repaint();
235     void cancelRepaint(bool destroying = false);
236
237     static void repaintCallback(MediaPlayerPrivateGStreamerBase*, GstSample*);
238     static void repaintCancelledCallback(MediaPlayerPrivateGStreamerBase*);
239
240     void notifyPlayerOfVolumeChange();
241     void notifyPlayerOfMute();
242
243     static void volumeChangedCallback(MediaPlayerPrivateGStreamerBase*);
244     static void muteChangedCallback(MediaPlayerPrivateGStreamerBase*);
245
246 #if USE(TEXTURE_MAPPER_GL)
247     void updateTextureMapperFlags();
248     TextureMapperGL::Flags m_textureMapperFlags;
249 #endif
250
251     enum MainThreadNotification {
252         VideoChanged = 1 << 0,
253         AudioChanged = 1 << 2,
254         VolumeChanged = 1 << 3,
255         MuteChanged = 1 << 4,
256 #if ENABLE(VIDEO_TRACK)
257         TextChanged = 1 << 5,
258 #endif
259         SizeChanged = 1 << 6,
260         StreamCollectionChanged = 1 << 7
261     };
262
263     Ref<MainThreadNotifier<MainThreadNotification>> m_notifier;
264     MediaPlayer* m_player;
265     GRefPtr<GstElement> m_pipeline;
266     GRefPtr<GstStreamVolume> m_volumeElement;
267     GRefPtr<GstElement> m_videoSink;
268     GRefPtr<GstElement> m_fpsSink;
269     MediaPlayer::ReadyState m_readyState;
270     mutable MediaPlayer::NetworkState m_networkState;
271     IntSize m_size;
272
273     mutable Lock m_sampleMutex;
274     GRefPtr<GstSample> m_sample;
275     mutable FloatSize m_videoSize;
276
277     bool m_usingFallbackVideoSink { false };
278     bool m_renderingCanBeAccelerated { false };
279
280     Condition m_drawCondition;
281     Lock m_drawMutex;
282     bool m_destroying { false };
283     RunLoop::Timer<MediaPlayerPrivateGStreamerBase> m_drawTimer;
284
285 #if USE(TEXTURE_MAPPER_GL)
286 #if USE(NICOSIA)
287     Ref<Nicosia::ContentLayer> m_nicosiaLayer;
288 #else
289     RefPtr<TextureMapperPlatformLayerProxy> m_platformLayerProxy;
290 #endif
291 #endif
292
293 #if USE(GSTREAMER_GL)
294     GRefPtr<GstGLContext> m_glContext;
295     GRefPtr<GstGLDisplay> m_glDisplay;
296     GRefPtr<GstContext> m_glDisplayElementContext;
297     GRefPtr<GstContext> m_glAppElementContext;
298     std::unique_ptr<VideoTextureCopierGStreamer> m_videoTextureCopier;
299
300     GRefPtr<GstGLColorConvert> m_colorConvert;
301     GRefPtr<GstCaps> m_colorConvertInputCaps;
302     GRefPtr<GstCaps> m_colorConvertOutputCaps;
303 #endif
304
305     ImageOrientation m_videoSourceOrientation;
306
307 #if ENABLE(ENCRYPTED_MEDIA)
308     BinarySemaphore m_cdmAttachmentSemaphore;
309     RefPtr<const CDMInstance> m_cdmInstance;
310
311     Lock m_protectionMutex; // Guards access to m_handledProtectionEvents.
312     HashSet<uint32_t> m_handledProtectionEvents;
313
314     bool m_waitingForKey { false };
315 #endif
316
317     enum class WebKitGstVideoDecoderPlatform { Video4Linux };
318     Optional<WebKitGstVideoDecoderPlatform> m_videoDecoderPlatform;
319
320 private:
321     FloatSize naturalSizeFromCaps(GstCaps*) const;
322     bool doSamplesHaveDifferentNaturalSizes(GstSample* sampleA, GstSample* sampleB) const;
323 };
324
325 }
326
327 #endif // USE(GSTREAMER)
328 #endif