Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2022 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include <algorithm>
21 : #include <stdexcept>
22 :
23 : #include "ActiveRequests.h"
24 : #include "DataReaderFactory.h"
25 : #include "IDataReader.h"
26 : #include "IRdkGstreamerUtilsWrapper.h"
27 : #include "ISharedMemoryBuffer.h"
28 : #include "MediaPipelineServerInternal.h"
29 : #include "NeedMediaData.h"
30 : #include "RialtoServerLogging.h"
31 : #include "TypeConverters.h"
32 :
33 : namespace
34 : {
35 1 : const char *toString(const firebolt::rialto::MediaSourceStatus &status)
36 : {
37 1 : switch (status)
38 : {
39 0 : case firebolt::rialto::MediaSourceStatus::OK:
40 0 : return "OK";
41 0 : case firebolt::rialto::MediaSourceStatus::EOS:
42 0 : return "EOS";
43 1 : case firebolt::rialto::MediaSourceStatus::ERROR:
44 1 : return "ERROR";
45 0 : case firebolt::rialto::MediaSourceStatus::CODEC_CHANGED:
46 0 : return "CODEC_CHANGED";
47 0 : case firebolt::rialto::MediaSourceStatus::NO_AVAILABLE_SAMPLES:
48 0 : return "NO_AVAILABLE_SAMPLES";
49 : }
50 0 : return "Unknown";
51 : }
52 :
53 32 : std::int32_t generateSourceId()
54 : {
55 : static std::int32_t sourceId{1};
56 32 : return sourceId++;
57 : }
58 : } // namespace
59 :
60 : namespace firebolt::rialto
61 : {
62 1 : std::shared_ptr<IMediaPipelineFactory> IMediaPipelineFactory::createFactory()
63 : {
64 1 : return server::MediaPipelineServerInternalFactory::createFactory();
65 : }
66 : }; // namespace firebolt::rialto
67 :
68 : namespace firebolt::rialto::server
69 : {
70 0 : std::shared_ptr<server::IMediaPipelineServerInternalFactory> IMediaPipelineServerInternalFactory::createFactory()
71 : {
72 0 : return MediaPipelineServerInternalFactory::createFactory();
73 : }
74 :
75 2 : std::shared_ptr<MediaPipelineServerInternalFactory> MediaPipelineServerInternalFactory::createFactory()
76 : {
77 2 : std::shared_ptr<MediaPipelineServerInternalFactory> factory;
78 :
79 : try
80 : {
81 2 : factory = std::make_shared<MediaPipelineServerInternalFactory>();
82 : }
83 0 : catch (const std::exception &e)
84 : {
85 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the media player server internal factory, reason: %s", e.what());
86 : }
87 :
88 2 : return factory;
89 : }
90 :
91 : std::unique_ptr<IMediaPipeline>
92 1 : MediaPipelineServerInternalFactory::createMediaPipeline(std::weak_ptr<IMediaPipelineClient> client,
93 : const VideoRequirements &videoRequirements) const
94 : {
95 1 : RIALTO_SERVER_LOG_ERROR(
96 : "This function can't be used by rialto server. Please use createMediaPipelineServerInternal");
97 1 : return nullptr;
98 : }
99 :
100 1 : std::unique_ptr<server::IMediaPipelineServerInternal> MediaPipelineServerInternalFactory::createMediaPipelineServerInternal(
101 : std::weak_ptr<IMediaPipelineClient> client, const VideoRequirements &videoRequirements, int sessionId,
102 : const std::shared_ptr<ISharedMemoryBuffer> &shmBuffer, IDecryptionService &decryptionService) const
103 : {
104 1 : std::shared_ptr<IMediaPipelineClient> sharedClient = client.lock();
105 1 : if (!sharedClient)
106 : {
107 0 : RIALTO_SERVER_LOG_ERROR("Couldn't create client's shared pointer");
108 0 : return nullptr;
109 : }
110 :
111 1 : std::unique_ptr<server::MediaPipelineServerInternal> mediaPipeline;
112 : try
113 : {
114 : mediaPipeline =
115 2 : std::make_unique<server::MediaPipelineServerInternal>(sharedClient, videoRequirements,
116 2 : server::IGstGenericPlayerFactory::getFactory(),
117 : sessionId, shmBuffer,
118 2 : server::IMainThreadFactory::createFactory(),
119 2 : common::ITimerFactory::getFactory(),
120 2 : std::make_unique<DataReaderFactory>(),
121 3 : std::make_unique<ActiveRequests>(), decryptionService);
122 : }
123 0 : catch (const std::exception &e)
124 : {
125 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the media player server internal, reason: %s", e.what());
126 : }
127 :
128 1 : return mediaPipeline;
129 : }
130 :
131 148 : MediaPipelineServerInternal::MediaPipelineServerInternal(
132 : const 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 : const std::shared_ptr<common::ITimerFactory> &timerFactory, std::unique_ptr<IDataReaderFactory> &&dataReaderFactory,
136 148 : std::unique_ptr<IActiveRequests> &&activeRequests, IDecryptionService &decryptionService)
137 148 : : m_mediaPipelineClient(client), m_kGstPlayerFactory(gstPlayerFactory), m_kVideoRequirements(videoRequirements),
138 148 : m_sessionId{sessionId}, m_shmBuffer{shmBuffer}, m_dataReaderFactory{std::move(dataReaderFactory)},
139 148 : m_timerFactory{timerFactory}, m_activeRequests{std::move(activeRequests)}, m_decryptionService{decryptionService},
140 444 : m_currentPlaybackState{PlaybackState::UNKNOWN}, m_wasAllSourcesAttachedCalled{false}
141 : {
142 148 : RIALTO_SERVER_LOG_DEBUG("entry:");
143 :
144 148 : m_mainThread = mainThreadFactory->getMainThread();
145 148 : if (!m_mainThread)
146 : {
147 0 : throw std::runtime_error("Failed to get the main thread");
148 : }
149 148 : m_mainThreadClientId = m_mainThread->registerClient();
150 :
151 148 : bool result = false;
152 148 : auto task = [&]()
153 : {
154 148 : if (!m_shmBuffer->mapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId))
155 : {
156 0 : RIALTO_SERVER_LOG_ERROR("Unable to map shm partition");
157 : }
158 : else
159 : {
160 148 : result = true;
161 : }
162 296 : };
163 :
164 148 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
165 148 : if (!result)
166 : {
167 0 : throw std::runtime_error("MediaPipelineServerInternal construction failed");
168 : }
169 148 : }
170 :
171 444 : MediaPipelineServerInternal::~MediaPipelineServerInternal()
172 : {
173 148 : RIALTO_SERVER_LOG_DEBUG("entry:");
174 :
175 148 : auto task = [&]()
176 : {
177 153 : for (const auto &timer : m_needMediaDataTimers)
178 : {
179 5 : if (timer.second && timer.second->isActive())
180 : {
181 5 : timer.second->cancel();
182 : }
183 : }
184 148 : if (!m_shmBuffer->unmapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId))
185 : {
186 0 : RIALTO_SERVER_LOG_ERROR("Unable to unmap shm partition");
187 : }
188 :
189 148 : m_shmBuffer.reset();
190 148 : m_mainThread->unregisterClient(m_mainThreadClientId);
191 296 : };
192 148 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
193 296 : }
194 :
195 104 : bool MediaPipelineServerInternal::load(MediaType type, const std::string &mimeType, const std::string &url)
196 : {
197 104 : RIALTO_SERVER_LOG_DEBUG("entry:");
198 :
199 : bool result;
200 104 : auto task = [&]() { result = loadInternal(type, mimeType, url); };
201 :
202 104 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
203 104 : return result;
204 : }
205 :
206 104 : bool MediaPipelineServerInternal::loadInternal(MediaType type, const std::string &mimeType, const std::string &url)
207 : {
208 104 : std::unique_lock lock{m_getPropertyMutex};
209 : /* If gstreamer player already created, destroy the old one first */
210 104 : if (m_gstPlayer)
211 : {
212 0 : m_gstPlayer.reset();
213 : }
214 :
215 : m_gstPlayer =
216 104 : m_kGstPlayerFactory
217 312 : ->createGstGenericPlayer(this, m_decryptionService, type, m_kVideoRequirements,
218 312 : firebolt::rialto::wrappers::IRdkGstreamerUtilsWrapperFactory::getFactory());
219 104 : if (!m_gstPlayer)
220 : {
221 1 : RIALTO_SERVER_LOG_ERROR("Failed to load gstreamer player");
222 1 : return false;
223 : }
224 :
225 103 : notifyNetworkState(NetworkState::BUFFERING);
226 :
227 103 : return true;
228 104 : }
229 :
230 34 : bool MediaPipelineServerInternal::attachSource(const std::unique_ptr<MediaSource> &source)
231 : {
232 34 : RIALTO_SERVER_LOG_DEBUG("entry:");
233 :
234 : bool result;
235 34 : auto task = [&]() { result = attachSourceInternal(source); };
236 :
237 34 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
238 34 : return result;
239 : }
240 :
241 34 : bool MediaPipelineServerInternal::attachSourceInternal(const std::unique_ptr<MediaSource> &source)
242 : {
243 34 : source->setId(-1);
244 :
245 34 : if (!m_gstPlayer)
246 : {
247 1 : RIALTO_SERVER_LOG_ERROR("Gstreamer player has not been loaded");
248 1 : return false;
249 : }
250 :
251 33 : if (source->getType() == MediaSourceType::UNKNOWN)
252 : {
253 0 : RIALTO_SERVER_LOG_ERROR("Media source type unknown");
254 0 : return false;
255 : }
256 :
257 33 : m_gstPlayer->attachSource(source);
258 :
259 33 : const auto kSourceIter = m_attachedSources.find(source->getType());
260 33 : if (m_attachedSources.cend() == kSourceIter)
261 : {
262 32 : source->setId(generateSourceId());
263 32 : RIALTO_SERVER_LOG_DEBUG("New ID generated for MediaSourceType: %s: %d",
264 : common::convertMediaSourceType(source->getType()), source->getId());
265 32 : m_attachedSources.emplace(source->getType(), source->getId());
266 : }
267 : else
268 : {
269 1 : RIALTO_SERVER_LOG_WARN("SourceType '%s' already attached", common::convertMediaSourceType(source->getType()));
270 1 : return false;
271 : }
272 :
273 32 : return true;
274 : }
275 :
276 4 : bool MediaPipelineServerInternal::removeSource(int32_t id)
277 : {
278 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
279 :
280 : bool result;
281 4 : auto task = [&]() { result = removeSourceInternal(id); };
282 :
283 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
284 4 : return result;
285 : }
286 :
287 4 : bool MediaPipelineServerInternal::removeSourceInternal(int32_t id)
288 : {
289 4 : if (!m_gstPlayer)
290 : {
291 1 : RIALTO_SERVER_LOG_ERROR("Failed to remove source - Gstreamer player has not been loaded");
292 1 : return false;
293 : }
294 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
295 2 : [id](const auto &src) { return src.second == id; });
296 3 : if (sourceIter == m_attachedSources.end())
297 : {
298 1 : RIALTO_SERVER_LOG_ERROR("Failed to remove source with id %d- Source not found", id);
299 1 : return false;
300 : }
301 :
302 2 : m_needMediaDataTimers.erase(sourceIter->first);
303 2 : m_attachedSources.erase(sourceIter);
304 2 : return true;
305 : }
306 :
307 4 : bool MediaPipelineServerInternal::allSourcesAttached()
308 : {
309 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
310 :
311 : bool result;
312 4 : auto task = [&]() { result = allSourcesAttachedInternal(); };
313 :
314 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
315 4 : return result;
316 : }
317 :
318 4 : bool MediaPipelineServerInternal::allSourcesAttachedInternal()
319 : {
320 4 : if (!m_gstPlayer)
321 : {
322 1 : RIALTO_SERVER_LOG_ERROR("Failed to notify all sources attached - Gstreamer player has not been loaded");
323 1 : return false;
324 : }
325 :
326 3 : if (m_wasAllSourcesAttachedCalled)
327 : {
328 1 : RIALTO_SERVER_LOG_WARN("Failed to notify all sources attached - It was already called");
329 1 : return false;
330 : }
331 :
332 2 : m_gstPlayer->allSourcesAttached();
333 2 : m_wasAllSourcesAttachedCalled = true;
334 2 : return true;
335 : }
336 :
337 2 : bool MediaPipelineServerInternal::play(bool &async)
338 : {
339 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
340 :
341 : bool result;
342 2 : auto task = [&]() { result = playInternal(async); };
343 :
344 2 : m_mainThread->enqueuePriorityTaskAndWait(m_mainThreadClientId, task);
345 2 : return result;
346 : }
347 :
348 2 : bool MediaPipelineServerInternal::playInternal(bool &async)
349 : {
350 2 : if (!m_gstPlayer)
351 : {
352 1 : RIALTO_SERVER_LOG_ERROR("Failed to play - Gstreamer player has not been loaded");
353 1 : return false;
354 : }
355 :
356 1 : m_gstPlayer->play(async);
357 1 : return true;
358 : }
359 :
360 2 : bool MediaPipelineServerInternal::pause()
361 : {
362 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
363 :
364 : bool result;
365 2 : auto task = [&]() { result = pauseInternal(); };
366 :
367 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
368 2 : return result;
369 : }
370 :
371 2 : bool MediaPipelineServerInternal::pauseInternal()
372 : {
373 2 : if (!m_gstPlayer)
374 : {
375 1 : RIALTO_SERVER_LOG_ERROR("Failed to pause - Gstreamer player has not been loaded");
376 1 : return false;
377 : }
378 :
379 1 : m_gstPlayer->pause();
380 1 : return true;
381 : }
382 :
383 2 : bool MediaPipelineServerInternal::stop()
384 : {
385 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
386 :
387 : bool result;
388 2 : auto task = [&]() { result = stopInternal(); };
389 :
390 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
391 2 : return result;
392 : }
393 :
394 2 : bool MediaPipelineServerInternal::stopInternal()
395 : {
396 2 : if (!m_gstPlayer)
397 : {
398 1 : RIALTO_SERVER_LOG_ERROR("Failed to stop - Gstreamer player has not been loaded");
399 1 : return false;
400 : }
401 :
402 1 : m_gstPlayer->stop();
403 1 : return true;
404 : }
405 :
406 3 : bool MediaPipelineServerInternal::setPlaybackRate(double rate)
407 : {
408 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
409 :
410 : bool result;
411 3 : auto task = [&]() { result = setPlaybackRateInternal(rate); };
412 :
413 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
414 3 : return result;
415 : }
416 :
417 3 : bool MediaPipelineServerInternal::setPlaybackRateInternal(double rate)
418 : {
419 3 : if (!m_gstPlayer)
420 : {
421 2 : RIALTO_SERVER_LOG_ERROR("Failed to set playback rate - Gstreamer player has not been loaded");
422 2 : return false;
423 : }
424 :
425 1 : if (0.0 == rate)
426 : {
427 0 : RIALTO_SERVER_LOG_ERROR("Failed to set playback rate to 0.0 - pause method should be used instead.");
428 0 : return false;
429 : }
430 :
431 1 : m_gstPlayer->setPlaybackRate(rate);
432 1 : return true;
433 : }
434 :
435 2 : bool MediaPipelineServerInternal::setPosition(int64_t position)
436 : {
437 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
438 :
439 : bool result;
440 2 : auto task = [&]() { result = setPositionInternal(position); };
441 :
442 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
443 2 : return result;
444 : }
445 :
446 2 : bool MediaPipelineServerInternal::setPositionInternal(int64_t position)
447 : {
448 2 : if (!m_gstPlayer)
449 : {
450 1 : RIALTO_SERVER_LOG_ERROR("Failed to set position - Gstreamer player has not been loaded");
451 1 : return false;
452 : }
453 :
454 1 : m_gstPlayer->setPosition(position);
455 :
456 : // Reset Eos on seek
457 1 : for (auto &isMediaTypeEos : m_isMediaTypeEosMap)
458 : {
459 0 : isMediaTypeEos.second = false;
460 : }
461 :
462 1 : return true;
463 : }
464 :
465 3 : bool MediaPipelineServerInternal::getPosition(int64_t &position)
466 : {
467 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
468 :
469 3 : std::shared_lock lock{m_getPropertyMutex};
470 :
471 3 : if (!m_gstPlayer)
472 : {
473 1 : RIALTO_SERVER_LOG_ERROR("Failed to get position - Gstreamer player has not been loaded");
474 1 : return false;
475 : }
476 2 : return m_gstPlayer->getPosition(position);
477 3 : }
478 :
479 4 : bool MediaPipelineServerInternal::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
480 : {
481 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
482 :
483 : bool result;
484 4 : auto task = [&]() { result = getStatsInternal(sourceId, renderedFrames, droppedFrames); };
485 :
486 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
487 4 : return result;
488 : }
489 :
490 4 : bool MediaPipelineServerInternal::getStatsInternal(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
491 : {
492 4 : if (!m_gstPlayer)
493 : {
494 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stats - Gstreamer player has not been loaded");
495 1 : return false;
496 : }
497 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
498 2 : [sourceId](const auto &src) { return src.second == sourceId; });
499 3 : if (sourceIter == m_attachedSources.end())
500 : {
501 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stats - Source not found");
502 1 : return false;
503 : }
504 2 : return m_gstPlayer->getStats(sourceIter->first, renderedFrames, droppedFrames);
505 : }
506 :
507 6 : bool MediaPipelineServerInternal::setImmediateOutput(int32_t sourceId, bool immediateOutput)
508 : {
509 6 : RIALTO_SERVER_LOG_DEBUG("entry:");
510 :
511 : bool result;
512 6 : auto task = [&]() { result = setImmediateOutputInternal(sourceId, immediateOutput); };
513 :
514 6 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
515 6 : return result;
516 : }
517 :
518 6 : bool MediaPipelineServerInternal::setImmediateOutputInternal(int32_t sourceId, bool immediateOutput)
519 : {
520 6 : if (!m_gstPlayer)
521 : {
522 1 : RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded");
523 1 : return false;
524 : }
525 5 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
526 4 : [sourceId](const auto &src) { return src.second == sourceId; });
527 5 : if (sourceIter == m_attachedSources.end())
528 : {
529 1 : RIALTO_SERVER_LOG_ERROR("Failed - Source not found");
530 1 : return false;
531 : }
532 :
533 4 : m_IsLowLatencyVideoPlayer = immediateOutput;
534 4 : return m_gstPlayer->setImmediateOutput(sourceIter->first, immediateOutput);
535 : }
536 :
537 5 : bool MediaPipelineServerInternal::getImmediateOutput(int32_t sourceId, bool &immediateOutput)
538 : {
539 5 : RIALTO_SERVER_LOG_DEBUG("entry:");
540 :
541 : bool result;
542 5 : auto task = [&]() { result = getImmediateOutputInternal(sourceId, immediateOutput); };
543 :
544 5 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
545 5 : return result;
546 : }
547 :
548 5 : bool MediaPipelineServerInternal::getImmediateOutputInternal(int32_t sourceId, bool &immediateOutput)
549 : {
550 5 : if (!m_gstPlayer)
551 : {
552 1 : RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded");
553 1 : return false;
554 : }
555 4 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
556 3 : [sourceId](const auto &src) { return src.second == sourceId; });
557 4 : if (sourceIter == m_attachedSources.end())
558 : {
559 1 : RIALTO_SERVER_LOG_ERROR("Failed - Source not found");
560 1 : return false;
561 : }
562 3 : return m_gstPlayer->getImmediateOutput(sourceIter->first, immediateOutput);
563 : }
564 :
565 2 : bool MediaPipelineServerInternal::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
566 : {
567 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
568 :
569 : bool result;
570 2 : auto task = [&]() { result = setVideoWindowInternal(x, y, width, height); };
571 :
572 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
573 2 : return result;
574 : }
575 :
576 2 : bool MediaPipelineServerInternal::setVideoWindowInternal(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
577 : {
578 2 : if (!m_gstPlayer)
579 : {
580 1 : RIALTO_SERVER_LOG_ERROR("Failed to set video window - Gstreamer player has not been loaded");
581 1 : return false;
582 : }
583 :
584 1 : m_gstPlayer->setVideoGeometry(x, y, width, height);
585 1 : return true;
586 : }
587 :
588 12 : bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t needDataRequestId)
589 : {
590 12 : RIALTO_SERVER_LOG_DEBUG("entry:");
591 :
592 : bool result;
593 12 : auto task = [&]() { result = haveDataInternal(status, needDataRequestId); };
594 :
595 12 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
596 12 : return result;
597 : }
598 :
599 12 : bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t needDataRequestId)
600 : {
601 12 : if (!m_gstPlayer)
602 : {
603 1 : RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded");
604 1 : return false;
605 : }
606 :
607 11 : MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId);
608 11 : if (MediaSourceType::UNKNOWN == mediaSourceType)
609 : {
610 1 : RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId);
611 1 : return true;
612 : }
613 :
614 10 : unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType];
615 10 : if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS)
616 : {
617 : // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS.
618 :
619 3 : ++counter;
620 3 : if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES)
621 : {
622 2 : RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u "
623 : "consecutively for mediaSourceType: %s",
624 : needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType));
625 : }
626 : else
627 : {
628 1 : RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status: %s",
629 : common::convertMediaSourceType(mediaSourceType), needDataRequestId, toString(status));
630 1 : counter = 0;
631 : }
632 :
633 3 : m_activeRequests->erase(needDataRequestId);
634 3 : scheduleNotifyNeedMediaData(mediaSourceType);
635 3 : return true;
636 : }
637 : else
638 : {
639 7 : RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status",
640 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
641 7 : counter = 0;
642 : }
643 :
644 : try
645 : {
646 7 : const IMediaPipeline::MediaSegmentVector &kSegments = m_activeRequests->getSegments(needDataRequestId);
647 6 : m_gstPlayer->attachSamples(kSegments);
648 : }
649 1 : catch (const std::runtime_error &e)
650 : {
651 1 : RIALTO_SERVER_LOG_ERROR("Failed to get segments %s", e.what());
652 1 : m_activeRequests->erase(needDataRequestId);
653 1 : return false;
654 : }
655 :
656 6 : m_activeRequests->erase(needDataRequestId);
657 6 : if (status == MediaSourceStatus::EOS)
658 : {
659 5 : m_gstPlayer->setEos(mediaSourceType);
660 5 : m_isMediaTypeEosMap[mediaSourceType] = true;
661 : }
662 :
663 6 : return true;
664 : }
665 :
666 13 : bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId)
667 : {
668 13 : RIALTO_SERVER_LOG_DEBUG("entry:");
669 :
670 : bool result;
671 13 : auto task = [&]() { result = haveDataInternal(status, numFrames, needDataRequestId); };
672 :
673 13 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
674 13 : return result;
675 : }
676 :
677 13 : bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t numFrames,
678 : uint32_t needDataRequestId)
679 : {
680 13 : if (!m_gstPlayer)
681 : {
682 1 : RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded");
683 1 : return false;
684 : }
685 12 : MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId);
686 12 : if (MediaSourceType::UNKNOWN == mediaSourceType)
687 : {
688 1 : RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId);
689 1 : return true;
690 : }
691 11 : m_activeRequests->erase(needDataRequestId);
692 :
693 11 : unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType];
694 11 : if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS)
695 : {
696 : // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS.
697 :
698 4 : ++counter;
699 4 : if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES)
700 : {
701 0 : RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u "
702 : "consecutively for mediaSourceType: %s",
703 : needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType));
704 : }
705 : else
706 : {
707 4 : RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status",
708 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
709 4 : counter = 0;
710 : }
711 4 : scheduleNotifyNeedMediaData(mediaSourceType);
712 4 : return true;
713 : }
714 : else
715 : {
716 7 : RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status",
717 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
718 7 : counter = 0;
719 : }
720 :
721 7 : uint8_t *buffer = m_shmBuffer->getBuffer();
722 7 : if (!buffer)
723 : {
724 1 : RIALTO_SERVER_LOG_ERROR("No buffer available");
725 1 : notifyPlaybackState(PlaybackState::FAILURE);
726 1 : return false;
727 : }
728 :
729 6 : std::uint32_t regionOffset = 0;
730 : try
731 : {
732 : regionOffset =
733 6 : m_shmBuffer->getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType);
734 : }
735 1 : catch (const std::runtime_error &e)
736 : {
737 1 : RIALTO_SERVER_LOG_ERROR("Failed to get region's buffer offset, reason: %s", e.what());
738 1 : notifyPlaybackState(PlaybackState::FAILURE);
739 1 : return false;
740 : }
741 :
742 5 : if (0 != numFrames)
743 : {
744 : std::shared_ptr<IDataReader> dataReader =
745 4 : m_dataReaderFactory->createDataReader(mediaSourceType, buffer, regionOffset, numFrames);
746 4 : if (!dataReader)
747 : {
748 1 : RIALTO_SERVER_LOG_ERROR("Metadata version not supported for %s request id: %u",
749 : common::convertMediaSourceType(mediaSourceType), needDataRequestId);
750 1 : notifyPlaybackState(PlaybackState::FAILURE);
751 1 : return false;
752 : }
753 3 : m_gstPlayer->attachSamples(dataReader);
754 4 : }
755 4 : if (status == MediaSourceStatus::EOS)
756 : {
757 2 : m_gstPlayer->setEos(mediaSourceType);
758 2 : m_isMediaTypeEosMap[mediaSourceType] = true;
759 : }
760 :
761 4 : return true;
762 : }
763 :
764 2 : void MediaPipelineServerInternal::ping(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
765 : {
766 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
767 :
768 2 : auto task = [&]() { pingInternal(std::move(heartbeatHandler)); };
769 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
770 : }
771 :
772 2 : void MediaPipelineServerInternal::pingInternal(std::unique_ptr<IHeartbeatHandler> &&heartbeatHandler)
773 : {
774 2 : if (!m_gstPlayer)
775 : {
776 : // No need to check GstPlayer worker thread, we reached this function, so main thread is working fine.
777 1 : heartbeatHandler.reset();
778 1 : return;
779 : }
780 : // Check GstPlayer worker thread
781 1 : m_gstPlayer->ping(std::move(heartbeatHandler));
782 : }
783 :
784 2 : bool MediaPipelineServerInternal::renderFrame()
785 : {
786 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
787 :
788 : bool result;
789 2 : auto task = [&]() { result = renderFrameInternal(); };
790 :
791 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
792 2 : return result;
793 : }
794 :
795 2 : bool MediaPipelineServerInternal::renderFrameInternal()
796 : {
797 2 : if (!m_gstPlayer)
798 : {
799 1 : RIALTO_SERVER_LOG_ERROR("renderFrame failed - Gstreamer player has not been loaded");
800 1 : return false;
801 : }
802 :
803 1 : m_gstPlayer->renderFrame();
804 1 : return true;
805 : }
806 :
807 3 : bool MediaPipelineServerInternal::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType)
808 : {
809 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
810 :
811 3 : m_isSetVolumeInProgress = true;
812 : bool result;
813 3 : auto task = [&]() { result = setVolumeInternal(targetVolume, volumeDuration, easeType); };
814 :
815 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
816 3 : return result;
817 : }
818 :
819 3 : bool MediaPipelineServerInternal::setVolumeInternal(double targetVolume, uint32_t volumeDuration, EaseType easeType)
820 : {
821 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
822 :
823 3 : 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 2 : m_gstPlayer->setVolume(targetVolume, volumeDuration, easeType);
829 2 : m_isSetVolumeInProgress = false;
830 2 : return true;
831 : }
832 :
833 4 : bool MediaPipelineServerInternal::getVolume(double ¤tVolume)
834 : {
835 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
836 :
837 4 : if (m_isSetVolumeInProgress)
838 : {
839 : bool result;
840 1 : auto task = [&]() { result = getVolumeInternal(currentVolume); };
841 :
842 1 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
843 1 : return result;
844 : }
845 3 : std::shared_lock lock{m_getPropertyMutex};
846 3 : return getVolumeInternal(currentVolume);
847 : }
848 :
849 4 : bool MediaPipelineServerInternal::getVolumeInternal(double ¤tVolume)
850 : {
851 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
852 :
853 4 : if (!m_gstPlayer)
854 : {
855 1 : RIALTO_SERVER_LOG_ERROR("Failed to get volume - Gstreamer player has not been loaded");
856 1 : return false;
857 : }
858 3 : return m_gstPlayer->getVolume(currentVolume);
859 : }
860 :
861 3 : bool MediaPipelineServerInternal::setMute(std::int32_t sourceId, bool mute)
862 : {
863 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
864 :
865 : bool result;
866 3 : auto task = [&]() { result = setMuteInternal(sourceId, mute); };
867 :
868 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
869 3 : return result;
870 : }
871 :
872 3 : bool MediaPipelineServerInternal::setMuteInternal(std::int32_t sourceId, bool mute)
873 : {
874 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
875 :
876 3 : if (!m_gstPlayer)
877 : {
878 1 : RIALTO_SERVER_LOG_ERROR("Failed to set mute - Gstreamer player has not been loaded");
879 1 : return false;
880 : }
881 :
882 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
883 1 : [sourceId](const auto &src) { return src.second == sourceId; });
884 2 : if (sourceIter == m_attachedSources.end())
885 : {
886 1 : RIALTO_SERVER_LOG_ERROR("Failed to set mute - Source with id: %d not found", sourceId);
887 1 : return false;
888 : }
889 :
890 1 : m_gstPlayer->setMute(sourceIter->first, mute);
891 :
892 1 : return true;
893 : }
894 :
895 4 : bool MediaPipelineServerInternal::getMute(std::int32_t sourceId, bool &mute)
896 : {
897 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
898 :
899 : bool result;
900 4 : auto task = [&]() { result = getMuteInternal(sourceId, mute); };
901 :
902 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
903 4 : return result;
904 : }
905 :
906 4 : bool MediaPipelineServerInternal::getMuteInternal(std::int32_t sourceId, bool &mute)
907 : {
908 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
909 :
910 4 : if (!m_gstPlayer)
911 : {
912 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded");
913 1 : return false;
914 : }
915 :
916 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
917 2 : [sourceId](const auto &src) { return src.second == sourceId; });
918 3 : if (sourceIter == m_attachedSources.end())
919 : {
920 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Source with id: %d not found", sourceId);
921 1 : return false;
922 : }
923 :
924 2 : return m_gstPlayer->getMute(sourceIter->first, mute);
925 : }
926 :
927 2 : bool MediaPipelineServerInternal::setTextTrackIdentifier(const std::string &textTrackIdentifier)
928 : {
929 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
930 :
931 : bool result;
932 2 : auto task = [&]() { result = setTextTrackIdentifierInternal(textTrackIdentifier); };
933 :
934 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
935 2 : return result;
936 : }
937 :
938 2 : bool MediaPipelineServerInternal::setTextTrackIdentifierInternal(const std::string &textTrackIdentifier)
939 : {
940 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
941 :
942 2 : if (!m_gstPlayer)
943 : {
944 1 : RIALTO_SERVER_LOG_ERROR("Failed to set text track identifier - Gstreamer player has not been loaded");
945 1 : return false;
946 : }
947 :
948 1 : m_gstPlayer->setTextTrackIdentifier(textTrackIdentifier);
949 :
950 1 : return true;
951 : }
952 :
953 3 : bool MediaPipelineServerInternal::getTextTrackIdentifier(std::string &textTrackIdentifier)
954 : {
955 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
956 :
957 : bool result;
958 3 : auto task = [&]() { result = getTextTrackIdentifierInternal(textTrackIdentifier); };
959 :
960 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
961 3 : return result;
962 : }
963 :
964 3 : bool MediaPipelineServerInternal::getTextTrackIdentifierInternal(std::string &textTrackIdentifier)
965 : {
966 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
967 :
968 3 : if (!m_gstPlayer)
969 : {
970 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded");
971 1 : return false;
972 : }
973 :
974 2 : return m_gstPlayer->getTextTrackIdentifier(textTrackIdentifier);
975 : }
976 :
977 4 : bool MediaPipelineServerInternal::flush(int32_t sourceId, bool resetTime, bool &async)
978 : {
979 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
980 :
981 : bool result;
982 4 : auto task = [&]() { result = flushInternal(sourceId, resetTime, async); };
983 :
984 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
985 4 : return result;
986 : }
987 :
988 4 : bool MediaPipelineServerInternal::setLowLatency(bool lowLatency)
989 : {
990 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
991 :
992 : bool result;
993 4 : auto task = [&]() { result = setLowLatencyInternal(lowLatency); };
994 :
995 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
996 4 : return result;
997 : }
998 :
999 4 : bool MediaPipelineServerInternal::setLowLatencyInternal(bool lowLatency)
1000 : {
1001 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1002 :
1003 4 : if (!m_gstPlayer)
1004 : {
1005 1 : RIALTO_SERVER_LOG_ERROR("Failed to set low latency - Gstreamer player has not been loaded");
1006 1 : return false;
1007 : }
1008 3 : m_IsLowLatencyAudioPlayer = lowLatency;
1009 :
1010 3 : return m_gstPlayer->setLowLatency(lowLatency);
1011 : }
1012 :
1013 3 : bool MediaPipelineServerInternal::setSync(bool sync)
1014 : {
1015 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1016 :
1017 : bool result;
1018 3 : auto task = [&]() { result = setSyncInternal(sync); };
1019 :
1020 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1021 3 : return result;
1022 : }
1023 :
1024 3 : bool MediaPipelineServerInternal::setSyncInternal(bool sync)
1025 : {
1026 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1027 :
1028 3 : if (!m_gstPlayer)
1029 : {
1030 1 : RIALTO_SERVER_LOG_ERROR("Failed to set sync - Gstreamer player has not been loaded");
1031 1 : return false;
1032 : }
1033 2 : return m_gstPlayer->setSync(sync);
1034 : }
1035 :
1036 3 : bool MediaPipelineServerInternal::getSync(bool &sync)
1037 : {
1038 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1039 :
1040 : bool result;
1041 3 : auto task = [&]() { result = getSyncInternal(sync); };
1042 :
1043 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1044 3 : return result;
1045 : }
1046 :
1047 3 : bool MediaPipelineServerInternal::getSyncInternal(bool &sync)
1048 : {
1049 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1050 :
1051 3 : if (!m_gstPlayer)
1052 : {
1053 1 : RIALTO_SERVER_LOG_ERROR("Failed to get sync - Gstreamer player has not been loaded");
1054 1 : return false;
1055 : }
1056 2 : return m_gstPlayer->getSync(sync);
1057 : }
1058 :
1059 3 : bool MediaPipelineServerInternal::setSyncOff(bool syncOff)
1060 : {
1061 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1062 :
1063 : bool result;
1064 3 : auto task = [&]() { result = setSyncOffInternal(syncOff); };
1065 :
1066 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1067 3 : return result;
1068 : }
1069 :
1070 3 : bool MediaPipelineServerInternal::setSyncOffInternal(bool syncOff)
1071 : {
1072 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1073 :
1074 3 : if (!m_gstPlayer)
1075 : {
1076 1 : RIALTO_SERVER_LOG_ERROR("Failed to set sync off - Gstreamer player has not been loaded");
1077 1 : return false;
1078 : }
1079 2 : return m_gstPlayer->setSyncOff(syncOff);
1080 : }
1081 :
1082 4 : bool MediaPipelineServerInternal::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode)
1083 : {
1084 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1085 :
1086 : bool result;
1087 4 : auto task = [&]() { result = setStreamSyncModeInternal(sourceId, streamSyncMode); };
1088 :
1089 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1090 4 : return result;
1091 : }
1092 :
1093 4 : bool MediaPipelineServerInternal::setStreamSyncModeInternal(int32_t sourceId, int32_t streamSyncMode)
1094 : {
1095 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1096 :
1097 4 : if (!m_gstPlayer)
1098 : {
1099 1 : RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Gstreamer player has not been loaded");
1100 1 : return false;
1101 : }
1102 :
1103 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1104 2 : [sourceId](const auto &src) { return src.second == sourceId; });
1105 3 : if (sourceIter == m_attachedSources.end())
1106 : {
1107 1 : RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Source with id: %d not found", sourceId);
1108 1 : return false;
1109 : }
1110 :
1111 2 : return m_gstPlayer->setStreamSyncMode(sourceIter->first, streamSyncMode);
1112 : }
1113 :
1114 3 : bool MediaPipelineServerInternal::getStreamSyncMode(int32_t &streamSyncMode)
1115 : {
1116 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1117 :
1118 : bool result;
1119 3 : auto task = [&]() { result = getStreamSyncModeInternal(streamSyncMode); };
1120 :
1121 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1122 3 : return result;
1123 : }
1124 :
1125 3 : bool MediaPipelineServerInternal::getStreamSyncModeInternal(int32_t &streamSyncMode)
1126 : {
1127 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1128 :
1129 3 : if (!m_gstPlayer)
1130 : {
1131 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stream sync mode - Gstreamer player has not been loaded");
1132 1 : return false;
1133 : }
1134 2 : return m_gstPlayer->getStreamSyncMode(streamSyncMode);
1135 : }
1136 :
1137 4 : bool MediaPipelineServerInternal::flushInternal(int32_t sourceId, bool resetTime, bool &async)
1138 : {
1139 4 : if (!m_gstPlayer)
1140 : {
1141 1 : RIALTO_SERVER_LOG_ERROR("Failed to flush - Gstreamer player has not been loaded");
1142 1 : return false;
1143 : }
1144 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1145 2 : [sourceId](const auto &src) { return src.second == sourceId; });
1146 3 : if (sourceIter == m_attachedSources.end())
1147 : {
1148 1 : RIALTO_SERVER_LOG_ERROR("Failed to flush - Source with id: %d not found", sourceId);
1149 1 : return false;
1150 : }
1151 :
1152 2 : m_gstPlayer->flush(sourceIter->first, resetTime, async);
1153 :
1154 2 : m_needMediaDataTimers.erase(sourceIter->first);
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 3 : bool MediaPipelineServerInternal::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime,
1167 : double appliedRate, uint64_t stopPosition)
1168 : {
1169 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1170 :
1171 : bool result;
1172 3 : auto task = [&]() { result = setSourcePositionInternal(sourceId, position, resetTime, appliedRate, stopPosition); };
1173 :
1174 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1175 3 : return result;
1176 : }
1177 :
1178 3 : bool MediaPipelineServerInternal::setSourcePositionInternal(int32_t sourceId, int64_t position, bool resetTime,
1179 : double appliedRate, uint64_t stopPosition)
1180 : {
1181 3 : 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 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1187 1 : [sourceId](const auto &src) { return src.second == sourceId; });
1188 2 : 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 1 : m_gstPlayer->setSourcePosition(sourceIter->first, position, resetTime, appliedRate, stopPosition);
1195 :
1196 : // Reset Eos on seek
1197 1 : auto it = m_isMediaTypeEosMap.find(sourceIter->first);
1198 1 : if (it != m_isMediaTypeEosMap.end() && it->second)
1199 : {
1200 0 : it->second = false;
1201 : }
1202 :
1203 1 : 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 7 : bool MediaPipelineServerInternal::notifyNeedMediaData(MediaSourceType mediaSourceType)
1404 : {
1405 7 : 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 7 : bool result{true};
1411 :
1412 7 : auto task = [&]() { result = notifyNeedMediaDataInternal(mediaSourceType); };
1413 :
1414 7 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1415 :
1416 7 : return result;
1417 : }
1418 :
1419 8 : bool MediaPipelineServerInternal::notifyNeedMediaDataInternal(MediaSourceType mediaSourceType)
1420 : {
1421 8 : m_needMediaDataTimers.erase(mediaSourceType);
1422 8 : m_shmBuffer->clearData(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType);
1423 8 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1424 :
1425 8 : 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 7 : auto it = m_isMediaTypeEosMap.find(mediaSourceType);
1432 7 : 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 5 : NeedMediaData event{m_mediaPipelineClient, *m_activeRequests, *m_shmBuffer, m_sessionId,
1438 10 : mediaSourceType, kSourceIter->second, m_currentPlaybackState};
1439 5 : 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 5 : RIALTO_SERVER_LOG_DEBUG("%s NeedMediaData sent.", common::convertMediaSourceType(mediaSourceType));
1447 :
1448 5 : 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 104 : void MediaPipelineServerInternal::notifyNetworkState(NetworkState state)
1467 : {
1468 104 : RIALTO_SERVER_LOG_DEBUG("entry:");
1469 :
1470 104 : auto task = [&, state]()
1471 : {
1472 104 : if (m_mediaPipelineClient)
1473 : {
1474 104 : m_mediaPipelineClient->notifyNetworkState(state);
1475 : }
1476 208 : };
1477 :
1478 104 : 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 0 : void MediaPipelineServerInternal::notifyPlaybackInfo(const PlaybackInfo &playbackInfo)
1589 : {
1590 0 : if (m_mediaPipelineClient)
1591 : {
1592 0 : m_mediaPipelineClient->notifyPlaybackInfo(playbackInfo);
1593 : }
1594 : }
1595 :
1596 7 : void MediaPipelineServerInternal::scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType)
1597 : {
1598 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
1599 7 : auto timer = m_needMediaDataTimers.find(mediaSourceType);
1600 7 : if (m_needMediaDataTimers.end() != timer && timer->second && timer->second->isActive())
1601 : {
1602 1 : RIALTO_SERVER_LOG_DEBUG("Skip scheduling need media data for %s - it is already scheduled",
1603 : common::convertMediaSourceType(mediaSourceType));
1604 1 : return;
1605 : }
1606 :
1607 6 : m_needMediaDataTimers[mediaSourceType] =
1608 6 : m_timerFactory
1609 18 : ->createTimer(getNeedMediaDataTimeout(mediaSourceType),
1610 12 : [this, mediaSourceType]()
1611 : {
1612 1 : m_mainThread
1613 2 : ->enqueueTask(m_mainThreadClientId,
1614 1 : [this, mediaSourceType]()
1615 : {
1616 1 : m_needMediaDataTimers.erase(mediaSourceType);
1617 1 : if (!notifyNeedMediaDataInternal(mediaSourceType))
1618 : {
1619 0 : RIALTO_SERVER_LOG_WARN("Scheduled Need media data sending "
1620 : "failed for: %s. Scheduling again...",
1621 : common::convertMediaSourceType(
1622 : mediaSourceType));
1623 0 : scheduleNotifyNeedMediaData(mediaSourceType);
1624 : }
1625 1 : });
1626 7 : });
1627 : }
1628 :
1629 6 : std::chrono::milliseconds MediaPipelineServerInternal::getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const
1630 : {
1631 6 : constexpr std::chrono::milliseconds kDefaultNeedMediaDataResendTimeMs{15};
1632 6 : constexpr std::chrono::milliseconds kNeedMediaDataResendTimeMsForLowLatency{5};
1633 6 : if ((mediaSourceType == MediaSourceType::VIDEO && m_IsLowLatencyVideoPlayer) ||
1634 1 : (mediaSourceType == MediaSourceType::AUDIO && m_IsLowLatencyAudioPlayer))
1635 : {
1636 2 : return kNeedMediaDataResendTimeMsForLowLatency;
1637 : }
1638 4 : return kDefaultNeedMediaDataResendTimeMs;
1639 : }
1640 : }; // namespace firebolt::rialto::server
|