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 151 : 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 151 : std::unique_ptr<IActiveRequests> &&activeRequests, IDecryptionService &decryptionService)
137 151 : : m_mediaPipelineClient(client), m_kGstPlayerFactory(gstPlayerFactory), m_kVideoRequirements(videoRequirements),
138 151 : m_sessionId{sessionId}, m_shmBuffer{shmBuffer}, m_dataReaderFactory{std::move(dataReaderFactory)},
139 151 : m_timerFactory{timerFactory}, m_activeRequests{std::move(activeRequests)}, m_decryptionService{decryptionService},
140 453 : m_currentPlaybackState{PlaybackState::UNKNOWN}, m_wasAllSourcesAttachedCalled{false}
141 : {
142 151 : RIALTO_SERVER_LOG_DEBUG("entry:");
143 :
144 151 : m_mainThread = mainThreadFactory->getMainThread();
145 151 : if (!m_mainThread)
146 : {
147 0 : throw std::runtime_error("Failed to get the main thread");
148 : }
149 151 : m_mainThreadClientId = m_mainThread->registerClient();
150 :
151 151 : bool result = false;
152 151 : auto task = [&]()
153 : {
154 151 : 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 151 : result = true;
161 : }
162 302 : };
163 :
164 151 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
165 151 : if (!result)
166 : {
167 0 : throw std::runtime_error("MediaPipelineServerInternal construction failed");
168 : }
169 151 : }
170 :
171 453 : MediaPipelineServerInternal::~MediaPipelineServerInternal()
172 : {
173 151 : RIALTO_SERVER_LOG_DEBUG("entry:");
174 :
175 151 : auto task = [&]()
176 : {
177 156 : for (const auto &timer : m_needMediaDataTimers)
178 : {
179 5 : if (timer.second && timer.second->isActive())
180 : {
181 5 : timer.second->cancel();
182 : }
183 : }
184 151 : if (!m_shmBuffer->unmapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId))
185 : {
186 0 : RIALTO_SERVER_LOG_ERROR("Unable to unmap shm partition");
187 : }
188 :
189 151 : m_shmBuffer.reset();
190 151 : m_mainThread->unregisterClient(m_mainThreadClientId);
191 302 : };
192 151 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
193 302 : }
194 :
195 106 : bool MediaPipelineServerInternal::load(MediaType type, const std::string &mimeType, const std::string &url, bool isLive)
196 : {
197 106 : RIALTO_SERVER_LOG_DEBUG("entry:");
198 :
199 : bool result;
200 106 : auto task = [&]() { result = loadInternal(type, mimeType, url, isLive); };
201 :
202 106 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
203 106 : return result;
204 : }
205 :
206 106 : bool MediaPipelineServerInternal::loadInternal(MediaType type, const std::string &mimeType, const std::string &url,
207 : bool isLive)
208 : {
209 106 : std::unique_lock lock{m_getPropertyMutex};
210 : /* If gstreamer player already created, destroy the old one first */
211 106 : if (m_gstPlayer)
212 : {
213 0 : m_gstPlayer.reset();
214 : }
215 :
216 : m_gstPlayer =
217 106 : m_kGstPlayerFactory
218 318 : ->createGstGenericPlayer(this, m_decryptionService, type, m_kVideoRequirements, isLive,
219 318 : firebolt::rialto::wrappers::IRdkGstreamerUtilsWrapperFactory::getFactory());
220 106 : if (!m_gstPlayer)
221 : {
222 1 : RIALTO_SERVER_LOG_ERROR("Failed to load gstreamer player");
223 1 : return false;
224 : }
225 :
226 105 : notifyNetworkState(NetworkState::BUFFERING);
227 :
228 105 : return true;
229 106 : }
230 :
231 34 : bool MediaPipelineServerInternal::attachSource(const std::unique_ptr<MediaSource> &source)
232 : {
233 34 : RIALTO_SERVER_LOG_DEBUG("entry:");
234 :
235 : bool result;
236 34 : auto task = [&]() { result = attachSourceInternal(source); };
237 :
238 34 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
239 34 : return result;
240 : }
241 :
242 34 : bool MediaPipelineServerInternal::attachSourceInternal(const std::unique_ptr<MediaSource> &source)
243 : {
244 34 : source->setId(-1);
245 :
246 34 : if (!m_gstPlayer)
247 : {
248 1 : RIALTO_SERVER_LOG_ERROR("Gstreamer player has not been loaded");
249 1 : return false;
250 : }
251 :
252 33 : if (source->getType() == MediaSourceType::UNKNOWN)
253 : {
254 0 : RIALTO_SERVER_LOG_ERROR("Media source type unknown");
255 0 : return false;
256 : }
257 :
258 33 : m_gstPlayer->attachSource(source);
259 :
260 33 : const auto kSourceIter = m_attachedSources.find(source->getType());
261 33 : if (m_attachedSources.cend() == kSourceIter)
262 : {
263 32 : source->setId(generateSourceId());
264 32 : RIALTO_SERVER_LOG_DEBUG("New ID generated for MediaSourceType: %s: %d",
265 : common::convertMediaSourceType(source->getType()), source->getId());
266 32 : 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 32 : 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 3 : bool MediaPipelineServerInternal::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType)
828 : {
829 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
830 :
831 3 : m_isSetVolumeInProgress = true;
832 : bool result;
833 3 : auto task = [&]() { result = setVolumeInternal(targetVolume, volumeDuration, easeType); };
834 :
835 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
836 3 : return result;
837 : }
838 :
839 3 : bool MediaPipelineServerInternal::setVolumeInternal(double targetVolume, uint32_t volumeDuration, EaseType easeType)
840 : {
841 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
842 :
843 3 : if (!m_gstPlayer)
844 : {
845 1 : RIALTO_SERVER_LOG_ERROR("Failed to set volume - Gstreamer player has not been loaded");
846 1 : return false;
847 : }
848 2 : m_gstPlayer->setVolume(targetVolume, volumeDuration, easeType);
849 2 : m_isSetVolumeInProgress = false;
850 2 : return true;
851 : }
852 :
853 4 : bool MediaPipelineServerInternal::getVolume(double ¤tVolume)
854 : {
855 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
856 :
857 4 : if (m_isSetVolumeInProgress)
858 : {
859 : bool result;
860 1 : auto task = [&]() { result = getVolumeInternal(currentVolume); };
861 :
862 1 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
863 1 : return result;
864 : }
865 3 : std::shared_lock lock{m_getPropertyMutex};
866 3 : return getVolumeInternal(currentVolume);
867 : }
868 :
869 4 : bool MediaPipelineServerInternal::getVolumeInternal(double ¤tVolume)
870 : {
871 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
872 :
873 4 : if (!m_gstPlayer)
874 : {
875 1 : RIALTO_SERVER_LOG_ERROR("Failed to get volume - Gstreamer player has not been loaded");
876 1 : return false;
877 : }
878 3 : return m_gstPlayer->getVolume(currentVolume);
879 : }
880 :
881 3 : bool MediaPipelineServerInternal::setMute(std::int32_t sourceId, bool mute)
882 : {
883 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
884 :
885 : bool result;
886 3 : auto task = [&]() { result = setMuteInternal(sourceId, mute); };
887 :
888 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
889 3 : return result;
890 : }
891 :
892 3 : bool MediaPipelineServerInternal::setMuteInternal(std::int32_t sourceId, bool mute)
893 : {
894 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
895 :
896 3 : if (!m_gstPlayer)
897 : {
898 1 : RIALTO_SERVER_LOG_ERROR("Failed to set mute - Gstreamer player has not been loaded");
899 1 : return false;
900 : }
901 :
902 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
903 1 : [sourceId](const auto &src) { return src.second == sourceId; });
904 2 : if (sourceIter == m_attachedSources.end())
905 : {
906 1 : RIALTO_SERVER_LOG_ERROR("Failed to set mute - Source with id: %d not found", sourceId);
907 1 : return false;
908 : }
909 :
910 1 : m_gstPlayer->setMute(sourceIter->first, mute);
911 :
912 1 : return true;
913 : }
914 :
915 4 : bool MediaPipelineServerInternal::getMute(std::int32_t sourceId, bool &mute)
916 : {
917 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
918 :
919 : bool result;
920 4 : auto task = [&]() { result = getMuteInternal(sourceId, mute); };
921 :
922 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
923 4 : return result;
924 : }
925 :
926 4 : bool MediaPipelineServerInternal::getMuteInternal(std::int32_t sourceId, bool &mute)
927 : {
928 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
929 :
930 4 : if (!m_gstPlayer)
931 : {
932 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded");
933 1 : return false;
934 : }
935 :
936 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
937 2 : [sourceId](const auto &src) { return src.second == sourceId; });
938 3 : if (sourceIter == m_attachedSources.end())
939 : {
940 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Source with id: %d not found", sourceId);
941 1 : return false;
942 : }
943 :
944 2 : return m_gstPlayer->getMute(sourceIter->first, mute);
945 : }
946 :
947 2 : bool MediaPipelineServerInternal::setTextTrackIdentifier(const std::string &textTrackIdentifier)
948 : {
949 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
950 :
951 : bool result;
952 2 : auto task = [&]() { result = setTextTrackIdentifierInternal(textTrackIdentifier); };
953 :
954 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
955 2 : return result;
956 : }
957 :
958 2 : bool MediaPipelineServerInternal::setTextTrackIdentifierInternal(const std::string &textTrackIdentifier)
959 : {
960 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
961 :
962 2 : if (!m_gstPlayer)
963 : {
964 1 : RIALTO_SERVER_LOG_ERROR("Failed to set text track identifier - Gstreamer player has not been loaded");
965 1 : return false;
966 : }
967 :
968 1 : m_gstPlayer->setTextTrackIdentifier(textTrackIdentifier);
969 :
970 1 : return true;
971 : }
972 :
973 3 : bool MediaPipelineServerInternal::getTextTrackIdentifier(std::string &textTrackIdentifier)
974 : {
975 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
976 :
977 : bool result;
978 3 : auto task = [&]() { result = getTextTrackIdentifierInternal(textTrackIdentifier); };
979 :
980 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
981 3 : return result;
982 : }
983 :
984 3 : bool MediaPipelineServerInternal::getTextTrackIdentifierInternal(std::string &textTrackIdentifier)
985 : {
986 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
987 :
988 3 : if (!m_gstPlayer)
989 : {
990 1 : RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded");
991 1 : return false;
992 : }
993 :
994 2 : return m_gstPlayer->getTextTrackIdentifier(textTrackIdentifier);
995 : }
996 :
997 4 : bool MediaPipelineServerInternal::flush(int32_t sourceId, bool resetTime, bool &async)
998 : {
999 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1000 :
1001 : bool result;
1002 4 : auto task = [&]() { result = flushInternal(sourceId, resetTime, async); };
1003 :
1004 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1005 4 : return result;
1006 : }
1007 :
1008 4 : bool MediaPipelineServerInternal::setLowLatency(bool lowLatency)
1009 : {
1010 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1011 :
1012 : bool result;
1013 4 : auto task = [&]() { result = setLowLatencyInternal(lowLatency); };
1014 :
1015 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1016 4 : return result;
1017 : }
1018 :
1019 4 : bool MediaPipelineServerInternal::setLowLatencyInternal(bool lowLatency)
1020 : {
1021 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1022 :
1023 4 : if (!m_gstPlayer)
1024 : {
1025 1 : RIALTO_SERVER_LOG_ERROR("Failed to set low latency - Gstreamer player has not been loaded");
1026 1 : return false;
1027 : }
1028 3 : m_IsLowLatencyAudioPlayer = lowLatency;
1029 :
1030 3 : return m_gstPlayer->setLowLatency(lowLatency);
1031 : }
1032 :
1033 3 : bool MediaPipelineServerInternal::setSync(bool sync)
1034 : {
1035 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1036 :
1037 : bool result;
1038 3 : auto task = [&]() { result = setSyncInternal(sync); };
1039 :
1040 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1041 3 : return result;
1042 : }
1043 :
1044 3 : bool MediaPipelineServerInternal::setSyncInternal(bool sync)
1045 : {
1046 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1047 :
1048 3 : if (!m_gstPlayer)
1049 : {
1050 1 : RIALTO_SERVER_LOG_ERROR("Failed to set sync - Gstreamer player has not been loaded");
1051 1 : return false;
1052 : }
1053 2 : return m_gstPlayer->setSync(sync);
1054 : }
1055 :
1056 3 : bool MediaPipelineServerInternal::getSync(bool &sync)
1057 : {
1058 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1059 :
1060 : bool result;
1061 3 : auto task = [&]() { result = getSyncInternal(sync); };
1062 :
1063 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1064 3 : return result;
1065 : }
1066 :
1067 3 : bool MediaPipelineServerInternal::getSyncInternal(bool &sync)
1068 : {
1069 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1070 :
1071 3 : if (!m_gstPlayer)
1072 : {
1073 1 : RIALTO_SERVER_LOG_ERROR("Failed to get sync - Gstreamer player has not been loaded");
1074 1 : return false;
1075 : }
1076 2 : return m_gstPlayer->getSync(sync);
1077 : }
1078 :
1079 3 : bool MediaPipelineServerInternal::setSyncOff(bool syncOff)
1080 : {
1081 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1082 :
1083 : bool result;
1084 3 : auto task = [&]() { result = setSyncOffInternal(syncOff); };
1085 :
1086 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1087 3 : return result;
1088 : }
1089 :
1090 3 : bool MediaPipelineServerInternal::setSyncOffInternal(bool syncOff)
1091 : {
1092 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1093 :
1094 3 : if (!m_gstPlayer)
1095 : {
1096 1 : RIALTO_SERVER_LOG_ERROR("Failed to set sync off - Gstreamer player has not been loaded");
1097 1 : return false;
1098 : }
1099 2 : return m_gstPlayer->setSyncOff(syncOff);
1100 : }
1101 :
1102 4 : bool MediaPipelineServerInternal::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode)
1103 : {
1104 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1105 :
1106 : bool result;
1107 4 : auto task = [&]() { result = setStreamSyncModeInternal(sourceId, streamSyncMode); };
1108 :
1109 4 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1110 4 : return result;
1111 : }
1112 :
1113 4 : bool MediaPipelineServerInternal::setStreamSyncModeInternal(int32_t sourceId, int32_t streamSyncMode)
1114 : {
1115 4 : RIALTO_SERVER_LOG_DEBUG("entry:");
1116 :
1117 4 : if (!m_gstPlayer)
1118 : {
1119 1 : RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Gstreamer player has not been loaded");
1120 1 : return false;
1121 : }
1122 :
1123 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1124 2 : [sourceId](const auto &src) { return src.second == sourceId; });
1125 3 : if (sourceIter == m_attachedSources.end())
1126 : {
1127 1 : RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Source with id: %d not found", sourceId);
1128 1 : return false;
1129 : }
1130 :
1131 2 : return m_gstPlayer->setStreamSyncMode(sourceIter->first, streamSyncMode);
1132 : }
1133 :
1134 3 : bool MediaPipelineServerInternal::getStreamSyncMode(int32_t &streamSyncMode)
1135 : {
1136 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1137 :
1138 : bool result;
1139 3 : auto task = [&]() { result = getStreamSyncModeInternal(streamSyncMode); };
1140 :
1141 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1142 3 : return result;
1143 : }
1144 :
1145 3 : bool MediaPipelineServerInternal::getStreamSyncModeInternal(int32_t &streamSyncMode)
1146 : {
1147 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1148 :
1149 3 : if (!m_gstPlayer)
1150 : {
1151 1 : RIALTO_SERVER_LOG_ERROR("Failed to get stream sync mode - Gstreamer player has not been loaded");
1152 1 : return false;
1153 : }
1154 2 : return m_gstPlayer->getStreamSyncMode(streamSyncMode);
1155 : }
1156 :
1157 4 : bool MediaPipelineServerInternal::flushInternal(int32_t sourceId, bool resetTime, bool &async)
1158 : {
1159 4 : if (!m_gstPlayer)
1160 : {
1161 1 : RIALTO_SERVER_LOG_ERROR("Failed to flush - Gstreamer player has not been loaded");
1162 1 : return false;
1163 : }
1164 3 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1165 2 : [sourceId](const auto &src) { return src.second == sourceId; });
1166 3 : if (sourceIter == m_attachedSources.end())
1167 : {
1168 1 : RIALTO_SERVER_LOG_ERROR("Failed to flush - Source with id: %d not found", sourceId);
1169 1 : return false;
1170 : }
1171 :
1172 2 : m_gstPlayer->flush(sourceIter->first, resetTime, async);
1173 :
1174 2 : m_needMediaDataTimers.erase(sourceIter->first);
1175 :
1176 : // Reset Eos on flush
1177 2 : auto it = m_isMediaTypeEosMap.find(sourceIter->first);
1178 2 : if (it != m_isMediaTypeEosMap.end() && it->second)
1179 : {
1180 1 : it->second = false;
1181 : }
1182 :
1183 2 : return true;
1184 : }
1185 :
1186 3 : bool MediaPipelineServerInternal::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime,
1187 : double appliedRate, uint64_t stopPosition)
1188 : {
1189 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1190 :
1191 : bool result;
1192 3 : auto task = [&]() { result = setSourcePositionInternal(sourceId, position, resetTime, appliedRate, stopPosition); };
1193 :
1194 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1195 3 : return result;
1196 : }
1197 :
1198 3 : bool MediaPipelineServerInternal::setSourcePositionInternal(int32_t sourceId, int64_t position, bool resetTime,
1199 : double appliedRate, uint64_t stopPosition)
1200 : {
1201 3 : if (!m_gstPlayer)
1202 : {
1203 1 : RIALTO_SERVER_LOG_ERROR("Failed to set source position - Gstreamer player has not been loaded");
1204 1 : return false;
1205 : }
1206 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1207 1 : [sourceId](const auto &src) { return src.second == sourceId; });
1208 2 : if (sourceIter == m_attachedSources.end())
1209 : {
1210 1 : RIALTO_SERVER_LOG_ERROR("Failed to set source position - Source with id: %d not found", sourceId);
1211 1 : return false;
1212 : }
1213 :
1214 1 : m_gstPlayer->setSourcePosition(sourceIter->first, position, resetTime, appliedRate, stopPosition);
1215 :
1216 : // Reset Eos on seek
1217 1 : auto it = m_isMediaTypeEosMap.find(sourceIter->first);
1218 1 : if (it != m_isMediaTypeEosMap.end() && it->second)
1219 : {
1220 0 : it->second = false;
1221 : }
1222 :
1223 1 : return true;
1224 : }
1225 :
1226 3 : bool MediaPipelineServerInternal::setSubtitleOffset(int32_t sourceId, int64_t position)
1227 : {
1228 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1229 :
1230 : bool result;
1231 3 : auto task = [&]() { result = setSubtitleOffsetInternal(sourceId, position); };
1232 :
1233 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1234 3 : return result;
1235 : }
1236 :
1237 3 : bool MediaPipelineServerInternal::setSubtitleOffsetInternal(int32_t sourceId, int64_t position)
1238 : {
1239 3 : if (!m_gstPlayer)
1240 : {
1241 1 : RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Gstreamer player has not been loaded");
1242 1 : return false;
1243 : }
1244 2 : auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(),
1245 1 : [sourceId](const auto &src) { return src.second == sourceId; });
1246 2 : if (sourceIter == m_attachedSources.end())
1247 : {
1248 1 : RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Source with id: %d not found", sourceId);
1249 1 : return false;
1250 : }
1251 :
1252 1 : m_gstPlayer->setSubtitleOffset(position);
1253 1 : return true;
1254 : }
1255 :
1256 2 : bool MediaPipelineServerInternal::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap,
1257 : bool audioAac)
1258 : {
1259 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1260 :
1261 : bool result;
1262 2 : auto task = [&]() { result = processAudioGapInternal(position, duration, discontinuityGap, audioAac); };
1263 :
1264 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1265 2 : return result;
1266 : }
1267 :
1268 2 : bool MediaPipelineServerInternal::processAudioGapInternal(int64_t position, uint32_t duration, int64_t discontinuityGap,
1269 : bool audioAac)
1270 : {
1271 2 : if (!m_gstPlayer)
1272 : {
1273 1 : RIALTO_SERVER_LOG_ERROR("Failed to process audio gap - Gstreamer player has not been loaded");
1274 1 : return false;
1275 : }
1276 1 : m_gstPlayer->processAudioGap(position, duration, discontinuityGap, audioAac);
1277 1 : return true;
1278 : }
1279 :
1280 2 : bool MediaPipelineServerInternal::setBufferingLimit(uint32_t limitBufferingMs)
1281 : {
1282 : bool result;
1283 2 : auto task = [&]() { result = setBufferingLimitInternal(limitBufferingMs); };
1284 :
1285 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1286 2 : return result;
1287 : }
1288 :
1289 2 : bool MediaPipelineServerInternal::setBufferingLimitInternal(uint32_t limitBufferingMs)
1290 : {
1291 2 : if (!m_gstPlayer)
1292 : {
1293 1 : RIALTO_SERVER_LOG_ERROR("Failed to set buffering limit - Gstreamer player has not been loaded");
1294 1 : return false;
1295 : }
1296 1 : m_gstPlayer->setBufferingLimit(limitBufferingMs);
1297 1 : return true;
1298 : }
1299 :
1300 3 : bool MediaPipelineServerInternal::getBufferingLimit(uint32_t &limitBufferingMs)
1301 : {
1302 : bool result;
1303 3 : auto task = [&]() { result = getBufferingLimitInternal(limitBufferingMs); };
1304 :
1305 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1306 3 : return result;
1307 : }
1308 :
1309 3 : bool MediaPipelineServerInternal::getBufferingLimitInternal(uint32_t &limitBufferingMs)
1310 : {
1311 3 : if (!m_gstPlayer)
1312 : {
1313 1 : RIALTO_SERVER_LOG_ERROR("Failed to get buffering limit - Gstreamer player has not been loaded");
1314 1 : return false;
1315 : }
1316 2 : return m_gstPlayer->getBufferingLimit(limitBufferingMs);
1317 : }
1318 :
1319 2 : bool MediaPipelineServerInternal::setUseBuffering(bool useBuffering)
1320 : {
1321 : bool result;
1322 2 : auto task = [&]() { result = setUseBufferingInternal(useBuffering); };
1323 :
1324 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1325 2 : return result;
1326 : }
1327 :
1328 2 : bool MediaPipelineServerInternal::setUseBufferingInternal(bool useBuffering)
1329 : {
1330 2 : if (!m_gstPlayer)
1331 : {
1332 1 : RIALTO_SERVER_LOG_ERROR("Failed to set use buffering - Gstreamer player has not been loaded");
1333 1 : return false;
1334 : }
1335 1 : m_gstPlayer->setUseBuffering(useBuffering);
1336 1 : return true;
1337 : }
1338 :
1339 3 : bool MediaPipelineServerInternal::getUseBuffering(bool &useBuffering)
1340 : {
1341 : bool result;
1342 3 : auto task = [&]() { result = getUseBufferingInternal(useBuffering); };
1343 :
1344 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1345 3 : return result;
1346 : }
1347 :
1348 3 : bool MediaPipelineServerInternal::getUseBufferingInternal(bool &useBuffering)
1349 : {
1350 3 : if (!m_gstPlayer)
1351 : {
1352 1 : RIALTO_SERVER_LOG_ERROR("Failed to get use buffering - Gstreamer player has not been loaded");
1353 1 : return false;
1354 : }
1355 2 : return m_gstPlayer->getUseBuffering(useBuffering);
1356 : }
1357 :
1358 2 : bool MediaPipelineServerInternal::switchSource(const std::unique_ptr<MediaSource> &source)
1359 : {
1360 : bool result;
1361 2 : auto task = [&]() { result = switchSourceInternal(source); };
1362 :
1363 2 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1364 2 : return result;
1365 : }
1366 :
1367 2 : bool MediaPipelineServerInternal::switchSourceInternal(const std::unique_ptr<MediaSource> &source)
1368 : {
1369 2 : if (!m_gstPlayer)
1370 : {
1371 1 : RIALTO_SERVER_LOG_ERROR("Failed to switch source - Gstreamer player has not been loaded");
1372 1 : return false;
1373 : }
1374 1 : m_gstPlayer->switchSource(source);
1375 1 : return true;
1376 : }
1377 :
1378 3 : AddSegmentStatus MediaPipelineServerInternal::addSegment(uint32_t needDataRequestId,
1379 : const std::unique_ptr<MediaSegment> &mediaSegment)
1380 : {
1381 3 : RIALTO_SERVER_LOG_DEBUG("entry:");
1382 :
1383 3 : AddSegmentStatus status{AddSegmentStatus::ERROR};
1384 3 : auto task = [&]() { status = addSegmentInternal(needDataRequestId, mediaSegment); };
1385 :
1386 3 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1387 3 : return status;
1388 : }
1389 :
1390 3 : AddSegmentStatus MediaPipelineServerInternal::addSegmentInternal(uint32_t needDataRequestId,
1391 : const std::unique_ptr<MediaSegment> &mediaSegment)
1392 : {
1393 3 : AddSegmentStatus status = m_activeRequests->addSegment(needDataRequestId, mediaSegment);
1394 3 : if (status != AddSegmentStatus::OK)
1395 : {
1396 2 : RIALTO_SERVER_LOG_ERROR("Failed to add segment for request id: %u", needDataRequestId);
1397 : }
1398 :
1399 3 : return status;
1400 : }
1401 :
1402 0 : std::weak_ptr<IMediaPipelineClient> MediaPipelineServerInternal::getClient()
1403 : {
1404 0 : return m_mediaPipelineClient;
1405 : }
1406 :
1407 8 : void MediaPipelineServerInternal::notifyPlaybackState(PlaybackState state)
1408 : {
1409 8 : RIALTO_SERVER_LOG_DEBUG("entry:");
1410 :
1411 8 : auto task = [&, state]()
1412 : {
1413 8 : m_currentPlaybackState = state;
1414 8 : if (m_mediaPipelineClient)
1415 : {
1416 8 : m_mediaPipelineClient->notifyPlaybackState(state);
1417 : }
1418 16 : };
1419 :
1420 8 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1421 : }
1422 :
1423 7 : bool MediaPipelineServerInternal::notifyNeedMediaData(MediaSourceType mediaSourceType)
1424 : {
1425 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
1426 :
1427 : // the task won't execute for a disconnected client therefore
1428 : // set a default value of true which will help to stop any further
1429 : // action being taken
1430 7 : bool result{true};
1431 :
1432 7 : auto task = [&]() { result = notifyNeedMediaDataInternal(mediaSourceType); };
1433 :
1434 7 : m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task);
1435 :
1436 7 : return result;
1437 : }
1438 :
1439 8 : bool MediaPipelineServerInternal::notifyNeedMediaDataInternal(MediaSourceType mediaSourceType)
1440 : {
1441 8 : m_needMediaDataTimers.erase(mediaSourceType);
1442 8 : m_shmBuffer->clearData(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType);
1443 8 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1444 :
1445 8 : if (m_attachedSources.cend() == kSourceIter)
1446 : {
1447 1 : RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s - sourceId not found",
1448 : common::convertMediaSourceType(mediaSourceType));
1449 1 : return false;
1450 : }
1451 7 : auto it = m_isMediaTypeEosMap.find(mediaSourceType);
1452 7 : if (it != m_isMediaTypeEosMap.end() && it->second)
1453 : {
1454 2 : RIALTO_SERVER_LOG_INFO("EOS, NeedMediaData not needed for %s", common::convertMediaSourceType(mediaSourceType));
1455 2 : return false;
1456 : }
1457 5 : NeedMediaData event{m_mediaPipelineClient, *m_activeRequests, *m_shmBuffer, m_sessionId,
1458 10 : mediaSourceType, kSourceIter->second, m_currentPlaybackState};
1459 5 : if (!event.send())
1460 : {
1461 0 : RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s",
1462 : common::convertMediaSourceType(mediaSourceType));
1463 0 : return false;
1464 : }
1465 :
1466 5 : RIALTO_SERVER_LOG_DEBUG("%s NeedMediaData sent.", common::convertMediaSourceType(mediaSourceType));
1467 :
1468 5 : return true;
1469 : }
1470 :
1471 1 : void MediaPipelineServerInternal::notifyPosition(std::int64_t position)
1472 : {
1473 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1474 :
1475 1 : auto task = [&, position]()
1476 : {
1477 1 : if (m_mediaPipelineClient)
1478 : {
1479 1 : m_mediaPipelineClient->notifyPosition(position);
1480 : }
1481 2 : };
1482 :
1483 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1484 : }
1485 :
1486 106 : void MediaPipelineServerInternal::notifyNetworkState(NetworkState state)
1487 : {
1488 106 : RIALTO_SERVER_LOG_DEBUG("entry:");
1489 :
1490 106 : auto task = [&, state]()
1491 : {
1492 106 : if (m_mediaPipelineClient)
1493 : {
1494 106 : m_mediaPipelineClient->notifyNetworkState(state);
1495 : }
1496 212 : };
1497 :
1498 106 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1499 : }
1500 :
1501 1 : void MediaPipelineServerInternal::clearActiveRequestsCache()
1502 : {
1503 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1504 :
1505 1 : auto task = [&]() { m_activeRequests->clear(); };
1506 :
1507 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1508 : }
1509 :
1510 1 : void MediaPipelineServerInternal::invalidateActiveRequests(const MediaSourceType &type)
1511 : {
1512 1 : RIALTO_SERVER_LOG_DEBUG("entry:");
1513 :
1514 1 : auto task = [&, type]() { m_activeRequests->erase(type); };
1515 :
1516 1 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1517 : }
1518 :
1519 2 : void MediaPipelineServerInternal::notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo)
1520 : {
1521 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1522 :
1523 2 : auto task = [&, mediaSourceType, qosInfo]()
1524 : {
1525 2 : if (m_mediaPipelineClient)
1526 : {
1527 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1528 2 : if (m_attachedSources.cend() == kSourceIter)
1529 : {
1530 1 : RIALTO_SERVER_LOG_WARN("Qos notification failed - sourceId not found for %s",
1531 : common::convertMediaSourceType(mediaSourceType));
1532 1 : return;
1533 : }
1534 1 : m_mediaPipelineClient->notifyQos(kSourceIter->second, qosInfo);
1535 : }
1536 2 : };
1537 :
1538 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1539 : }
1540 :
1541 0 : void MediaPipelineServerInternal::notifyBufferUnderflow(MediaSourceType mediaSourceType)
1542 : {
1543 0 : RIALTO_SERVER_LOG_DEBUG("entry:");
1544 :
1545 0 : auto task = [&, mediaSourceType]()
1546 : {
1547 0 : if (m_mediaPipelineClient)
1548 : {
1549 0 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1550 0 : if (m_attachedSources.cend() == kSourceIter)
1551 : {
1552 0 : RIALTO_SERVER_LOG_WARN("Buffer underflow notification failed - sourceId not found for %s",
1553 : common::convertMediaSourceType(mediaSourceType));
1554 0 : return;
1555 : }
1556 0 : m_mediaPipelineClient->notifyBufferUnderflow(kSourceIter->second);
1557 : }
1558 0 : };
1559 :
1560 0 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1561 : }
1562 :
1563 2 : void MediaPipelineServerInternal::notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error)
1564 : {
1565 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1566 :
1567 2 : auto task = [&, mediaSourceType, error]()
1568 : {
1569 2 : if (m_mediaPipelineClient)
1570 : {
1571 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1572 2 : if (m_attachedSources.cend() == kSourceIter)
1573 : {
1574 1 : RIALTO_SERVER_LOG_WARN("Playback error notification failed - sourceId not found for %s",
1575 : common::convertMediaSourceType(mediaSourceType));
1576 1 : return;
1577 : }
1578 1 : m_mediaPipelineClient->notifyPlaybackError(kSourceIter->second, error);
1579 : }
1580 2 : };
1581 :
1582 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1583 : }
1584 :
1585 2 : void MediaPipelineServerInternal::notifySourceFlushed(MediaSourceType mediaSourceType)
1586 : {
1587 2 : RIALTO_SERVER_LOG_DEBUG("entry:");
1588 :
1589 2 : auto task = [&, mediaSourceType]()
1590 : {
1591 2 : if (m_mediaPipelineClient)
1592 : {
1593 2 : const auto kSourceIter = m_attachedSources.find(mediaSourceType);
1594 2 : if (m_attachedSources.cend() == kSourceIter)
1595 : {
1596 1 : RIALTO_SERVER_LOG_WARN("Source flushed notification failed - sourceId not found for: %s",
1597 : common::convertMediaSourceType(mediaSourceType));
1598 1 : return;
1599 : }
1600 1 : m_mediaPipelineClient->notifySourceFlushed(kSourceIter->second);
1601 1 : RIALTO_SERVER_LOG_DEBUG("%s source flushed", common::convertMediaSourceType(mediaSourceType));
1602 : }
1603 2 : };
1604 :
1605 2 : m_mainThread->enqueueTask(m_mainThreadClientId, task);
1606 : }
1607 :
1608 0 : void MediaPipelineServerInternal::notifyPlaybackInfo(const PlaybackInfo &playbackInfo)
1609 : {
1610 0 : if (m_mediaPipelineClient)
1611 : {
1612 0 : m_mediaPipelineClient->notifyPlaybackInfo(playbackInfo);
1613 : }
1614 : }
1615 :
1616 7 : void MediaPipelineServerInternal::scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType)
1617 : {
1618 7 : RIALTO_SERVER_LOG_DEBUG("entry:");
1619 7 : auto timer = m_needMediaDataTimers.find(mediaSourceType);
1620 7 : if (m_needMediaDataTimers.end() != timer && timer->second && timer->second->isActive())
1621 : {
1622 1 : RIALTO_SERVER_LOG_DEBUG("Skip scheduling need media data for %s - it is already scheduled",
1623 : common::convertMediaSourceType(mediaSourceType));
1624 1 : return;
1625 : }
1626 :
1627 6 : m_needMediaDataTimers[mediaSourceType] =
1628 6 : m_timerFactory
1629 18 : ->createTimer(getNeedMediaDataTimeout(mediaSourceType),
1630 12 : [this, mediaSourceType]()
1631 : {
1632 1 : m_mainThread
1633 2 : ->enqueueTask(m_mainThreadClientId,
1634 1 : [this, mediaSourceType]()
1635 : {
1636 1 : m_needMediaDataTimers.erase(mediaSourceType);
1637 1 : if (!notifyNeedMediaDataInternal(mediaSourceType))
1638 : {
1639 0 : RIALTO_SERVER_LOG_WARN("Scheduled Need media data sending "
1640 : "failed for: %s. Scheduling again...",
1641 : common::convertMediaSourceType(
1642 : mediaSourceType));
1643 0 : scheduleNotifyNeedMediaData(mediaSourceType);
1644 : }
1645 1 : });
1646 7 : });
1647 : }
1648 :
1649 6 : std::chrono::milliseconds MediaPipelineServerInternal::getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const
1650 : {
1651 6 : constexpr std::chrono::milliseconds kDefaultNeedMediaDataResendTimeMs{15};
1652 6 : constexpr std::chrono::milliseconds kNeedMediaDataResendTimeMsForLowLatency{5};
1653 6 : if ((mediaSourceType == MediaSourceType::VIDEO && m_IsLowLatencyVideoPlayer) ||
1654 1 : (mediaSourceType == MediaSourceType::AUDIO && m_IsLowLatencyAudioPlayer))
1655 : {
1656 2 : return kNeedMediaDataResendTimeMsForLowLatency;
1657 : }
1658 4 : return kDefaultNeedMediaDataResendTimeMs;
1659 : }
1660 : }; // namespace firebolt::rialto::server
|