RELEASE_LOG should not be Cocoa specific
[WebKit.git] / Source / WebCore / platform / graphics / gstreamer / MediaPlayerPrivateGStreamer.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) 2014 Cable Television Laboratories, Inc.
6  * Copyright (C) 2009, 2019 Igalia S.L
7  * Copyright (C) 2015, 2019 Metrological Group B.V.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * aint with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #pragma once
26
27 #if ENABLE(VIDEO) && USE(GSTREAMER)
28
29 #include "GStreamerCommon.h"
30 #include "GStreamerEMEUtilities.h"
31 #include "Logging.h"
32 #include "MainThreadNotifier.h"
33 #include "MediaPlayerPrivate.h"
34 #include "PlatformLayer.h"
35 #include <glib.h>
36 #include <gst/gst.h>
37 #include <gst/pbutils/install-plugins.h>
38 #include <wtf/Atomics.h>
39 #include <wtf/Condition.h>
40 #include <wtf/Forward.h>
41 #include <wtf/LoggerHelper.h>
42 #include <wtf/RunLoop.h>
43 #include <wtf/WeakPtr.h>
44
45 #if ENABLE(VIDEO_TRACK)
46 #include "TrackPrivateBaseGStreamer.h"
47 #include <wtf/text/AtomStringHash.h>
48 #endif
49 typedef struct _GstMpegtsSection GstMpegtsSection;
50
51 #if USE(GSTREAMER_GL)
52 #if USE(LIBEPOXY)
53 // Include the <epoxy/gl.h> header before <gst/gl/gl.h>.
54 #include <epoxy/gl.h>
55
56 // Workaround build issue with RPi userland GLESv2 headers and libepoxy <https://webkit.org/b/185639>
57 #if !GST_CHECK_VERSION(1, 14, 0)
58 #include <gst/gl/gstglconfig.h>
59 #if defined(GST_GL_HAVE_WINDOW_DISPMANX) && GST_GL_HAVE_WINDOW_DISPMANX
60 #define __gl2_h_
61 #undef GST_GL_HAVE_GLSYNC
62 #define GST_GL_HAVE_GLSYNC 1
63 #endif
64 #endif // !GST_CHECK_VERSION(1, 14, 0)
65 #endif // USE(LIBEPOXY)
66
67 #define GST_USE_UNSTABLE_API
68 #include <gst/gl/gl.h>
69 #undef GST_USE_UNSTABLE_API
70 #endif
71
72 #if USE(TEXTURE_MAPPER_GL)
73 #include "TextureMapperGL.h"
74 #if USE(NICOSIA)
75 #include "NicosiaContentLayerTextureMapperImpl.h"
76 #else
77 #include "TextureMapperPlatformLayerProxyProvider.h"
78 #endif
79 #endif
80
81 #if ENABLE(ENCRYPTED_MEDIA)
82 #include "CDMProxy.h"
83 #endif
84
85 typedef struct _GstStreamVolume GstStreamVolume;
86 typedef struct _GstVideoInfo GstVideoInfo;
87
88 #if USE(WPE_VIDEO_PLANE_DISPLAY_DMABUF)
89 struct wpe_video_plane_display_dmabuf_source;
90 #endif
91
92 namespace WebCore {
93
94 class BitmapTextureGL;
95 class GLContext;
96 class GraphicsContext;
97 class GraphicsContextGLOpenGL;
98 class IntSize;
99 class IntRect;
100 class VideoTextureCopierGStreamer;
101
102 #if USE(TEXTURE_MAPPER_GL)
103 class TextureMapperPlatformLayerProxy;
104 #endif
105
106 #if ENABLE(WEB_AUDIO)
107 class AudioSourceProvider;
108 class AudioSourceProviderGStreamer;
109 #endif
110
111 class AudioTrackPrivateGStreamer;
112 class InbandMetadataTextTrackPrivateGStreamer;
113 class InbandTextTrackPrivateGStreamer;
114 class MediaPlayerRequestInstallMissingPluginsCallback;
115 class VideoTrackPrivateGStreamer;
116
117 void registerWebKitGStreamerElements();
118
119 // Use eager initialization for the WeakPtrFactory since we call makeWeakPtr() from another thread.
120 class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface
121     , public CanMakeWeakPtr<MediaPlayerPrivateGStreamer, WeakPtrFactoryInitialization::Eager>
122     , private LoggerHelper
123 #if USE(TEXTURE_MAPPER_GL)
124 #if USE(NICOSIA)
125     , public Nicosia::ContentLayerTextureMapperImpl::Client
126 #else
127     , public PlatformLayer
128 #endif
129 #endif
130 {
131     WTF_MAKE_FAST_ALLOCATED;
132 public:
133     MediaPlayerPrivateGStreamer(MediaPlayer*);
134     virtual ~MediaPlayerPrivateGStreamer();
135
136     static void registerMediaEngine(MediaEngineRegistrar);
137     static MediaPlayer::SupportsType extendedSupportsType(const MediaEngineSupportParameters&, MediaPlayer::SupportsType);
138     static bool supportsKeySystem(const String& keySystem, const String& mimeType);
139
140     bool hasVideo() const final { return m_hasVideo; }
141     bool hasAudio() const final { return m_hasAudio; }
142     void load(const String &url) override;
143 #if ENABLE(MEDIA_SOURCE)
144     void load(const String& url, MediaSourcePrivateClient*) override;
145 #endif
146 #if ENABLE(MEDIA_STREAM)
147     void load(MediaStreamPrivate&) override;
148 #endif
149     void cancelLoad() final;
150     void prepareToPlay() final;
151     void play() final;
152     void pause() override;
153     bool paused() const final;
154     bool seeking() const override { return m_isSeeking; }
155     void seek(const MediaTime&) override;
156     void setRate(float) override;
157     double rate() const final;
158     void setPreservesPitch(bool) final; 
159     void setPreload(MediaPlayer::Preload) final;
160     FloatSize naturalSize() const final;
161     void setVolume(float) final;
162     float volume() const final;
163     void setMuted(bool) final;
164     MediaPlayer::NetworkState networkState() const final;
165     MediaPlayer::ReadyState readyState() const final;
166     void setVisible(bool) final { }
167     void setSize(const IntSize&) final;
168     // Prefer MediaTime based methods over float based.
169     float duration() const final { return durationMediaTime().toFloat(); }
170     double durationDouble() const final { return durationMediaTime().toDouble(); }
171     MediaTime durationMediaTime() const override;
172     float currentTime() const final { return currentMediaTime().toFloat(); }
173     double currentTimeDouble() const final { return currentMediaTime().toDouble(); }
174     MediaTime currentMediaTime() const override;
175     std::unique_ptr<PlatformTimeRanges> buffered() const override;
176     void seek(float time) final { seek(MediaTime::createWithFloat(time)); }
177     void seekDouble(double time) final { seek(MediaTime::createWithDouble(time)); }
178     float maxTimeSeekable() const final { return maxMediaTimeSeekable().toFloat(); }
179     MediaTime maxMediaTimeSeekable() const override;
180     double minTimeSeekable() const final { return minMediaTimeSeekable().toFloat(); }
181     MediaTime minMediaTimeSeekable() const final { return MediaTime::zeroTime(); }
182     bool didLoadingProgress() const final;
183     unsigned long long totalBytes() const final;
184     bool hasSingleSecurityOrigin() const final;
185     Optional<bool> wouldTaintOrigin(const SecurityOrigin&) const final;
186     void simulateAudioInterruption() final;
187 #if ENABLE(WEB_AUDIO)
188     AudioSourceProvider* audioSourceProvider() final;
189 #endif
190     void paint(GraphicsContext&, const FloatRect&) final;
191     bool supportsFullscreen() const final;
192     MediaPlayer::MovieLoadType movieLoadType() const final;
193
194     Optional<VideoPlaybackQualityMetrics> videoPlaybackQualityMetrics() final;
195     void acceleratedRenderingStateChanged() final;
196
197 #if USE(TEXTURE_MAPPER_GL)
198     PlatformLayer* platformLayer() const override;
199 #if PLATFORM(WIN_CAIRO)
200     // FIXME: Accelerated rendering has not been implemented for WinCairo yet.
201     bool supportsAcceleratedRendering() const override { return false; }
202 #else
203     bool supportsAcceleratedRendering() const override { return true; }
204 #endif
205 #endif
206
207 #if ENABLE(ENCRYPTED_MEDIA)
208     void cdmInstanceAttached(CDMInstance&) final;
209     void cdmInstanceDetached(CDMInstance&) final;
210     void attemptToDecryptWithInstance(CDMInstance&) final;
211     bool waitingForKey() const final;
212
213     void handleProtectionEvent(GstEvent*);
214 #endif
215
216 #if USE(GSTREAMER_GL)
217     bool copyVideoTextureToPlatformTexture(GraphicsContextGLOpenGL*, PlatformGLObject, GCGLenum, GCGLint, GCGLenum, GCGLenum, GCGLenum, bool, bool) override;
218     NativeImagePtr nativeImageForCurrentTime() override;
219 #endif
220
221     void enableTrack(TrackPrivateBaseGStreamer::TrackType, unsigned index);
222
223     // Append pipeline interface
224     // FIXME: Use the client interface pattern, AppendPipeline does not need the full interface to this class just for these two functions.
225     bool handleSyncMessage(GstMessage*);
226     void handleMessage(GstMessage*);
227
228     void triggerRepaint(GstSample*);
229 #if USE(GSTREAMER_GL)
230     void flushCurrentBuffer();
231 #endif
232
233     const Logger& logger() const final { return m_logger; }
234     const char* logClassName() const override { return "MediaPlayerPrivateGStreamer"; }
235     const void* logIdentifier() const final { return reinterpret_cast<const void*>(m_logIdentifier); }
236     WTFLogChannel& logChannel() const override;
237
238     const void* mediaPlayerLogIdentifier() { return logIdentifier(); }
239     const Logger& mediaPlayerLogger() { return logger(); }
240
241 protected:
242     enum MainThreadNotification {
243         VideoChanged = 1 << 0,
244         VideoCapsChanged = 1 << 1,
245         AudioChanged = 1 << 2,
246         VolumeChanged = 1 << 3,
247         MuteChanged = 1 << 4,
248 #if ENABLE(VIDEO_TRACK)
249         TextChanged = 1 << 5,
250 #endif
251         SizeChanged = 1 << 6,
252         StreamCollectionChanged = 1 << 7
253     };
254
255     static bool isAvailable();
256
257     virtual void durationChanged();
258     virtual void sourceSetup(GstElement*);
259     virtual void configurePlaySink() { }
260     virtual bool changePipelineState(GstState);
261     virtual void updatePlaybackRate();
262
263 #if USE(GSTREAMER_HOLEPUNCH)
264     GstElement* createHolePunchVideoSink();
265     void pushNextHolePunchBuffer();
266     bool shouldIgnoreIntrinsicSize() final { return true; }
267 #endif
268
269 #if USE(GSTREAMER_GL)
270     GstElement* createVideoSinkGL();
271 #endif
272
273 #if USE(TEXTURE_MAPPER_GL)
274     void pushTextureToCompositor();
275 #if USE(NICOSIA)
276     void swapBuffersIfNeeded() final;
277 #else
278     RefPtr<TextureMapperPlatformLayerProxy> proxy() const final;
279     void swapBuffersIfNeeded() final;
280 #endif
281 #endif
282
283     GstElement* videoSink() const { return m_videoSink.get(); }
284
285     void setStreamVolumeElement(GstStreamVolume*);
286
287     void setPipeline(GstElement*);
288     GstElement* pipeline() const { return m_pipeline.get(); }
289
290     void repaint();
291     void cancelRepaint(bool destroying = false);
292
293     static void repaintCallback(MediaPlayerPrivateGStreamer*, GstSample*);
294     static void repaintCancelledCallback(MediaPlayerPrivateGStreamer*);
295
296     void notifyPlayerOfVolumeChange();
297     void notifyPlayerOfMute();
298
299     static void volumeChangedCallback(MediaPlayerPrivateGStreamer*);
300     static void muteChangedCallback(MediaPlayerPrivateGStreamer*);
301
302     void readyTimerFired();
303
304     void notifyPlayerOfVideo();
305     void notifyPlayerOfVideoCaps();
306     void notifyPlayerOfAudio();
307
308 #if ENABLE(VIDEO_TRACK)
309     void notifyPlayerOfText();
310     void newTextSample();
311 #endif
312
313     void ensureAudioSourceProvider();
314     void setAudioStreamProperties(GObject*);
315
316     static void setAudioStreamPropertiesCallback(MediaPlayerPrivateGStreamer*, GObject*);
317
318     static void sourceSetupCallback(MediaPlayerPrivateGStreamer*, GstElement*);
319     static void videoChangedCallback(MediaPlayerPrivateGStreamer*);
320     static void videoSinkCapsChangedCallback(MediaPlayerPrivateGStreamer*);
321     static void audioChangedCallback(MediaPlayerPrivateGStreamer*);
322 #if ENABLE(VIDEO_TRACK)
323     static void textChangedCallback(MediaPlayerPrivateGStreamer*);
324     static GstFlowReturn newTextSampleCallback(MediaPlayerPrivateGStreamer*);
325 #endif
326
327     void timeChanged();
328     void loadingFailed(MediaPlayer::NetworkState, MediaPlayer::ReadyState = MediaPlayer::ReadyState::HaveNothing, bool forceNotifications = false);
329     void loadStateChanged();
330
331 #if USE(TEXTURE_MAPPER_GL)
332     void updateTextureMapperFlags();
333 #endif
334
335     Ref<MainThreadNotifier<MainThreadNotification>> m_notifier;
336     MediaPlayer* m_player;
337     mutable MediaTime m_cachedPosition;
338     mutable MediaTime m_cachedDuration;
339     bool m_canFallBackToLastFinishedSeekPosition { false };
340     bool m_isChangingRate { false };
341     bool m_didDownloadFinish { false };
342     bool m_didErrorOccur { false };
343     mutable bool m_isEndReached { false };
344     mutable bool m_isLiveStream { false };
345     bool m_isPaused { true };
346     float m_playbackRate { 1 };
347     GstState m_currentState;
348     GstState m_oldState;
349     GstState m_requestedState { GST_STATE_VOID_PENDING };
350     bool m_shouldResetPipeline { false };
351     bool m_isSeeking { false };
352     bool m_isSeekPending { false };
353     MediaTime m_seekTime;
354     GRefPtr<GstElement> m_source { nullptr };
355     bool m_areVolumeAndMuteInitialized { false };
356
357 #if USE(TEXTURE_MAPPER_GL)
358     TextureMapperGL::Flags m_textureMapperFlags;
359 #endif
360
361     GRefPtr<GstStreamVolume> m_volumeElement;
362     GRefPtr<GstElement> m_videoSink;
363     GRefPtr<GstElement> m_pipeline;
364     IntSize m_size;
365
366     MediaPlayer::ReadyState m_readyState { MediaPlayer::ReadyState::HaveNothing };
367     mutable MediaPlayer::NetworkState m_networkState { MediaPlayer::NetworkState::Empty };
368
369     mutable Lock m_sampleMutex;
370     GRefPtr<GstSample> m_sample;
371
372     mutable FloatSize m_videoSize;
373     bool m_isUsingFallbackVideoSink { false };
374     bool m_canRenderingBeAccelerated { false };
375
376     bool m_isBeingDestroyed { false };
377
378 #if USE(GSTREAMER_GL)
379     std::unique_ptr<VideoTextureCopierGStreamer> m_videoTextureCopier;
380     GRefPtr<GstGLColorConvert> m_colorConvert;
381     GRefPtr<GstCaps> m_colorConvertInputCaps;
382     GRefPtr<GstCaps> m_colorConvertOutputCaps;
383 #endif
384
385     ImageOrientation m_videoSourceOrientation;
386
387 #if ENABLE(ENCRYPTED_MEDIA)
388     Lock m_cdmAttachmentMutex;
389     Condition m_cdmAttachmentCondition;
390     RefPtr<CDMInstanceProxy> m_cdmInstance;
391
392     Lock m_protectionMutex; // Guards access to m_handledProtectionEvents.
393     HashSet<uint32_t> m_handledProtectionEvents;
394
395     bool m_isWaitingForKey { false };
396 #endif
397
398     Optional<GstVideoDecoderPlatform> m_videoDecoderPlatform;
399
400 private:
401     bool isPlayerShuttingDown() const { return m_isPlayerShuttingDown.load(); }
402     MediaTime maxTimeLoaded() const;
403     void setVideoSourceOrientation(ImageOrientation);
404     MediaTime platformDuration() const;
405     bool isMuted() const;
406     void commitLoad();
407     void fillTimerFired();
408     void didEnd();
409
410     GstElement* createVideoSink();
411     GstElement* createAudioSink();
412     GstElement* audioSink() const;
413
414     friend class MediaPlayerFactoryGStreamer;
415     static void getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>&);
416     static MediaPlayer::SupportsType supportsType(const MediaEngineSupportParameters&);
417
418     void syncOnClock(bool sync);
419
420     MediaTime playbackPosition() const;
421
422     virtual void updateStates();
423     virtual void asyncStateChangeDone();
424
425     void createGSTPlayBin(const URL&, const String& pipelineName);
426
427     bool loadNextLocation();
428     void mediaLocationChanged(GstMessage*);
429
430     virtual void updateDownloadBufferingFlag();
431     void processBufferingStats(GstMessage*);
432     void updateBufferingStatus(GstBufferingMode, double percentage);
433     void updateMaxTimeLoaded(double percentage);
434
435 #if ENABLE(VIDEO_TRACK)
436 #if USE(GSTREAMER_MPEGTS)
437     void processMpegTsSection(GstMpegtsSection*);
438 #endif
439
440     void processTableOfContents(GstMessage*);
441     void processTableOfContentsEntry(GstTocEntry*);
442
443     void purgeInvalidAudioTracks(Vector<String> validTrackIds);
444     void purgeInvalidVideoTracks(Vector<String> validTrackIds);
445     void purgeInvalidTextTracks(Vector<String> validTrackIds);
446 #endif
447     virtual bool doSeek(const MediaTime& position, float rate, GstSeekFlags seekType);
448
449     String engineDescription() const override { return "GStreamer"; }
450     bool didPassCORSAccessCheck() const override;
451     bool canSaveMediaData() const override;
452
453     void purgeOldDownloadFiles(const char*);
454     static void uriDecodeBinElementAddedCallback(GstBin*, GstElement*, MediaPlayerPrivateGStreamer*);
455     static void downloadBufferFileCreatedCallback(MediaPlayerPrivateGStreamer*);
456
457     void setPlaybinURL(const URL& urlString);
458     void loadFull(const String& url, const String& pipelineName);
459
460     void updateTracks();
461     void clearTracks();
462
463 #if ENABLE(ENCRYPTED_MEDIA)
464     bool isCDMAttached() const { return m_cdmInstance; }
465     void attemptToDecryptWithLocalInstance();
466     void initializationDataEncountered(InitData&&);
467     InitData parseInitDataFromProtectionMessage(GstMessage*);
468     bool waitForCDMAttachment();
469 #endif
470
471     Atomic<bool> m_isPlayerShuttingDown;
472 #if ENABLE(VIDEO_TRACK)
473     GRefPtr<GstElement> m_textAppSink;
474     GRefPtr<GstPad> m_textAppSinkPad;
475 #endif
476     GstStructure* m_mediaLocations { nullptr };
477     int m_mediaLocationCurrentIndex { 0 };
478     bool m_isPlaybackRatePaused { false };
479     MediaTime m_timeOfOverlappingSeek;
480     float m_lastPlaybackRate { 1 };
481     Timer m_fillTimer;
482     MediaTime m_maxTimeLoaded;
483     bool m_loadingStalled { false };
484     MediaPlayer::Preload m_preload;
485     bool m_isDelayingLoad { false };
486     mutable MediaTime m_maxTimeLoadedAtLastDidLoadingProgress;
487     bool m_hasVideo { false };
488     bool m_hasAudio { false };
489     Condition m_drawCondition;
490     Lock m_drawMutex;
491     RunLoop::Timer<MediaPlayerPrivateGStreamer> m_drawTimer;
492     RunLoop::Timer<MediaPlayerPrivateGStreamer> m_readyTimerHandler;
493 #if USE(TEXTURE_MAPPER_GL)
494 #if USE(NICOSIA)
495     Ref<Nicosia::ContentLayer> m_nicosiaLayer;
496 #else
497     RefPtr<TextureMapperPlatformLayerProxy> m_platformLayerProxy;
498 #endif
499 #endif
500     bool m_isBuffering { false };
501     int m_bufferingPercentage { 0 };
502     mutable unsigned long long m_totalBytes { 0 };
503     URL m_url;
504     bool m_shouldPreservePitch { false };
505     mutable Optional<Seconds> m_lastQueryTime;
506     bool m_isLegacyPlaybin;
507     GRefPtr<GstStreamCollection> m_streamCollection;
508 #if ENABLE(MEDIA_STREAM)
509     RefPtr<MediaStreamPrivate> m_streamPrivate;
510 #endif
511     String m_currentAudioStreamId;
512     String m_currentVideoStreamId;
513     String m_currentTextStreamId;
514 #if ENABLE(WEB_AUDIO)
515     std::unique_ptr<AudioSourceProviderGStreamer> m_audioSourceProvider;
516 #endif
517     GRefPtr<GstElement> m_autoAudioSink;
518     GRefPtr<GstElement> m_downloadBuffer;
519     Vector<RefPtr<MediaPlayerRequestInstallMissingPluginsCallback>> m_missingPluginCallbacks;
520 #if ENABLE(VIDEO_TRACK)
521     HashMap<AtomString, RefPtr<AudioTrackPrivateGStreamer>> m_audioTracks;
522     HashMap<AtomString, RefPtr<InbandTextTrackPrivateGStreamer>> m_textTracks;
523     HashMap<AtomString, RefPtr<VideoTrackPrivateGStreamer>> m_videoTracks;
524     RefPtr<InbandMetadataTextTrackPrivateGStreamer> m_chaptersTrack;
525 #if USE(GSTREAMER_MPEGTS)
526     HashMap<AtomString, RefPtr<InbandMetadataTextTrackPrivateGStreamer>> m_metadataTracks;
527 #endif
528 #endif // ENABLE(VIDEO_TRACK)
529     virtual bool isMediaSource() const { return false; }
530
531     uint64_t m_httpResponseTotalSize { 0 };
532     uint64_t m_networkReadPosition { 0 };
533     mutable uint64_t m_readPositionAtLastDidLoadingProgress { 0 };
534
535     HashSet<RefPtr<WebCore::SecurityOrigin>> m_origins;
536     Optional<bool> m_hasTaintedOrigin { WTF::nullopt };
537
538     GRefPtr<GstElement> m_fpsSink { nullptr };
539
540 private:
541 #if USE(WPE_VIDEO_PLANE_DISPLAY_DMABUF)
542     GUniquePtr<struct wpe_video_plane_display_dmabuf_source> m_wpeVideoPlaneDisplayDmaBuf;
543 #endif
544     Ref<const Logger> m_logger;
545     const void* m_logIdentifier;
546 };
547
548 }
549 #endif // ENABLE(VIDEO) && USE(GSTREAMER)