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
37namespace WebCore {
38
39#if !LOG_DISABLED || ENABLE(ENCRYPTED_MEDIA)
40struct PadProbeInformation {
41 AppendPipeline* appendPipeline;
42 const char* description;
43 gulong probeId;
44};
45#endif
46
47class AppendPipeline : public ThreadSafeRefCounted<AppendPipeline> {
48public:
49 AppendPipeline(Ref<MediaSourceClientGStreamerMSE>, Ref<SourceBufferPrivateGStreamer>, MediaPlayerPrivateGStreamerMSE&);
50 virtual ~AppendPipeline();
51
52 void pushNewBuffer(GRefPtr<GstBuffer>&&);
53 void resetParserState();
54 Ref<SourceBufferPrivateGStreamer> sourceBufferPrivate() { return m_sourceBufferPrivate.get(); }
55 GstCaps* appsinkCaps() { return m_appsinkCaps.get(); }
56 RefPtr<WebCore::TrackPrivateBase> track() { return m_track; }
57 MediaPlayerPrivateGStreamerMSE* playerPrivate() { return m_playerPrivate; }
58
59private:
60
61 void handleErrorSyncMessage(GstMessage*);
62 void handleNeedContextSyncMessage(GstMessage*);
63 // For debug purposes only:
64 void handleStateChangeMessage(GstMessage*);
65
66 gint id();
67
68 void handleAppsinkNewSampleFromStreamingThread(GstElement*);
69
70 // Takes ownership of caps.
71 void parseDemuxerSrcPadCaps(GstCaps*);
72 void appsinkCapsChanged();
73 void appsinkNewSample(GRefPtr<GstSample>&&);
74 void handleEndOfAppend();
75 void didReceiveInitializationSegment();
76 AtomicString trackId();
77
78 GstBus* bus() { return m_bus.get(); }
79 GstElement* pipeline() { return m_pipeline.get(); }
80 GstElement* appsrc() { return m_appsrc.get(); }
81 GstElement* appsink() { return m_appsink.get(); }
82 GstCaps* demuxerSrcPadCaps() { return m_demuxerSrcPadCaps.get(); }
83 WebCore::MediaSourceStreamTypeGStreamer streamType() { return m_streamType; }
84
85 void disconnectDemuxerSrcPadFromAppsinkFromAnyThread(GstPad*);
86 void connectDemuxerSrcPadToAppsinkFromStreamingThread(GstPad*);
87 void connectDemuxerSrcPadToAppsink(GstPad*);
88
89 void resetPipeline();
90
91 void consumeAppsinkAvailableSamples();
92
93 GstPadProbeReturn appsrcEndOfAppendCheckerProbe(GstPadProbeInfo*);
94
95 static void staticInitialization();
96
97 static std::once_flag s_staticInitializationFlag;
98 static GType s_endOfAppendMetaType;
99 static const GstMetaInfo* s_webKitEndOfAppendMetaInfo;
100
101 // Used only for asserting that there is only one streaming thread.
102 // Only the pointers are compared.
103 WTF::Thread* m_streamingThread;
104
105 // Used only for asserting EOS events are only caused by demuxing errors.
106 bool m_errorReceived { false };
107
108 Ref<MediaSourceClientGStreamerMSE> m_mediaSourceClient;
109 Ref<SourceBufferPrivateGStreamer> m_sourceBufferPrivate;
110 MediaPlayerPrivateGStreamerMSE* m_playerPrivate;
111
112 // (m_mediaType, m_id) is unique.
113 gint m_id;
114
115 MediaTime m_initialDuration;
116
117 GRefPtr<GstElement> m_pipeline;
118 GRefPtr<GstBus> m_bus;
119 GRefPtr<GstElement> m_appsrc;
120 GRefPtr<GstElement> m_demux;
121 GRefPtr<GstElement> m_parser; // Optional.
122 // The demuxer has one src stream only, so only one appsink is needed and linked to it.
123 GRefPtr<GstElement> m_appsink;
124
125 // Used to avoid unnecessary notifications per sample.
126 // It is read and written from the streaming thread and written from the main thread.
127 // The main thread must set it to false before actually pulling samples.
128 // This strategy ensures that at any time, there are at most two notifications in the bus
129 // queue, instead of it growing unbounded.
130 std::atomic_flag m_wasBusAlreadyNotifiedOfAvailableSamples;
131
132 GRefPtr<GstCaps> m_appsinkCaps;
133 GRefPtr<GstCaps> m_demuxerSrcPadCaps;
134 FloatSize m_presentationSize;
135
136#if !LOG_DISABLED
137 struct PadProbeInformation m_demuxerDataEnteringPadProbeInformation;
138 struct PadProbeInformation m_appsinkDataEnteringPadProbeInformation;
139#endif
140
141#if ENABLE(ENCRYPTED_MEDIA)
142 struct PadProbeInformation m_appsinkPadEventProbeInformation;
143#endif
144
145 WebCore::MediaSourceStreamTypeGStreamer m_streamType;
146 RefPtr<WebCore::TrackPrivateBase> m_track;
147
148 AbortableTaskQueue m_taskQueue;
149
150 GRefPtr<GstBuffer> m_pendingBuffer;
151};
152
153} // namespace WebCore.
154
155#endif // USE(GSTREAMER)
156