LCOV - code coverage report
Current view: top level - media/client/main/source - MediaPipeline.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.1 % 445 392
Test Date: 2026-07-31 13:30:47 Functions: 91.3 % 69 63

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

Generated by: LCOV version 2.0-1