[MSE][GStreamer] Introduce AbortableTaskQueue
[WebKit-https.git] / Source / WebCore / platform / graphics / gstreamer / mse / AppendPipeline.h
1 /*
2  * Copyright (C) 2016 Metrological Group B.V.
3  * Copyright (C) 2016 Igalia S.L
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 #pragma once
22
23 #if ENABLE(VIDEO) && USE(GSTREAMER) && ENABLE(MEDIA_SOURCE)
24
25 #include "AbortableTaskQueue.h"
26 #include "GStreamerCommon.h"
27 #include "MediaPlayerPrivateGStreamerMSE.h"
28 #include "MediaSourceClientGStreamerMSE.h"
29 #include "SourceBufferPrivateGStreamer.h"
30
31 #include <atomic>
32 #include <gst/gst.h>
33 #include <mutex>
34 #include <wtf/Condition.h>
35 #include <wtf/Threading.h>
36
37 namespace WebCore {
38
39 #if !LOG_DISABLED || ENABLE(ENCRYPTED_MEDIA)
40 struct PadProbeInformation {
41     AppendPipeline* appendPipeline;
42     const char* description;
43     gulong probeId;
44 };
45 #endif
46
47 class AppendPipeline : public ThreadSafeRefCounted<AppendPipeline> {
48 public:
49     AppendPipeline(Ref<MediaSourceClientGStreamerMSE>, Ref<SourceBufferPrivateGStreamer>, MediaPlayerPrivateGStreamerMSE&);
50     virtual ~AppendPipeline();
51
52     GstFlowReturn pushNewBuffer(GstBuffer*);
53     void clearPlayerPrivate();
54     void abort();
55     Ref<SourceBufferPrivateGStreamer> sourceBufferPrivate() { return m_sourceBufferPrivate.get(); }
56     GstCaps* appsinkCaps() { return m_appsinkCaps.get(); }
57     RefPtr<WebCore::TrackPrivateBase> track() { return m_track; }
58     MediaPlayerPrivateGStreamerMSE* playerPrivate() { return m_playerPrivate; }
59
60 private:
61     enum class AppendState { Invalid, NotStarted, Ongoing, DataStarve, Sampling, LastSample, Aborting };
62
63     void handleNeedContextSyncMessage(GstMessage*);
64     void handleStateChangeMessage(GstMessage*);
65
66     gint id();
67     AppendState appendState() { return m_appendState; }
68     void setAppendState(AppendState);
69
70     GstFlowReturn handleAppsinkNewSampleFromStreamingThread(GstElement*);
71
72     // Takes ownership of caps.
73     void parseDemuxerSrcPadCaps(GstCaps*);
74     void appsinkCapsChanged();
75     void appsinkNewSample(GRefPtr<GstSample>&&);
76     void appsinkEOS();
77     void handleEndOfAppend();
78     void didReceiveInitializationSegment();
79     AtomicString trackId();
80
81     GstBus* bus() { return m_bus.get(); }
82     GstElement* pipeline() { return m_pipeline.get(); }
83     GstElement* appsrc() { return m_appsrc.get(); }
84     GstElement* appsink() { return m_appsink.get(); }
85     GstCaps* demuxerSrcPadCaps() { return m_demuxerSrcPadCaps.get(); }
86     WebCore::MediaSourceStreamTypeGStreamer streamType() { return m_streamType; }
87
88     void disconnectDemuxerSrcPadFromAppsinkFromAnyThread(GstPad*);
89     void connectDemuxerSrcPadToAppsinkFromStreamingThread(GstPad*);
90     void connectDemuxerSrcPadToAppsink(GstPad*);
91
92     void resetPipeline();
93     void checkEndOfAppend();
94     void demuxerNoMorePads();
95
96     void consumeAppsinkAvailableSamples();
97
98     GstPadProbeReturn appsrcEndOfAppendCheckerProbe(GstPadProbeInfo*);
99
100     static void staticInitialization();
101     static const char* dumpAppendState(AppendPipeline::AppendState);
102
103     static std::once_flag s_staticInitializationFlag;
104     static GType s_endOfAppendMetaType;
105     static const GstMetaInfo* s_webKitEndOfAppendMetaInfo;
106
107     // Used only for asserting that there is only one streaming thread.
108     // Only the pointers are compared.
109     WTF::Thread* m_streamingThread;
110
111     Ref<MediaSourceClientGStreamerMSE> m_mediaSourceClient;
112     Ref<SourceBufferPrivateGStreamer> m_sourceBufferPrivate;
113     MediaPlayerPrivateGStreamerMSE* m_playerPrivate;
114
115     // (m_mediaType, m_id) is unique.
116     gint m_id;
117
118     MediaTime m_initialDuration;
119
120     GRefPtr<GstElement> m_pipeline;
121     GRefPtr<GstBus> m_bus;
122     GRefPtr<GstElement> m_appsrc;
123     GRefPtr<GstElement> m_demux;
124     GRefPtr<GstElement> m_parser; // Optional.
125     // The demuxer has one src stream only, so only one appsink is needed and linked to it.
126     GRefPtr<GstElement> m_appsink;
127
128     // Used to avoid unnecessary notifications per sample.
129     // It is read and written from the streaming thread and written from the main thread.
130     // The main thread must set it to false before actually pulling samples.
131     // This strategy ensures that at any time, there are at most two notifications in the bus
132     // queue, instead of it growing unbounded.
133     std::atomic_flag m_wasBusAlreadyNotifiedOfAvailableSamples;
134
135     GRefPtr<GstCaps> m_appsinkCaps;
136     GRefPtr<GstCaps> m_demuxerSrcPadCaps;
137     FloatSize m_presentationSize;
138
139 #if !LOG_DISABLED
140     struct PadProbeInformation m_demuxerDataEnteringPadProbeInformation;
141     struct PadProbeInformation m_appsinkDataEnteringPadProbeInformation;
142 #endif
143
144 #if ENABLE(ENCRYPTED_MEDIA)
145     struct PadProbeInformation m_appsinkPadEventProbeInformation;
146 #endif
147     // Keeps track of the states of append processing, to avoid performing actions inappropriate for the current state
148     // (eg: processing more samples when the last one has been detected, etc.). See setAppendState() for valid
149     // transitions.
150     AppendState m_appendState;
151
152     // Aborts can only be completed when the normal sample detection has finished. Meanwhile, the willing to abort is
153     // expressed in this field.
154     bool m_abortPending;
155
156     WebCore::MediaSourceStreamTypeGStreamer m_streamType;
157     RefPtr<WebCore::TrackPrivateBase> m_track;
158
159     AbortableTaskQueue m_taskQueue;
160
161     GRefPtr<GstBuffer> m_pendingBuffer;
162 };
163
164 } // namespace WebCore.
165
166 #endif // USE(GSTREAMER)