LCOV - code coverage report
Current view: top level - media/client/main/source - MediaPipeline.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.8 % 426 374
Test Date: 2025-02-18 13:13:53 Functions: 90.5 % 63 57

            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            3 :                                    : client::IClientControllerAccessor::instance().getClientController();
     142              : 
     143              :         auto mp{std::make_shared<client::MediaPipeline>(client, videoRequirements,
     144              :                                                         mediaPipelineIpcFactoryLocked
     145            6 :                                                             ? mediaPipelineIpcFactoryLocked
     146            3 :                                                             : client::IMediaPipelineIpcFactory::getFactory(),
     147            7 :                                                         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          114 : 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          114 :                              IClientController &clientController)
     186          342 :     : m_mediaPipelineClient(client), m_clientController{clientController}, m_currentAppState{ApplicationState::UNKNOWN},
     187          114 :       m_mediaFrameWriterFactory(mediaFrameWriterFactory), m_currentState(State::IDLE)
     188              : {
     189          114 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     190              : 
     191          114 :     m_mediaPipelineIpc = mediaPipelineIpcFactory->createMediaPipelineIpc(this, videoRequirements);
     192              : 
     193          114 :     if (!m_mediaPipelineIpc)
     194              :     {
     195            2 :         throw std::runtime_error("Media player ipc could not be created");
     196              :     }
     197          128 : }
     198              : 
     199          222 : MediaPipeline::~MediaPipeline()
     200              : {
     201          112 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     202              : 
     203          112 :     m_mediaPipelineIpc.reset();
     204          222 : }
     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)
     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))
     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::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac)
     581              : {
     582            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     583              : 
     584            2 :     return m_mediaPipelineIpc->processAudioGap(position, duration, discontinuityGap, audioAac);
     585              : }
     586              : 
     587            2 : bool MediaPipeline::setBufferingLimit(uint32_t limitBufferingMs)
     588              : {
     589            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     590              : 
     591            2 :     return m_mediaPipelineIpc->setBufferingLimit(limitBufferingMs);
     592              : }
     593              : 
     594            2 : bool MediaPipeline::getBufferingLimit(uint32_t &limitBufferingMs)
     595              : {
     596            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     597              : 
     598            2 :     return m_mediaPipelineIpc->getBufferingLimit(limitBufferingMs);
     599              : }
     600              : 
     601            2 : bool MediaPipeline::setUseBuffering(bool useBuffering)
     602              : {
     603            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     604              : 
     605            2 :     return m_mediaPipelineIpc->setUseBuffering(useBuffering);
     606              : }
     607              : 
     608            2 : bool MediaPipeline::getUseBuffering(bool &useBuffering)
     609              : {
     610            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     611              : 
     612            2 :     return m_mediaPipelineIpc->getUseBuffering(useBuffering);
     613              : }
     614              : 
     615            2 : bool MediaPipeline::switchSource(const std::unique_ptr<MediaSource> &source)
     616              : {
     617            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     618              : 
     619            2 :     return m_mediaPipelineIpc->switchSource(source);
     620              : }
     621              : 
     622            5 : void MediaPipeline::discardNeedDataRequest(uint32_t needDataRequestId)
     623              : {
     624              :     // Find the needDataRequest for this needDataRequestId
     625              :     // The needData request can be cancelled from another thread
     626              :     {
     627            5 :         std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     628              : 
     629            5 :         auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId);
     630            5 :         if (needDataRequestIt == m_needDataRequestMap.end())
     631              :         {
     632            0 :             RIALTO_CLIENT_LOG_INFO("Could not find need data request, with id %u", needDataRequestId);
     633              :         }
     634              :         else
     635              :         {
     636            5 :             RIALTO_CLIENT_LOG_INFO("Discarding need data request with id %u", needDataRequestId);
     637            5 :             m_needDataRequestMap.erase(needDataRequestIt);
     638              :         }
     639              :     }
     640              : }
     641              : 
     642            0 : std::weak_ptr<IMediaPipelineClient> MediaPipeline::getClient()
     643              : {
     644            0 :     return m_mediaPipelineClient;
     645              : }
     646              : 
     647            4 : void MediaPipeline::updateState(NetworkState state)
     648              : {
     649            4 :     State newState = m_currentState;
     650              : 
     651            4 :     switch (state)
     652              :     {
     653            3 :     case NetworkState::BUFFERING:
     654              :     case NetworkState::BUFFERING_PROGRESS:
     655              :     case NetworkState::STALLED:
     656              :     {
     657            3 :         newState = State::BUFFERING;
     658            3 :         break;
     659              :     }
     660            0 :     case NetworkState::FORMAT_ERROR:
     661              :     case NetworkState::NETWORK_ERROR:
     662              :     case NetworkState::DECODE_ERROR:
     663              :     {
     664            0 :         newState = State::FAILURE;
     665            0 :         break;
     666              :     }
     667            1 :     default:
     668              :     {
     669            1 :         break;
     670              :     }
     671              :     }
     672              : 
     673            4 :     RIALTO_CLIENT_LOG_DEBUG("Received network state '%s', old state '%s', new state '%s'", toString(state),
     674              :                             toString(m_currentState), toString(newState));
     675            4 :     m_currentState = newState;
     676              : }
     677              : 
     678           68 : void MediaPipeline::updateState(PlaybackState state)
     679              : {
     680           68 :     State newState = m_currentState;
     681              : 
     682           68 :     switch (state)
     683              :     {
     684           50 :     case PlaybackState::PLAYING:
     685              :     case PlaybackState::PAUSED:
     686              :     {
     687           50 :         newState = State::PLAYING;
     688           50 :         break;
     689              :     }
     690            4 :     case PlaybackState::SEEKING:
     691              :     {
     692            4 :         newState = State::SEEKING;
     693            4 :         break;
     694              :     }
     695            3 :     case PlaybackState::STOPPED:
     696              :     {
     697            3 :         newState = State::IDLE;
     698            3 :         break;
     699              :     }
     700            3 :     case PlaybackState::SEEK_DONE:
     701              :     {
     702            3 :         newState = State::BUFFERING;
     703            3 :         break;
     704              :     }
     705            4 :     case PlaybackState::END_OF_STREAM:
     706              :     {
     707            4 :         newState = State::END_OF_STREAM;
     708            4 :         break;
     709              :     }
     710            3 :     case PlaybackState::FAILURE:
     711              :     {
     712            3 :         newState = State::FAILURE;
     713            3 :         break;
     714              :     }
     715            1 :     default:
     716              :     {
     717            1 :         break;
     718              :     }
     719              :     }
     720              : 
     721           68 :     RIALTO_CLIENT_LOG_DEBUG("Received playback state '%s', old state '%s', new state '%s'", toString(state),
     722              :                             toString(m_currentState), toString(newState));
     723           68 :     m_currentState = newState;
     724              : }
     725              : 
     726           68 : void MediaPipeline::notifyPlaybackState(PlaybackState state)
     727              : {
     728           68 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     729              : 
     730           68 :     updateState(state);
     731              : 
     732           68 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     733           68 :     if (client)
     734              :     {
     735           68 :         client->notifyPlaybackState(state);
     736              :     }
     737              : }
     738              : 
     739            0 : void MediaPipeline::notifyPosition(int64_t position)
     740              : {
     741            0 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     742              : 
     743            0 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     744            0 :     if (client)
     745              :     {
     746            0 :         client->notifyPosition(position);
     747              :     }
     748              : }
     749              : 
     750            4 : void MediaPipeline::notifyNetworkState(NetworkState state)
     751              : {
     752            4 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     753              : 
     754            4 :     updateState(state);
     755              : 
     756            4 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     757            4 :     if (client)
     758              :     {
     759            4 :         client->notifyNetworkState(state);
     760              :     }
     761              : }
     762              : 
     763           49 : void MediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId,
     764              :                                         const std::shared_ptr<MediaPlayerShmInfo> &shmInfo)
     765              : {
     766           49 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     767              : 
     768              :     // If attach source is ongoing wait till it has completed so that all sources are attached
     769              :     {
     770           49 :         std::unique_lock<std::mutex> lock{m_attachSourceMutex};
     771           49 :         if (m_attachingSource)
     772            0 :             m_attachSourceCond.wait(lock, [this] { return !m_attachingSource; });
     773           49 :     }
     774              : 
     775           49 :     if (MediaSourceType::UNKNOWN == m_attachedSources.getType(sourceId))
     776              :     {
     777            2 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received for unknown source %d, ignoring request id %u", sourceId,
     778              :                                requestId);
     779            2 :         return;
     780              :     }
     781           47 :     if (m_attachedSources.isFlushing(sourceId))
     782              :     {
     783            1 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received for flushing source %d, ignoring request id %u", sourceId,
     784              :                                requestId);
     785            1 :         return;
     786              :     }
     787              : 
     788           46 :     switch (m_currentState)
     789              :     {
     790           39 :     case State::BUFFERING:
     791              :     case State::PLAYING:
     792              :     {
     793           39 :         std::shared_ptr<NeedDataRequest> needDataRequest = std::make_shared<NeedDataRequest>();
     794           39 :         needDataRequest->sourceId = sourceId;
     795           39 :         needDataRequest->shmInfo = shmInfo;
     796              : 
     797              :         {
     798           39 :             std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     799           39 :             if (ApplicationState::RUNNING != m_currentAppState)
     800              :             {
     801            1 :                 RIALTO_CLIENT_LOG_INFO("NeedMediaData received in state != RUNNING, ignoring request id %u", requestId);
     802            1 :                 break;
     803              :             }
     804           38 :             m_needDataRequestMap[requestId] = needDataRequest;
     805           39 :         }
     806              : 
     807           38 :         std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     808           38 :         if (client)
     809              :         {
     810           38 :             client->notifyNeedMediaData(sourceId, frameCount, requestId, nullptr);
     811              :         }
     812              : 
     813           38 :         break;
     814           39 :     }
     815            1 :     case State::SEEKING:
     816              :     {
     817            1 :         RIALTO_CLIENT_LOG_INFO("NeedMediaData received while seeking, ignoring request id %u", requestId);
     818            1 :         break;
     819              :     }
     820            6 :     case State::IDLE:
     821              :     case State::END_OF_STREAM:
     822              :     case State::FAILURE:
     823              :     default:
     824              :     {
     825            6 :         RIALTO_CLIENT_LOG_WARN("NeedMediaData received in unexpected state '%s', ignoring request id %u",
     826              :                                toString(m_currentState), requestId);
     827            6 :         break;
     828              :     }
     829              :     }
     830              : }
     831              : 
     832          111 : void MediaPipeline::notifyApplicationState(ApplicationState state)
     833              : {
     834          111 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     835          111 :     std::lock_guard<std::mutex> lock{m_needDataRequestMapMutex};
     836          111 :     m_currentAppState = state;
     837          111 :     if (ApplicationState::RUNNING != state)
     838              :     {
     839              :         // If shared memory in use, wait for it to finish before returning
     840            4 :         m_needDataRequestMap.clear();
     841              :     }
     842          111 : }
     843              : 
     844            1 : void MediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo)
     845              : {
     846            1 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     847              : 
     848            1 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     849            1 :     if (client)
     850              :     {
     851            1 :         client->notifyQos(sourceId, qosInfo);
     852              :     }
     853              : }
     854              : 
     855            0 : void MediaPipeline::notifyBufferUnderflow(int32_t sourceId)
     856              : {
     857            0 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     858              : 
     859            0 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     860            0 :     if (client)
     861              :     {
     862            0 :         client->notifyBufferUnderflow(sourceId);
     863              :     }
     864              : }
     865              : 
     866            1 : void MediaPipeline::notifyPlaybackError(int32_t sourceId, PlaybackError error)
     867              : {
     868            1 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     869              : 
     870            1 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     871            1 :     if (client)
     872              :     {
     873            1 :         client->notifyPlaybackError(sourceId, error);
     874              :     }
     875              : }
     876              : 
     877            4 : void MediaPipeline::notifySourceFlushed(int32_t sourceId)
     878              : {
     879            4 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     880              :     {
     881            4 :         std::lock_guard<std::mutex> lock{m_flushMutex};
     882            4 :         m_attachedSources.setFlushing(sourceId, false);
     883              :     }
     884            4 :     std::shared_ptr<IMediaPipelineClient> client = m_mediaPipelineClient.lock();
     885            4 :     if (client)
     886              :     {
     887            4 :         client->notifySourceFlushed(sourceId);
     888              :     }
     889              : 
     890            4 :     State expected = State::END_OF_STREAM;
     891            4 :     m_currentState.compare_exchange_strong(expected, State::BUFFERING);
     892              : }
     893              : 
     894              : }; // namespace firebolt::rialto::client
        

Generated by: LCOV version 2.0-1