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