LCOV - code coverage report
Current view: top level - media/client/main/source - MediaPipeline.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.6 % 429 376
Test Date: 2025-10-07 14:22:52 Functions: 90.6 % 64 58

            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          116 : 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          116 :                              IClientController &clientController)
     186          348 :     : m_mediaPipelineClient(client), m_clientController{clientController}, m_currentAppState{ApplicationState::UNKNOWN},
     187          116 :       m_mediaFrameWriterFactory(mediaFrameWriterFactory), m_currentState(State::IDLE)
     188              : {
     189          116 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     190              : 
     191          116 :     m_mediaPipelineIpc = mediaPipelineIpcFactory->createMediaPipelineIpc(this, videoRequirements);
     192              : 
     193          116 :     if (!m_mediaPipelineIpc)
     194              :     {
     195            2 :         throw std::runtime_error("Media player ipc could not be created");
     196              :     }
     197          130 : }
     198              : 
     199          226 : MediaPipeline::~MediaPipeline()
     200              : {
     201          114 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     202              : 
     203          114 :     m_mediaPipelineIpc.reset();
     204          226 : }
     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()
     256              : {
     257            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     258              : 
     259            2 :     return m_mediaPipelineIpc->play();
     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::getImmediateOutput(int32_t sourceId, bool &immediateOutput)
     317              : {
     318            2 :     return m_mediaPipelineIpc->getImmediateOutput(sourceId, immediateOutput);
     319              : }
     320              : 
     321            2 : bool MediaPipeline::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
     322              : {
     323            2 :     return m_mediaPipelineIpc->getStats(sourceId, renderedFrames, droppedFrames);
     324              : }
     325              : 
     326            5 : bool MediaPipeline::handleSetPosition(int64_t position)
     327              : {
     328              :     // needData requests no longer valid
     329              :     {
     330            5 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     331            5 :         m_needDataRequestMap.clear();
     332              :     }
     333            5 :     return m_mediaPipelineIpc->setPosition(position);
     334              : }
     335              : 
     336            2 : bool MediaPipeline::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
     337              : {
     338            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     339              : 
     340            2 :     return m_mediaPipelineIpc->setVideoWindow(x, y, width, height);
     341              : }
     342              : 
     343           27 : bool MediaPipeline::haveData(MediaSourceStatus status, uint32_t needDataRequestId)
     344              : {
     345           27 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     346              : 
     347           27 :     switch (m_currentState)
     348              :     {
     349           22 :     case State::BUFFERING:
     350              :     case State::PLAYING:
     351              :     {
     352           22 :         return handleHaveData(status, needDataRequestId);
     353              :     }
     354            2 :     case State::SEEKING:
     355              :     {
     356            2 :         RIALTO_CLIENT_LOG_INFO("HaveData received while seeking, discarding NeedData request %u", needDataRequestId);
     357            2 :         discardNeedDataRequest(needDataRequestId);
     358            2 :         return true;
     359              :     }
     360            3 :     case State::IDLE:
     361              :     case State::END_OF_STREAM:
     362              :     case State::FAILURE:
     363              :     default:
     364              :     {
     365            3 :         RIALTO_CLIENT_LOG_WARN("HaveData received in unexpected state '%s', discarding NeedData request %u",
     366              :                                toString(m_currentState), needDataRequestId);
     367            3 :         discardNeedDataRequest(needDataRequestId);
     368            3 :         return false;
     369              :     }
     370              :     }
     371              : }
     372              : 
     373           22 : bool MediaPipeline::handleHaveData(MediaSourceStatus status, uint32_t needDataRequestId)
     374              : {
     375           22 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     376              : 
     377           22 :     std::shared_ptr<NeedDataRequest> needDataRequest;
     378              : 
     379              :     // Find the needDataRequest for this needDataRequestId
     380              :     // The needData request can be cancelled from another thread
     381              :     {
     382           22 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     383              : 
     384           22 :         auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId);
     385           22 :         if (needDataRequestIt == m_needDataRequestMap.end())
     386              :         {
     387              :             // Return success here as the data written is just ignored
     388           19 :             RIALTO_CLIENT_LOG_WARN("Could not find need data request, with id %u", needDataRequestId);
     389           19 :             return true;
     390              :         }
     391              : 
     392            3 :         needDataRequest = needDataRequestIt->second;
     393            3 :         m_needDataRequestMap.erase(needDataRequestIt);
     394           22 :     }
     395            3 :     if (m_attachedSources.isFlushing(needDataRequest->sourceId))
     396              :     {
     397            0 :         RIALTO_CLIENT_LOG_WARN("Source %d is flushing. Ignoring need data request, with id %u",
     398              :                                needDataRequest->sourceId, needDataRequestId);
     399            0 :         return true;
     400              :     }
     401              : 
     402            3 :     uint32_t numFrames = needDataRequest->frameWriter ? needDataRequest->frameWriter->getNumFrames() : 0;
     403            3 :     return m_mediaPipelineIpc->haveData(status, numFrames, needDataRequestId);
     404           22 : }
     405              : 
     406           53 : AddSegmentStatus MediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr<MediaSegment> &mediaSegment)
     407              : {
     408           53 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     409              : 
     410           53 :     if (nullptr == mediaSegment || nullptr == mediaSegment->getData())
     411              :     {
     412            2 :         return AddSegmentStatus::ERROR;
     413              :     }
     414              : 
     415           51 :     std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     416           51 :     auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId);
     417           51 :     if (needDataRequestIt == m_needDataRequestMap.end())
     418              :     {
     419            0 :         RIALTO_CLIENT_LOG_ERROR("Could not find need data request, with id %u", needDataRequestId);
     420            0 :         return AddSegmentStatus::ERROR;
     421              :     }
     422              : 
     423           51 :     std::shared_ptr<NeedDataRequest> needDataRequest = needDataRequestIt->second;
     424           51 :     std::shared_ptr<ISharedMemoryHandle> shmHandle = m_clientController.getSharedMemoryHandle();
     425           51 :     if (nullptr == shmHandle || nullptr == shmHandle->getShm())
     426              :     {
     427            2 :         RIALTO_CLIENT_LOG_ERROR("Shared buffer no longer valid");
     428            2 :         return AddSegmentStatus::ERROR;
     429              :     }
     430              : 
     431              :     // This block of code is only for playready apps using rialto c++ interface
     432              :     // Widevine apps and playready apps using rialto-ocdm set MediaSegment::keyId earlier
     433           49 :     if (mediaSegment->isEncrypted())
     434              :     {
     435            2 :         auto keyId = KeyIdMap::instance().get(mediaSegment->getMediaKeySessionId());
     436            2 :         if (!keyId.empty() && mediaSegment->getKeyId().empty())
     437              :         {
     438            1 :             RIALTO_CLIENT_LOG_DEBUG("Adding Playready keyID to media segment");
     439            1 :             mediaSegment->setKeyId(keyId);
     440              :         }
     441            2 :     }
     442              : 
     443           49 :     if (!needDataRequest->frameWriter)
     444              :     {
     445           17 :         if (firebolt::rialto::MediaSourceType::UNKNOWN != mediaSegment->getType())
     446              :         {
     447           16 :             needDataRequest->frameWriter =
     448           32 :                 m_mediaFrameWriterFactory->createFrameWriter(shmHandle->getShm(), needDataRequest->shmInfo);
     449              :         }
     450              :         else
     451              :         {
     452            1 :             RIALTO_CLIENT_LOG_ERROR("Unrecognised type %u", static_cast<uint32_t>(mediaSegment->getType()));
     453            1 :             return AddSegmentStatus::ERROR;
     454              :         }
     455              : 
     456           16 :         if (!needDataRequest->frameWriter)
     457              :         {
     458            1 :             RIALTO_CLIENT_LOG_ERROR("Could not create frame writer");
     459            1 :             return AddSegmentStatus::ERROR;
     460              :         }
     461              :     }
     462              : 
     463           47 :     return needDataRequest->frameWriter->writeFrame(mediaSegment);
     464           51 : }
     465              : 
     466            2 : bool MediaPipeline::renderFrame()
     467              : {
     468            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     469            2 :     return m_mediaPipelineIpc->renderFrame();
     470              : }
     471              : 
     472            3 : bool MediaPipeline::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType)
     473              : {
     474            3 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     475            3 :     return m_mediaPipelineIpc->setVolume(targetVolume, volumeDuration, easeType);
     476              : }
     477              : 
     478            2 : bool MediaPipeline::getVolume(double &currentVolume)
     479              : {
     480            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     481            2 :     return m_mediaPipelineIpc->getVolume(currentVolume);
     482              : }
     483              : 
     484            2 : bool MediaPipeline::setMute(int32_t sourceId, bool mute)
     485              : {
     486            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     487            2 :     return m_mediaPipelineIpc->setMute(sourceId, mute);
     488              : }
     489              : 
     490            2 : bool MediaPipeline::getMute(int32_t sourceId, bool &mute)
     491              : {
     492            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     493            2 :     return m_mediaPipelineIpc->getMute(sourceId, mute);
     494              : }
     495              : 
     496            2 : bool MediaPipeline::setTextTrackIdentifier(const std::string &textTrackIdentifier)
     497              : {
     498            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     499            2 :     return m_mediaPipelineIpc->setTextTrackIdentifier(textTrackIdentifier);
     500              : }
     501              : 
     502            2 : bool MediaPipeline::getTextTrackIdentifier(std::string &textTrackIdentifier)
     503              : {
     504            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     505            2 :     return m_mediaPipelineIpc->getTextTrackIdentifier(textTrackIdentifier);
     506              : }
     507              : 
     508            2 : bool MediaPipeline::setLowLatency(bool lowLatency)
     509              : {
     510            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     511            2 :     return m_mediaPipelineIpc->setLowLatency(lowLatency);
     512              : }
     513              : 
     514            2 : bool MediaPipeline::setSync(bool sync)
     515              : {
     516            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     517            2 :     return m_mediaPipelineIpc->setSync(sync);
     518              : }
     519              : 
     520            2 : bool MediaPipeline::getSync(bool &sync)
     521              : {
     522            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     523            2 :     return m_mediaPipelineIpc->getSync(sync);
     524              : }
     525              : 
     526            2 : bool MediaPipeline::setSyncOff(bool syncOff)
     527              : {
     528            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     529            2 :     return m_mediaPipelineIpc->setSyncOff(syncOff);
     530              : }
     531              : 
     532            2 : bool MediaPipeline::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode)
     533              : {
     534            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     535            2 :     return m_mediaPipelineIpc->setStreamSyncMode(sourceId, streamSyncMode);
     536              : }
     537              : 
     538            2 : bool MediaPipeline::getStreamSyncMode(int32_t &streamSyncMode)
     539              : {
     540            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     541            2 :     return m_mediaPipelineIpc->getStreamSyncMode(streamSyncMode);
     542              : }
     543              : 
     544            7 : bool MediaPipeline::flush(int32_t sourceId, bool resetTime, bool &async)
     545              : {
     546            7 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     547              : 
     548            7 :     std::unique_lock<std::mutex> flushLock{m_flushMutex};
     549            7 :     if (m_mediaPipelineIpc->flush(sourceId, resetTime, async))
     550              :     {
     551            6 :         m_attachedSources.setFlushing(sourceId, true);
     552            6 :         flushLock.unlock();
     553              : 
     554              :         // Clear all need datas for flushed source
     555            6 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     556            8 :         for (auto it = m_needDataRequestMap.begin(); it != m_needDataRequestMap.end();)
     557              :         {
     558            2 :             if (it->second->sourceId == sourceId)
     559              :             {
     560            2 :                 it = m_needDataRequestMap.erase(it);
     561              :             }
     562              :             else
     563              :             {
     564            0 :                 ++it;
     565              :             }
     566              :         }
     567            6 :         return true;
     568              :     }
     569            1 :     return false;
     570            7 : }
     571              : 
     572            2 : bool MediaPipeline::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate,
     573              :                                       uint64_t stopPosition)
     574              : {
     575            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     576              : 
     577            2 :     return m_mediaPipelineIpc->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition);
     578              : }
     579              : 
     580            2 : bool MediaPipeline::setSubtitleOffset(int32_t sourceId, int64_t position)
     581              : {
     582            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     583              : 
     584            2 :     return m_mediaPipelineIpc->setSubtitleOffset(sourceId, position);
     585              : }
     586              : 
     587            2 : bool MediaPipeline::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac)
     588              : {
     589            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     590              : 
     591            2 :     return m_mediaPipelineIpc->processAudioGap(position, duration, discontinuityGap, audioAac);
     592              : }
     593              : 
     594            2 : bool MediaPipeline::setBufferingLimit(uint32_t limitBufferingMs)
     595              : {
     596            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     597              : 
     598            2 :     return m_mediaPipelineIpc->setBufferingLimit(limitBufferingMs);
     599              : }
     600              : 
     601            2 : bool MediaPipeline::getBufferingLimit(uint32_t &limitBufferingMs)
     602              : {
     603            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     604              : 
     605            2 :     return m_mediaPipelineIpc->getBufferingLimit(limitBufferingMs);
     606              : }
     607              : 
     608            2 : bool MediaPipeline::setUseBuffering(bool useBuffering)
     609              : {
     610            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     611              : 
     612            2 :     return m_mediaPipelineIpc->setUseBuffering(useBuffering);
     613              : }
     614              : 
     615            2 : bool MediaPipeline::getUseBuffering(bool &useBuffering)
     616              : {
     617            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     618              : 
     619            2 :     return m_mediaPipelineIpc->getUseBuffering(useBuffering);
     620              : }
     621              : 
     622            2 : bool MediaPipeline::switchSource(const std::unique_ptr<MediaSource> &source)
     623              : {
     624            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     625              : 
     626            2 :     return m_mediaPipelineIpc->switchSource(source);
     627              : }
     628              : 
     629            5 : void MediaPipeline::discardNeedDataRequest(uint32_t needDataRequestId)
     630              : {
     631              :     // Find the needDataRequest for this needDataRequestId
     632              :     // The needData request can be cancelled from another thread
     633              :     {
     634            5 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     635              : 
     636            5 :         auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId);
     637            5 :         if (needDataRequestIt == m_needDataRequestMap.end())
     638              :         {
     639            0 :             RIALTO_CLIENT_LOG_INFO("Could not find need data request, with id %u", needDataRequestId);
     640              :         }
     641              :         else
     642              :         {
     643            5 :             RIALTO_CLIENT_LOG_INFO("Discarding need data request with id %u", needDataRequestId);
     644            5 :             m_needDataRequestMap.erase(needDataRequestIt);
     645              :         }
     646              :     }
     647              : }
     648              : 
     649            0 : std::weak_ptr<IMediaPipelineClient> MediaPipeline::getClient()
     650              : {
     651            0 :     return m_mediaPipelineClient;
     652              : }
     653              : 
     654            4 : void MediaPipeline::updateState(NetworkState state)
     655              : {
     656            4 :     State newState = m_currentState;
     657              : 
     658            4 :     switch (state)
     659              :     {
     660            3 :     case NetworkState::BUFFERING:
     661              :     case NetworkState::BUFFERING_PROGRESS:
     662              :     case NetworkState::STALLED:
     663              :     {
     664            3 :         newState = State::BUFFERING;
     665            3 :         break;
     666              :     }
     667            0 :     case NetworkState::FORMAT_ERROR:
     668              :     case NetworkState::NETWORK_ERROR:
     669              :     case NetworkState::DECODE_ERROR:
     670              :     {
     671            0 :         newState = State::FAILURE;
     672            0 :         break;
     673              :     }
     674            1 :     default:
     675              :     {
     676            1 :         break;
     677              :     }
     678              :     }
     679              : 
     680            4 :     RIALTO_CLIENT_LOG_DEBUG("Received network state '%s', old state '%s', new state '%s'", toString(state),
     681              :                             toString(m_currentState), toString(newState));
     682            4 :     m_currentState = newState;
     683              : }
     684              : 
     685           68 : void MediaPipeline::updateState(PlaybackState state)
     686              : {
     687           68 :     State newState = m_currentState;
     688              : 
     689           68 :     switch (state)
     690              :     {
     691           50 :     case PlaybackState::PLAYING:
     692              :     case PlaybackState::PAUSED:
     693              :     {
     694           50 :         newState = State::PLAYING;
     695           50 :         break;
     696              :     }
     697            4 :     case PlaybackState::SEEKING:
     698              :     {
     699            4 :         newState = State::SEEKING;
     700            4 :         break;
     701              :     }
     702            3 :     case PlaybackState::STOPPED:
     703              :     {
     704            3 :         newState = State::IDLE;
     705            3 :         break;
     706              :     }
     707            3 :     case PlaybackState::SEEK_DONE:
     708              :     {
     709            3 :         newState = State::BUFFERING;
     710            3 :         break;
     711              :     }
     712            4 :     case PlaybackState::END_OF_STREAM:
     713              :     {
     714            4 :         newState = State::END_OF_STREAM;
     715            4 :         break;
     716              :     }
     717            3 :     case PlaybackState::FAILURE:
     718              :     {
     719            3 :         newState = State::FAILURE;
     720            3 :         break;
     721              :     }
     722            1 :     default:
     723              :     {
     724            1 :         break;
     725              :     }
     726              :     }
     727              : 
     728           68 :     RIALTO_CLIENT_LOG_DEBUG("Received playback state '%s', old state '%s', new state '%s'", toString(state),
     729              :                             toString(m_currentState), toString(newState));
     730           68 :     m_currentState = newState;
     731              : }
     732              : 
     733           68 : void MediaPipeline::notifyPlaybackState(PlaybackState state)
     734              : {
     735           68 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     736              : 
     737           68 :     updateState(state);
     738              : 
     739           68 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     740           68 :     if (client)
     741              :     {
     742           68 :         client->notifyPlaybackState(state);
     743              :     }
     744              : }
     745              : 
     746            0 : void MediaPipeline::notifyPosition(int64_t position)
     747              : {
     748            0 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     749              : 
     750            0 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     751            0 :     if (client)
     752              :     {
     753            0 :         client->notifyPosition(position);
     754              :     }
     755              : }
     756              : 
     757            4 : void MediaPipeline::notifyNetworkState(NetworkState state)
     758              : {
     759            4 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     760              : 
     761            4 :     updateState(state);
     762              : 
     763            4 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     764            4 :     if (client)
     765              :     {
     766            4 :         client->notifyNetworkState(state);
     767              :     }
     768              : }
     769              : 
     770           49 : void MediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId,
     771              :                                         const std::shared_ptr<MediaPlayerShmInfo> &shmInfo)
     772              : {
     773           49 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     774              : 
     775              :     // If attach source is ongoing wait till it has completed so that all sources are attached
     776              :     {
     777           49 :         std::unique_lock<std::mutex> lock{m_attachSourceMutex};
     778           49 :         if (m_attachingSource)
     779            0 :             m_attachSourceCond.wait(lock, [this] { return !m_attachingSource; });
     780           49 :     }
     781              : 
     782           49 :     if (MediaSourceType::UNKNOWN == m_attachedSources.getType(sourceId))
     783              :     {
     784            2 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received for unknown source %d, ignoring request id %u", sourceId,
     785              :                                requestId);
     786            2 :         return;
     787              :     }
     788           47 :     if (m_attachedSources.isFlushing(sourceId))
     789              :     {
     790            1 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received for flushing source %d, ignoring request id %u", sourceId,
     791              :                                requestId);
     792            1 :         return;
     793              :     }
     794              : 
     795           46 :     switch (m_currentState)
     796              :     {
     797           39 :     case State::BUFFERING:
     798              :     case State::PLAYING:
     799              :     {
     800           39 :         std::shared_ptr<NeedDataRequest> needDataRequest = std::make_shared<NeedDataRequest>();
     801           39 :         needDataRequest->sourceId = sourceId;
     802           39 :         needDataRequest->shmInfo = shmInfo;
     803              : 
     804              :         {
     805           39 :             std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     806           39 :             if (ApplicationState::RUNNING != m_currentAppState)
     807              :             {
     808            1 :                 RIALTO_CLIENT_LOG_INFO("NeedMediaData received in state != RUNNING, ignoring request id %u", requestId);
     809            1 :                 break;
     810              :             }
     811           38 :             m_needDataRequestMap[requestId] = needDataRequest;
     812           39 :         }
     813              : 
     814           38 :         std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     815           38 :         if (client)
     816              :         {
     817           38 :             client->notifyNeedMediaData(sourceId, frameCount, requestId, nullptr);
     818              :         }
     819              : 
     820           38 :         break;
     821           39 :     }
     822            1 :     case State::SEEKING:
     823              :     {
     824            1 :         RIALTO_CLIENT_LOG_INFO("NeedMediaData received while seeking, ignoring request id %u", requestId);
     825            1 :         break;
     826              :     }
     827            6 :     case State::IDLE:
     828              :     case State::END_OF_STREAM:
     829              :     case State::FAILURE:
     830              :     default:
     831              :     {
     832            6 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received in unexpected state '%s', ignoring request id %u",
     833              :                                toString(m_currentState), requestId);
     834            6 :         break;
     835              :     }
     836              :     }
     837              : }
     838              : 
     839          113 : void MediaPipeline::notifyApplicationState(ApplicationState state)
     840              : {
     841          113 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     842          113 :     std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     843          113 :     m_currentAppState = state;
     844          113 :     if (ApplicationState::RUNNING != state)
     845              :     {
     846              :         // If shared memory in use, wait for it to finish before returning
     847            4 :         m_needDataRequestMap.clear();
     848              :     }
     849          113 : }
     850              : 
     851            1 : void MediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo)
     852              : {
     853            1 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     854              : 
     855            1 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     856            1 :     if (client)
     857              :     {
     858            1 :         client->notifyQos(sourceId, qosInfo);
     859              :     }
     860              : }
     861              : 
     862            0 : void MediaPipeline::notifyBufferUnderflow(int32_t sourceId)
     863              : {
     864            0 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     865              : 
     866            0 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     867            0 :     if (client)
     868              :     {
     869            0 :         client->notifyBufferUnderflow(sourceId);
     870              :     }
     871              : }
     872              : 
     873            1 : void MediaPipeline::notifyPlaybackError(int32_t sourceId, PlaybackError error)
     874              : {
     875            1 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     876              : 
     877            1 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     878            1 :     if (client)
     879              :     {
     880            1 :         client->notifyPlaybackError(sourceId, error);
     881              :     }
     882              : }
     883              : 
     884            4 : void MediaPipeline::notifySourceFlushed(int32_t sourceId)
     885              : {
     886            4 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     887              :     {
     888            4 :         std::lock_guard<std::mutex> lock{m_flushMutex};
     889            4 :         m_attachedSources.setFlushing(sourceId, false);
     890              :     }
     891            4 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     892            4 :     if (client)
     893              :     {
     894            4 :         client->notifySourceFlushed(sourceId);
     895              :     }
     896              : 
     897            4 :     State expected = State::END_OF_STREAM;
     898            4 :     m_currentState.compare_exchange_strong(expected, State::BUFFERING);
     899              : }
     900              : 
     901              : }; // namespace firebolt::rialto::client
        

Generated by: LCOV version 2.0-1