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