Line data Source code
1 : /*
2 : * Copyright (C) 2022 Sky UK
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Lesser General Public
6 : * License as published by the Free Software Foundation;
7 : * version 2.1 of the License.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Lesser General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public
15 : * License along with this library; if not, write to the Free Software
16 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 : */
18 :
19 : #pragma once
20 :
21 : #include <atomic>
22 : #include <condition_variable>
23 : #include <functional>
24 : #include <memory>
25 : #include <mutex>
26 : #include <thread>
27 : #include <unordered_map>
28 : #include <unordered_set>
29 : #include <vector>
30 :
31 : #include <gst/gst.h>
32 : #include <sys/syscall.h>
33 : #include <sys/types.h>
34 : #include <unistd.h>
35 :
36 : #include "BufferParser.h"
37 : #include "Constants.h"
38 : #include "IMediaPipeline.h"
39 : #include "IMessageQueue.h"
40 : #include "IPullModePlaybackDelegate.h"
41 : #include "MediaCommon.h"
42 : #include "MediaPlayerClientBackendInterface.h"
43 : #include "RialtoGStreamerMSEBaseSink.h"
44 :
45 : #define DEFAULT_MAX_VIDEO_WIDTH 3840
46 : #define DEFAULT_MAX_VIDEO_HEIGHT 2160
47 :
48 : class GStreamerMSEMediaPlayerClient;
49 :
50 : enum class ClientState
51 : {
52 : IDLE,
53 : READY,
54 : AWAITING_PAUSED,
55 : PAUSED,
56 : AWAITING_PLAYING,
57 : PLAYING
58 : };
59 :
60 : class BufferPuller
61 : {
62 : public:
63 : BufferPuller(const std::shared_ptr<IMessageQueueFactory> &messageQueueFactory, GstElement *rialtoSink,
64 : const std::shared_ptr<BufferParser> &bufferParser,
65 : const std::shared_ptr<IPullModePlaybackDelegate> &delegate);
66 :
67 : void start();
68 : void stop();
69 : bool requestPullBuffer(int sourceId, size_t frameCount, unsigned int needDataRequestId,
70 : GStreamerMSEMediaPlayerClient *player);
71 :
72 : private:
73 : std::unique_ptr<IMessageQueue> m_queue;
74 : GstElement *m_rialtoSink;
75 : std::shared_ptr<BufferParser> m_bufferParser;
76 : std::shared_ptr<IPullModePlaybackDelegate> m_delegate;
77 : };
78 :
79 : class AttachedSource
80 : {
81 : friend class GStreamerMSEMediaPlayerClient;
82 :
83 : public:
84 197 : AttachedSource(RialtoMSEBaseSink *rialtoSink, std::shared_ptr<BufferPuller> puller,
85 : const std::shared_ptr<IPullModePlaybackDelegate> &delegate, firebolt::rialto::MediaSourceType type,
86 : ClientState state = ClientState::READY)
87 197 : : m_rialtoSink(rialtoSink), m_bufferPuller(puller), m_delegate{delegate}, m_type(type), m_state(state)
88 : {
89 : }
90 :
91 394 : firebolt::rialto::MediaSourceType getType() const { return m_type; }
92 1 : void setPosition(int64_t position) { m_position = position; }
93 :
94 : private:
95 : RialtoMSEBaseSink *m_rialtoSink;
96 : std::shared_ptr<BufferPuller> m_bufferPuller;
97 : std::shared_ptr<IPullModePlaybackDelegate> m_delegate;
98 : std::unordered_set<uint32_t> m_ongoingNeedDataRequests;
99 : firebolt::rialto::MediaSourceType m_type = firebolt::rialto::MediaSourceType::UNKNOWN;
100 : int64_t m_position = 0;
101 : bool m_isFlushing = false;
102 : ClientState m_state = ClientState::READY;
103 : };
104 :
105 : class HaveDataMessage : public Message
106 : {
107 : public:
108 : HaveDataMessage(firebolt::rialto::MediaSourceStatus status, int sourceId, unsigned int needDataRequestId,
109 : GStreamerMSEMediaPlayerClient *player);
110 : void handle() override;
111 :
112 : private:
113 : firebolt::rialto::MediaSourceStatus m_status;
114 : int m_sourceId;
115 : unsigned int m_needDataRequestId;
116 : GStreamerMSEMediaPlayerClient *m_player;
117 : };
118 :
119 : class PullBufferMessage : public Message
120 : {
121 : public:
122 : PullBufferMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, GstElement *rialtoSink,
123 : const std::shared_ptr<BufferParser> &bufferParser, IMessageQueue &pullerQueue,
124 : GStreamerMSEMediaPlayerClient *player, const std::shared_ptr<IPullModePlaybackDelegate> &delegate);
125 : void handle() override;
126 :
127 : private:
128 : int m_sourceId;
129 : size_t m_frameCount;
130 : unsigned int m_needDataRequestId;
131 : GstElement *m_rialtoSink;
132 : std::shared_ptr<BufferParser> m_bufferParser;
133 : IMessageQueue &m_pullerQueue;
134 : GStreamerMSEMediaPlayerClient *m_player;
135 : std::shared_ptr<IPullModePlaybackDelegate> m_delegate;
136 : };
137 :
138 : class NeedDataMessage : public Message
139 : {
140 : public:
141 : NeedDataMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId,
142 : GStreamerMSEMediaPlayerClient *player);
143 : void handle() override;
144 :
145 : private:
146 : int m_sourceId;
147 : size_t m_frameCount;
148 : unsigned int m_needDataRequestId;
149 : GStreamerMSEMediaPlayerClient *m_player;
150 : };
151 :
152 : class PlaybackStateMessage : public Message
153 : {
154 : public:
155 : PlaybackStateMessage(firebolt::rialto::PlaybackState state, GStreamerMSEMediaPlayerClient *player);
156 : void handle() override;
157 :
158 : private:
159 : firebolt::rialto::PlaybackState m_state;
160 : GStreamerMSEMediaPlayerClient *m_player;
161 : };
162 :
163 : class QosMessage : public Message
164 : {
165 : public:
166 : QosMessage(int sourceId, firebolt::rialto::QosInfo qosInfo, GStreamerMSEMediaPlayerClient *player);
167 : void handle() override;
168 :
169 : private:
170 : int m_sourceId;
171 : firebolt::rialto::QosInfo m_qosInfo;
172 : GStreamerMSEMediaPlayerClient *m_player;
173 : };
174 :
175 : class BufferUnderflowMessage : public Message
176 : {
177 : public:
178 : BufferUnderflowMessage(int sourceId, GStreamerMSEMediaPlayerClient *player);
179 : void handle() override;
180 :
181 : private:
182 : int m_sourceId;
183 : GStreamerMSEMediaPlayerClient *m_player;
184 : };
185 :
186 : class PlaybackErrorMessage : public Message
187 : {
188 : public:
189 : PlaybackErrorMessage(int sourceId, firebolt::rialto::PlaybackError error, GStreamerMSEMediaPlayerClient *player);
190 : void handle() override;
191 :
192 : private:
193 : int m_sourceId;
194 : firebolt::rialto::PlaybackError m_error;
195 : GStreamerMSEMediaPlayerClient *m_player;
196 : };
197 :
198 : class SetPositionMessage : public Message
199 : {
200 : public:
201 : SetPositionMessage(int64_t newPosition, std::unordered_map<int32_t, AttachedSource> &attachedSources);
202 : void handle() override;
203 :
204 : private:
205 : int64_t m_newPosition;
206 : std::unordered_map<int32_t, AttachedSource> &m_attachedSources;
207 : };
208 :
209 : class SetDurationMessage : public Message
210 : {
211 : public:
212 : SetDurationMessage(int64_t newDuration, int64_t &targetDuration);
213 : void handle() override;
214 :
215 : private:
216 : int64_t m_newDuration;
217 : int64_t &m_targetDuration;
218 : };
219 :
220 : class SourceFlushedMessage : public Message
221 : {
222 : public:
223 : SourceFlushedMessage(int32_t sourceId, GStreamerMSEMediaPlayerClient *player);
224 : void handle() override;
225 :
226 : private:
227 : int32_t m_sourceId;
228 : GStreamerMSEMediaPlayerClient *m_player;
229 : };
230 :
231 : enum class StateChangeResult
232 : {
233 : SUCCESS_ASYNC,
234 : SUCCESS_SYNC,
235 : NOT_ATTACHED
236 : };
237 :
238 : class GStreamerMSEMediaPlayerClient : public firebolt::rialto::IMediaPipelineClient,
239 : public std::enable_shared_from_this<GStreamerMSEMediaPlayerClient>
240 : {
241 : friend class NeedDataMessage;
242 : friend class PullBufferMessage;
243 : friend class HaveDataMessage;
244 : friend class QosMessage;
245 :
246 : public:
247 : GStreamerMSEMediaPlayerClient(
248 : const std::shared_ptr<IMessageQueueFactory> &messageQueueFactory,
249 : const std::shared_ptr<firebolt::rialto::client::MediaPlayerClientBackendInterface> &MediaPlayerClientBackend,
250 : const uint32_t maxVideoWidth, const uint32_t maxVideoHeight);
251 : virtual ~GStreamerMSEMediaPlayerClient();
252 :
253 : void notifyDuration(int64_t duration) override;
254 : void notifyPosition(int64_t position) override;
255 : void notifyNativeSize(uint32_t width, uint32_t height, double aspect) override;
256 : void notifyNetworkState(firebolt::rialto::NetworkState state) override;
257 : void notifyPlaybackState(firebolt::rialto::PlaybackState state) override;
258 : void notifyVideoData(bool hasData) override;
259 : void notifyAudioData(bool hasData) override;
260 : void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId,
261 : const std::shared_ptr<firebolt::rialto::MediaPlayerShmInfo> &shmInfo) override;
262 : void notifyCancelNeedMediaData(int32_t sourceId) override;
263 : void notifyQos(int32_t sourceId, const firebolt::rialto::QosInfo &qosInfo) override;
264 : void notifyBufferUnderflow(int32_t sourceId) override;
265 : void notifyPlaybackError(int32_t sourceId, firebolt::rialto::PlaybackError error) override;
266 : void notifySourceFlushed(int32_t sourceId) override;
267 :
268 : void getPositionDo(int64_t *position, int32_t sourceId);
269 : int64_t getPosition(int32_t sourceId);
270 : bool setImmediateOutput(int32_t sourceId, bool immediateOutput);
271 : bool getImmediateOutput(int32_t sourceId, bool &immediateOutput);
272 : bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames);
273 :
274 : firebolt::rialto::AddSegmentStatus
275 : addSegment(unsigned int needDataRequestId,
276 : const std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSegment> &mediaSegment);
277 :
278 : bool createBackend();
279 : StateChangeResult play(int32_t sourceId);
280 : StateChangeResult pause(int32_t sourceId);
281 : void stop();
282 : void setPlaybackRate(double rate);
283 : void flush(int32_t sourceId, bool resetTime);
284 : void setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate = 1.0,
285 : uint64_t stopPosition = GST_CLOCK_TIME_NONE);
286 : void processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac);
287 :
288 : bool attachSource(std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSource> &source,
289 : RialtoMSEBaseSink *rialtoSink, const std::shared_ptr<IPullModePlaybackDelegate> &delegate);
290 : void removeSource(int32_t sourceId);
291 : void handlePlaybackStateChange(firebolt::rialto::PlaybackState state);
292 : void handleSourceFlushed(int32_t sourceId);
293 : void sendAllSourcesAttachedIfPossible();
294 :
295 : void setVideoRectangle(const std::string &rectangleString);
296 : std::string getVideoRectangle();
297 :
298 : bool requestPullBuffer(int streamId, size_t frameCount, unsigned int needDataRequestId);
299 : bool handleQos(int sourceId, firebolt::rialto::QosInfo qosInfo);
300 : bool handleBufferUnderflow(int sourceId);
301 : bool handlePlaybackError(int sourceId, firebolt::rialto::PlaybackError error);
302 : void stopStreaming();
303 : void destroyClientBackend();
304 : bool renderFrame(int32_t sourceId);
305 : void setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType);
306 : bool getVolume(double &volume);
307 : void setMute(bool mute, int32_t sourceId);
308 : bool getMute(int sourceId);
309 : void setTextTrackIdentifier(const std::string &textTrackIdentifier);
310 : std::string getTextTrackIdentifier();
311 : bool setLowLatency(bool lowLatency);
312 : bool setSync(bool sync);
313 : bool getSync(bool &sync);
314 : bool setSyncOff(bool syncOff);
315 : bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode);
316 : bool getStreamSyncMode(int32_t &streamSyncMode);
317 : ClientState getClientState();
318 : void handleStreamCollection(int32_t audioStreams, int32_t videoStreams, int32_t subtitleStreams);
319 : void setBufferingLimit(uint32_t limitBufferingMs);
320 : uint32_t getBufferingLimit();
321 : void setUseBuffering(bool useBuffering);
322 : bool getUseBuffering();
323 : bool switchSource(const std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSource> &source);
324 :
325 : private:
326 : bool areAllStreamsAttached();
327 : void sendAllSourcesAttachedIfPossibleInternal();
328 : bool checkIfAllAttachedSourcesInStates(const std::vector<ClientState> &states);
329 :
330 : std::unique_ptr<IMessageQueue> m_backendQueue;
331 : std::shared_ptr<IMessageQueueFactory> m_messageQueueFactory;
332 : std::shared_ptr<firebolt::rialto::client::MediaPlayerClientBackendInterface> m_clientBackend;
333 : int64_t m_position;
334 : int64_t m_duration;
335 : std::mutex m_playerMutex;
336 : std::unordered_map<int32_t, AttachedSource> m_attachedSources;
337 : bool m_wasAllSourcesAttachedSent = false;
338 : int32_t m_audioStreams;
339 : int32_t m_videoStreams;
340 : int32_t m_subtitleStreams;
341 :
342 : struct Rectangle
343 : {
344 : unsigned int x, y, width, height;
345 : } m_videoRectangle;
346 :
347 : firebolt::rialto::PlaybackState m_serverPlaybackState = firebolt::rialto::PlaybackState::IDLE;
348 : ClientState m_clientState = ClientState::IDLE;
349 : // To check if the backend message queue and pulling of data to serve backend is stopped or not
350 : bool m_streamingStopped;
351 :
352 : const uint32_t m_maxWidth;
353 : const uint32_t m_maxHeight;
354 : };
|