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