Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2022 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include <algorithm>
21 : #include <stdexcept>
22 :
23 : #include "ActiveRequests.h"
24 : #include "DataReaderFactory.h"
25 : #include "IDataReader.h"
26 : #include "IRdkGstreamerUtilsWrapper.h"
27 : #include "ISharedMemoryBuffer.h"
28 : #include "MediaPipelineServerInternal.h"
29 : #include "NeedMediaData.h"
30 : #include "RialtoServerLogging.h"
31 : #include "TypeConverters.h"
32 :
33 : namespace
34 : {
35 1 : const char *toString(const firebolt::rialto::MediaSourceStatus &status)
36 : {
37 1 : switch (status)
38 : {
39 0 : case firebolt::rialto::MediaSourceStatus::OK:
40 0 : return "OK";
41 0 : case firebolt::rialto::MediaSourceStatus::EOS:
42 0 : return "EOS";
43 1 : case firebolt::rialto::MediaSourceStatus::ERROR:
44 1 : return "ERROR";
45 0 : case firebolt::rialto::MediaSourceStatus::CODEC_CHANGED:
46 0 : return "CODEC_CHANGED";
47 0 : case firebolt::rialto::MediaSourceStatus::NO_AVAILABLE_SAMPLES:
48 0 : return "NO_AVAILABLE_SAMPLES";
49 : }
50 0 : return "Unknown";
51 : }
52 :
53 32 : std::int32_t generateSourceId()
54 : {
55 : static std::int32_t sourceId{1};
56 32 : return sourceId++;
57 : }
58 : } // namespace
59 :
60 : namespace firebolt::rialto
61 : {
62 1 : std::shared_ptr<IMediaPipelineFactory> IMediaPipelineFactory::createFactory()
63 : {
64 1 : return server::MediaPipelineServerInternalFactory::createFactory();
65 : }
66 : }; // namespace firebolt::rialto
67 :
68 : namespace firebolt::rialto::server
69 : {
70 0 : std::shared_ptr<server::IMediaPipelineServerInternalFactory> IMediaPipelineServerInternalFactory::createFactory()
71 : {
72 0 : return MediaPipelineServerInternalFactory::createFactory();
73 : }
74 :
75 2 : std::shared_ptr<MediaPipelineServerInternalFactory> MediaPipelineServerInternalFactory::createFactory()
76 : {
77 2 : std::shared_ptr<MediaPipelineServerInternalFactory> factory;
78 :
79 : try
80 : {
81 2 : factory = std::make_shared<MediaPipelineServerInternalFactory>();
82 : }
83 0 : catch (const std::exception &e)
84 : {
85 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the media player server internal factory, reason: %s", e.what());
86 : }
87 :
88 2 : return factory;
89 : }
90 :
91 : std::unique_ptr<IMediaPipeline>
92 1 : MediaPipelineServerInternalFactory::createMediaPipeline(std::weak_ptr<IMediaPipelineClient> client,
93 : const VideoRequirements &videoRequirements) const
94 : {
95 1 : RIALTO_SERVER_LOG_ERROR(
96 : "This function can't be used by rialto server. Please use createMediaPipelineServerInternal");
97 1 : return nullptr;
98 : }
99 :
100 1 : std::unique_ptr<server::IMediaPipelineServerInternal> MediaPipelineServerInternalFactory::createMediaPipelineServerInternal(
101 : std::weak_ptr<IMediaPipelineClient> client, const VideoRequirements &videoRequirements, int sessionId,
102 : const std::shared_ptr<ISharedMemoryBuffer> &shmBuffer, IDecryptionService &decryptionService) const
103 : {
104 1 : std::shared_ptr<IMediaPipelineClient> sharedClient = client.lock();
105 1 : if (!sharedClient)
106 : {
107 0 : RIALTO_SERVER_LOG_ERROR("Couldn't create client's shared pointer");
108 0 : return nullptr;
109 : }
110 :
111 1 : std::unique_ptr<server::MediaPipelineServerInternal> mediaPipeline;
112 : try
113 : {
114 : mediaPipeline =
115 2 : std::make_unique<server::MediaPipelineServerInternal>(sharedClient, videoRequirements,
116 2 : server::IGstGenericPlayerFactory::getFactory(),
117 : sessionId, shmBuffer,
118 2 : server::IMainThreadFactory::createFactory(),
119 2 : common::ITimerFactory::getFactory(),
120 2 : std::make_unique<DataReaderFactory>(),
121 3 : std::make_unique<ActiveRequests>(), decryptionService);
122 : }
123 0 : catch (const std::exception &e)
124 : {
125 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the media player server internal, reason: %s", e.what());
126 : }
127 :
128 1 : return mediaPipeline;
129 : }
130 :
131 148 : MediaPipelineServerInternal::MediaPipelineServerInternal(
132 : const std::shared_ptr<IMediaPipelineClient> &client, const VideoRequirements &videoRequirements,
133 : const std::shared_ptr<IGstGenericPlayerFactory> &gstPlayerFactory, int sessionId,
134 : const std::shared_ptr<ISharedMemoryBuffer> &shmBuffer, const std::shared_ptr<IMainThreadFactory> &mainThreadFactory,
135 : const std::shared_ptr<common::ITimerFactory> &timerFactory, std::unique_ptr<IDataReaderFactory> &&dataReaderFactory,
136 148 : std::unique_ptr<IActiveRequests> &&activeRequests, IDecryptionService &decryptionService)
137 148 : : m_mediaPipelineClient(client), m_kGstPlayerFactory(gstPlayerFactory), m_kVideoRequirements(videoRequirements),
138 148 : m_sessionId{sessionId}, m_shmBuffer{shmBuffer}, m_dataReaderFactory{std::move(dataReaderFactory)},
139 148 : m_timerFactory{timerFactory}, m_activeRequests{std::move(activeRequests)}, m_decryptionService{decryptionService},
140 444 : m_currentPlaybackState{PlaybackState::UNKNOWN}, m_wasAllSourcesAttachedCalled{false}
141 : {
142 148 : RIALTO_SERVER_LOG_DEBUG("entry:");
143 :
144 148 : m_mainThread = mainThreadFactory->getMainThread();
145 148 : if (!m_mainThread)
146 : {
147 0 : throw std::runtime_error("Failed to get the main thread");
148 : }
149 148 : m_mainThreadClientId = m_mainThread->registerClient();
150 :
151 148 : bool result = false;
152 148 : auto task = [&]()
153 : {
154 148 : if (!m_shmBuffer->mapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId))
155 : {
156 0 : RIALTO_SERVER_LOG_ERROR("Unable to map shm partition");
157 : }
158 : else
159 : {
160 148 : result = true;
161 : }
162 296 : };
163 :
164 148 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
165 148 : if (!result)
166 : {
167 0 : throw std::runtime_error("MediaPipelineServerInternal construction failed");
168 : }
169 148 : }
170 :
171 444 : MediaPipelineServerInternal::~MediaPipelineServerInternal()
172 : {
173 148 : RIALTO_SERVER_LOG_DEBUG("entry:");
174 :
175 148 : auto task = [&]()
176 : {
177 153 : for (const auto &timer : m_needMediaDataTimers)
178 : {
179 5 : if (timer.second && timer.second->isActive())
180 : {
181 5 : timer.second->cancel();
182 : }
183 : }
184 148 : if (!m_shmBuffer->unmapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId))
185 : {
186 0 : RIALTO_SERVER_LOG_ERROR("Unable to unmap shm partition");
187 : }
188 :
189 148 : m_shmBuffer.reset();
190 148 : m_mainThread->unregisterClient(m_mainThreadClientId);
191 296 : };
192 148 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
193 296 : }
194 :
195 104 : bool MediaPipelineServerInternal::load(MediaType type, const std::string &mimeType, const std::string &url)
196 : {
197 104 : RIALTO_SERVER_LOG_DEBUG("entry:");
198 :
199 : bool result;
200 104 : auto task = [&]() { result = loadInternal(type, mimeType, url); };
201 :
202 104 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
203 104 : return result;
204 : }
205 :
206 104 : bool MediaPipelineServerInternal::loadInternal(MediaType type, const std::string &mimeType, const std::string &url)
207 : {
208 104 : std::unique_lock lock{m_getPropertyMutex};
209 : /* If gstreamer player already created, destroy the old one first */
210 104 : if (m_gstPlayer)
211 : {
212 0 : m_gstPlayer.reset();
213 : }
214 :
215 : m_gstPlayer =
216 104 : m_kGstPlayerFactory
217 312 : ->createGstGenericPlayer(this, m_decryptionService, type, m_kVideoRequirements,
218 312 : firebolt::rialto::wrappers::IRdkGstreamerUtilsWrapperFactory::getFactory());
219 104 : if (!m_gstPlayer)
220 : {
221 1 : RIALTO_SERVER_LOG_ERROR("Failed to load gstreamer player");
222 1 : return false;
223 : }
224 :
225 103 : notifyNetworkState(NetworkState::BUFFERING);
226 :
227 103 : return true;
228 104 : }
229 :
230 34 : bool MediaPipelineServerInternal::attachSource(const std::unique_ptr<MediaSource> &source)
231 : {
232 34 : RIALTO_SERVER_LOG_DEBUG("entry:");
233 :
234 : bool result;
235 34 : auto task = [&]() { result = attachSourceInternal(source); };
236 :
237 34 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
238 34 : return result;
239 : }
240 :
241 34 : bool MediaPipelineServerInternal::attachSourceInternal(const std::unique_ptr<MediaSource> &source)
242 : {
243 34 : source->setId(-1);
244 :
245 34 : if (!m_gstPlayer)
246 : {
247 1 : RIALTO_SERVER_LOG_ERROR("Gstreamer player has not been loaded");
248 1 : return false;
249 : }
250 :
251 33 : if (source->getType() == MediaSourceType::UNKNOWN)
252 : {
253 0 : RIALTO_SERVER_LOG_ERROR("Media source type unknown");
254 0 : return false;
255 : }
256 :
257 33 : m_gstPlayer->attachSource(source);
258 :
259 33 : const auto kSourceIter = m_attachedSources.find(source->getType());
260 33 : if (m_attachedSources.cend() == kSourceIter)
261 : {
262 32 : source->setId(generateSourceId());
263 32 : RIALTO_SERVER_LOG_DEBUG("New ID generated for MediaSourceType: %s: %d",
264 : common::convertMediaSourceType(source->getType()), source->getId());
265 32 : m_attachedSources.emplace(source->getType(), source->getId());
266 : }
267 : else
268 : {
269 1 : RIALTO_SERVER_LOG_WARN("SourceType '%s' already attached", common::convertMediaSourceType(source->getType()));
270 1 : return false;
271 : }
272 :
273 32 : return true;
274 : }
275 :
276 4 : bool MediaPipelineServerInternal::removeSource(int32_t id)
277 : {
278 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
279 :
280 : bool result;
281 4 : auto task = [&]() { result = removeSourceInternal(id); };
282 :
283 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
284 4 : return result;
285 : }
286 :
287 4 : bool MediaPipelineServerInternal::removeSourceInternal(int32_t id)
288 : {
289 4 : if (!m_gstPlayer)
290 : {
291 1 : RIALTO_SERVER_LOG_ERROR("Failed to remove source - Gstreamer player has not been loaded");
292 1 : return false;
293 : }
294 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
295 2 : [id](const auto &src) { return src.second == id; });
296 3 : if (sourceIter == m_attachedSources.end())
297 : {
298 1 : RIALTO_SERVER_LOG_ERROR("Failed to remove source with id %d- Source not found", id);
299 1 : return false;
300 : }
301 :
302 2 : MediaSourceType type = sourceIter->first;
303 :
304 2 : m_needMediaDataTimers.erase(type);
305 2 : m_noAvailableSamplesCounter.erase(type);
306 2 : m_isMediaTypeEosMap.erase(type);
307 :
308 2 : m_attachedSources.erase(sourceIter);
309 2 : return true;
310 : }
311 :
312 4 : bool MediaPipelineServerInternal::allSourcesAttached()
313 : {
314 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
315 :
316 : bool result;
317 4 : auto task = [&]() { result = allSourcesAttachedInternal(); };
318 :
319 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
320 4 : return result;
321 : }
322 :
323 4 : bool MediaPipelineServerInternal::allSourcesAttachedInternal()
324 : {
325 4 : if (!m_gstPlayer)
326 : {
327 1 : RIALTO_SERVER_LOG_ERROR("Failed to notify all sources attached - Gstreamer player has not been loaded");
328 1 : return false;
329 : }
330 :
331 3 : if (m_wasAllSourcesAttachedCalled)
332 : {
333 1 : RIALTO_SERVER_LOG_WARN("Failed to notify all sources attached - It was already called");
334 1 : return false;
335 : }
336 :
337 2 : m_gstPlayer->allSourcesAttached();
338 2 : m_wasAllSourcesAttachedCalled = true;
339 2 : return true;
340 : }
341 :
342 2 : bool MediaPipelineServerInternal::play(bool &async)
343 : {
344 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
345 :
346 : bool result;
347 2 : auto task = [&]() { result = playInternal(async); };
348 :
349 2 : m_mainThread->enqueuePriorityTaskAndWait(m_mainThreadClientId, task);
350 2 : return result;
351 : }
352 :
353 2 : bool MediaPipelineServerInternal::playInternal(bool &async)
354 : {
355 2 : if (!m_gstPlayer)
356 : {
357 1 : RIALTO_SERVER_LOG_ERROR("Failed to play - Gstreamer player has not been loaded");
358 1 : return false;
359 : }
360 :
361 1 : m_gstPlayer->play(async);
362 1 : return true;
363 : }
364 :
365 2 : bool MediaPipelineServerInternal::pause()
366 : {
367 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
368 :
369 : bool result;
370 2 : auto task = [&]() { result = pauseInternal(); };
371 :
372 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
373 2 : return result;
374 : }
375 :
376 2 : bool MediaPipelineServerInternal::pauseInternal()
377 : {
378 2 : if (!m_gstPlayer)
379 : {
380 1 : RIALTO_SERVER_LOG_ERROR("Failed to pause - Gstreamer player has not been loaded");
381 1 : return false;
382 : }
383 :
384 1 : m_gstPlayer->pause();
385 1 : return true;
386 : }
387 :
388 2 : bool MediaPipelineServerInternal::stop()
389 : {
390 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
391 :
392 : bool result;
393 2 : auto task = [&]() { result = stopInternal(); };
394 :
395 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
396 2 : return result;
397 : }
398 :
399 2 : bool MediaPipelineServerInternal::stopInternal()
400 : {
401 2 : if (!m_gstPlayer)
402 : {
403 1 : RIALTO_SERVER_LOG_ERROR("Failed to stop - Gstreamer player has not been loaded");
404 1 : return false;
405 : }
406 :
407 1 : m_gstPlayer->stop();
408 1 : return true;
409 : }
410 :
411 3 : bool MediaPipelineServerInternal::setPlaybackRate(double rate)
412 : {
413 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
414 :
415 : bool result;
416 3 : auto task = [&]() { result = setPlaybackRateInternal(rate); };
417 :
418 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
419 3 : return result;
420 : }
421 :
422 3 : bool MediaPipelineServerInternal::setPlaybackRateInternal(double rate)
423 : {
424 3 : if (!m_gstPlayer)
425 : {
426 2 : RIALTO_SERVER_LOG_ERROR("Failed to set playback rate - Gstreamer player has not been loaded");
427 2 : return false;
428 : }
429 :
430 1 : if (0.0 == rate)
431 : {
432 0 : RIALTO_SERVER_LOG_ERROR("Failed to set playback rate to 0.0 - pause method should be used instead.");
433 0 : return false;
434 : }
435 :
436 1 : m_gstPlayer->setPlaybackRate(rate);
437 1 : return true;
438 : }
439 :
440 2 : bool MediaPipelineServerInternal::setPosition(int64_t position)
441 : {
442 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
443 :
444 : bool result;
445 2 : auto task = [&]() { result = setPositionInternal(position); };
446 :
447 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
448 2 : return result;
449 : }
450 :
451 2 : bool MediaPipelineServerInternal::setPositionInternal(int64_t position)
452 : {
453 2 : if (!m_gstPlayer)
454 : {
455 1 : RIALTO_SERVER_LOG_ERROR("Failed to set position - Gstreamer player has not been loaded");
456 1 : return false;
457 : }
458 :
459 1 : m_gstPlayer->setPosition(position);
460 :
461 : // Reset Eos on seek
462 1 : for (auto &isMediaTypeEos : m_isMediaTypeEosMap)
463 : {
464 0 : isMediaTypeEos.second = false;
465 : }
466 :
467 1 : return true;
468 : }
469 :
470 3 : bool MediaPipelineServerInternal::getPosition(int64_t &position)
471 : {
472 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
473 :
474 3 : std::shared_lock lock{m_getPropertyMutex};
475 :
476 3 : if (!m_gstPlayer)
477 : {
478 1 : RIALTO_SERVER_LOG_ERROR("Failed to get position - Gstreamer player has not been loaded");
479 1 : return false;
480 : }
481 2 : return m_gstPlayer->getPosition(position);
482 3 : }
483 :
484 4 : bool MediaPipelineServerInternal::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
485 : {
486 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
487 :
488 : bool result;
489 4 : auto task = [&]() { result = getStatsInternal(sourceId, renderedFrames, droppedFrames); };
490 :
491 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
492 4 : return result;
493 : }
494 :
495 4 : bool MediaPipelineServerInternal::getStatsInternal(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
496 : {
497 4 : if (!m_gstPlayer)
498 : {
499 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stats - Gstreamer player has not been loaded");
500 1 : return false;
501 : }
502 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
503 2 : [sourceId](const auto &src) { return src.second == sourceId; });
504 3 : if (sourceIter == m_attachedSources.end())
505 : {
506 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stats - Source not found");
507 1 : return false;
508 : }
509 2 : return m_gstPlayer->getStats(sourceIter->first, renderedFrames, droppedFrames);
510 : }
511 :
512 6 : bool MediaPipelineServerInternal::setImmediateOutput(int32_t sourceId, bool immediateOutput)
513 : {
514 6 : RIALTO_SERVER_LOG_DEBUG("entry:");
515 :
516 : bool result;
517 6 : auto task = [&]() { result = setImmediateOutputInternal(sourceId, immediateOutput); };
518 :
519 6 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
520 6 : return result;
521 : }
522 :
523 6 : bool MediaPipelineServerInternal::setImmediateOutputInternal(int32_t sourceId, bool immediateOutput)
524 : {
525 6 : if (!m_gstPlayer)
526 : {
527 1 : RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded");
528 1 : return false;
529 : }
530 5 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
531 4 : [sourceId](const auto &src) { return src.second == sourceId; });
532 5 : if (sourceIter == m_attachedSources.end())
533 : {
534 1 : RIALTO_SERVER_LOG_ERROR("Failed - Source not found");
535 1 : return false;
536 : }
537 :
538 4 : m_IsLowLatencyVideoPlayer = immediateOutput;
539 4 : return m_gstPlayer->setImmediateOutput(sourceIter->first, immediateOutput);
540 : }
541 :
542 5 : bool MediaPipelineServerInternal::getImmediateOutput(int32_t sourceId, bool &immediateOutput)
543 : {
544 5 : RIALTO_SERVER_LOG_DEBUG("entry:");
545 :
546 : bool result;
547 5 : auto task = [&]() { result = getImmediateOutputInternal(sourceId, immediateOutput); };
548 :
549 5 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
550 5 : return result;
551 : }
552 :
553 5 : bool MediaPipelineServerInternal::getImmediateOutputInternal(int32_t sourceId, bool &immediateOutput)
554 : {
555 5 : if (!m_gstPlayer)
556 : {
557 1 : RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded");
558 1 : return false;
559 : }
560 4 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
561 3 : [sourceId](const auto &src) { return src.second == sourceId; });
562 4 : if (sourceIter == m_attachedSources.end())
563 : {
564 1 : RIALTO_SERVER_LOG_ERROR("Failed - Source not found");
565 1 : return false;
566 : }
567 3 : return m_gstPlayer->getImmediateOutput(sourceIter->first, immediateOutput);
568 : }
569 :
570 2 : bool MediaPipelineServerInternal::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
571 : {
572 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
573 :
574 : bool result;
575 2 : auto task = [&]() { result = setVideoWindowInternal(x, y, width, height); };
576 :
577 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
578 2 : return result;
579 : }
580 :
581 2 : bool MediaPipelineServerInternal::setVideoWindowInternal(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
582 : {
583 2 : if (!m_gstPlayer)
584 : {
585 1 : RIALTO_SERVER_LOG_ERROR("Failed to set video window - Gstreamer player has not been loaded");
586 1 : return false;
587 : }
588 :
589 1 : m_gstPlayer->setVideoGeometry(x, y, width, height);
590 1 : return true;
591 : }
592 :
593 12 : bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t needDataRequestId)
594 : {
595 12 : RIALTO_SERVER_LOG_DEBUG("entry:");
596 :
597 : bool result;
598 12 : auto task = [&]() { result = haveDataInternal(status, needDataRequestId); };
599 :
600 12 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
601 12 : return result;
602 : }
603 :
604 12 : bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t needDataRequestId)
605 : {
606 12 : if (!m_gstPlayer)
607 : {
608 1 : RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded");
609 1 : return false;
610 : }
611 :
612 11 : MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId);
613 11 : if (MediaSourceType::UNKNOWN == mediaSourceType)
614 : {
615 1 : RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId);
616 1 : return true;
617 : }
618 :
619 10 : unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType];
620 10 : if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS)
621 : {
622 : // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS.
623 :
624 3 : ++counter;
625 3 : if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES)
626 : {
627 2 : RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u "
628 : "consecutively for mediaSourceType: %s",
629 : needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType));
630 : }
631 : else
632 : {
633 1 : RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status: %s",
634 : common::convertMediaSourceType(mediaSourceType), needDataRequestId, toString(status));
635 1 : counter = 0;
636 : }
637 :
638 3 : m_activeRequests->erase(needDataRequestId);
639 3 : scheduleNotifyNeedMediaData(mediaSourceType);
640 3 : return true;
641 : }
642 : else
643 : {
644 7 : RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status",
645 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
646 7 : counter = 0;
647 : }
648 :
649 : try
650 : {
651 7 : const IMediaPipeline::MediaSegmentVector &kSegments = m_activeRequests->getSegments(needDataRequestId);
652 6 : m_gstPlayer->attachSamples(kSegments);
653 : }
654 1 : catch (const std::runtime_error &e)
655 : {
656 1 : RIALTO_SERVER_LOG_ERROR("Failed to get segments %s", e.what());
657 1 : m_activeRequests->erase(needDataRequestId);
658 1 : return false;
659 : }
660 :
661 6 : m_activeRequests->erase(needDataRequestId);
662 6 : if (status == MediaSourceStatus::EOS)
663 : {
664 5 : m_gstPlayer->setEos(mediaSourceType);
665 5 : m_isMediaTypeEosMap[mediaSourceType] = true;
666 : }
667 :
668 6 : return true;
669 : }
670 :
671 13 : bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId)
672 : {
673 13 : RIALTO_SERVER_LOG_DEBUG("entry:");
674 :
675 : bool result;
676 13 : auto task = [&]() { result = haveDataInternal(status, numFrames, needDataRequestId); };
677 :
678 13 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
679 13 : return result;
680 : }
681 :
682 13 : bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t numFrames,
683 : uint32_t needDataRequestId)
684 : {
685 13 : if (!m_gstPlayer)
686 : {
687 1 : RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded");
688 1 : return false;
689 : }
690 12 : MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId);
691 12 : if (MediaSourceType::UNKNOWN == mediaSourceType)
692 : {
693 1 : RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId);
694 1 : return true;
695 : }
696 11 : m_activeRequests->erase(needDataRequestId);
697 :
698 11 : unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType];
699 11 : if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS)
700 : {
701 : // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS.
702 :
703 4 : ++counter;
704 4 : if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES)
705 : {
706 0 : RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u "
707 : "consecutively for mediaSourceType: %s",
708 : needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType));
709 : }
710 : else
711 : {
712 4 : RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status",
713 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
714 4 : counter = 0;
715 : }
716 4 : scheduleNotifyNeedMediaData(mediaSourceType);
717 4 : return true;
718 : }
719 : else
720 : {
721 7 : RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status",
722 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
723 7 : counter = 0;
724 : }
725 :
726 7 : uint8_t *buffer = m_shmBuffer->getBuffer();
727 7 : if (!buffer)
728 : {
729 1 : RIALTO_SERVER_LOG_ERROR("No buffer available");
730 1 : notifyPlaybackState(PlaybackState::FAILURE);
731 1 : return false;
732 : }
733 :
734 6 : std::uint32_t regionOffset = 0;
735 : try
736 : {
737 : regionOffset =
738 6 : m_shmBuffer->getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType);
739 : }
740 1 : catch (const std::runtime_error &e)
741 : {
742 1 : RIALTO_SERVER_LOG_ERROR("Failed to get region's buffer offset, reason: %s", e.what());
743 1 : notifyPlaybackState(PlaybackState::FAILURE);
744 1 : return false;
745 : }
746 :
747 5 : if (0 != numFrames)
748 : {
749 : std::shared_ptr<IDataReader> dataReader =
750 4 : m_dataReaderFactory->createDataReader(mediaSourceType, buffer, regionOffset, numFrames);
751 4 : if (!dataReader)
752 : {
753 1 : RIALTO_SERVER_LOG_ERROR("Metadata version not supported for %s request id: %u",
754 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
755 1 : notifyPlaybackState(PlaybackState::FAILURE);
756 1 : return false;
757 : }
758 3 : m_gstPlayer->attachSamples(dataReader);
759 4 : }
760 4 : if (status == MediaSourceStatus::EOS)
761 : {
762 2 : m_gstPlayer->setEos(mediaSourceType);
763 2 : m_isMediaTypeEosMap[mediaSourceType] = true;
764 : }
765 :
766 4 : return true;
767 : }
768 :
769 2 : void MediaPipelineServerInternal::ping(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
770 : {
771 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
772 :
773 2 : auto task = [&]() { pingInternal(std::move(heartbeatHandler)); };
774 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
775 : }
776 :
777 2 : void MediaPipelineServerInternal::pingInternal(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
778 : {
779 2 : if (!m_gstPlayer)
780 : {
781 : // No need to check GstPlayer worker thread, we reached this function, so main thread is working fine.
782 1 : heartbeatHandler.reset();
783 1 : return;
784 : }
785 : // Check GstPlayer worker thread
786 1 : m_gstPlayer->ping(std::move(heartbeatHandler));
787 : }
788 :
789 2 : bool MediaPipelineServerInternal::renderFrame()
790 : {
791 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
792 :
793 : bool result;
794 2 : auto task = [&]() { result = renderFrameInternal(); };
795 :
796 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
797 2 : return result;
798 : }
799 :
800 2 : bool MediaPipelineServerInternal::renderFrameInternal()
801 : {
802 2 : if (!m_gstPlayer)
803 : {
804 1 : RIALTO_SERVER_LOG_ERROR("renderFrame failed - Gstreamer player has not been loaded");
805 1 : return false;
806 : }
807 :
808 1 : m_gstPlayer->renderFrame();
809 1 : return true;
810 : }
811 :
812 3 : bool MediaPipelineServerInternal::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType)
813 : {
814 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
815 :
816 3 : m_isSetVolumeInProgress = true;
817 : bool result;
818 3 : auto task = [&]() { result = setVolumeInternal(targetVolume, volumeDuration, easeType); };
819 :
820 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
821 3 : return result;
822 : }
823 :
824 3 : bool MediaPipelineServerInternal::setVolumeInternal(double targetVolume, uint32_t volumeDuration, EaseType easeType)
825 : {
826 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
827 :
828 3 : if (!m_gstPlayer)
829 : {
830 1 : RIALTO_SERVER_LOG_ERROR("Failed to set volume - Gstreamer player has not been loaded");
831 1 : return false;
832 : }
833 2 : m_gstPlayer->setVolume(targetVolume, volumeDuration, easeType);
834 2 : m_isSetVolumeInProgress = false;
835 2 : return true;
836 : }
837 :
838 4 : bool MediaPipelineServerInternal::getVolume(double ¤tVolume)
839 : {
840 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
841 :
842 4 : if (m_isSetVolumeInProgress)
843 : {
844 : bool result;
845 1 : auto task = [&]() { result = getVolumeInternal(currentVolume); };
846 :
847 1 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
848 1 : return result;
849 : }
850 3 : std::shared_lock lock{m_getPropertyMutex};
851 3 : return getVolumeInternal(currentVolume);
852 : }
853 :
854 4 : bool MediaPipelineServerInternal::getVolumeInternal(double ¤tVolume)
855 : {
856 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
857 :
858 4 : if (!m_gstPlayer)
859 : {
860 1 : RIALTO_SERVER_LOG_ERROR("Failed to get volume - Gstreamer player has not been loaded");
861 1 : return false;
862 : }
863 3 : return m_gstPlayer->getVolume(currentVolume);
864 : }
865 :
866 3 : bool MediaPipelineServerInternal::setMute(std::int32_t sourceId, bool mute)
867 : {
868 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
869 :
870 : bool result;
871 3 : auto task = [&]() { result = setMuteInternal(sourceId, mute); };
872 :
873 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
874 3 : return result;
875 : }
876 :
877 3 : bool MediaPipelineServerInternal::setMuteInternal(std::int32_t sourceId, bool mute)
878 : {
879 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
880 :
881 3 : if (!m_gstPlayer)
882 : {
883 1 : RIALTO_SERVER_LOG_ERROR("Failed to set mute - Gstreamer player has not been loaded");
884 1 : return false;
885 : }
886 :
887 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
888 1 : [sourceId](const auto &src) { return src.second == sourceId; });
889 2 : if (sourceIter == m_attachedSources.end())
890 : {
891 1 : RIALTO_SERVER_LOG_ERROR("Failed to set mute - Source with id: %d not found", sourceId);
892 1 : return false;
893 : }
894 :
895 1 : m_gstPlayer->setMute(sourceIter->first, mute);
896 :
897 1 : return true;
898 : }
899 :
900 4 : bool MediaPipelineServerInternal::getMute(std::int32_t sourceId, bool &mute)
901 : {
902 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
903 :
904 : bool result;
905 4 : auto task = [&]() { result = getMuteInternal(sourceId, mute); };
906 :
907 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
908 4 : return result;
909 : }
910 :
911 4 : bool MediaPipelineServerInternal::getMuteInternal(std::int32_t sourceId, bool &mute)
912 : {
913 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
914 :
915 4 : if (!m_gstPlayer)
916 : {
917 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded");
918 1 : return false;
919 : }
920 :
921 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
922 2 : [sourceId](const auto &src) { return src.second == sourceId; });
923 3 : if (sourceIter == m_attachedSources.end())
924 : {
925 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Source with id: %d not found", sourceId);
926 1 : return false;
927 : }
928 :
929 2 : return m_gstPlayer->getMute(sourceIter->first, mute);
930 : }
931 :
932 2 : bool MediaPipelineServerInternal::setTextTrackIdentifier(const std::string &textTrackIdentifier)
933 : {
934 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
935 :
936 : bool result;
937 2 : auto task = [&]() { result = setTextTrackIdentifierInternal(textTrackIdentifier); };
938 :
939 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
940 2 : return result;
941 : }
942 :
943 2 : bool MediaPipelineServerInternal::setTextTrackIdentifierInternal(const std::string &textTrackIdentifier)
944 : {
945 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
946 :
947 2 : if (!m_gstPlayer)
948 : {
949 1 : RIALTO_SERVER_LOG_ERROR("Failed to set text track identifier - Gstreamer player has not been loaded");
950 1 : return false;
951 : }
952 :
953 1 : m_gstPlayer->setTextTrackIdentifier(textTrackIdentifier);
954 :
955 1 : return true;
956 : }
957 :
958 3 : bool MediaPipelineServerInternal::getTextTrackIdentifier(std::string &textTrackIdentifier)
959 : {
960 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
961 :
962 : bool result;
963 3 : auto task = [&]() { result = getTextTrackIdentifierInternal(textTrackIdentifier); };
964 :
965 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
966 3 : return result;
967 : }
968 :
969 3 : bool MediaPipelineServerInternal::getTextTrackIdentifierInternal(std::string &textTrackIdentifier)
970 : {
971 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
972 :
973 3 : if (!m_gstPlayer)
974 : {
975 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded");
976 1 : return false;
977 : }
978 :
979 2 : return m_gstPlayer->getTextTrackIdentifier(textTrackIdentifier);
980 : }
981 :
982 4 : bool MediaPipelineServerInternal::flush(int32_t sourceId, bool resetTime, bool &async)
983 : {
984 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
985 :
986 : bool result;
987 4 : auto task = [&]() { result = flushInternal(sourceId, resetTime, async); };
988 :
989 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
990 4 : return result;
991 : }
992 :
993 4 : bool MediaPipelineServerInternal::setLowLatency(bool lowLatency)
994 : {
995 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
996 :
997 : bool result;
998 4 : auto task = [&]() { result = setLowLatencyInternal(lowLatency); };
999 :
1000 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1001 4 : return result;
1002 : }
1003 :
1004 4 : bool MediaPipelineServerInternal::setLowLatencyInternal(bool lowLatency)
1005 : {
1006 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1007 :
1008 4 : if (!m_gstPlayer)
1009 : {
1010 1 : RIALTO_SERVER_LOG_ERROR("Failed to set low latency - Gstreamer player has not been loaded");
1011 1 : return false;
1012 : }
1013 3 : m_IsLowLatencyAudioPlayer = lowLatency;
1014 :
1015 3 : return m_gstPlayer->setLowLatency(lowLatency);
1016 : }
1017 :
1018 3 : bool MediaPipelineServerInternal::setSync(bool sync)
1019 : {
1020 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1021 :
1022 : bool result;
1023 3 : auto task = [&]() { result = setSyncInternal(sync); };
1024 :
1025 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1026 3 : return result;
1027 : }
1028 :
1029 3 : bool MediaPipelineServerInternal::setSyncInternal(bool sync)
1030 : {
1031 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1032 :
1033 3 : if (!m_gstPlayer)
1034 : {
1035 1 : RIALTO_SERVER_LOG_ERROR("Failed to set sync - Gstreamer player has not been loaded");
1036 1 : return false;
1037 : }
1038 2 : return m_gstPlayer->setSync(sync);
1039 : }
1040 :
1041 3 : bool MediaPipelineServerInternal::getSync(bool &sync)
1042 : {
1043 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1044 :
1045 : bool result;
1046 3 : auto task = [&]() { result = getSyncInternal(sync); };
1047 :
1048 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1049 3 : return result;
1050 : }
1051 :
1052 3 : bool MediaPipelineServerInternal::getSyncInternal(bool &sync)
1053 : {
1054 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1055 :
1056 3 : if (!m_gstPlayer)
1057 : {
1058 1 : RIALTO_SERVER_LOG_ERROR("Failed to get sync - Gstreamer player has not been loaded");
1059 1 : return false;
1060 : }
1061 2 : return m_gstPlayer->getSync(sync);
1062 : }
1063 :
1064 3 : bool MediaPipelineServerInternal::setSyncOff(bool syncOff)
1065 : {
1066 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1067 :
1068 : bool result;
1069 3 : auto task = [&]() { result = setSyncOffInternal(syncOff); };
1070 :
1071 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1072 3 : return result;
1073 : }
1074 :
1075 3 : bool MediaPipelineServerInternal::setSyncOffInternal(bool syncOff)
1076 : {
1077 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1078 :
1079 3 : if (!m_gstPlayer)
1080 : {
1081 1 : RIALTO_SERVER_LOG_ERROR("Failed to set sync off - Gstreamer player has not been loaded");
1082 1 : return false;
1083 : }
1084 2 : return m_gstPlayer->setSyncOff(syncOff);
1085 : }
1086 :
1087 4 : bool MediaPipelineServerInternal::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode)
1088 : {
1089 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1090 :
1091 : bool result;
1092 4 : auto task = [&]() { result = setStreamSyncModeInternal(sourceId, streamSyncMode); };
1093 :
1094 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1095 4 : return result;
1096 : }
1097 :
1098 4 : bool MediaPipelineServerInternal::setStreamSyncModeInternal(int32_t sourceId, int32_t streamSyncMode)
1099 : {
1100 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1101 :
1102 4 : if (!m_gstPlayer)
1103 : {
1104 1 : RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Gstreamer player has not been loaded");
1105 1 : return false;
1106 : }
1107 :
1108 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1109 2 : [sourceId](const auto &src) { return src.second == sourceId; });
1110 3 : if (sourceIter == m_attachedSources.end())
1111 : {
1112 1 : RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Source with id: %d not found", sourceId);
1113 1 : return false;
1114 : }
1115 :
1116 2 : return m_gstPlayer->setStreamSyncMode(sourceIter->first, streamSyncMode);
1117 : }
1118 :
1119 3 : bool MediaPipelineServerInternal::getStreamSyncMode(int32_t &streamSyncMode)
1120 : {
1121 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1122 :
1123 : bool result;
1124 3 : auto task = [&]() { result = getStreamSyncModeInternal(streamSyncMode); };
1125 :
1126 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1127 3 : return result;
1128 : }
1129 :
1130 3 : bool MediaPipelineServerInternal::getStreamSyncModeInternal(int32_t &streamSyncMode)
1131 : {
1132 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1133 :
1134 3 : if (!m_gstPlayer)
1135 : {
1136 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stream sync mode - Gstreamer player has not been loaded");
1137 1 : return false;
1138 : }
1139 2 : return m_gstPlayer->getStreamSyncMode(streamSyncMode);
1140 : }
1141 :
1142 4 : bool MediaPipelineServerInternal::flushInternal(int32_t sourceId, bool resetTime, bool &async)
1143 : {
1144 4 : if (!m_gstPlayer)
1145 : {
1146 1 : RIALTO_SERVER_LOG_ERROR("Failed to flush - Gstreamer player has not been loaded");
1147 1 : return false;
1148 : }
1149 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1150 2 : [sourceId](const auto &src) { return src.second == sourceId; });
1151 3 : if (sourceIter == m_attachedSources.end())
1152 : {
1153 1 : RIALTO_SERVER_LOG_ERROR("Failed to flush - Source with id: %d not found", sourceId);
1154 1 : return false;
1155 : }
1156 :
1157 2 : m_gstPlayer->flush(sourceIter->first, resetTime, async);
1158 :
1159 2 : m_needMediaDataTimers.erase(sourceIter->first);
1160 :
1161 : // Reset Eos on flush
1162 2 : auto it = m_isMediaTypeEosMap.find(sourceIter->first);
1163 2 : if (it != m_isMediaTypeEosMap.end() && it->second)
1164 : {
1165 1 : it->second = false;
1166 : }
1167 :
1168 2 : return true;
1169 : }
1170 :
1171 3 : bool MediaPipelineServerInternal::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime,
1172 : double appliedRate, uint64_t stopPosition)
1173 : {
1174 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1175 :
1176 : bool result;
1177 3 : auto task = [&]() { result = setSourcePositionInternal(sourceId, position, resetTime, appliedRate, stopPosition); };
1178 :
1179 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1180 3 : return result;
1181 : }
1182 :
1183 3 : bool MediaPipelineServerInternal::setSourcePositionInternal(int32_t sourceId, int64_t position, bool resetTime,
1184 : double appliedRate, uint64_t stopPosition)
1185 : {
1186 3 : if (!m_gstPlayer)
1187 : {
1188 1 : RIALTO_SERVER_LOG_ERROR("Failed to set source position - Gstreamer player has not been loaded");
1189 1 : return false;
1190 : }
1191 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1192 1 : [sourceId](const auto &src) { return src.second == sourceId; });
1193 2 : if (sourceIter == m_attachedSources.end())
1194 : {
1195 1 : RIALTO_SERVER_LOG_ERROR("Failed to set source position - Source with id: %d not found", sourceId);
1196 1 : return false;
1197 : }
1198 :
1199 1 : m_gstPlayer->setSourcePosition(sourceIter->first, position, resetTime, appliedRate, stopPosition);
1200 :
1201 : // Reset Eos on seek
1202 1 : auto it = m_isMediaTypeEosMap.find(sourceIter->first);
1203 1 : if (it != m_isMediaTypeEosMap.end() && it->second)
1204 : {
1205 0 : it->second = false;
1206 : }
1207 :
1208 1 : return true;
1209 : }
1210 :
1211 3 : bool MediaPipelineServerInternal::setSubtitleOffset(int32_t sourceId, int64_t position)
1212 : {
1213 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1214 :
1215 : bool result;
1216 3 : auto task = [&]() { result = setSubtitleOffsetInternal(sourceId, position); };
1217 :
1218 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1219 3 : return result;
1220 : }
1221 :
1222 3 : bool MediaPipelineServerInternal::setSubtitleOffsetInternal(int32_t sourceId, int64_t position)
1223 : {
1224 3 : if (!m_gstPlayer)
1225 : {
1226 1 : RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Gstreamer player has not been loaded");
1227 1 : return false;
1228 : }
1229 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1230 1 : [sourceId](const auto &src) { return src.second == sourceId; });
1231 2 : if (sourceIter == m_attachedSources.end())
1232 : {
1233 1 : RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Source with id: %d not found", sourceId);
1234 1 : return false;
1235 : }
1236 :
1237 1 : m_gstPlayer->setSubtitleOffset(position);
1238 1 : return true;
1239 : }
1240 :
1241 2 : bool MediaPipelineServerInternal::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap,
1242 : bool audioAac)
1243 : {
1244 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1245 :
1246 : bool result;
1247 2 : auto task = [&]() { result = processAudioGapInternal(position, duration, discontinuityGap, audioAac); };
1248 :
1249 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1250 2 : return result;
1251 : }
1252 :
1253 2 : bool MediaPipelineServerInternal::processAudioGapInternal(int64_t position, uint32_t duration, int64_t discontinuityGap,
1254 : bool audioAac)
1255 : {
1256 2 : if (!m_gstPlayer)
1257 : {
1258 1 : RIALTO_SERVER_LOG_ERROR("Failed to process audio gap - Gstreamer player has not been loaded");
1259 1 : return false;
1260 : }
1261 1 : m_gstPlayer->processAudioGap(position, duration, discontinuityGap, audioAac);
1262 1 : return true;
1263 : }
1264 :
1265 2 : bool MediaPipelineServerInternal::setBufferingLimit(uint32_t limitBufferingMs)
1266 : {
1267 : bool result;
1268 2 : auto task = [&]() { result = setBufferingLimitInternal(limitBufferingMs); };
1269 :
1270 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1271 2 : return result;
1272 : }
1273 :
1274 2 : bool MediaPipelineServerInternal::setBufferingLimitInternal(uint32_t limitBufferingMs)
1275 : {
1276 2 : if (!m_gstPlayer)
1277 : {
1278 1 : RIALTO_SERVER_LOG_ERROR("Failed to set buffering limit - Gstreamer player has not been loaded");
1279 1 : return false;
1280 : }
1281 1 : m_gstPlayer->setBufferingLimit(limitBufferingMs);
1282 1 : return true;
1283 : }
1284 :
1285 3 : bool MediaPipelineServerInternal::getBufferingLimit(uint32_t &limitBufferingMs)
1286 : {
1287 : bool result;
1288 3 : auto task = [&]() { result = getBufferingLimitInternal(limitBufferingMs); };
1289 :
1290 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1291 3 : return result;
1292 : }
1293 :
1294 3 : bool MediaPipelineServerInternal::getBufferingLimitInternal(uint32_t &limitBufferingMs)
1295 : {
1296 3 : if (!m_gstPlayer)
1297 : {
1298 1 : RIALTO_SERVER_LOG_ERROR("Failed to get buffering limit - Gstreamer player has not been loaded");
1299 1 : return false;
1300 : }
1301 2 : return m_gstPlayer->getBufferingLimit(limitBufferingMs);
1302 : }
1303 :
1304 2 : bool MediaPipelineServerInternal::setUseBuffering(bool useBuffering)
1305 : {
1306 : bool result;
1307 2 : auto task = [&]() { result = setUseBufferingInternal(useBuffering); };
1308 :
1309 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1310 2 : return result;
1311 : }
1312 :
1313 2 : bool MediaPipelineServerInternal::setUseBufferingInternal(bool useBuffering)
1314 : {
1315 2 : if (!m_gstPlayer)
1316 : {
1317 1 : RIALTO_SERVER_LOG_ERROR("Failed to set use buffering - Gstreamer player has not been loaded");
1318 1 : return false;
1319 : }
1320 1 : m_gstPlayer->setUseBuffering(useBuffering);
1321 1 : return true;
1322 : }
1323 :
1324 3 : bool MediaPipelineServerInternal::getUseBuffering(bool &useBuffering)
1325 : {
1326 : bool result;
1327 3 : auto task = [&]() { result = getUseBufferingInternal(useBuffering); };
1328 :
1329 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1330 3 : return result;
1331 : }
1332 :
1333 3 : bool MediaPipelineServerInternal::getUseBufferingInternal(bool &useBuffering)
1334 : {
1335 3 : if (!m_gstPlayer)
1336 : {
1337 1 : RIALTO_SERVER_LOG_ERROR("Failed to get use buffering - Gstreamer player has not been loaded");
1338 1 : return false;
1339 : }
1340 2 : return m_gstPlayer->getUseBuffering(useBuffering);
1341 : }
1342 :
1343 2 : bool MediaPipelineServerInternal::switchSource(const std::unique_ptr<MediaSource> &source)
1344 : {
1345 : bool result;
1346 2 : auto task = [&]() { result = switchSourceInternal(source); };
1347 :
1348 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1349 2 : return result;
1350 : }
1351 :
1352 2 : bool MediaPipelineServerInternal::switchSourceInternal(const std::unique_ptr<MediaSource> &source)
1353 : {
1354 2 : if (!m_gstPlayer)
1355 : {
1356 1 : RIALTO_SERVER_LOG_ERROR("Failed to switch source - Gstreamer player has not been loaded");
1357 1 : return false;
1358 : }
1359 1 : m_gstPlayer->switchSource(source);
1360 1 : return true;
1361 : }
1362 :
1363 3 : AddSegmentStatus MediaPipelineServerInternal::addSegment(uint32_t needDataRequestId,
1364 : const std::unique_ptr<MediaSegment> &mediaSegment)
1365 : {
1366 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1367 :
1368 3 : AddSegmentStatus status{AddSegmentStatus::ERROR};
1369 3 : auto task = [&]() { status = addSegmentInternal(needDataRequestId, mediaSegment); };
1370 :
1371 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1372 3 : return status;
1373 : }
1374 :
1375 3 : AddSegmentStatus MediaPipelineServerInternal::addSegmentInternal(uint32_t needDataRequestId,
1376 : const std::unique_ptr<MediaSegment> &mediaSegment)
1377 : {
1378 3 : AddSegmentStatus status = m_activeRequests->addSegment(needDataRequestId, mediaSegment);
1379 3 : if (status != AddSegmentStatus::OK)
1380 : {
1381 2 : RIALTO_SERVER_LOG_ERROR("Failed to add segment for request id: %u", needDataRequestId);
1382 : }
1383 :
1384 3 : return status;
1385 : }
1386 :
1387 0 : std::weak_ptr<IMediaPipelineClient> MediaPipelineServerInternal::getClient()
1388 : {
1389 0 : return m_mediaPipelineClient;
1390 : }
1391 :
1392 8 : void MediaPipelineServerInternal::notifyPlaybackState(PlaybackState state)
1393 : {
1394 8 : RIALTO_SERVER_LOG_DEBUG("entry:");
1395 :
1396 8 : auto task = [&, state]()
1397 : {
1398 8 : m_currentPlaybackState = state;
1399 8 : if (m_mediaPipelineClient)
1400 : {
1401 8 : m_mediaPipelineClient->notifyPlaybackState(state);
1402 : }
1403 16 : };
1404 :
1405 8 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1406 : }
1407 :
1408 7 : bool MediaPipelineServerInternal::notifyNeedMediaData(MediaSourceType mediaSourceType)
1409 : {
1410 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
1411 :
1412 : // the task won't execute for a disconnected client therefore
1413 : // set a default value of true which will help to stop any further
1414 : // action being taken
1415 7 : bool result{true};
1416 :
1417 7 : auto task = [&]() { result = notifyNeedMediaDataInternal(mediaSourceType); };
1418 :
1419 7 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1420 :
1421 7 : return result;
1422 : }
1423 :
1424 8 : bool MediaPipelineServerInternal::notifyNeedMediaDataInternal(MediaSourceType mediaSourceType)
1425 : {
1426 8 : m_needMediaDataTimers.erase(mediaSourceType);
1427 8 : m_shmBuffer->clearData(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType);
1428 8 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1429 :
1430 8 : if (m_attachedSources.cend() == kSourceIter)
1431 : {
1432 1 : RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s - sourceId not found",
1433 : common::convertMediaSourceType(mediaSourceType));
1434 1 : return false;
1435 : }
1436 7 : auto it = m_isMediaTypeEosMap.find(mediaSourceType);
1437 7 : if (it != m_isMediaTypeEosMap.end() && it->second)
1438 : {
1439 2 : RIALTO_SERVER_LOG_INFO("EOS, NeedMediaData not needed for %s", common::convertMediaSourceType(mediaSourceType));
1440 2 : return false;
1441 : }
1442 5 : NeedMediaData event{m_mediaPipelineClient, *m_activeRequests, *m_shmBuffer, m_sessionId,
1443 10 : mediaSourceType, kSourceIter->second, m_currentPlaybackState};
1444 5 : if (!event.send())
1445 : {
1446 0 : RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s",
1447 : common::convertMediaSourceType(mediaSourceType));
1448 0 : return false;
1449 : }
1450 :
1451 5 : RIALTO_SERVER_LOG_DEBUG("%s NeedMediaData sent.", common::convertMediaSourceType(mediaSourceType));
1452 :
1453 5 : return true;
1454 : }
1455 :
1456 1 : void MediaPipelineServerInternal::notifyPosition(std::int64_t position)
1457 : {
1458 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1459 :
1460 1 : auto task = [&, position]()
1461 : {
1462 1 : if (m_mediaPipelineClient)
1463 : {
1464 1 : m_mediaPipelineClient->notifyPosition(position);
1465 : }
1466 2 : };
1467 :
1468 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1469 : }
1470 :
1471 104 : void MediaPipelineServerInternal::notifyNetworkState(NetworkState state)
1472 : {
1473 104 : RIALTO_SERVER_LOG_DEBUG("entry:");
1474 :
1475 104 : auto task = [&, state]()
1476 : {
1477 104 : if (m_mediaPipelineClient)
1478 : {
1479 104 : m_mediaPipelineClient->notifyNetworkState(state);
1480 : }
1481 208 : };
1482 :
1483 104 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1484 : }
1485 :
1486 1 : void MediaPipelineServerInternal::clearActiveRequestsCache()
1487 : {
1488 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1489 :
1490 1 : auto task = [&]() { m_activeRequests->clear(); };
1491 :
1492 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1493 : }
1494 :
1495 1 : void MediaPipelineServerInternal::invalidateActiveRequests(const MediaSourceType &type)
1496 : {
1497 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1498 :
1499 1 : auto task = [&, type]() { m_activeRequests->erase(type); };
1500 :
1501 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1502 : }
1503 :
1504 2 : void MediaPipelineServerInternal::notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo)
1505 : {
1506 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1507 :
1508 2 : auto task = [&, mediaSourceType, qosInfo]()
1509 : {
1510 2 : if (m_mediaPipelineClient)
1511 : {
1512 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1513 2 : if (m_attachedSources.cend() == kSourceIter)
1514 : {
1515 1 : RIALTO_SERVER_LOG_WARN("Qos notification failed - sourceId not found for %s",
1516 : common::convertMediaSourceType(mediaSourceType));
1517 1 : return;
1518 : }
1519 1 : m_mediaPipelineClient->notifyQos(kSourceIter->second, qosInfo);
1520 : }
1521 2 : };
1522 :
1523 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1524 : }
1525 :
1526 0 : void MediaPipelineServerInternal::notifyBufferUnderflow(MediaSourceType mediaSourceType)
1527 : {
1528 0 : RIALTO_SERVER_LOG_DEBUG("entry:");
1529 :
1530 0 : auto task = [&, mediaSourceType]()
1531 : {
1532 0 : if (m_mediaPipelineClient)
1533 : {
1534 0 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1535 0 : if (m_attachedSources.cend() == kSourceIter)
1536 : {
1537 0 : RIALTO_SERVER_LOG_WARN("Buffer underflow notification failed - sourceId not found for %s",
1538 : common::convertMediaSourceType(mediaSourceType));
1539 0 : return;
1540 : }
1541 0 : m_mediaPipelineClient->notifyBufferUnderflow(kSourceIter->second);
1542 : }
1543 0 : };
1544 :
1545 0 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1546 : }
1547 :
1548 2 : void MediaPipelineServerInternal::notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error)
1549 : {
1550 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1551 :
1552 2 : auto task = [&, mediaSourceType, error]()
1553 : {
1554 2 : if (m_mediaPipelineClient)
1555 : {
1556 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1557 2 : if (m_attachedSources.cend() == kSourceIter)
1558 : {
1559 1 : RIALTO_SERVER_LOG_WARN("Playback error notification failed - sourceId not found for %s",
1560 : common::convertMediaSourceType(mediaSourceType));
1561 1 : return;
1562 : }
1563 1 : m_mediaPipelineClient->notifyPlaybackError(kSourceIter->second, error);
1564 : }
1565 2 : };
1566 :
1567 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1568 : }
1569 :
1570 2 : void MediaPipelineServerInternal::notifySourceFlushed(MediaSourceType mediaSourceType)
1571 : {
1572 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1573 :
1574 2 : auto task = [&, mediaSourceType]()
1575 : {
1576 2 : if (m_mediaPipelineClient)
1577 : {
1578 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1579 2 : if (m_attachedSources.cend() == kSourceIter)
1580 : {
1581 1 : RIALTO_SERVER_LOG_WARN("Source flushed notification failed - sourceId not found for: %s",
1582 : common::convertMediaSourceType(mediaSourceType));
1583 1 : return;
1584 : }
1585 1 : m_mediaPipelineClient->notifySourceFlushed(kSourceIter->second);
1586 1 : RIALTO_SERVER_LOG_DEBUG("%s source flushed", common::convertMediaSourceType(mediaSourceType));
1587 : }
1588 2 : };
1589 :
1590 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1591 : }
1592 :
1593 0 : void MediaPipelineServerInternal::notifyPlaybackInfo(const PlaybackInfo &playbackInfo)
1594 : {
1595 0 : if (m_mediaPipelineClient)
1596 : {
1597 0 : m_mediaPipelineClient->notifyPlaybackInfo(playbackInfo);
1598 : }
1599 : }
1600 :
1601 7 : void MediaPipelineServerInternal::scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType)
1602 : {
1603 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
1604 7 : auto timer = m_needMediaDataTimers.find(mediaSourceType);
1605 7 : if (m_needMediaDataTimers.end() != timer && timer->second && timer->second->isActive())
1606 : {
1607 1 : RIALTO_SERVER_LOG_DEBUG("Skip scheduling need media data for %s - it is already scheduled",
1608 : common::convertMediaSourceType(mediaSourceType));
1609 1 : return;
1610 : }
1611 :
1612 6 : m_needMediaDataTimers[mediaSourceType] =
1613 6 : m_timerFactory
1614 18 : ->createTimer(getNeedMediaDataTimeout(mediaSourceType),
1615 12 : [this, mediaSourceType]()
1616 : {
1617 1 : m_mainThread
1618 2 : ->enqueueTask(m_mainThreadClientId,
1619 1 : [this, mediaSourceType]()
1620 : {
1621 1 : m_needMediaDataTimers.erase(mediaSourceType);
1622 1 : if (!notifyNeedMediaDataInternal(mediaSourceType))
1623 : {
1624 0 : RIALTO_SERVER_LOG_WARN("Scheduled Need media data sending "
1625 : "failed for: %s. Scheduling again...",
1626 : common::convertMediaSourceType(
1627 : mediaSourceType));
1628 0 : scheduleNotifyNeedMediaData(mediaSourceType);
1629 : }
1630 1 : });
1631 7 : });
1632 : }
1633 :
1634 6 : std::chrono::milliseconds MediaPipelineServerInternal::getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const
1635 : {
1636 6 : constexpr std::chrono::milliseconds kDefaultNeedMediaDataResendTimeMs{15};
1637 6 : constexpr std::chrono::milliseconds kNeedMediaDataResendTimeMsForLowLatency{5};
1638 6 : if ((mediaSourceType == MediaSourceType::VIDEO && m_IsLowLatencyVideoPlayer) ||
1639 1 : (mediaSourceType == MediaSourceType::AUDIO && m_IsLowLatencyAudioPlayer))
1640 : {
1641 2 : return kNeedMediaDataResendTimeMsForLowLatency;
1642 : }
1643 4 : return kDefaultNeedMediaDataResendTimeMs;
1644 : }
1645 : }; // namespace firebolt::rialto::server
|