LCOV - code coverage report
Current view: top level - media/client/main/source - MediaPipeline.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.9 % 438 385
Test Date: 2026-03-04 13:20:25 Functions: 91.0 % 67 61

            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 <inttypes.h>
      21              : #include <stdexcept>
      22              : #include <stdint.h>
      23              : 
      24              : #include "KeyIdMap.h"
      25              : #include "MediaPipeline.h"
      26              : #include "MediaPipelineProxy.h"
      27              : #include "RialtoClientLogging.h"
      28              : 
      29              : namespace
      30              : {
      31          155 : const char *toString(const firebolt::rialto::client::MediaPipeline::State &state)
      32              : {
      33          155 :     switch (state)
      34              :     {
      35           49 :     case firebolt::rialto::client::MediaPipeline::State::IDLE:
      36           49 :         return "IDLE";
      37            8 :     case firebolt::rialto::client::MediaPipeline::State::BUFFERING:
      38            8 :         return "BUFFERING";
      39           72 :     case firebolt::rialto::client::MediaPipeline::State::PLAYING:
      40           72 :         return "PLAYING";
      41            8 :     case firebolt::rialto::client::MediaPipeline::State::SEEKING:
      42            8 :         return "SEEKING";
      43            8 :     case firebolt::rialto::client::MediaPipeline::State::FAILURE:
      44            8 :         return "FAILURE";
      45           10 :     case firebolt::rialto::client::MediaPipeline::State::END_OF_STREAM:
      46           10 :         return "END_OF_STREAM";
      47              :     }
      48            0 :     return "UNKNOWN";
      49              : }
      50              : 
      51           68 : const char *toString(const firebolt::rialto::PlaybackState &state)
      52              : {
      53           68 :     switch (state)
      54              :     {
      55            1 :     case firebolt::rialto::PlaybackState::IDLE:
      56            1 :         return "IDLE";
      57           50 :     case firebolt::rialto::PlaybackState::PLAYING:
      58           50 :         return "PLAYING";
      59            0 :     case firebolt::rialto::PlaybackState::PAUSED:
      60            0 :         return "PAUSED";
      61            4 :     case firebolt::rialto::PlaybackState::SEEKING:
      62            4 :         return "SEEKING";
      63            3 :     case firebolt::rialto::PlaybackState::SEEK_DONE:
      64            3 :         return "SEEK_DONE";
      65            3 :     case firebolt::rialto::PlaybackState::STOPPED:
      66            3 :         return "STOPPED";
      67            4 :     case firebolt::rialto::PlaybackState::END_OF_STREAM:
      68            4 :         return "END_OF_STREAM";
      69            3 :     case firebolt::rialto::PlaybackState::FAILURE:
      70            3 :         return "FAILURE";
      71            0 :     case firebolt::rialto::PlaybackState::UNKNOWN:
      72            0 :         return "UNKNOWN";
      73              :     }
      74            0 :     return "UNKNOWN";
      75              : }
      76              : 
      77            4 : const char *toString(const firebolt::rialto::NetworkState &state)
      78              : {
      79            4 :     switch (state)
      80              :     {
      81            1 :     case firebolt::rialto::NetworkState::IDLE:
      82            1 :         return "IDLE";
      83            3 :     case firebolt::rialto::NetworkState::BUFFERING:
      84            3 :         return "BUFFERING";
      85            0 :     case firebolt::rialto::NetworkState::BUFFERING_PROGRESS:
      86            0 :         return "BUFFERING_PROGRESS";
      87            0 :     case firebolt::rialto::NetworkState::BUFFERED:
      88            0 :         return "BUFFERED";
      89            0 :     case firebolt::rialto::NetworkState::STALLED:
      90            0 :         return "STALLED";
      91            0 :     case firebolt::rialto::NetworkState::FORMAT_ERROR:
      92            0 :         return "FORMAT_ERROR";
      93            0 :     case firebolt::rialto::NetworkState::NETWORK_ERROR:
      94            0 :         return "NETWORK_ERROR";
      95            0 :     case firebolt::rialto::NetworkState::DECODE_ERROR:
      96            0 :         return "DECODE_ERROR";
      97            0 :     case firebolt::rialto::NetworkState::UNKNOWN:
      98            0 :         return "UNKNOWN";
      99              :     }
     100            0 :     return "UNKNOWN";
     101              : }
     102              : } // namespace
     103              : 
     104              : namespace firebolt::rialto
     105              : {
     106            3 : std::shared_ptr<IMediaPipelineFactory> IMediaPipelineFactory::createFactory()
     107              : {
     108            3 :     std::shared_ptr<IMediaPipelineFactory> factory;
     109              : 
     110              :     try
     111              :     {
     112            3 :         factory = std::make_shared<MediaPipelineFactory>();
     113              :     }
     114            0 :     catch (const std::exception &e)
     115              :     {
     116            0 :         RIALTO_CLIENT_LOG_ERROR("Failed to create the media player factory, reason: %s", e.what());
     117              :     }
     118              : 
     119            3 :     return factory;
     120              : }
     121              : 
     122            0 : std::unique_ptr<IMediaPipeline> MediaPipelineFactory::createMediaPipeline(std::weak_ptr<IMediaPipelineClient> client,
     123              :                                                                           const VideoRequirements &videoRequirements) const
     124              : {
     125            0 :     return createMediaPipeline(client, videoRequirements, {}, {});
     126              : }
     127              : 
     128              : std::unique_ptr<IMediaPipeline>
     129            3 : MediaPipelineFactory::createMediaPipeline(std::weak_ptr<IMediaPipelineClient> client,
     130              :                                           const VideoRequirements &videoRequirements,
     131              :                                           std::weak_ptr<client::IMediaPipelineIpcFactory> mediaPipelineIpcFactory,
     132              :                                           std::weak_ptr<client::IClientController> clientController) const
     133              : {
     134            3 :     std::unique_ptr<IMediaPipeline> mediaPipeline;
     135              :     try
     136              :     {
     137            3 :         std::shared_ptr<client::IMediaPipelineIpcFactory> mediaPipelineIpcFactoryLocked = mediaPipelineIpcFactory.lock();
     138            3 :         std::shared_ptr<client::IClientController> clientControllerLocked = clientController.lock();
     139              :         firebolt::rialto::client::IClientController &cc =
     140            3 :             clientControllerLocked ? *clientControllerLocked
     141            0 :                                    : client::IClientControllerAccessor::instance().getClientController();
     142              : 
     143              :         auto mp{std::make_shared<client::MediaPipeline>(client, videoRequirements,
     144            3 :                                                         mediaPipelineIpcFactoryLocked
     145            7 :                                                             ? mediaPipelineIpcFactoryLocked
     146              :                                                             : client::IMediaPipelineIpcFactory::getFactory(),
     147           10 :                                                         common::IMediaFrameWriterFactory::getFactory(), cc)};
     148            2 :         mediaPipeline = std::move(std::make_unique<client::MediaPipelineProxy>(mp, cc));
     149            6 :     }
     150            2 :     catch (const std::exception &e)
     151              :     {
     152            2 :         RIALTO_CLIENT_LOG_ERROR("Failed to create the media player, reason: %s", e.what());
     153              :     }
     154              : 
     155            3 :     return mediaPipeline;
     156              : }
     157              : 
     158              : }; // namespace firebolt::rialto
     159              : 
     160              : namespace firebolt::rialto::client
     161              : {
     162            5 : MediaPipelineProxy::MediaPipelineProxy(const std::shared_ptr<IMediaPipelineAndIControlClient> &mediaPipeline,
     163            5 :                                        IClientController &clientController)
     164            5 :     : m_mediaPipeline{mediaPipeline}, m_clientController{clientController}
     165              : {
     166            5 :     ApplicationState state{ApplicationState::UNKNOWN};
     167            5 :     if (!m_clientController.registerClient(m_mediaPipeline, state))
     168              :     {
     169            2 :         throw std::runtime_error("Failed to register client with clientController");
     170              :     }
     171            3 :     m_mediaPipeline->notifyApplicationState(state);
     172            7 : }
     173              : 
     174            5 : MediaPipelineProxy::~MediaPipelineProxy()
     175              : {
     176            3 :     if (!m_clientController.unregisterClient(m_mediaPipeline))
     177              :     {
     178            0 :         RIALTO_CLIENT_LOG_WARN("Failed to unregister client with clientController");
     179              :     }
     180            5 : }
     181              : 
     182          121 : MediaPipeline::MediaPipeline(std::weak_ptr<IMediaPipelineClient> client, const VideoRequirements &videoRequirements,
     183              :                              const std::shared_ptr<IMediaPipelineIpcFactory> &mediaPipelineIpcFactory,
     184              :                              const std::shared_ptr<common::IMediaFrameWriterFactory> &mediaFrameWriterFactory,
     185          121 :                              IClientController &clientController)
     186          363 :     : m_mediaPipelineClient(client), m_clientController{clientController}, m_currentAppState{ApplicationState::UNKNOWN},
     187          121 :       m_mediaFrameWriterFactory(mediaFrameWriterFactory), m_currentState(State::IDLE)
     188              : {
     189          121 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     190              : 
     191          121 :     m_mediaPipelineIpc = mediaPipelineIpcFactory->createMediaPipelineIpc(this, videoRequirements);
     192              : 
     193          121 :     if (!m_mediaPipelineIpc)
     194              :     {
     195            2 :         throw std::runtime_error("Media player ipc could not be created");
     196              :     }
     197          135 : }
     198              : 
     199          236 : MediaPipeline::~MediaPipeline()
     200              : {
     201          119 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     202              : 
     203          119 :     m_mediaPipelineIpc.reset();
     204          236 : }
     205              : 
     206            2 : bool MediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url)
     207              : {
     208            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     209              : 
     210            2 :     return m_mediaPipelineIpc->load(type, mimeType, url);
     211              : }
     212              : 
     213           39 : bool MediaPipeline::attachSource(const std::unique_ptr<IMediaPipeline::MediaSource> &source)
     214              : {
     215           39 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     216              : 
     217              :     // We should not process needDatas while attach source is ongoing
     218              :     {
     219           39 :         std::unique_lock<std::mutex> lock{m_attachSourceMutex};
     220           39 :         m_attachingSource = true;
     221              :     }
     222              : 
     223           39 :     int32_t sourceId = -1;
     224              : 
     225           39 :     bool status = m_mediaPipelineIpc->attachSource(source, sourceId);
     226           39 :     if (status)
     227              :     {
     228           38 :         source->setId(sourceId);
     229           38 :         m_attachedSources.add(sourceId, source->getType());
     230              :     }
     231              : 
     232              :     // Unblock needDatas
     233              :     {
     234           39 :         std::unique_lock<std::mutex> lock{m_attachSourceMutex};
     235           39 :         m_attachingSource = false;
     236           39 :         m_attachSourceCond.notify_all();
     237              :     }
     238           39 :     return status;
     239              : }
     240              : 
     241            5 : bool MediaPipeline::removeSource(int32_t id)
     242              : {
     243            5 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     244            5 :     m_attachedSources.remove(id);
     245            5 :     return m_mediaPipelineIpc->removeSource(id);
     246              : }
     247              : 
     248            2 : bool MediaPipeline::allSourcesAttached()
     249              : {
     250            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     251              : 
     252            2 :     return m_mediaPipelineIpc->allSourcesAttached();
     253              : }
     254              : 
     255            2 : bool MediaPipeline::play(bool &async)
     256              : {
     257            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     258              : 
     259            2 :     return m_mediaPipelineIpc->play(async);
     260              : }
     261              : 
     262            2 : bool MediaPipeline::pause()
     263              : {
     264            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     265              : 
     266            2 :     return m_mediaPipelineIpc->pause();
     267              : }
     268              : 
     269            0 : bool MediaPipeline::stop()
     270              : {
     271            0 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     272              : 
     273            0 :     m_currentState = State::IDLE;
     274              : 
     275            0 :     return m_mediaPipelineIpc->stop();
     276              : }
     277              : 
     278            2 : bool MediaPipeline::setPlaybackRate(double rate)
     279              : {
     280            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     281              : 
     282            2 :     return m_mediaPipelineIpc->setPlaybackRate(rate);
     283              : }
     284              : 
     285            7 : bool MediaPipeline::setPosition(int64_t position)
     286              : {
     287            7 :     switch (m_currentState)
     288              :     {
     289            5 :     case State::PLAYING:
     290              :     case State::BUFFERING:
     291              :     case State::SEEKING:
     292              :     case State::END_OF_STREAM:
     293              :     {
     294            5 :         return handleSetPosition(position);
     295              :     }
     296            2 :     case State::IDLE:
     297              :     case State::FAILURE:
     298              :     default:
     299              :     {
     300            2 :         RIALTO_CLIENT_LOG_WARN("SetPosition received in unexpected state '%s'", toString(m_currentState));
     301            2 :         return false;
     302              :     }
     303              :     }
     304              : }
     305              : 
     306            2 : bool MediaPipeline::getPosition(int64_t &position)
     307              : {
     308            2 :     return m_mediaPipelineIpc->getPosition(position);
     309              : }
     310              : 
     311            2 : bool MediaPipeline::setImmediateOutput(int32_t sourceId, bool immediateOutput)
     312              : {
     313            2 :     return m_mediaPipelineIpc->setImmediateOutput(sourceId, immediateOutput);
     314              : }
     315              : 
     316            2 : bool MediaPipeline::setReportDecodeErrors(int32_t sourceId, bool reportDecodeErrors)
     317              : {
     318            2 :     return m_mediaPipelineIpc->setReportDecodeErrors(sourceId, reportDecodeErrors);
     319              : }
     320              : 
     321            2 : bool MediaPipeline::getQueuedFrames(int32_t sourceId, uint32_t &queuedFrames)
     322              : {
     323            2 :     return m_mediaPipelineIpc->getQueuedFrames(sourceId, queuedFrames);
     324              : }
     325              : 
     326            2 : bool MediaPipeline::getImmediateOutput(int32_t sourceId, bool &immediateOutput)
     327              : {
     328            2 :     return m_mediaPipelineIpc->getImmediateOutput(sourceId, immediateOutput);
     329              : }
     330              : 
     331            2 : bool MediaPipeline::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
     332              : {
     333            2 :     return m_mediaPipelineIpc->getStats(sourceId, renderedFrames, droppedFrames);
     334              : }
     335              : 
     336            5 : bool MediaPipeline::handleSetPosition(int64_t position)
     337              : {
     338              :     // needData requests no longer valid
     339              :     {
     340            5 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     341            5 :         m_needDataRequestMap.clear();
     342              :     }
     343            5 :     return m_mediaPipelineIpc->setPosition(position);
     344              : }
     345              : 
     346            2 : bool MediaPipeline::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
     347              : {
     348            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     349              : 
     350            2 :     return m_mediaPipelineIpc->setVideoWindow(x, y, width, height);
     351              : }
     352              : 
     353           27 : bool MediaPipeline::haveData(MediaSourceStatus status, uint32_t needDataRequestId)
     354              : {
     355           27 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     356              : 
     357           27 :     switch (m_currentState)
     358              :     {
     359           22 :     case State::BUFFERING:
     360              :     case State::PLAYING:
     361              :     {
     362           22 :         return handleHaveData(status, needDataRequestId);
     363              :     }
     364            2 :     case State::SEEKING:
     365              :     {
     366            2 :         RIALTO_CLIENT_LOG_INFO("HaveData received while seeking, discarding NeedData request %u", needDataRequestId);
     367            2 :         discardNeedDataRequest(needDataRequestId);
     368            2 :         return true;
     369              :     }
     370            3 :     case State::IDLE:
     371              :     case State::END_OF_STREAM:
     372              :     case State::FAILURE:
     373              :     default:
     374              :     {
     375            3 :         RIALTO_CLIENT_LOG_WARN("HaveData received in unexpected state '%s', discarding NeedData request %u",
     376              :                                toString(m_currentState), needDataRequestId);
     377            3 :         discardNeedDataRequest(needDataRequestId);
     378            3 :         return false;
     379              :     }
     380              :     }
     381              : }
     382              : 
     383           22 : bool MediaPipeline::handleHaveData(MediaSourceStatus status, uint32_t needDataRequestId)
     384              : {
     385           22 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     386              : 
     387           22 :     std::shared_ptr<NeedDataRequest> needDataRequest;
     388              : 
     389              :     // Find the needDataRequest for this needDataRequestId
     390              :     // The needData request can be cancelled from another thread
     391              :     {
     392           22 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     393              : 
     394           22 :         auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId);
     395           22 :         if (needDataRequestIt == m_needDataRequestMap.end())
     396              :         {
     397              :             // Return success here as the data written is just ignored
     398           19 :             RIALTO_CLIENT_LOG_WARN("Could not find need data request, with id %u", needDataRequestId);
     399           19 :             return true;
     400              :         }
     401              : 
     402            3 :         needDataRequest = needDataRequestIt->second;
     403            3 :         m_needDataRequestMap.erase(needDataRequestIt);
     404           22 :     }
     405            3 :     if (m_attachedSources.isFlushing(needDataRequest->sourceId))
     406              :     {
     407            0 :         RIALTO_CLIENT_LOG_WARN("Source %d is flushing. Ignoring need data request, with id %u",
     408              :                                needDataRequest->sourceId, needDataRequestId);
     409            0 :         return true;
     410              :     }
     411              : 
     412            3 :     uint32_t numFrames = needDataRequest->frameWriter ? needDataRequest->frameWriter->getNumFrames() : 0;
     413            3 :     return m_mediaPipelineIpc->haveData(status, numFrames, needDataRequestId);
     414           22 : }
     415              : 
     416           53 : AddSegmentStatus MediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr<MediaSegment> &mediaSegment)
     417              : {
     418           53 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     419              : 
     420           53 :     if (nullptr == mediaSegment || nullptr == mediaSegment->getData())
     421              :     {
     422            2 :         return AddSegmentStatus::ERROR;
     423              :     }
     424              : 
     425           51 :     std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     426           51 :     auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId);
     427           51 :     if (needDataRequestIt == m_needDataRequestMap.end())
     428              :     {
     429            0 :         RIALTO_CLIENT_LOG_ERROR("Could not find need data request, with id %u", needDataRequestId);
     430            0 :         return AddSegmentStatus::ERROR;
     431              :     }
     432              : 
     433           51 :     std::shared_ptr<NeedDataRequest> needDataRequest = needDataRequestIt->second;
     434           51 :     std::shared_ptr<ISharedMemoryHandle> shmHandle = m_clientController.getSharedMemoryHandle();
     435           51 :     if (nullptr == shmHandle || nullptr == shmHandle->getShm())
     436              :     {
     437            2 :         RIALTO_CLIENT_LOG_ERROR("Shared buffer no longer valid");
     438            2 :         return AddSegmentStatus::ERROR;
     439              :     }
     440              : 
     441              :     // This block of code is only for playready apps using rialto c++ interface
     442              :     // Widevine apps and playready apps using rialto-ocdm set MediaSegment::keyId earlier
     443           49 :     if (mediaSegment->isEncrypted())
     444              :     {
     445            2 :         auto keyId = KeyIdMap::instance().get(mediaSegment->getMediaKeySessionId());
     446            2 :         if (!keyId.empty() && mediaSegment->getKeyId().empty())
     447              :         {
     448            1 :             RIALTO_CLIENT_LOG_DEBUG("Adding Playready keyID to media segment");
     449            1 :             mediaSegment->setKeyId(keyId);
     450              :         }
     451            2 :     }
     452              : 
     453           49 :     if (!needDataRequest->frameWriter)
     454              :     {
     455           17 :         if (firebolt::rialto::MediaSourceType::UNKNOWN != mediaSegment->getType())
     456              :         {
     457           16 :             needDataRequest->frameWriter =
     458           32 :                 m_mediaFrameWriterFactory->createFrameWriter(shmHandle->getShm(), needDataRequest->shmInfo);
     459              :         }
     460              :         else
     461              :         {
     462            1 :             RIALTO_CLIENT_LOG_ERROR("Unrecognised type %u", static_cast<uint32_t>(mediaSegment->getType()));
     463            1 :             return AddSegmentStatus::ERROR;
     464              :         }
     465              : 
     466           16 :         if (!needDataRequest->frameWriter)
     467              :         {
     468            1 :             RIALTO_CLIENT_LOG_ERROR("Could not create frame writer");
     469            1 :             return AddSegmentStatus::ERROR;
     470              :         }
     471              :     }
     472              : 
     473           47 :     return needDataRequest->frameWriter->writeFrame(mediaSegment);
     474           51 : }
     475              : 
     476            2 : bool MediaPipeline::renderFrame()
     477              : {
     478            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     479            2 :     return m_mediaPipelineIpc->renderFrame();
     480              : }
     481              : 
     482            3 : bool MediaPipeline::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType)
     483              : {
     484            3 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     485            3 :     return m_mediaPipelineIpc->setVolume(targetVolume, volumeDuration, easeType);
     486              : }
     487              : 
     488            2 : bool MediaPipeline::getVolume(double &currentVolume)
     489              : {
     490            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     491            2 :     return m_mediaPipelineIpc->getVolume(currentVolume);
     492              : }
     493              : 
     494            2 : bool MediaPipeline::setMute(int32_t sourceId, bool mute)
     495              : {
     496            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     497            2 :     return m_mediaPipelineIpc->setMute(sourceId, mute);
     498              : }
     499              : 
     500            2 : bool MediaPipeline::getMute(int32_t sourceId, bool &mute)
     501              : {
     502            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     503            2 :     return m_mediaPipelineIpc->getMute(sourceId, mute);
     504              : }
     505              : 
     506            2 : bool MediaPipeline::setTextTrackIdentifier(const std::string &textTrackIdentifier)
     507              : {
     508            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     509            2 :     return m_mediaPipelineIpc->setTextTrackIdentifier(textTrackIdentifier);
     510              : }
     511              : 
     512            2 : bool MediaPipeline::getTextTrackIdentifier(std::string &textTrackIdentifier)
     513              : {
     514            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     515            2 :     return m_mediaPipelineIpc->getTextTrackIdentifier(textTrackIdentifier);
     516              : }
     517              : 
     518            2 : bool MediaPipeline::setLowLatency(bool lowLatency)
     519              : {
     520            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     521            2 :     return m_mediaPipelineIpc->setLowLatency(lowLatency);
     522              : }
     523              : 
     524            2 : bool MediaPipeline::setSync(bool sync)
     525              : {
     526            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     527            2 :     return m_mediaPipelineIpc->setSync(sync);
     528              : }
     529              : 
     530            2 : bool MediaPipeline::getSync(bool &sync)
     531              : {
     532            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     533            2 :     return m_mediaPipelineIpc->getSync(sync);
     534              : }
     535              : 
     536            2 : bool MediaPipeline::setSyncOff(bool syncOff)
     537              : {
     538            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     539            2 :     return m_mediaPipelineIpc->setSyncOff(syncOff);
     540              : }
     541              : 
     542            2 : bool MediaPipeline::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode)
     543              : {
     544            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     545            2 :     return m_mediaPipelineIpc->setStreamSyncMode(sourceId, streamSyncMode);
     546              : }
     547              : 
     548            2 : bool MediaPipeline::getStreamSyncMode(int32_t &streamSyncMode)
     549              : {
     550            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     551            2 :     return m_mediaPipelineIpc->getStreamSyncMode(streamSyncMode);
     552              : }
     553              : 
     554            7 : bool MediaPipeline::flush(int32_t sourceId, bool resetTime, bool &async)
     555              : {
     556            7 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     557              : 
     558            7 :     std::unique_lock<std::mutex> flushLock{m_flushMutex};
     559            7 :     if (m_mediaPipelineIpc->flush(sourceId, resetTime, async))
     560              :     {
     561            6 :         m_attachedSources.setFlushing(sourceId, true);
     562            6 :         flushLock.unlock();
     563              : 
     564              :         // Clear all need datas for flushed source
     565            6 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     566            8 :         for (auto it = m_needDataRequestMap.begin(); it != m_needDataRequestMap.end();)
     567              :         {
     568            2 :             if (it->second->sourceId == sourceId)
     569              :             {
     570            2 :                 it = m_needDataRequestMap.erase(it);
     571              :             }
     572              :             else
     573              :             {
     574            0 :                 ++it;
     575              :             }
     576              :         }
     577            6 :         return true;
     578              :     }
     579            1 :     return false;
     580            7 : }
     581              : 
     582            2 : bool MediaPipeline::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate,
     583              :                                       uint64_t stopPosition)
     584              : {
     585            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     586              : 
     587            2 :     return m_mediaPipelineIpc->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition);
     588              : }
     589              : 
     590            2 : bool MediaPipeline::setSubtitleOffset(int32_t sourceId, int64_t position)
     591              : {
     592            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     593              : 
     594            2 :     return m_mediaPipelineIpc->setSubtitleOffset(sourceId, position);
     595              : }
     596              : 
     597            2 : bool MediaPipeline::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac)
     598              : {
     599            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     600              : 
     601            2 :     return m_mediaPipelineIpc->processAudioGap(position, duration, discontinuityGap, audioAac);
     602              : }
     603              : 
     604            2 : bool MediaPipeline::setBufferingLimit(uint32_t limitBufferingMs)
     605              : {
     606            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     607              : 
     608            2 :     return m_mediaPipelineIpc->setBufferingLimit(limitBufferingMs);
     609              : }
     610              : 
     611            2 : bool MediaPipeline::getBufferingLimit(uint32_t &limitBufferingMs)
     612              : {
     613            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     614              : 
     615            2 :     return m_mediaPipelineIpc->getBufferingLimit(limitBufferingMs);
     616              : }
     617              : 
     618            2 : bool MediaPipeline::setUseBuffering(bool useBuffering)
     619              : {
     620            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     621              : 
     622            2 :     return m_mediaPipelineIpc->setUseBuffering(useBuffering);
     623              : }
     624              : 
     625            2 : bool MediaPipeline::getUseBuffering(bool &useBuffering)
     626              : {
     627            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     628              : 
     629            2 :     return m_mediaPipelineIpc->getUseBuffering(useBuffering);
     630              : }
     631              : 
     632            2 : bool MediaPipeline::switchSource(const std::unique_ptr<MediaSource> &source)
     633              : {
     634            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     635              : 
     636            2 :     return m_mediaPipelineIpc->switchSource(source);
     637              : }
     638              : 
     639            5 : void MediaPipeline::discardNeedDataRequest(uint32_t needDataRequestId)
     640              : {
     641              :     // Find the needDataRequest for this needDataRequestId
     642              :     // The needData request can be cancelled from another thread
     643              :     {
     644            5 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     645              : 
     646            5 :         auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId);
     647            5 :         if (needDataRequestIt == m_needDataRequestMap.end())
     648              :         {
     649            0 :             RIALTO_CLIENT_LOG_INFO("Could not find need data request, with id %u", needDataRequestId);
     650              :         }
     651              :         else
     652              :         {
     653            5 :             RIALTO_CLIENT_LOG_INFO("Discarding need data request with id %u", needDataRequestId);
     654            5 :             m_needDataRequestMap.erase(needDataRequestIt);
     655              :         }
     656              :     }
     657              : }
     658              : 
     659            0 : std::weak_ptr<IMediaPipelineClient> MediaPipeline::getClient()
     660              : {
     661            0 :     return m_mediaPipelineClient;
     662              : }
     663              : 
     664            4 : void MediaPipeline::updateState(NetworkState state)
     665              : {
     666            4 :     State newState = m_currentState;
     667              : 
     668            4 :     switch (state)
     669              :     {
     670            3 :     case NetworkState::BUFFERING:
     671              :     case NetworkState::BUFFERING_PROGRESS:
     672              :     case NetworkState::STALLED:
     673              :     {
     674            3 :         newState = State::BUFFERING;
     675            3 :         break;
     676              :     }
     677            0 :     case NetworkState::FORMAT_ERROR:
     678              :     case NetworkState::NETWORK_ERROR:
     679              :     case NetworkState::DECODE_ERROR:
     680              :     {
     681            0 :         newState = State::FAILURE;
     682            0 :         break;
     683              :     }
     684            1 :     default:
     685              :     {
     686            1 :         break;
     687              :     }
     688              :     }
     689              : 
     690            4 :     RIALTO_CLIENT_LOG_DEBUG("Received network state '%s', old state '%s', new state '%s'", toString(state),
     691              :                             toString(m_currentState), toString(newState));
     692            4 :     m_currentState = newState;
     693              : }
     694              : 
     695           68 : void MediaPipeline::updateState(PlaybackState state)
     696              : {
     697           68 :     State newState = m_currentState;
     698              : 
     699           68 :     switch (state)
     700              :     {
     701           50 :     case PlaybackState::PLAYING:
     702              :     case PlaybackState::PAUSED:
     703              :     {
     704           50 :         newState = State::PLAYING;
     705           50 :         break;
     706              :     }
     707            4 :     case PlaybackState::SEEKING:
     708              :     {
     709            4 :         newState = State::SEEKING;
     710            4 :         break;
     711              :     }
     712            3 :     case PlaybackState::STOPPED:
     713              :     {
     714            3 :         newState = State::IDLE;
     715            3 :         break;
     716              :     }
     717            3 :     case PlaybackState::SEEK_DONE:
     718              :     {
     719            3 :         newState = State::BUFFERING;
     720            3 :         break;
     721              :     }
     722            4 :     case PlaybackState::END_OF_STREAM:
     723              :     {
     724            4 :         newState = State::END_OF_STREAM;
     725            4 :         break;
     726              :     }
     727            3 :     case PlaybackState::FAILURE:
     728              :     {
     729            3 :         newState = State::FAILURE;
     730            3 :         break;
     731              :     }
     732            1 :     default:
     733              :     {
     734            1 :         break;
     735              :     }
     736              :     }
     737              : 
     738           68 :     RIALTO_CLIENT_LOG_DEBUG("Received playback state '%s', old state '%s', new state '%s'", toString(state),
     739              :                             toString(m_currentState), toString(newState));
     740           68 :     m_currentState = newState;
     741              : }
     742              : 
     743           68 : void MediaPipeline::notifyPlaybackState(PlaybackState state)
     744              : {
     745           68 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     746              : 
     747           68 :     updateState(state);
     748              : 
     749           68 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     750           68 :     if (client)
     751              :     {
     752           68 :         client->notifyPlaybackState(state);
     753              :     }
     754              : }
     755              : 
     756            0 : void MediaPipeline::notifyPosition(int64_t position)
     757              : {
     758            0 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     759              : 
     760            0 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     761            0 :     if (client)
     762              :     {
     763            0 :         client->notifyPosition(position);
     764              :     }
     765              : }
     766              : 
     767            4 : void MediaPipeline::notifyNetworkState(NetworkState state)
     768              : {
     769            4 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     770              : 
     771            4 :     updateState(state);
     772              : 
     773            4 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     774            4 :     if (client)
     775              :     {
     776            4 :         client->notifyNetworkState(state);
     777              :     }
     778              : }
     779              : 
     780           49 : void MediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId,
     781              :                                         const std::shared_ptr<MediaPlayerShmInfo> &shmInfo)
     782              : {
     783           49 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     784              : 
     785              :     // If attach source is ongoing wait till it has completed so that all sources are attached
     786              :     {
     787           49 :         std::unique_lock<std::mutex> lock{m_attachSourceMutex};
     788           49 :         if (m_attachingSource)
     789            0 :             m_attachSourceCond.wait(lock, [this] { return !m_attachingSource; });
     790           49 :     }
     791              : 
     792           49 :     if (MediaSourceType::UNKNOWN == m_attachedSources.getType(sourceId))
     793              :     {
     794            2 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received for unknown source %d, ignoring request id %u", sourceId,
     795              :                                requestId);
     796            2 :         return;
     797              :     }
     798           47 :     if (m_attachedSources.isFlushing(sourceId))
     799              :     {
     800            1 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received for flushing source %d, ignoring request id %u", sourceId,
     801              :                                requestId);
     802            1 :         return;
     803              :     }
     804              : 
     805           46 :     switch (m_currentState)
     806              :     {
     807           39 :     case State::BUFFERING:
     808              :     case State::PLAYING:
     809              :     {
     810           39 :         std::shared_ptr<NeedDataRequest> needDataRequest = std::make_shared<NeedDataRequest>();
     811           39 :         needDataRequest->sourceId = sourceId;
     812           39 :         needDataRequest->shmInfo = shmInfo;
     813              : 
     814              :         {
     815           39 :             std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     816           39 :             if (ApplicationState::RUNNING != m_currentAppState)
     817              :             {
     818            1 :                 RIALTO_CLIENT_LOG_INFO("NeedMediaData received in state != RUNNING, ignoring request id %u", requestId);
     819            1 :                 break;
     820              :             }
     821           38 :             m_needDataRequestMap[requestId] = needDataRequest;
     822           39 :         }
     823              : 
     824           38 :         std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     825           38 :         if (client)
     826              :         {
     827           38 :             client->notifyNeedMediaData(sourceId, frameCount, requestId, nullptr);
     828              :         }
     829              : 
     830           38 :         break;
     831           39 :     }
     832            1 :     case State::SEEKING:
     833              :     {
     834            1 :         RIALTO_CLIENT_LOG_INFO("NeedMediaData received while seeking, ignoring request id %u", requestId);
     835            1 :         break;
     836              :     }
     837            6 :     case State::IDLE:
     838              :     case State::END_OF_STREAM:
     839              :     case State::FAILURE:
     840              :     default:
     841              :     {
     842            6 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received in unexpected state '%s', ignoring request id %u",
     843              :                                toString(m_currentState), requestId);
     844            6 :         break;
     845              :     }
     846              :     }
     847              : }
     848              : 
     849          118 : void MediaPipeline::notifyApplicationState(ApplicationState state)
     850              : {
     851          118 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     852          118 :     std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     853          118 :     m_currentAppState = state;
     854          118 :     if (ApplicationState::RUNNING != state)
     855              :     {
     856              :         // If shared memory in use, wait for it to finish before returning
     857            4 :         m_needDataRequestMap.clear();
     858              :     }
     859          118 : }
     860              : 
     861            1 : void MediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo)
     862              : {
     863            1 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     864              : 
     865            1 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     866            1 :     if (client)
     867              :     {
     868            1 :         client->notifyQos(sourceId, qosInfo);
     869              :     }
     870              : }
     871              : 
     872            0 : void MediaPipeline::notifyBufferUnderflow(int32_t sourceId)
     873              : {
     874            0 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     875              : 
     876            0 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     877            0 :     if (client)
     878              :     {
     879            0 :         client->notifyBufferUnderflow(sourceId);
     880              :     }
     881              : }
     882              : 
     883            1 : void MediaPipeline::notifyPlaybackError(int32_t sourceId, PlaybackError error)
     884              : {
     885            1 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     886              : 
     887            1 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     888            1 :     if (client)
     889              :     {
     890            1 :         client->notifyPlaybackError(sourceId, error);
     891              :     }
     892              : }
     893              : 
     894            4 : void MediaPipeline::notifySourceFlushed(int32_t sourceId)
     895              : {
     896            4 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     897              :     {
     898            4 :         std::lock_guard<std::mutex> lock{m_flushMutex};
     899            4 :         m_attachedSources.setFlushing(sourceId, false);
     900              :     }
     901            4 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     902            4 :     if (client)
     903              :     {
     904            4 :         client->notifySourceFlushed(sourceId);
     905              :     }
     906              : 
     907            4 :     State expected = State::END_OF_STREAM;
     908            4 :     m_currentState.compare_exchange_strong(expected, State::BUFFERING);
     909              : }
     910              : 
     911            1 : void MediaPipeline::notifyPlaybackInfo(const PlaybackInfo &playbackInfo)
     912              : {
     913            1 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     914              : 
     915            1 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     916            1 :     if (client)
     917              :     {
     918            1 :         client->notifyPlaybackInfo(playbackInfo);
     919              :     }
     920              : }
     921              : 
     922              : }; // namespace firebolt::rialto::client
        

Generated by: LCOV version 2.0-1