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