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