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, 2011, 2012, 2013, 2015, 2016 Igalia S.L
6 * Copyright (C) 2014 Cable Television Laboratories, Inc.
7 * Copyright (C) 2015, 2016 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 "MediaPlayerPrivateGStreamerBase.h"
31
32#include <glib.h>
33#include <gst/gst.h>
34#include <gst/pbutils/install-plugins.h>
35#include <wtf/Forward.h>
36#include <wtf/RunLoop.h>
37#include <wtf/WeakPtr.h>
38
39#if ENABLE(VIDEO_TRACK)
40#include "TrackPrivateBaseGStreamer.h"
41#include <wtf/text/AtomicStringHash.h>
42#endif
43
44typedef struct _GstMpegtsSection GstMpegtsSection;
45
46namespace WebCore {
47
48#if ENABLE(WEB_AUDIO)
49class AudioSourceProvider;
50class AudioSourceProviderGStreamer;
51#endif
52
53class AudioTrackPrivateGStreamer;
54class InbandMetadataTextTrackPrivateGStreamer;
55class InbandTextTrackPrivateGStreamer;
56class MediaPlayerRequestInstallMissingPluginsCallback;
57class VideoTrackPrivateGStreamer;
58
59#if ENABLE(MEDIA_SOURCE)
60class MediaSourcePrivateClient;
61#endif
62
63class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateGStreamerBase {
64public:
65 explicit MediaPlayerPrivateGStreamer(MediaPlayer*);
66 virtual ~MediaPlayerPrivateGStreamer();
67
68 static void registerMediaEngine(MediaEngineRegistrar);
69 static bool isAvailable();
70
71 void handleMessage(GstMessage*);
72 void handlePluginInstallerResult(GstInstallPluginsReturn);
73
74 bool hasVideo() const override { return m_hasVideo; }
75 bool hasAudio() const override { return m_hasAudio; }
76
77 void load(const String &url) override;
78#if ENABLE(MEDIA_SOURCE)
79 void load(const String& url, MediaSourcePrivateClient*) override;
80#endif
81#if ENABLE(MEDIA_STREAM)
82 void load(MediaStreamPrivate&) override;
83#endif
84 void commitLoad();
85 void cancelLoad() override;
86
87 void prepareToPlay() override;
88 void play() override;
89 void pause() override;
90
91 bool paused() const override;
92 bool seeking() const override;
93
94 MediaTime platformDuration() const;
95 MediaTime durationMediaTime() const override;
96 MediaTime currentMediaTime() const override;
97 void seek(const MediaTime&) override;
98
99 void setRate(float) override;
100 double rate() const override;
101 void setPreservesPitch(bool) override;
102
103 void setPreload(MediaPlayer::Preload) override;
104 void fillTimerFired();
105
106 std::unique_ptr<PlatformTimeRanges> buffered() const override;
107 MediaTime maxMediaTimeSeekable() const override;
108 bool didLoadingProgress() const override;
109 unsigned long long totalBytes() const override;
110 MediaTime maxTimeLoaded() const override;
111
112 bool hasSingleSecurityOrigin() const override;
113 Optional<bool> wouldTaintOrigin(const SecurityOrigin&) const override;
114
115 void loadStateChanged();
116 void timeChanged();
117 void didEnd();
118 virtual void durationChanged();
119 void loadingFailed(MediaPlayer::NetworkState, MediaPlayer::ReadyState = MediaPlayer::HaveNothing, bool forceNotifications = false);
120
121 virtual void sourceSetup(GstElement*);
122
123 GstElement* audioSink() const override;
124 virtual void configurePlaySink() { }
125
126 void simulateAudioInterruption() override;
127
128 virtual bool changePipelineState(GstState);
129
130#if ENABLE(WEB_AUDIO)
131 AudioSourceProvider* audioSourceProvider() override;
132#endif
133
134 bool isLiveStream() const override { return m_isStreaming; }
135
136 void enableTrack(TrackPrivateBaseGStreamer::TrackType, unsigned index);
137
138 bool handleSyncMessage(GstMessage*) override;
139
140private:
141 static void getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>&);
142 static MediaPlayer::SupportsType supportsType(const MediaEngineSupportParameters&);
143 void syncOnClock(bool sync);
144
145 GstElement* createAudioSink() override;
146
147 MediaTime playbackPosition() const;
148
149 virtual void updateStates();
150 virtual void asyncStateChangeDone();
151
152 void createGSTPlayBin(const URL&, const String& pipelineName);
153
154 bool loadNextLocation();
155 void mediaLocationChanged(GstMessage*);
156
157 virtual void setDownloadBuffering();
158 void processBufferingStats(GstMessage*);
159#if ENABLE(VIDEO_TRACK)
160#if USE(GSTREAMER_MPEGTS)
161 void processMpegTsSection(GstMpegtsSection*);
162#endif
163
164 void processTableOfContents(GstMessage*);
165 void processTableOfContentsEntry(GstTocEntry*);
166
167 void purgeInvalidAudioTracks(Vector<String> validTrackIds);
168 void purgeInvalidVideoTracks(Vector<String> validTrackIds);
169 void purgeInvalidTextTracks(Vector<String> validTrackIds);
170#endif
171 virtual bool doSeek(const MediaTime& position, float rate, GstSeekFlags seekType);
172 virtual void updatePlaybackRate();
173
174 String engineDescription() const override { return "GStreamer"; }
175 bool didPassCORSAccessCheck() const override;
176 bool canSaveMediaData() const override;
177
178 void purgeOldDownloadFiles(const char*);
179 static void uriDecodeBinElementAddedCallback(GstBin*, GstElement*, MediaPlayerPrivateGStreamer*);
180 static void downloadBufferFileCreatedCallback(MediaPlayerPrivateGStreamer*);
181
182 void setPlaybinURL(const URL& urlString);
183 void loadFull(const String& url, const String& pipelineName);
184
185#if GST_CHECK_VERSION(1, 10, 0)
186 void updateTracks();
187 void clearTracks();
188#endif
189
190protected:
191 bool m_buffering;
192 int m_bufferingPercentage;
193 mutable MediaTime m_cachedPosition;
194 mutable MediaTime m_cachedDuration;
195 bool m_canFallBackToLastFinishedSeekPosition;
196 bool m_changingRate;
197 bool m_downloadFinished;
198 bool m_errorOccured;
199 mutable bool m_isEndReached;
200 mutable bool m_isStreaming;
201 bool m_paused;
202 float m_playbackRate;
203 GstState m_currentState;
204 GstState m_oldState;
205 GstState m_requestedState;
206 bool m_resetPipeline;
207 bool m_seeking;
208 bool m_seekIsPending;
209 MediaTime m_seekTime;
210 GRefPtr<GstElement> m_source;
211 bool m_volumeAndMuteInitialized;
212
213 void readyTimerFired();
214
215 void notifyPlayerOfVideo();
216 void notifyPlayerOfVideoCaps();
217 void notifyPlayerOfAudio();
218
219#if ENABLE(VIDEO_TRACK)
220 void notifyPlayerOfText();
221 void newTextSample();
222#endif
223
224 void ensureAudioSourceProvider();
225 void setAudioStreamProperties(GObject*);
226
227 static void setAudioStreamPropertiesCallback(MediaPlayerPrivateGStreamer*, GObject*);
228
229 static void sourceSetupCallback(MediaPlayerPrivateGStreamer*, GstElement*);
230 static void videoChangedCallback(MediaPlayerPrivateGStreamer*);
231 static void videoSinkCapsChangedCallback(MediaPlayerPrivateGStreamer*);
232 static void audioChangedCallback(MediaPlayerPrivateGStreamer*);
233#if ENABLE(VIDEO_TRACK)
234 static void textChangedCallback(MediaPlayerPrivateGStreamer*);
235 static GstFlowReturn newTextSampleCallback(MediaPlayerPrivateGStreamer*);
236#endif
237
238private:
239
240#if ENABLE(VIDEO_TRACK)
241 GRefPtr<GstElement> m_textAppSink;
242 GRefPtr<GstPad> m_textAppSinkPad;
243#endif
244 GstStructure* m_mediaLocations;
245 int m_mediaLocationCurrentIndex;
246 bool m_playbackRatePause;
247 MediaTime m_timeOfOverlappingSeek;
248 float m_lastPlaybackRate;
249 Timer m_fillTimer;
250 MediaTime m_maxTimeLoaded;
251 bool m_loadingStalled { false };
252 MediaPlayer::Preload m_preload;
253 bool m_delayingLoad;
254 mutable MediaTime m_maxTimeLoadedAtLastDidLoadingProgress;
255 bool m_hasVideo;
256 bool m_hasAudio;
257 RunLoop::Timer<MediaPlayerPrivateGStreamer> m_readyTimerHandler;
258 mutable unsigned long long m_totalBytes;
259 URL m_url;
260 bool m_preservesPitch;
261 mutable Optional<Seconds> m_lastQueryTime;
262 bool m_isLegacyPlaybin;
263#if GST_CHECK_VERSION(1, 10, 0)
264 GRefPtr<GstStreamCollection> m_streamCollection;
265 FloatSize naturalSize() const final;
266#if ENABLE(MEDIA_STREAM)
267 RefPtr<MediaStreamPrivate> m_streamPrivate;
268#endif // ENABLE(MEDIA_STREAM)
269#endif // GST_CHECK_VERSION(1, 10, 0)
270 String m_currentAudioStreamId;
271 String m_currentVideoStreamId;
272 String m_currentTextStreamId;
273#if ENABLE(WEB_AUDIO)
274 std::unique_ptr<AudioSourceProviderGStreamer> m_audioSourceProvider;
275#endif
276 GRefPtr<GstElement> m_autoAudioSink;
277 GRefPtr<GstElement> m_downloadBuffer;
278 Vector<RefPtr<MediaPlayerRequestInstallMissingPluginsCallback>> m_missingPluginCallbacks;
279#if ENABLE(VIDEO_TRACK)
280 HashMap<AtomicString, RefPtr<AudioTrackPrivateGStreamer>> m_audioTracks;
281 HashMap<AtomicString, RefPtr<InbandTextTrackPrivateGStreamer>> m_textTracks;
282 HashMap<AtomicString, RefPtr<VideoTrackPrivateGStreamer>> m_videoTracks;
283 RefPtr<InbandMetadataTextTrackPrivateGStreamer> m_chaptersTrack;
284#if USE(GSTREAMER_MPEGTS)
285 HashMap<AtomicString, RefPtr<InbandMetadataTextTrackPrivateGStreamer>> m_metadataTracks;
286#endif
287#endif
288 virtual bool isMediaSource() const { return false; }
289
290 uint64_t m_httpResponseTotalSize { 0 };
291 uint64_t m_networkReadPosition { 0 };
292 mutable uint64_t m_readPositionAtLastDidLoadingProgress { 0 };
293
294 HashSet<RefPtr<WebCore::SecurityOrigin>> m_origins;
295 Optional<bool> m_hasTaintedOrigin { WTF::nullopt };
296};
297
298}
299
300#endif // USE(GSTREAMER)
301