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 : 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 : 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 : m_gstPlayer->removeSource(sourceIter->first);
303 2 : m_needMediaDataTimers.erase(sourceIter->first);
304 2 : m_attachedSources.erase(sourceIter);
305 2 : return true;
306 : }
307 :
308 4 : bool MediaPipelineServerInternal::allSourcesAttached()
309 : {
310 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
311 :
312 : bool result;
313 4 : auto task = [&]() { result = allSourcesAttachedInternal(); };
314 :
315 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
316 4 : return result;
317 : }
318 :
319 4 : bool MediaPipelineServerInternal::allSourcesAttachedInternal()
320 : {
321 4 : if (!m_gstPlayer)
322 : {
323 1 : RIALTO_SERVER_LOG_ERROR("Failed to notify all sources attached - Gstreamer player has not been loaded");
324 1 : return false;
325 : }
326 :
327 3 : if (m_wasAllSourcesAttachedCalled)
328 : {
329 1 : RIALTO_SERVER_LOG_WARN("Failed to notify all sources attached - It was already called");
330 1 : return false;
331 : }
332 :
333 2 : m_gstPlayer->allSourcesAttached();
334 2 : m_wasAllSourcesAttachedCalled = true;
335 2 : return true;
336 : }
337 :
338 2 : bool MediaPipelineServerInternal::play(bool &async)
339 : {
340 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
341 :
342 : bool result;
343 2 : auto task = [&]() { result = playInternal(async); };
344 :
345 2 : m_mainThread->enqueuePriorityTaskAndWait(m_mainThreadClientId, task);
346 2 : return result;
347 : }
348 :
349 2 : bool MediaPipelineServerInternal::playInternal(bool &async)
350 : {
351 2 : if (!m_gstPlayer)
352 : {
353 1 : RIALTO_SERVER_LOG_ERROR("Failed to play - Gstreamer player has not been loaded");
354 1 : return false;
355 : }
356 :
357 1 : m_gstPlayer->play(async);
358 1 : return true;
359 : }
360 :
361 2 : bool MediaPipelineServerInternal::pause()
362 : {
363 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
364 :
365 : bool result;
366 2 : auto task = [&]() { result = pauseInternal(); };
367 :
368 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
369 2 : return result;
370 : }
371 :
372 2 : bool MediaPipelineServerInternal::pauseInternal()
373 : {
374 2 : if (!m_gstPlayer)
375 : {
376 1 : RIALTO_SERVER_LOG_ERROR("Failed to pause - Gstreamer player has not been loaded");
377 1 : return false;
378 : }
379 :
380 1 : m_gstPlayer->pause();
381 1 : return true;
382 : }
383 :
384 2 : bool MediaPipelineServerInternal::stop()
385 : {
386 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
387 :
388 : bool result;
389 2 : auto task = [&]() { result = stopInternal(); };
390 :
391 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
392 2 : return result;
393 : }
394 :
395 2 : bool MediaPipelineServerInternal::stopInternal()
396 : {
397 2 : if (!m_gstPlayer)
398 : {
399 1 : RIALTO_SERVER_LOG_ERROR("Failed to stop - Gstreamer player has not been loaded");
400 1 : return false;
401 : }
402 :
403 1 : m_gstPlayer->stop();
404 1 : return true;
405 : }
406 :
407 3 : bool MediaPipelineServerInternal::setPlaybackRate(double rate)
408 : {
409 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
410 :
411 : bool result;
412 3 : auto task = [&]() { result = setPlaybackRateInternal(rate); };
413 :
414 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
415 3 : return result;
416 : }
417 :
418 3 : bool MediaPipelineServerInternal::setPlaybackRateInternal(double rate)
419 : {
420 3 : if (!m_gstPlayer)
421 : {
422 2 : RIALTO_SERVER_LOG_ERROR("Failed to set playback rate - Gstreamer player has not been loaded");
423 2 : return false;
424 : }
425 :
426 1 : if (0.0 == rate)
427 : {
428 0 : RIALTO_SERVER_LOG_ERROR("Failed to set playback rate to 0.0 - pause method should be used instead.");
429 0 : return false;
430 : }
431 :
432 1 : m_gstPlayer->setPlaybackRate(rate);
433 1 : return true;
434 : }
435 :
436 2 : bool MediaPipelineServerInternal::setPosition(int64_t position)
437 : {
438 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
439 :
440 : bool result;
441 2 : auto task = [&]() { result = setPositionInternal(position); };
442 :
443 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
444 2 : return result;
445 : }
446 :
447 2 : bool MediaPipelineServerInternal::setPositionInternal(int64_t position)
448 : {
449 2 : if (!m_gstPlayer)
450 : {
451 1 : RIALTO_SERVER_LOG_ERROR("Failed to set position - Gstreamer player has not been loaded");
452 1 : return false;
453 : }
454 :
455 1 : m_gstPlayer->setPosition(position);
456 :
457 : // Reset Eos on seek
458 1 : for (auto &isMediaTypeEos : m_isMediaTypeEosMap)
459 : {
460 0 : isMediaTypeEos.second = false;
461 : }
462 :
463 1 : return true;
464 : }
465 :
466 3 : bool MediaPipelineServerInternal::getPosition(int64_t &position)
467 : {
468 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
469 :
470 3 : std::shared_lock lock{m_getPropertyMutex};
471 :
472 3 : if (!m_gstPlayer)
473 : {
474 1 : RIALTO_SERVER_LOG_ERROR("Failed to get position - Gstreamer player has not been loaded");
475 1 : return false;
476 : }
477 2 : return m_gstPlayer->getPosition(position);
478 3 : }
479 :
480 4 : bool MediaPipelineServerInternal::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
481 : {
482 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
483 :
484 : bool result;
485 4 : auto task = [&]() { result = getStatsInternal(sourceId, renderedFrames, droppedFrames); };
486 :
487 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
488 4 : return result;
489 : }
490 :
491 4 : bool MediaPipelineServerInternal::getStatsInternal(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
492 : {
493 4 : if (!m_gstPlayer)
494 : {
495 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stats - Gstreamer player has not been loaded");
496 1 : return false;
497 : }
498 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
499 2 : [sourceId](const auto &src) { return src.second == sourceId; });
500 3 : if (sourceIter == m_attachedSources.end())
501 : {
502 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stats - Source not found");
503 1 : return false;
504 : }
505 2 : return m_gstPlayer->getStats(sourceIter->first, renderedFrames, droppedFrames);
506 : }
507 :
508 6 : bool MediaPipelineServerInternal::setImmediateOutput(int32_t sourceId, bool immediateOutput)
509 : {
510 6 : RIALTO_SERVER_LOG_DEBUG("entry:");
511 :
512 : bool result;
513 6 : auto task = [&]() { result = setImmediateOutputInternal(sourceId, immediateOutput); };
514 :
515 6 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
516 6 : return result;
517 : }
518 :
519 6 : bool MediaPipelineServerInternal::setImmediateOutputInternal(int32_t sourceId, bool immediateOutput)
520 : {
521 6 : if (!m_gstPlayer)
522 : {
523 1 : RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded");
524 1 : return false;
525 : }
526 5 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
527 4 : [sourceId](const auto &src) { return src.second == sourceId; });
528 5 : if (sourceIter == m_attachedSources.end())
529 : {
530 1 : RIALTO_SERVER_LOG_ERROR("Failed - Source not found");
531 1 : return false;
532 : }
533 :
534 4 : m_IsLowLatencyVideoPlayer = immediateOutput;
535 4 : return m_gstPlayer->setImmediateOutput(sourceIter->first, immediateOutput);
536 : }
537 :
538 5 : bool MediaPipelineServerInternal::getImmediateOutput(int32_t sourceId, bool &immediateOutput)
539 : {
540 5 : RIALTO_SERVER_LOG_DEBUG("entry:");
541 :
542 : bool result;
543 5 : auto task = [&]() { result = getImmediateOutputInternal(sourceId, immediateOutput); };
544 :
545 5 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
546 5 : return result;
547 : }
548 :
549 5 : bool MediaPipelineServerInternal::getImmediateOutputInternal(int32_t sourceId, bool &immediateOutput)
550 : {
551 5 : if (!m_gstPlayer)
552 : {
553 1 : RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded");
554 1 : return false;
555 : }
556 4 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
557 3 : [sourceId](const auto &src) { return src.second == sourceId; });
558 4 : if (sourceIter == m_attachedSources.end())
559 : {
560 1 : RIALTO_SERVER_LOG_ERROR("Failed - Source not found");
561 1 : return false;
562 : }
563 3 : return m_gstPlayer->getImmediateOutput(sourceIter->first, immediateOutput);
564 : }
565 :
566 2 : bool MediaPipelineServerInternal::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
567 : {
568 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
569 :
570 : bool result;
571 2 : auto task = [&]() { result = setVideoWindowInternal(x, y, width, height); };
572 :
573 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
574 2 : return result;
575 : }
576 :
577 2 : bool MediaPipelineServerInternal::setVideoWindowInternal(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
578 : {
579 2 : if (!m_gstPlayer)
580 : {
581 1 : RIALTO_SERVER_LOG_ERROR("Failed to set video window - Gstreamer player has not been loaded");
582 1 : return false;
583 : }
584 :
585 1 : m_gstPlayer->setVideoGeometry(x, y, width, height);
586 1 : return true;
587 : }
588 :
589 12 : bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t needDataRequestId)
590 : {
591 12 : RIALTO_SERVER_LOG_DEBUG("entry:");
592 :
593 : bool result;
594 12 : auto task = [&]() { result = haveDataInternal(status, needDataRequestId); };
595 :
596 12 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
597 12 : return result;
598 : }
599 :
600 12 : bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t needDataRequestId)
601 : {
602 12 : if (!m_gstPlayer)
603 : {
604 1 : RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded");
605 1 : return false;
606 : }
607 :
608 11 : MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId);
609 11 : if (MediaSourceType::UNKNOWN == mediaSourceType)
610 : {
611 1 : RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId);
612 1 : return true;
613 : }
614 :
615 10 : unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType];
616 10 : if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS)
617 : {
618 : // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS.
619 :
620 3 : ++counter;
621 3 : if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES)
622 : {
623 2 : RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u "
624 : "consecutively for mediaSourceType: %s",
625 : needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType));
626 : }
627 : else
628 : {
629 1 : RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status: %s",
630 : common::convertMediaSourceType(mediaSourceType), needDataRequestId, toString(status));
631 1 : counter = 0;
632 : }
633 :
634 3 : m_activeRequests->erase(needDataRequestId);
635 3 : scheduleNotifyNeedMediaData(mediaSourceType);
636 3 : return true;
637 : }
638 : else
639 : {
640 7 : RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status",
641 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
642 7 : counter = 0;
643 : }
644 :
645 : try
646 : {
647 7 : const IMediaPipeline::MediaSegmentVector &kSegments = m_activeRequests->getSegments(needDataRequestId);
648 6 : m_gstPlayer->attachSamples(kSegments);
649 : }
650 1 : catch (const std::runtime_error &e)
651 : {
652 1 : RIALTO_SERVER_LOG_ERROR("Failed to get segments %s", e.what());
653 1 : m_activeRequests->erase(needDataRequestId);
654 1 : return false;
655 : }
656 :
657 6 : m_activeRequests->erase(needDataRequestId);
658 6 : if (status == MediaSourceStatus::EOS)
659 : {
660 5 : m_gstPlayer->setEos(mediaSourceType);
661 5 : m_isMediaTypeEosMap[mediaSourceType] = true;
662 : }
663 :
664 6 : return true;
665 : }
666 :
667 13 : bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId)
668 : {
669 13 : RIALTO_SERVER_LOG_DEBUG("entry:");
670 :
671 : bool result;
672 13 : auto task = [&]() { result = haveDataInternal(status, numFrames, needDataRequestId); };
673 :
674 13 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
675 13 : return result;
676 : }
677 :
678 13 : bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t numFrames,
679 : uint32_t needDataRequestId)
680 : {
681 13 : if (!m_gstPlayer)
682 : {
683 1 : RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded");
684 1 : return false;
685 : }
686 12 : MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId);
687 12 : if (MediaSourceType::UNKNOWN == mediaSourceType)
688 : {
689 1 : RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId);
690 1 : return true;
691 : }
692 11 : m_activeRequests->erase(needDataRequestId);
693 :
694 11 : unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType];
695 11 : if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS)
696 : {
697 : // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS.
698 :
699 4 : ++counter;
700 4 : if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES)
701 : {
702 0 : RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u "
703 : "consecutively for mediaSourceType: %s",
704 : needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType));
705 : }
706 : else
707 : {
708 4 : RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status",
709 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
710 4 : counter = 0;
711 : }
712 4 : scheduleNotifyNeedMediaData(mediaSourceType);
713 4 : return true;
714 : }
715 : else
716 : {
717 7 : RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status",
718 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
719 7 : counter = 0;
720 : }
721 :
722 7 : uint8_t *buffer = m_shmBuffer->getBuffer();
723 7 : if (!buffer)
724 : {
725 1 : RIALTO_SERVER_LOG_ERROR("No buffer available");
726 1 : notifyPlaybackState(PlaybackState::FAILURE);
727 1 : return false;
728 : }
729 :
730 6 : std::uint32_t regionOffset = 0;
731 : try
732 : {
733 : regionOffset =
734 6 : m_shmBuffer->getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType);
735 : }
736 1 : catch (const std::runtime_error &e)
737 : {
738 1 : RIALTO_SERVER_LOG_ERROR("Failed to get region's buffer offset, reason: %s", e.what());
739 1 : notifyPlaybackState(PlaybackState::FAILURE);
740 1 : return false;
741 : }
742 :
743 5 : if (0 != numFrames)
744 : {
745 : std::shared_ptr<IDataReader> dataReader =
746 4 : m_dataReaderFactory->createDataReader(mediaSourceType, buffer, regionOffset, numFrames);
747 4 : if (!dataReader)
748 : {
749 1 : RIALTO_SERVER_LOG_ERROR("Metadata version not supported for %s request id: %u",
750 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
751 1 : notifyPlaybackState(PlaybackState::FAILURE);
752 1 : return false;
753 : }
754 3 : m_gstPlayer->attachSamples(dataReader);
755 4 : }
756 4 : if (status == MediaSourceStatus::EOS)
757 : {
758 2 : m_gstPlayer->setEos(mediaSourceType);
759 2 : m_isMediaTypeEosMap[mediaSourceType] = true;
760 : }
761 :
762 4 : return true;
763 : }
764 :
765 2 : void MediaPipelineServerInternal::ping(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
766 : {
767 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
768 :
769 2 : auto task = [&]() { pingInternal(std::move(heartbeatHandler)); };
770 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
771 : }
772 :
773 2 : void MediaPipelineServerInternal::pingInternal(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
774 : {
775 2 : if (!m_gstPlayer)
776 : {
777 : // No need to check GstPlayer worker thread, we reached this function, so main thread is working fine.
778 1 : heartbeatHandler.reset();
779 1 : return;
780 : }
781 : // Check GstPlayer worker thread
782 1 : m_gstPlayer->ping(std::move(heartbeatHandler));
783 : }
784 :
785 2 : bool MediaPipelineServerInternal::renderFrame()
786 : {
787 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
788 :
789 : bool result;
790 2 : auto task = [&]() { result = renderFrameInternal(); };
791 :
792 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
793 2 : return result;
794 : }
795 :
796 2 : bool MediaPipelineServerInternal::renderFrameInternal()
797 : {
798 2 : if (!m_gstPlayer)
799 : {
800 1 : RIALTO_SERVER_LOG_ERROR("renderFrame failed - Gstreamer player has not been loaded");
801 1 : return false;
802 : }
803 :
804 1 : m_gstPlayer->renderFrame();
805 1 : return true;
806 : }
807 :
808 3 : bool MediaPipelineServerInternal::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType)
809 : {
810 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
811 :
812 3 : m_isSetVolumeInProgress = true;
813 : bool result;
814 3 : auto task = [&]() { result = setVolumeInternal(targetVolume, volumeDuration, easeType); };
815 :
816 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
817 3 : return result;
818 : }
819 :
820 3 : bool MediaPipelineServerInternal::setVolumeInternal(double targetVolume, uint32_t volumeDuration, EaseType easeType)
821 : {
822 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
823 :
824 3 : if (!m_gstPlayer)
825 : {
826 1 : RIALTO_SERVER_LOG_ERROR("Failed to set volume - Gstreamer player has not been loaded");
827 1 : return false;
828 : }
829 2 : m_gstPlayer->setVolume(targetVolume, volumeDuration, easeType);
830 2 : m_isSetVolumeInProgress = false;
831 2 : return true;
832 : }
833 :
834 4 : bool MediaPipelineServerInternal::getVolume(double ¤tVolume)
835 : {
836 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
837 :
838 4 : if (m_isSetVolumeInProgress)
839 : {
840 : bool result;
841 1 : auto task = [&]() { result = getVolumeInternal(currentVolume); };
842 :
843 1 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
844 1 : return result;
845 : }
846 3 : std::shared_lock lock{m_getPropertyMutex};
847 3 : return getVolumeInternal(currentVolume);
848 : }
849 :
850 4 : bool MediaPipelineServerInternal::getVolumeInternal(double ¤tVolume)
851 : {
852 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
853 :
854 4 : if (!m_gstPlayer)
855 : {
856 1 : RIALTO_SERVER_LOG_ERROR("Failed to get volume - Gstreamer player has not been loaded");
857 1 : return false;
858 : }
859 3 : return m_gstPlayer->getVolume(currentVolume);
860 : }
861 :
862 3 : bool MediaPipelineServerInternal::setMute(std::int32_t sourceId, bool mute)
863 : {
864 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
865 :
866 : bool result;
867 3 : auto task = [&]() { result = setMuteInternal(sourceId, mute); };
868 :
869 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
870 3 : return result;
871 : }
872 :
873 3 : bool MediaPipelineServerInternal::setMuteInternal(std::int32_t sourceId, bool mute)
874 : {
875 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
876 :
877 3 : if (!m_gstPlayer)
878 : {
879 1 : RIALTO_SERVER_LOG_ERROR("Failed to set mute - Gstreamer player has not been loaded");
880 1 : return false;
881 : }
882 :
883 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
884 1 : [sourceId](const auto &src) { return src.second == sourceId; });
885 2 : if (sourceIter == m_attachedSources.end())
886 : {
887 1 : RIALTO_SERVER_LOG_ERROR("Failed to set mute - Source with id: %d not found", sourceId);
888 1 : return false;
889 : }
890 :
891 1 : m_gstPlayer->setMute(sourceIter->first, mute);
892 :
893 1 : return true;
894 : }
895 :
896 4 : bool MediaPipelineServerInternal::getMute(std::int32_t sourceId, bool &mute)
897 : {
898 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
899 :
900 : bool result;
901 4 : auto task = [&]() { result = getMuteInternal(sourceId, mute); };
902 :
903 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
904 4 : return result;
905 : }
906 :
907 4 : bool MediaPipelineServerInternal::getMuteInternal(std::int32_t sourceId, bool &mute)
908 : {
909 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
910 :
911 4 : if (!m_gstPlayer)
912 : {
913 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded");
914 1 : return false;
915 : }
916 :
917 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
918 2 : [sourceId](const auto &src) { return src.second == sourceId; });
919 3 : if (sourceIter == m_attachedSources.end())
920 : {
921 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Source with id: %d not found", sourceId);
922 1 : return false;
923 : }
924 :
925 2 : return m_gstPlayer->getMute(sourceIter->first, mute);
926 : }
927 :
928 2 : bool MediaPipelineServerInternal::setTextTrackIdentifier(const std::string &textTrackIdentifier)
929 : {
930 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
931 :
932 : bool result;
933 2 : auto task = [&]() { result = setTextTrackIdentifierInternal(textTrackIdentifier); };
934 :
935 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
936 2 : return result;
937 : }
938 :
939 2 : bool MediaPipelineServerInternal::setTextTrackIdentifierInternal(const std::string &textTrackIdentifier)
940 : {
941 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
942 :
943 2 : if (!m_gstPlayer)
944 : {
945 1 : RIALTO_SERVER_LOG_ERROR("Failed to set text track identifier - Gstreamer player has not been loaded");
946 1 : return false;
947 : }
948 :
949 1 : m_gstPlayer->setTextTrackIdentifier(textTrackIdentifier);
950 :
951 1 : return true;
952 : }
953 :
954 3 : bool MediaPipelineServerInternal::getTextTrackIdentifier(std::string &textTrackIdentifier)
955 : {
956 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
957 :
958 : bool result;
959 3 : auto task = [&]() { result = getTextTrackIdentifierInternal(textTrackIdentifier); };
960 :
961 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
962 3 : return result;
963 : }
964 :
965 3 : bool MediaPipelineServerInternal::getTextTrackIdentifierInternal(std::string &textTrackIdentifier)
966 : {
967 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
968 :
969 3 : if (!m_gstPlayer)
970 : {
971 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded");
972 1 : return false;
973 : }
974 :
975 2 : return m_gstPlayer->getTextTrackIdentifier(textTrackIdentifier);
976 : }
977 :
978 4 : bool MediaPipelineServerInternal::flush(int32_t sourceId, bool resetTime, bool &async)
979 : {
980 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
981 :
982 : bool result;
983 4 : auto task = [&]() { result = flushInternal(sourceId, resetTime, async); };
984 :
985 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
986 4 : return result;
987 : }
988 :
989 4 : bool MediaPipelineServerInternal::setLowLatency(bool lowLatency)
990 : {
991 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
992 :
993 : bool result;
994 4 : auto task = [&]() { result = setLowLatencyInternal(lowLatency); };
995 :
996 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
997 4 : return result;
998 : }
999 :
1000 4 : bool MediaPipelineServerInternal::setLowLatencyInternal(bool lowLatency)
1001 : {
1002 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1003 :
1004 4 : if (!m_gstPlayer)
1005 : {
1006 1 : RIALTO_SERVER_LOG_ERROR("Failed to set low latency - Gstreamer player has not been loaded");
1007 1 : return false;
1008 : }
1009 3 : m_IsLowLatencyAudioPlayer = lowLatency;
1010 :
1011 3 : return m_gstPlayer->setLowLatency(lowLatency);
1012 : }
1013 :
1014 3 : bool MediaPipelineServerInternal::setSync(bool sync)
1015 : {
1016 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1017 :
1018 : bool result;
1019 3 : auto task = [&]() { result = setSyncInternal(sync); };
1020 :
1021 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1022 3 : return result;
1023 : }
1024 :
1025 3 : bool MediaPipelineServerInternal::setSyncInternal(bool sync)
1026 : {
1027 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1028 :
1029 3 : if (!m_gstPlayer)
1030 : {
1031 1 : RIALTO_SERVER_LOG_ERROR("Failed to set sync - Gstreamer player has not been loaded");
1032 1 : return false;
1033 : }
1034 2 : return m_gstPlayer->setSync(sync);
1035 : }
1036 :
1037 3 : bool MediaPipelineServerInternal::getSync(bool &sync)
1038 : {
1039 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1040 :
1041 : bool result;
1042 3 : auto task = [&]() { result = getSyncInternal(sync); };
1043 :
1044 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1045 3 : return result;
1046 : }
1047 :
1048 3 : bool MediaPipelineServerInternal::getSyncInternal(bool &sync)
1049 : {
1050 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1051 :
1052 3 : if (!m_gstPlayer)
1053 : {
1054 1 : RIALTO_SERVER_LOG_ERROR("Failed to get sync - Gstreamer player has not been loaded");
1055 1 : return false;
1056 : }
1057 2 : return m_gstPlayer->getSync(sync);
1058 : }
1059 :
1060 3 : bool MediaPipelineServerInternal::setSyncOff(bool syncOff)
1061 : {
1062 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1063 :
1064 : bool result;
1065 3 : auto task = [&]() { result = setSyncOffInternal(syncOff); };
1066 :
1067 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1068 3 : return result;
1069 : }
1070 :
1071 3 : bool MediaPipelineServerInternal::setSyncOffInternal(bool syncOff)
1072 : {
1073 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1074 :
1075 3 : if (!m_gstPlayer)
1076 : {
1077 1 : RIALTO_SERVER_LOG_ERROR("Failed to set sync off - Gstreamer player has not been loaded");
1078 1 : return false;
1079 : }
1080 2 : return m_gstPlayer->setSyncOff(syncOff);
1081 : }
1082 :
1083 4 : bool MediaPipelineServerInternal::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode)
1084 : {
1085 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1086 :
1087 : bool result;
1088 4 : auto task = [&]() { result = setStreamSyncModeInternal(sourceId, streamSyncMode); };
1089 :
1090 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1091 4 : return result;
1092 : }
1093 :
1094 4 : bool MediaPipelineServerInternal::setStreamSyncModeInternal(int32_t sourceId, int32_t streamSyncMode)
1095 : {
1096 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1097 :
1098 4 : if (!m_gstPlayer)
1099 : {
1100 1 : RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Gstreamer player has not been loaded");
1101 1 : return false;
1102 : }
1103 :
1104 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1105 2 : [sourceId](const auto &src) { return src.second == sourceId; });
1106 3 : if (sourceIter == m_attachedSources.end())
1107 : {
1108 1 : RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Source with id: %d not found", sourceId);
1109 1 : return false;
1110 : }
1111 :
1112 2 : return m_gstPlayer->setStreamSyncMode(sourceIter->first, streamSyncMode);
1113 : }
1114 :
1115 3 : bool MediaPipelineServerInternal::getStreamSyncMode(int32_t &streamSyncMode)
1116 : {
1117 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1118 :
1119 : bool result;
1120 3 : auto task = [&]() { result = getStreamSyncModeInternal(streamSyncMode); };
1121 :
1122 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1123 3 : return result;
1124 : }
1125 :
1126 3 : bool MediaPipelineServerInternal::getStreamSyncModeInternal(int32_t &streamSyncMode)
1127 : {
1128 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1129 :
1130 3 : if (!m_gstPlayer)
1131 : {
1132 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stream sync mode - Gstreamer player has not been loaded");
1133 1 : return false;
1134 : }
1135 2 : return m_gstPlayer->getStreamSyncMode(streamSyncMode);
1136 : }
1137 :
1138 4 : bool MediaPipelineServerInternal::flushInternal(int32_t sourceId, bool resetTime, bool &async)
1139 : {
1140 4 : if (!m_gstPlayer)
1141 : {
1142 1 : RIALTO_SERVER_LOG_ERROR("Failed to flush - Gstreamer player has not been loaded");
1143 1 : return false;
1144 : }
1145 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1146 2 : [sourceId](const auto &src) { return src.second == sourceId; });
1147 3 : if (sourceIter == m_attachedSources.end())
1148 : {
1149 1 : RIALTO_SERVER_LOG_ERROR("Failed to flush - Source with id: %d not found", sourceId);
1150 1 : return false;
1151 : }
1152 :
1153 2 : m_gstPlayer->flush(sourceIter->first, resetTime, async);
1154 :
1155 : // Reset Eos on flush
1156 2 : auto it = m_isMediaTypeEosMap.find(sourceIter->first);
1157 2 : if (it != m_isMediaTypeEosMap.end() && it->second)
1158 : {
1159 1 : it->second = false;
1160 : }
1161 :
1162 2 : return true;
1163 : }
1164 :
1165 3 : bool MediaPipelineServerInternal::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime,
1166 : double appliedRate, uint64_t stopPosition)
1167 : {
1168 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1169 :
1170 : bool result;
1171 3 : auto task = [&]() { result = setSourcePositionInternal(sourceId, position, resetTime, appliedRate, stopPosition); };
1172 :
1173 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1174 3 : return result;
1175 : }
1176 :
1177 3 : bool MediaPipelineServerInternal::setSourcePositionInternal(int32_t sourceId, int64_t position, bool resetTime,
1178 : double appliedRate, uint64_t stopPosition)
1179 : {
1180 3 : if (!m_gstPlayer)
1181 : {
1182 1 : RIALTO_SERVER_LOG_ERROR("Failed to set source position - Gstreamer player has not been loaded");
1183 1 : return false;
1184 : }
1185 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1186 1 : [sourceId](const auto &src) { return src.second == sourceId; });
1187 2 : if (sourceIter == m_attachedSources.end())
1188 : {
1189 1 : RIALTO_SERVER_LOG_ERROR("Failed to set source position - Source with id: %d not found", sourceId);
1190 1 : return false;
1191 : }
1192 :
1193 1 : m_gstPlayer->setSourcePosition(sourceIter->first, position, resetTime, appliedRate, stopPosition);
1194 :
1195 : // Reset Eos on seek
1196 1 : auto it = m_isMediaTypeEosMap.find(sourceIter->first);
1197 1 : if (it != m_isMediaTypeEosMap.end() && it->second)
1198 : {
1199 0 : it->second = false;
1200 : }
1201 :
1202 1 : return true;
1203 : }
1204 :
1205 3 : bool MediaPipelineServerInternal::setSubtitleOffset(int32_t sourceId, int64_t position)
1206 : {
1207 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1208 :
1209 : bool result;
1210 3 : auto task = [&]() { result = setSubtitleOffsetInternal(sourceId, position); };
1211 :
1212 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1213 3 : return result;
1214 : }
1215 :
1216 3 : bool MediaPipelineServerInternal::setSubtitleOffsetInternal(int32_t sourceId, int64_t position)
1217 : {
1218 3 : if (!m_gstPlayer)
1219 : {
1220 1 : RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Gstreamer player has not been loaded");
1221 1 : return false;
1222 : }
1223 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1224 1 : [sourceId](const auto &src) { return src.second == sourceId; });
1225 2 : if (sourceIter == m_attachedSources.end())
1226 : {
1227 1 : RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Source with id: %d not found", sourceId);
1228 1 : return false;
1229 : }
1230 :
1231 1 : m_gstPlayer->setSubtitleOffset(position);
1232 1 : return true;
1233 : }
1234 :
1235 2 : bool MediaPipelineServerInternal::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap,
1236 : bool audioAac)
1237 : {
1238 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1239 :
1240 : bool result;
1241 2 : auto task = [&]() { result = processAudioGapInternal(position, duration, discontinuityGap, audioAac); };
1242 :
1243 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1244 2 : return result;
1245 : }
1246 :
1247 2 : bool MediaPipelineServerInternal::processAudioGapInternal(int64_t position, uint32_t duration, int64_t discontinuityGap,
1248 : bool audioAac)
1249 : {
1250 2 : if (!m_gstPlayer)
1251 : {
1252 1 : RIALTO_SERVER_LOG_ERROR("Failed to process audio gap - Gstreamer player has not been loaded");
1253 1 : return false;
1254 : }
1255 1 : m_gstPlayer->processAudioGap(position, duration, discontinuityGap, audioAac);
1256 1 : return true;
1257 : }
1258 :
1259 2 : bool MediaPipelineServerInternal::setBufferingLimit(uint32_t limitBufferingMs)
1260 : {
1261 : bool result;
1262 2 : auto task = [&]() { result = setBufferingLimitInternal(limitBufferingMs); };
1263 :
1264 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1265 2 : return result;
1266 : }
1267 :
1268 2 : bool MediaPipelineServerInternal::setBufferingLimitInternal(uint32_t limitBufferingMs)
1269 : {
1270 2 : if (!m_gstPlayer)
1271 : {
1272 1 : RIALTO_SERVER_LOG_ERROR("Failed to set buffering limit - Gstreamer player has not been loaded");
1273 1 : return false;
1274 : }
1275 1 : m_gstPlayer->setBufferingLimit(limitBufferingMs);
1276 1 : return true;
1277 : }
1278 :
1279 3 : bool MediaPipelineServerInternal::getBufferingLimit(uint32_t &limitBufferingMs)
1280 : {
1281 : bool result;
1282 3 : auto task = [&]() { result = getBufferingLimitInternal(limitBufferingMs); };
1283 :
1284 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1285 3 : return result;
1286 : }
1287 :
1288 3 : bool MediaPipelineServerInternal::getBufferingLimitInternal(uint32_t &limitBufferingMs)
1289 : {
1290 3 : if (!m_gstPlayer)
1291 : {
1292 1 : RIALTO_SERVER_LOG_ERROR("Failed to get buffering limit - Gstreamer player has not been loaded");
1293 1 : return false;
1294 : }
1295 2 : return m_gstPlayer->getBufferingLimit(limitBufferingMs);
1296 : }
1297 :
1298 2 : bool MediaPipelineServerInternal::setUseBuffering(bool useBuffering)
1299 : {
1300 : bool result;
1301 2 : auto task = [&]() { result = setUseBufferingInternal(useBuffering); };
1302 :
1303 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1304 2 : return result;
1305 : }
1306 :
1307 2 : bool MediaPipelineServerInternal::setUseBufferingInternal(bool useBuffering)
1308 : {
1309 2 : if (!m_gstPlayer)
1310 : {
1311 1 : RIALTO_SERVER_LOG_ERROR("Failed to set use buffering - Gstreamer player has not been loaded");
1312 1 : return false;
1313 : }
1314 1 : m_gstPlayer->setUseBuffering(useBuffering);
1315 1 : return true;
1316 : }
1317 :
1318 3 : bool MediaPipelineServerInternal::getUseBuffering(bool &useBuffering)
1319 : {
1320 : bool result;
1321 3 : auto task = [&]() { result = getUseBufferingInternal(useBuffering); };
1322 :
1323 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1324 3 : return result;
1325 : }
1326 :
1327 3 : bool MediaPipelineServerInternal::getUseBufferingInternal(bool &useBuffering)
1328 : {
1329 3 : if (!m_gstPlayer)
1330 : {
1331 1 : RIALTO_SERVER_LOG_ERROR("Failed to get use buffering - Gstreamer player has not been loaded");
1332 1 : return false;
1333 : }
1334 2 : return m_gstPlayer->getUseBuffering(useBuffering);
1335 : }
1336 :
1337 2 : bool MediaPipelineServerInternal::switchSource(const std::unique_ptr<MediaSource> &source)
1338 : {
1339 : bool result;
1340 2 : auto task = [&]() { result = switchSourceInternal(source); };
1341 :
1342 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1343 2 : return result;
1344 : }
1345 :
1346 2 : bool MediaPipelineServerInternal::switchSourceInternal(const std::unique_ptr<MediaSource> &source)
1347 : {
1348 2 : if (!m_gstPlayer)
1349 : {
1350 1 : RIALTO_SERVER_LOG_ERROR("Failed to switch source - Gstreamer player has not been loaded");
1351 1 : return false;
1352 : }
1353 1 : m_gstPlayer->switchSource(source);
1354 1 : return true;
1355 : }
1356 :
1357 3 : AddSegmentStatus MediaPipelineServerInternal::addSegment(uint32_t needDataRequestId,
1358 : const std::unique_ptr<MediaSegment> &mediaSegment)
1359 : {
1360 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1361 :
1362 3 : AddSegmentStatus status{AddSegmentStatus::ERROR};
1363 3 : auto task = [&]() { status = addSegmentInternal(needDataRequestId, mediaSegment); };
1364 :
1365 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1366 3 : return status;
1367 : }
1368 :
1369 3 : AddSegmentStatus MediaPipelineServerInternal::addSegmentInternal(uint32_t needDataRequestId,
1370 : const std::unique_ptr<MediaSegment> &mediaSegment)
1371 : {
1372 3 : AddSegmentStatus status = m_activeRequests->addSegment(needDataRequestId, mediaSegment);
1373 3 : if (status != AddSegmentStatus::OK)
1374 : {
1375 2 : RIALTO_SERVER_LOG_ERROR("Failed to add segment for request id: %u", needDataRequestId);
1376 : }
1377 :
1378 3 : return status;
1379 : }
1380 :
1381 0 : std::weak_ptr<IMediaPipelineClient> MediaPipelineServerInternal::getClient()
1382 : {
1383 0 : return m_mediaPipelineClient;
1384 : }
1385 :
1386 8 : void MediaPipelineServerInternal::notifyPlaybackState(PlaybackState state)
1387 : {
1388 8 : RIALTO_SERVER_LOG_DEBUG("entry:");
1389 :
1390 8 : auto task = [&, state]()
1391 : {
1392 8 : m_currentPlaybackState = state;
1393 8 : if (m_mediaPipelineClient)
1394 : {
1395 8 : m_mediaPipelineClient->notifyPlaybackState(state);
1396 : }
1397 16 : };
1398 :
1399 8 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1400 : }
1401 :
1402 7 : bool MediaPipelineServerInternal::notifyNeedMediaData(MediaSourceType mediaSourceType)
1403 : {
1404 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
1405 :
1406 : // the task won't execute for a disconnected client therefore
1407 : // set a default value of true which will help to stop any further
1408 : // action being taken
1409 7 : bool result{true};
1410 :
1411 7 : auto task = [&]() { result = notifyNeedMediaDataInternal(mediaSourceType); };
1412 :
1413 7 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1414 :
1415 7 : return result;
1416 : }
1417 :
1418 8 : bool MediaPipelineServerInternal::notifyNeedMediaDataInternal(MediaSourceType mediaSourceType)
1419 : {
1420 8 : m_needMediaDataTimers.erase(mediaSourceType);
1421 8 : m_shmBuffer->clearData(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType);
1422 8 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1423 :
1424 8 : if (m_attachedSources.cend() == kSourceIter)
1425 : {
1426 1 : RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s - sourceId not found",
1427 : common::convertMediaSourceType(mediaSourceType));
1428 1 : return false;
1429 : }
1430 7 : auto it = m_isMediaTypeEosMap.find(mediaSourceType);
1431 7 : if (it != m_isMediaTypeEosMap.end() && it->second)
1432 : {
1433 2 : RIALTO_SERVER_LOG_INFO("EOS, NeedMediaData not needed for %s", common::convertMediaSourceType(mediaSourceType));
1434 2 : return false;
1435 : }
1436 5 : NeedMediaData event{m_mediaPipelineClient, *m_activeRequests, *m_shmBuffer, m_sessionId,
1437 10 : mediaSourceType, kSourceIter->second, m_currentPlaybackState};
1438 5 : if (!event.send())
1439 : {
1440 0 : RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s",
1441 : common::convertMediaSourceType(mediaSourceType));
1442 0 : return false;
1443 : }
1444 :
1445 5 : RIALTO_SERVER_LOG_DEBUG("%s NeedMediaData sent.", common::convertMediaSourceType(mediaSourceType));
1446 :
1447 5 : return true;
1448 : }
1449 :
1450 1 : void MediaPipelineServerInternal::notifyPosition(std::int64_t position)
1451 : {
1452 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1453 :
1454 1 : auto task = [&, position]()
1455 : {
1456 1 : if (m_mediaPipelineClient)
1457 : {
1458 1 : m_mediaPipelineClient->notifyPosition(position);
1459 : }
1460 2 : };
1461 :
1462 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1463 : }
1464 :
1465 104 : void MediaPipelineServerInternal::notifyNetworkState(NetworkState state)
1466 : {
1467 104 : RIALTO_SERVER_LOG_DEBUG("entry:");
1468 :
1469 104 : auto task = [&, state]()
1470 : {
1471 104 : if (m_mediaPipelineClient)
1472 : {
1473 104 : m_mediaPipelineClient->notifyNetworkState(state);
1474 : }
1475 208 : };
1476 :
1477 104 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1478 : }
1479 :
1480 1 : void MediaPipelineServerInternal::clearActiveRequestsCache()
1481 : {
1482 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1483 :
1484 1 : auto task = [&]() { m_activeRequests->clear(); };
1485 :
1486 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1487 : }
1488 :
1489 1 : void MediaPipelineServerInternal::invalidateActiveRequests(const MediaSourceType &type)
1490 : {
1491 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1492 :
1493 1 : auto task = [&, type]() { m_activeRequests->erase(type); };
1494 :
1495 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1496 : }
1497 :
1498 2 : void MediaPipelineServerInternal::notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo)
1499 : {
1500 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1501 :
1502 2 : auto task = [&, mediaSourceType, qosInfo]()
1503 : {
1504 2 : if (m_mediaPipelineClient)
1505 : {
1506 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1507 2 : if (m_attachedSources.cend() == kSourceIter)
1508 : {
1509 1 : RIALTO_SERVER_LOG_WARN("Qos notification failed - sourceId not found for %s",
1510 : common::convertMediaSourceType(mediaSourceType));
1511 1 : return;
1512 : }
1513 1 : m_mediaPipelineClient->notifyQos(kSourceIter->second, qosInfo);
1514 : }
1515 2 : };
1516 :
1517 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1518 : }
1519 :
1520 0 : void MediaPipelineServerInternal::notifyBufferUnderflow(MediaSourceType mediaSourceType)
1521 : {
1522 0 : RIALTO_SERVER_LOG_DEBUG("entry:");
1523 :
1524 0 : auto task = [&, mediaSourceType]()
1525 : {
1526 0 : if (m_mediaPipelineClient)
1527 : {
1528 0 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1529 0 : if (m_attachedSources.cend() == kSourceIter)
1530 : {
1531 0 : RIALTO_SERVER_LOG_WARN("Buffer underflow notification failed - sourceId not found for %s",
1532 : common::convertMediaSourceType(mediaSourceType));
1533 0 : return;
1534 : }
1535 0 : m_mediaPipelineClient->notifyBufferUnderflow(kSourceIter->second);
1536 : }
1537 0 : };
1538 :
1539 0 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1540 : }
1541 :
1542 2 : void MediaPipelineServerInternal::notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error)
1543 : {
1544 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1545 :
1546 2 : auto task = [&, mediaSourceType, error]()
1547 : {
1548 2 : if (m_mediaPipelineClient)
1549 : {
1550 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1551 2 : if (m_attachedSources.cend() == kSourceIter)
1552 : {
1553 1 : RIALTO_SERVER_LOG_WARN("Playback error notification failed - sourceId not found for %s",
1554 : common::convertMediaSourceType(mediaSourceType));
1555 1 : return;
1556 : }
1557 1 : m_mediaPipelineClient->notifyPlaybackError(kSourceIter->second, error);
1558 : }
1559 2 : };
1560 :
1561 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1562 : }
1563 :
1564 2 : void MediaPipelineServerInternal::notifySourceFlushed(MediaSourceType mediaSourceType)
1565 : {
1566 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1567 :
1568 2 : auto task = [&, mediaSourceType]()
1569 : {
1570 2 : if (m_mediaPipelineClient)
1571 : {
1572 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1573 2 : if (m_attachedSources.cend() == kSourceIter)
1574 : {
1575 1 : RIALTO_SERVER_LOG_WARN("Source flushed notification failed - sourceId not found for: %s",
1576 : common::convertMediaSourceType(mediaSourceType));
1577 1 : return;
1578 : }
1579 1 : m_mediaPipelineClient->notifySourceFlushed(kSourceIter->second);
1580 1 : RIALTO_SERVER_LOG_DEBUG("%s source flushed", common::convertMediaSourceType(mediaSourceType));
1581 : }
1582 2 : };
1583 :
1584 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1585 : }
1586 :
1587 0 : void MediaPipelineServerInternal::notifyPlaybackInfo(const PlaybackInfo &playbackInfo)
1588 : {
1589 0 : if (m_mediaPipelineClient)
1590 : {
1591 0 : m_mediaPipelineClient->notifyPlaybackInfo(playbackInfo);
1592 : }
1593 : }
1594 :
1595 7 : void MediaPipelineServerInternal::scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType)
1596 : {
1597 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
1598 7 : auto timer = m_needMediaDataTimers.find(mediaSourceType);
1599 7 : if (m_needMediaDataTimers.end() != timer && timer->second && timer->second->isActive())
1600 : {
1601 1 : RIALTO_SERVER_LOG_DEBUG("Skip scheduling need media data for %s - it is already scheduled",
1602 : common::convertMediaSourceType(mediaSourceType));
1603 1 : return;
1604 : }
1605 :
1606 6 : m_needMediaDataTimers[mediaSourceType] =
1607 6 : m_timerFactory
1608 18 : ->createTimer(getNeedMediaDataTimeout(mediaSourceType),
1609 12 : [this, mediaSourceType]()
1610 : {
1611 1 : m_mainThread
1612 2 : ->enqueueTask(m_mainThreadClientId,
1613 1 : [this, mediaSourceType]()
1614 : {
1615 1 : m_needMediaDataTimers.erase(mediaSourceType);
1616 1 : if (!notifyNeedMediaDataInternal(mediaSourceType))
1617 : {
1618 0 : RIALTO_SERVER_LOG_WARN("Scheduled Need media data sending "
1619 : "failed for: %s. Scheduling again...",
1620 : common::convertMediaSourceType(
1621 : mediaSourceType));
1622 0 : scheduleNotifyNeedMediaData(mediaSourceType);
1623 : }
1624 1 : });
1625 7 : });
1626 : }
1627 :
1628 6 : std::chrono::milliseconds MediaPipelineServerInternal::getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const
1629 : {
1630 6 : constexpr std::chrono::milliseconds kDefaultNeedMediaDataResendTimeMs{15};
1631 6 : constexpr std::chrono::milliseconds kNeedMediaDataResendTimeMsForLowLatency{5};
1632 6 : if ((mediaSourceType == MediaSourceType::VIDEO && m_IsLowLatencyVideoPlayer) ||
1633 1 : (mediaSourceType == MediaSourceType::AUDIO && m_IsLowLatencyAudioPlayer))
1634 : {
1635 2 : return kNeedMediaDataResendTimeMsForLowLatency;
1636 : }
1637 4 : return kDefaultNeedMediaDataResendTimeMs;
1638 : }
1639 : }; // namespace firebolt::rialto::server
|