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 | 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 | |
59 | private: |
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 | |