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 35 : std::int32_t generateSourceId()
54 : {
55 : static std::int32_t sourceId{1};
56 35 : 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 149 : 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 149 : std::unique_ptr<IActiveRequests> &&activeRequests, IDecryptionService &decryptionService)
137 149 : : m_mediaPipelineClient(client), m_kGstPlayerFactory(gstPlayerFactory), m_kVideoRequirements(videoRequirements),
138 149 : m_sessionId{sessionId}, m_shmBuffer{shmBuffer}, m_dataReaderFactory{std::move(dataReaderFactory)},
139 149 : m_timerFactory{timerFactory}, m_activeRequests{std::move(activeRequests)}, m_decryptionService{decryptionService},
140 447 : m_currentPlaybackState{PlaybackState::UNKNOWN}, m_wasAllSourcesAttachedCalled{false}
141 : {
142 149 : RIALTO_SERVER_LOG_DEBUG("entry:");
143 :
144 149 : m_mainThread = mainThreadFactory->getMainThread();
145 149 : if (!m_mainThread)
146 : {
147 0 : throw std::runtime_error("Failed to get the main thread");
148 : }
149 149 : m_mainThreadClientId = m_mainThread->registerClient();
150 :
151 149 : bool result = false;
152 149 : auto task = [&]()
153 : {
154 149 : 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 149 : result = true;
161 : }
162 298 : };
163 :
164 149 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
165 149 : if (!result)
166 : {
167 0 : throw std::runtime_error("MediaPipelineServerInternal construction failed");
168 : }
169 149 : }
170 :
171 447 : MediaPipelineServerInternal::~MediaPipelineServerInternal()
172 : {
173 149 : RIALTO_SERVER_LOG_DEBUG("entry:");
174 :
175 149 : auto task = [&]()
176 : {
177 154 : for (const auto &timer : m_needMediaDataTimers)
178 : {
179 5 : if (timer.second && timer.second->isActive())
180 : {
181 5 : timer.second->cancel();
182 : }
183 : }
184 149 : if (!m_shmBuffer->unmapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId))
185 : {
186 0 : RIALTO_SERVER_LOG_ERROR("Unable to unmap shm partition");
187 : }
188 :
189 149 : m_shmBuffer.reset();
190 149 : m_mainThread->unregisterClient(m_mainThreadClientId);
191 298 : };
192 149 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
193 298 : }
194 :
195 105 : bool MediaPipelineServerInternal::load(MediaType type, const std::string &mimeType, const std::string &url)
196 : {
197 105 : RIALTO_SERVER_LOG_DEBUG("entry:");
198 :
199 : bool result;
200 105 : auto task = [&]() { result = loadInternal(type, mimeType, url); };
201 :
202 105 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
203 105 : return result;
204 : }
205 :
206 105 : 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 105 : if (m_gstPlayer)
210 : {
211 0 : m_gstPlayer.reset();
212 : }
213 :
214 : m_gstPlayer =
215 105 : m_kGstPlayerFactory
216 315 : ->createGstGenericPlayer(this, m_decryptionService, type, m_kVideoRequirements,
217 315 : firebolt::rialto::wrappers::IRdkGstreamerUtilsWrapperFactory::getFactory());
218 105 : if (!m_gstPlayer)
219 : {
220 1 : RIALTO_SERVER_LOG_ERROR("Failed to load gstreamer player");
221 1 : return false;
222 : }
223 :
224 104 : notifyNetworkState(NetworkState::BUFFERING);
225 :
226 104 : return true;
227 : }
228 :
229 37 : bool MediaPipelineServerInternal::attachSource(const std::unique_ptr<MediaSource> &source)
230 : {
231 37 : RIALTO_SERVER_LOG_DEBUG("entry:");
232 :
233 : bool result;
234 37 : auto task = [&]() { result = attachSourceInternal(source); };
235 :
236 37 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
237 37 : return result;
238 : }
239 :
240 37 : bool MediaPipelineServerInternal::attachSourceInternal(const std::unique_ptr<MediaSource> &source)
241 : {
242 37 : source->setId(-1);
243 :
244 37 : if (!m_gstPlayer)
245 : {
246 1 : RIALTO_SERVER_LOG_ERROR("Gstreamer player has not been loaded");
247 1 : return false;
248 : }
249 :
250 36 : if (source->getType() == MediaSourceType::UNKNOWN)
251 : {
252 0 : RIALTO_SERVER_LOG_ERROR("Media source type unknown");
253 0 : return false;
254 : }
255 :
256 36 : m_gstPlayer->attachSource(source);
257 :
258 36 : const auto kSourceIter = m_attachedSources.find(source->getType());
259 36 : if (m_attachedSources.cend() == kSourceIter)
260 : {
261 35 : source->setId(generateSourceId());
262 35 : RIALTO_SERVER_LOG_DEBUG("New ID generated for MediaSourceType: %s: %d",
263 : common::convertMediaSourceType(source->getType()), source->getId());
264 35 : 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 35 : 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, bool &async)
980 : {
981 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
982 :
983 : bool result;
984 4 : auto task = [&]() { result = flushInternal(sourceId, resetTime, async); };
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, bool &async)
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, async);
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 3 : bool MediaPipelineServerInternal::setSubtitleOffset(int32_t sourceId, int64_t position)
1207 : {
1208 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1209 :
1210 : bool result;
1211 3 : auto task = [&]() { result = setSubtitleOffsetInternal(sourceId, position); };
1212 :
1213 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1214 3 : return result;
1215 : }
1216 :
1217 3 : bool MediaPipelineServerInternal::setSubtitleOffsetInternal(int32_t sourceId, int64_t position)
1218 : {
1219 3 : if (!m_gstPlayer)
1220 : {
1221 1 : RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Gstreamer player has not been loaded");
1222 1 : return false;
1223 : }
1224 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1225 1 : [sourceId](const auto &src) { return src.second == sourceId; });
1226 2 : if (sourceIter == m_attachedSources.end())
1227 : {
1228 1 : RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Source with id: %d not found", sourceId);
1229 1 : return false;
1230 : }
1231 :
1232 1 : m_gstPlayer->setSubtitleOffset(position);
1233 1 : return true;
1234 : }
1235 :
1236 2 : bool MediaPipelineServerInternal::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap,
1237 : bool audioAac)
1238 : {
1239 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1240 :
1241 : bool result;
1242 2 : auto task = [&]() { result = processAudioGapInternal(position, duration, discontinuityGap, audioAac); };
1243 :
1244 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1245 2 : return result;
1246 : }
1247 :
1248 2 : bool MediaPipelineServerInternal::processAudioGapInternal(int64_t position, uint32_t duration, int64_t discontinuityGap,
1249 : bool audioAac)
1250 : {
1251 2 : if (!m_gstPlayer)
1252 : {
1253 1 : RIALTO_SERVER_LOG_ERROR("Failed to process audio gap - Gstreamer player has not been loaded");
1254 1 : return false;
1255 : }
1256 1 : m_gstPlayer->processAudioGap(position, duration, discontinuityGap, audioAac);
1257 1 : return true;
1258 : }
1259 :
1260 2 : bool MediaPipelineServerInternal::setBufferingLimit(uint32_t limitBufferingMs)
1261 : {
1262 : bool result;
1263 2 : auto task = [&]() { result = setBufferingLimitInternal(limitBufferingMs); };
1264 :
1265 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1266 2 : return result;
1267 : }
1268 :
1269 2 : bool MediaPipelineServerInternal::setBufferingLimitInternal(uint32_t limitBufferingMs)
1270 : {
1271 2 : if (!m_gstPlayer)
1272 : {
1273 1 : RIALTO_SERVER_LOG_ERROR("Failed to set buffering limit - Gstreamer player has not been loaded");
1274 1 : return false;
1275 : }
1276 1 : m_gstPlayer->setBufferingLimit(limitBufferingMs);
1277 1 : return true;
1278 : }
1279 :
1280 3 : bool MediaPipelineServerInternal::getBufferingLimit(uint32_t &limitBufferingMs)
1281 : {
1282 : bool result;
1283 3 : auto task = [&]() { result = getBufferingLimitInternal(limitBufferingMs); };
1284 :
1285 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1286 3 : return result;
1287 : }
1288 :
1289 3 : bool MediaPipelineServerInternal::getBufferingLimitInternal(uint32_t &limitBufferingMs)
1290 : {
1291 3 : if (!m_gstPlayer)
1292 : {
1293 1 : RIALTO_SERVER_LOG_ERROR("Failed to get buffering limit - Gstreamer player has not been loaded");
1294 1 : return false;
1295 : }
1296 2 : return m_gstPlayer->getBufferingLimit(limitBufferingMs);
1297 : }
1298 :
1299 2 : bool MediaPipelineServerInternal::setUseBuffering(bool useBuffering)
1300 : {
1301 : bool result;
1302 2 : auto task = [&]() { result = setUseBufferingInternal(useBuffering); };
1303 :
1304 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1305 2 : return result;
1306 : }
1307 :
1308 2 : bool MediaPipelineServerInternal::setUseBufferingInternal(bool useBuffering)
1309 : {
1310 2 : if (!m_gstPlayer)
1311 : {
1312 1 : RIALTO_SERVER_LOG_ERROR("Failed to set use buffering - Gstreamer player has not been loaded");
1313 1 : return false;
1314 : }
1315 1 : m_gstPlayer->setUseBuffering(useBuffering);
1316 1 : return true;
1317 : }
1318 :
1319 3 : bool MediaPipelineServerInternal::getUseBuffering(bool &useBuffering)
1320 : {
1321 : bool result;
1322 3 : auto task = [&]() { result = getUseBufferingInternal(useBuffering); };
1323 :
1324 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1325 3 : return result;
1326 : }
1327 :
1328 3 : bool MediaPipelineServerInternal::getUseBufferingInternal(bool &useBuffering)
1329 : {
1330 3 : if (!m_gstPlayer)
1331 : {
1332 1 : RIALTO_SERVER_LOG_ERROR("Failed to get use buffering - Gstreamer player has not been loaded");
1333 1 : return false;
1334 : }
1335 2 : return m_gstPlayer->getUseBuffering(useBuffering);
1336 : }
1337 :
1338 2 : bool MediaPipelineServerInternal::switchSource(const std::unique_ptr<MediaSource> &source)
1339 : {
1340 : bool result;
1341 2 : auto task = [&]() { result = switchSourceInternal(source); };
1342 :
1343 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1344 2 : return result;
1345 : }
1346 :
1347 2 : bool MediaPipelineServerInternal::switchSourceInternal(const std::unique_ptr<MediaSource> &source)
1348 : {
1349 2 : if (!m_gstPlayer)
1350 : {
1351 1 : RIALTO_SERVER_LOG_ERROR("Failed to switch source - Gstreamer player has not been loaded");
1352 1 : return false;
1353 : }
1354 1 : m_gstPlayer->switchSource(source);
1355 1 : return true;
1356 : }
1357 :
1358 3 : AddSegmentStatus MediaPipelineServerInternal::addSegment(uint32_t needDataRequestId,
1359 : const std::unique_ptr<MediaSegment> &mediaSegment)
1360 : {
1361 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1362 :
1363 3 : AddSegmentStatus status{AddSegmentStatus::ERROR};
1364 3 : auto task = [&]() { status = addSegmentInternal(needDataRequestId, mediaSegment); };
1365 :
1366 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1367 3 : return status;
1368 : }
1369 :
1370 3 : AddSegmentStatus MediaPipelineServerInternal::addSegmentInternal(uint32_t needDataRequestId,
1371 : const std::unique_ptr<MediaSegment> &mediaSegment)
1372 : {
1373 3 : AddSegmentStatus status = m_activeRequests->addSegment(needDataRequestId, mediaSegment);
1374 3 : if (status != AddSegmentStatus::OK)
1375 : {
1376 2 : RIALTO_SERVER_LOG_ERROR("Failed to add segment for request id: %u", needDataRequestId);
1377 : }
1378 :
1379 3 : return status;
1380 : }
1381 :
1382 0 : std::weak_ptr<IMediaPipelineClient> MediaPipelineServerInternal::getClient()
1383 : {
1384 0 : return m_mediaPipelineClient;
1385 : }
1386 :
1387 8 : void MediaPipelineServerInternal::notifyPlaybackState(PlaybackState state)
1388 : {
1389 8 : RIALTO_SERVER_LOG_DEBUG("entry:");
1390 :
1391 8 : auto task = [&, state]()
1392 : {
1393 8 : m_currentPlaybackState = state;
1394 8 : if (m_mediaPipelineClient)
1395 : {
1396 8 : m_mediaPipelineClient->notifyPlaybackState(state);
1397 : }
1398 16 : };
1399 :
1400 8 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1401 : }
1402 :
1403 10 : bool MediaPipelineServerInternal::notifyNeedMediaData(MediaSourceType mediaSourceType)
1404 : {
1405 10 : RIALTO_SERVER_LOG_DEBUG("entry:");
1406 :
1407 : // the task won't execute for a disconnected client therefore
1408 : // set a default value of true which will help to stop any further
1409 : // action being taken
1410 10 : bool result{true};
1411 :
1412 10 : auto task = [&]() { result = notifyNeedMediaDataInternal(mediaSourceType); };
1413 :
1414 10 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1415 :
1416 10 : return result;
1417 : }
1418 :
1419 11 : bool MediaPipelineServerInternal::notifyNeedMediaDataInternal(MediaSourceType mediaSourceType)
1420 : {
1421 11 : m_needMediaDataTimers.erase(mediaSourceType);
1422 11 : m_shmBuffer->clearData(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType);
1423 11 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1424 :
1425 11 : if (m_attachedSources.cend() == kSourceIter)
1426 : {
1427 1 : RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s - sourceId not found",
1428 : common::convertMediaSourceType(mediaSourceType));
1429 1 : return false;
1430 : }
1431 10 : auto it = m_isMediaTypeEosMap.find(mediaSourceType);
1432 10 : if (it != m_isMediaTypeEosMap.end() && it->second)
1433 : {
1434 2 : RIALTO_SERVER_LOG_INFO("EOS, NeedMediaData not needed for %s", common::convertMediaSourceType(mediaSourceType));
1435 2 : return false;
1436 : }
1437 8 : NeedMediaData event{m_mediaPipelineClient, *m_activeRequests, *m_shmBuffer, m_sessionId,
1438 16 : mediaSourceType, kSourceIter->second, m_currentPlaybackState};
1439 8 : if (!event.send())
1440 : {
1441 0 : RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s",
1442 : common::convertMediaSourceType(mediaSourceType));
1443 0 : return false;
1444 : }
1445 :
1446 8 : RIALTO_SERVER_LOG_DEBUG("%s NeedMediaData sent.", common::convertMediaSourceType(mediaSourceType));
1447 :
1448 8 : return true;
1449 : }
1450 :
1451 1 : void MediaPipelineServerInternal::notifyPosition(std::int64_t position)
1452 : {
1453 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1454 :
1455 1 : auto task = [&, position]()
1456 : {
1457 1 : if (m_mediaPipelineClient)
1458 : {
1459 1 : m_mediaPipelineClient->notifyPosition(position);
1460 : }
1461 2 : };
1462 :
1463 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1464 : }
1465 :
1466 105 : void MediaPipelineServerInternal::notifyNetworkState(NetworkState state)
1467 : {
1468 105 : RIALTO_SERVER_LOG_DEBUG("entry:");
1469 :
1470 105 : auto task = [&, state]()
1471 : {
1472 105 : if (m_mediaPipelineClient)
1473 : {
1474 105 : m_mediaPipelineClient->notifyNetworkState(state);
1475 : }
1476 210 : };
1477 :
1478 105 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1479 : }
1480 :
1481 1 : void MediaPipelineServerInternal::clearActiveRequestsCache()
1482 : {
1483 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1484 :
1485 1 : auto task = [&]() { m_activeRequests->clear(); };
1486 :
1487 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1488 : }
1489 :
1490 1 : void MediaPipelineServerInternal::invalidateActiveRequests(const MediaSourceType &type)
1491 : {
1492 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1493 :
1494 1 : auto task = [&, type]() { m_activeRequests->erase(type); };
1495 :
1496 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1497 : }
1498 :
1499 2 : void MediaPipelineServerInternal::notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo)
1500 : {
1501 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1502 :
1503 2 : auto task = [&, mediaSourceType, qosInfo]()
1504 : {
1505 2 : if (m_mediaPipelineClient)
1506 : {
1507 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1508 2 : if (m_attachedSources.cend() == kSourceIter)
1509 : {
1510 1 : RIALTO_SERVER_LOG_WARN("Qos notification failed - sourceId not found for %s",
1511 : common::convertMediaSourceType(mediaSourceType));
1512 1 : return;
1513 : }
1514 1 : m_mediaPipelineClient->notifyQos(kSourceIter->second, qosInfo);
1515 : }
1516 2 : };
1517 :
1518 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1519 : }
1520 :
1521 0 : void MediaPipelineServerInternal::notifyBufferUnderflow(MediaSourceType mediaSourceType)
1522 : {
1523 0 : RIALTO_SERVER_LOG_DEBUG("entry:");
1524 :
1525 0 : auto task = [&, mediaSourceType]()
1526 : {
1527 0 : if (m_mediaPipelineClient)
1528 : {
1529 0 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1530 0 : if (m_attachedSources.cend() == kSourceIter)
1531 : {
1532 0 : RIALTO_SERVER_LOG_WARN("Buffer underflow notification failed - sourceId not found for %s",
1533 : common::convertMediaSourceType(mediaSourceType));
1534 0 : return;
1535 : }
1536 0 : m_mediaPipelineClient->notifyBufferUnderflow(kSourceIter->second);
1537 : }
1538 0 : };
1539 :
1540 0 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1541 : }
1542 :
1543 2 : void MediaPipelineServerInternal::notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error)
1544 : {
1545 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1546 :
1547 2 : auto task = [&, mediaSourceType, error]()
1548 : {
1549 2 : if (m_mediaPipelineClient)
1550 : {
1551 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1552 2 : if (m_attachedSources.cend() == kSourceIter)
1553 : {
1554 1 : RIALTO_SERVER_LOG_WARN("Playback error notification failed - sourceId not found for %s",
1555 : common::convertMediaSourceType(mediaSourceType));
1556 1 : return;
1557 : }
1558 1 : m_mediaPipelineClient->notifyPlaybackError(kSourceIter->second, error);
1559 : }
1560 2 : };
1561 :
1562 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1563 : }
1564 :
1565 2 : void MediaPipelineServerInternal::notifySourceFlushed(MediaSourceType mediaSourceType)
1566 : {
1567 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1568 :
1569 2 : auto task = [&, mediaSourceType]()
1570 : {
1571 2 : if (m_mediaPipelineClient)
1572 : {
1573 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1574 2 : if (m_attachedSources.cend() == kSourceIter)
1575 : {
1576 1 : RIALTO_SERVER_LOG_WARN("Source flushed notification failed - sourceId not found for: %s",
1577 : common::convertMediaSourceType(mediaSourceType));
1578 1 : return;
1579 : }
1580 1 : m_mediaPipelineClient->notifySourceFlushed(kSourceIter->second);
1581 1 : RIALTO_SERVER_LOG_DEBUG("%s source flushed", common::convertMediaSourceType(mediaSourceType));
1582 : }
1583 2 : };
1584 :
1585 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1586 : }
1587 :
1588 7 : void MediaPipelineServerInternal::scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType)
1589 : {
1590 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
1591 7 : auto timer = m_needMediaDataTimers.find(mediaSourceType);
1592 7 : if (m_needMediaDataTimers.end() != timer && timer->second && timer->second->isActive())
1593 : {
1594 1 : RIALTO_SERVER_LOG_DEBUG("Skip scheduling need media data for %s - it is already scheduled",
1595 : common::convertMediaSourceType(mediaSourceType));
1596 1 : return;
1597 : }
1598 :
1599 6 : m_needMediaDataTimers[mediaSourceType] =
1600 6 : m_timerFactory
1601 18 : ->createTimer(getNeedMediaDataTimeout(mediaSourceType),
1602 12 : [this, mediaSourceType]()
1603 : {
1604 1 : m_mainThread
1605 2 : ->enqueueTask(m_mainThreadClientId,
1606 1 : [this, mediaSourceType]()
1607 : {
1608 1 : m_needMediaDataTimers.erase(mediaSourceType);
1609 1 : if (!notifyNeedMediaDataInternal(mediaSourceType))
1610 : {
1611 0 : RIALTO_SERVER_LOG_WARN("Scheduled Need media data sending "
1612 : "failed for: %s. Scheduling again...",
1613 : common::convertMediaSourceType(
1614 : mediaSourceType));
1615 0 : scheduleNotifyNeedMediaData(mediaSourceType);
1616 : }
1617 1 : });
1618 7 : });
1619 : }
1620 :
1621 6 : std::chrono::milliseconds MediaPipelineServerInternal::getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const
1622 : {
1623 6 : constexpr std::chrono::milliseconds kDefaultNeedMediaDataResendTimeMs{100};
1624 6 : constexpr std::chrono::milliseconds kNeedMediaDataResendTimeMsForLowLatency{5};
1625 6 : if ((mediaSourceType == MediaSourceType::VIDEO && m_IsLowLatencyVideoPlayer) ||
1626 1 : (mediaSourceType == MediaSourceType::AUDIO && m_IsLowLatencyAudioPlayer))
1627 : {
1628 2 : return kNeedMediaDataResendTimeMsForLowLatency;
1629 : }
1630 4 : return kDefaultNeedMediaDataResendTimeMs;
1631 : }
1632 : }; // namespace firebolt::rialto::server
|