LCOV - code coverage report
Current view: top level - media/client/ipc/source - MediaPipelineIpc.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 86.1 % 1064 916
Test Date: 2026-05-08 12:58:51 Functions: 90.5 % 74 67

            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              : #include "MediaPipelineIpc.h"
      20              : #include "RialtoClientLogging.h"
      21              : #include "RialtoCommonIpc.h"
      22              : #include "mediapipelinemodule.pb.h"
      23              : #include <IMediaPipeline.h>
      24              : #include <unordered_map>
      25              : 
      26              : namespace firebolt::rialto::client
      27              : {
      28              : std::weak_ptr<IMediaPipelineIpcFactory> MediaPipelineIpcFactory::m_factory;
      29              : 
      30            1 : std::shared_ptr<IMediaPipelineIpcFactory> IMediaPipelineIpcFactory::getFactory()
      31              : {
      32            1 :     std::shared_ptr<IMediaPipelineIpcFactory> factory = MediaPipelineIpcFactory::m_factory.lock();
      33              : 
      34            1 :     if (!factory)
      35              :     {
      36              :         try
      37              :         {
      38            1 :             factory = std::make_shared<MediaPipelineIpcFactory>();
      39              :         }
      40            0 :         catch (const std::exception &e)
      41              :         {
      42            0 :             RIALTO_CLIENT_LOG_ERROR("Failed to create the media player ipc factory, reason: %s", e.what());
      43              :         }
      44              : 
      45            1 :         MediaPipelineIpcFactory::m_factory = factory;
      46              :     }
      47              : 
      48            1 :     return factory;
      49              : }
      50              : 
      51            1 : std::unique_ptr<IMediaPipelineIpc> MediaPipelineIpcFactory::createMediaPipelineIpc(
      52              :     IMediaPipelineIpcClient *client, const VideoRequirements &videoRequirements, std::weak_ptr<IIpcClient> ipcClientParam)
      53              : {
      54            1 :     std::unique_ptr<IMediaPipelineIpc> mediaPipelineIpc;
      55              :     try
      56              :     {
      57            1 :         std::shared_ptr<IIpcClient> ipcClient = ipcClientParam.lock();
      58              :         mediaPipelineIpc =
      59            3 :             std::make_unique<MediaPipelineIpc>(client, videoRequirements,
      60            2 :                                                ipcClient ? *ipcClient : IIpcClientAccessor::instance().getIpcClient(),
      61            3 :                                                firebolt::rialto::common::IEventThreadFactory::createFactory());
      62            1 :     }
      63            0 :     catch (const std::exception &e)
      64              :     {
      65            0 :         RIALTO_CLIENT_LOG_ERROR("Failed to create the media player ipc, reason: %s", e.what());
      66              :     }
      67              : 
      68            1 :     return mediaPipelineIpc;
      69              : }
      70              : 
      71          182 : MediaPipelineIpc::MediaPipelineIpc(IMediaPipelineIpcClient *client, const VideoRequirements &videoRequirements,
      72              :                                    IIpcClient &ipcClient,
      73          182 :                                    const std::shared_ptr<common::IEventThreadFactory> &eventThreadFactory)
      74          182 :     : IpcModule(ipcClient), m_mediaPipelineIpcClient(client),
      75          364 :       m_eventThread(eventThreadFactory->createEventThread("rialto-media-player-events"))
      76              : {
      77          182 :     if (!attachChannel())
      78              :     {
      79            4 :         throw std::runtime_error("Failed attach to the ipc channel");
      80              :     }
      81              : 
      82              :     // create media player session
      83          178 :     if (!createSession(videoRequirements))
      84              :     {
      85            1 :         detachChannel();
      86            1 :         throw std::runtime_error("Could not create the media player session");
      87              :     }
      88          197 : }
      89              : 
      90          354 : MediaPipelineIpc::~MediaPipelineIpc()
      91              : {
      92              :     // destroy media player session
      93          177 :     destroySession();
      94              : 
      95              :     // detach the Ipc channel
      96          177 :     detachChannel();
      97              : 
      98              :     // destroy the thread processing async notifications
      99          177 :     m_eventThread.reset();
     100          354 : }
     101              : 
     102          252 : bool MediaPipelineIpc::createRpcStubs(const std::shared_ptr<ipc::IChannel> &ipcChannel)
     103              : {
     104          252 :     m_mediaPipelineStub = std::make_unique<::firebolt::rialto::MediaPipelineModule_Stub>(ipcChannel.get());
     105          252 :     if (!m_mediaPipelineStub)
     106              :     {
     107            0 :         return false;
     108              :     }
     109          252 :     return true;
     110              : }
     111              : 
     112          252 : bool MediaPipelineIpc::subscribeToEvents(const std::shared_ptr<ipc::IChannel> &ipcChannel)
     113              : {
     114          252 :     if (!ipcChannel)
     115              :     {
     116            0 :         return false;
     117              :     }
     118              : 
     119          504 :     int eventTag = ipcChannel->subscribe<firebolt::rialto::PlaybackStateChangeEvent>(
     120          252 :         [this](const std::shared_ptr<firebolt::rialto::PlaybackStateChangeEvent> &event)
     121          254 :         { m_eventThread->add(&MediaPipelineIpc::onPlaybackStateUpdated, this, event); });
     122          252 :     if (eventTag < 0)
     123            0 :         return false;
     124          252 :     m_eventTags.push_back(eventTag);
     125              : 
     126          504 :     eventTag = ipcChannel->subscribe<firebolt::rialto::PositionChangeEvent>(
     127          252 :         [this](const std::shared_ptr<firebolt::rialto::PositionChangeEvent> &event)
     128            0 :         { m_eventThread->add(&MediaPipelineIpc::onPositionUpdated, this, event); });
     129          252 :     if (eventTag < 0)
     130            1 :         return false;
     131          251 :     m_eventTags.push_back(eventTag);
     132              : 
     133          502 :     eventTag = ipcChannel->subscribe<firebolt::rialto::NetworkStateChangeEvent>(
     134          251 :         [this](const std::shared_ptr<firebolt::rialto::NetworkStateChangeEvent> &event)
     135            2 :         { m_eventThread->add(&MediaPipelineIpc::onNetworkStateUpdated, this, event); });
     136          251 :     if (eventTag < 0)
     137            0 :         return false;
     138          251 :     m_eventTags.push_back(eventTag);
     139              : 
     140          502 :     eventTag = ipcChannel->subscribe<firebolt::rialto::NeedMediaDataEvent>(
     141          251 :         [this](const std::shared_ptr<firebolt::rialto::NeedMediaDataEvent> &event)
     142            3 :         { m_eventThread->add(&MediaPipelineIpc::onNeedMediaData, this, event); });
     143          251 :     if (eventTag < 0)
     144            0 :         return false;
     145          251 :     m_eventTags.push_back(eventTag);
     146              : 
     147          502 :     eventTag = ipcChannel->subscribe<firebolt::rialto::QosEvent>(
     148          251 :         [this](const std::shared_ptr<firebolt::rialto::QosEvent> &event)
     149            2 :         { m_eventThread->add(&MediaPipelineIpc::onQos, this, event); });
     150          251 :     if (eventTag < 0)
     151            0 :         return false;
     152          251 :     m_eventTags.push_back(eventTag);
     153              : 
     154          502 :     eventTag = ipcChannel->subscribe<firebolt::rialto::BufferUnderflowEvent>(
     155          251 :         [this](const std::shared_ptr<firebolt::rialto::BufferUnderflowEvent> &event)
     156            0 :         { m_eventThread->add(&MediaPipelineIpc::onBufferUnderflow, this, event); });
     157          251 :     if (eventTag < 0)
     158            0 :         return false;
     159          251 :     m_eventTags.push_back(eventTag);
     160              : 
     161          502 :     eventTag = ipcChannel->subscribe<firebolt::rialto::PlaybackErrorEvent>(
     162          251 :         [this](const std::shared_ptr<firebolt::rialto::PlaybackErrorEvent> &event)
     163            2 :         { m_eventThread->add(&MediaPipelineIpc::onPlaybackError, this, event); });
     164          251 :     if (eventTag < 0)
     165            0 :         return false;
     166          251 :     m_eventTags.push_back(eventTag);
     167              : 
     168          502 :     eventTag = ipcChannel->subscribe<firebolt::rialto::SourceFlushedEvent>(
     169          251 :         [this](const std::shared_ptr<firebolt::rialto::SourceFlushedEvent> &event)
     170            2 :         { m_eventThread->add(&MediaPipelineIpc::onSourceFlushed, this, event); });
     171          251 :     if (eventTag < 0)
     172            0 :         return false;
     173          251 :     m_eventTags.push_back(eventTag);
     174              : 
     175          502 :     eventTag = ipcChannel->subscribe<firebolt::rialto::PlaybackInfoEvent>(
     176          251 :         [this](const std::shared_ptr<firebolt::rialto::PlaybackInfoEvent> &event)
     177            1 :         { m_eventThread->add(&MediaPipelineIpc::onPlaybackInfo, this, event); });
     178          251 :     if (eventTag < 0)
     179            0 :         return false;
     180          251 :     m_eventTags.push_back(eventTag);
     181              : 
     182          251 :     return true;
     183              : }
     184              : 
     185            4 : bool MediaPipelineIpc::load(MediaType type, const std::string &mimeType, const std::string &url, bool isLive)
     186              : {
     187            4 :     if (!reattachChannelIfRequired())
     188              :     {
     189            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     190            1 :         return false;
     191              :     }
     192              : 
     193            3 :     firebolt::rialto::LoadRequest request;
     194              : 
     195            3 :     request.set_session_id(m_sessionId);
     196            3 :     request.set_type(convertLoadRequestMediaType(type));
     197              :     request.set_mime_type(mimeType);
     198              :     request.set_url(url);
     199            3 :     request.set_is_live(isLive);
     200              : 
     201            3 :     firebolt::rialto::LoadResponse response;
     202            3 :     auto ipcController = m_ipc.createRpcController();
     203            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     204            3 :     m_mediaPipelineStub->load(ipcController.get(), &request, &response, blockingClosure.get());
     205              : 
     206              :     // wait for the call to complete
     207            3 :     blockingClosure->wait();
     208              : 
     209              :     // check the result
     210            3 :     if (ipcController->Failed())
     211              :     {
     212            1 :         RIALTO_CLIENT_LOG_ERROR("failed to load media due to '%s'", ipcController->ErrorText().c_str());
     213            1 :         return false;
     214              :     }
     215              : 
     216            2 :     return true;
     217            3 : }
     218              : 
     219           14 : bool MediaPipelineIpc::attachSource(const std::unique_ptr<IMediaPipeline::MediaSource> &source, int32_t &sourceId)
     220              : {
     221           14 :     if (!reattachChannelIfRequired())
     222              :     {
     223            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     224            1 :         return false;
     225              :     }
     226              : 
     227           13 :     firebolt::rialto::AttachSourceRequest request;
     228              : 
     229           13 :     request.set_session_id(m_sessionId);
     230           13 :     request.set_switch_source(false);
     231           13 :     if (!buildAttachSourceRequest(request, source))
     232              :     {
     233            5 :         RIALTO_CLIENT_LOG_ERROR("Failed to parse source");
     234            5 :         return false;
     235              :     }
     236              : 
     237            8 :     firebolt::rialto::AttachSourceResponse response;
     238            8 :     auto ipcController = m_ipc.createRpcController();
     239            8 :     auto blockingClosure = m_ipc.createBlockingClosure();
     240            8 :     m_mediaPipelineStub->attachSource(ipcController.get(), &request, &response, blockingClosure.get());
     241              : 
     242              :     // wait for the call to complete
     243            8 :     blockingClosure->wait();
     244              : 
     245              :     // check the result
     246            8 :     if (ipcController->Failed())
     247              :     {
     248            1 :         RIALTO_CLIENT_LOG_ERROR("failed to attach source due to '%s'", ipcController->ErrorText().c_str());
     249            1 :         return false;
     250              :     }
     251              : 
     252            7 :     sourceId = response.source_id();
     253              : 
     254            7 :     return true;
     255           13 : }
     256              : 
     257            4 : bool MediaPipelineIpc::removeSource(int32_t sourceId)
     258              : {
     259            4 :     if (!reattachChannelIfRequired())
     260              :     {
     261            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     262            1 :         return false;
     263              :     }
     264              : 
     265            3 :     firebolt::rialto::RemoveSourceRequest request;
     266              : 
     267            3 :     request.set_session_id(m_sessionId);
     268            3 :     request.set_source_id(sourceId);
     269              : 
     270            3 :     firebolt::rialto::RemoveSourceResponse response;
     271            3 :     auto ipcController = m_ipc.createRpcController();
     272            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     273            3 :     m_mediaPipelineStub->removeSource(ipcController.get(), &request, &response, blockingClosure.get());
     274              : 
     275              :     // wait for the call to complete
     276            3 :     blockingClosure->wait();
     277              : 
     278              :     // check the result
     279            3 :     if (ipcController->Failed())
     280              :     {
     281            1 :         RIALTO_CLIENT_LOG_ERROR("failed to remove source due to '%s'", ipcController->ErrorText().c_str());
     282            1 :         return false;
     283              :     }
     284              : 
     285            2 :     return true;
     286            3 : }
     287              : 
     288            4 : bool MediaPipelineIpc::allSourcesAttached()
     289              : {
     290            4 :     if (!reattachChannelIfRequired())
     291              :     {
     292            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     293            1 :         return false;
     294              :     }
     295              : 
     296            3 :     firebolt::rialto::AllSourcesAttachedRequest request;
     297            3 :     request.set_session_id(m_sessionId);
     298              : 
     299            3 :     firebolt::rialto::AllSourcesAttachedResponse response;
     300            3 :     auto ipcController = m_ipc.createRpcController();
     301            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     302            3 :     m_mediaPipelineStub->allSourcesAttached(ipcController.get(), &request, &response, blockingClosure.get());
     303              : 
     304              :     // wait for the call to complete
     305            3 :     blockingClosure->wait();
     306              : 
     307              :     // check the result
     308            3 :     if (ipcController->Failed())
     309              :     {
     310            1 :         RIALTO_CLIENT_LOG_ERROR("failed to notify about all sources attached due to '%s'",
     311              :                                 ipcController->ErrorText().c_str());
     312            1 :         return false;
     313              :     }
     314              : 
     315            2 :     return true;
     316            3 : }
     317              : 
     318            4 : bool MediaPipelineIpc::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
     319              : {
     320            4 :     if (!reattachChannelIfRequired())
     321              :     {
     322            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     323            1 :         return false;
     324              :     }
     325              : 
     326            3 :     firebolt::rialto::SetVideoWindowRequest request;
     327              : 
     328            3 :     request.set_session_id(m_sessionId);
     329            3 :     request.set_x(x);
     330            3 :     request.set_y(y);
     331            3 :     request.set_width(width);
     332            3 :     request.set_height(height);
     333              : 
     334            3 :     firebolt::rialto::SetVideoWindowResponse response;
     335            3 :     auto ipcController = m_ipc.createRpcController();
     336            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     337            3 :     m_mediaPipelineStub->setVideoWindow(ipcController.get(), &request, &response, blockingClosure.get());
     338              : 
     339              :     // wait for the call to complete
     340            3 :     blockingClosure->wait();
     341              : 
     342              :     // check the result
     343            3 :     if (ipcController->Failed())
     344              :     {
     345            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set the video window due to '%s'", ipcController->ErrorText().c_str());
     346            1 :         return false;
     347              :     }
     348              : 
     349            2 :     return true;
     350            3 : }
     351              : 
     352            4 : bool MediaPipelineIpc::play(bool &async)
     353              : {
     354            4 :     if (!reattachChannelIfRequired())
     355              :     {
     356            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     357            1 :         return false;
     358              :     }
     359              : 
     360            3 :     firebolt::rialto::PlayRequest request;
     361              : 
     362            3 :     request.set_session_id(m_sessionId);
     363              : 
     364            3 :     firebolt::rialto::PlayResponse response;
     365            3 :     auto ipcController = m_ipc.createRpcController();
     366            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     367            3 :     m_mediaPipelineStub->play(ipcController.get(), &request, &response, blockingClosure.get());
     368              : 
     369              :     // wait for the call to complete
     370            3 :     blockingClosure->wait();
     371              : 
     372              :     // check the result
     373            3 :     if (ipcController->Failed())
     374              :     {
     375            1 :         RIALTO_CLIENT_LOG_ERROR("failed to play due to '%s'", ipcController->ErrorText().c_str());
     376            1 :         return false;
     377              :     }
     378              : 
     379            2 :     async = response.async();
     380              : 
     381            2 :     return true;
     382            3 : }
     383              : 
     384            4 : bool MediaPipelineIpc::pause()
     385              : {
     386            4 :     if (!reattachChannelIfRequired())
     387              :     {
     388            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     389            1 :         return false;
     390              :     }
     391              : 
     392            3 :     firebolt::rialto::PauseRequest request;
     393              : 
     394            3 :     request.set_session_id(m_sessionId);
     395              : 
     396            3 :     firebolt::rialto::PauseResponse response;
     397            3 :     auto ipcController = m_ipc.createRpcController();
     398            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     399            3 :     m_mediaPipelineStub->pause(ipcController.get(), &request, &response, blockingClosure.get());
     400              : 
     401              :     // wait for the call to complete
     402            3 :     blockingClosure->wait();
     403              : 
     404              :     // check the result
     405            3 :     if (ipcController->Failed())
     406              :     {
     407            1 :         RIALTO_CLIENT_LOG_ERROR("failed to pause due to '%s'", ipcController->ErrorText().c_str());
     408            1 :         return false;
     409              :     }
     410              : 
     411            2 :     return true;
     412            3 : }
     413              : 
     414            0 : bool MediaPipelineIpc::stop()
     415              : {
     416            0 :     if (!reattachChannelIfRequired())
     417              :     {
     418            0 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     419            0 :         return false;
     420              :     }
     421              : 
     422            0 :     firebolt::rialto::StopRequest request;
     423              : 
     424            0 :     request.set_session_id(m_sessionId);
     425              : 
     426            0 :     firebolt::rialto::StopResponse response;
     427            0 :     auto ipcController = m_ipc.createRpcController();
     428            0 :     auto blockingClosure = m_ipc.createBlockingClosure();
     429            0 :     m_mediaPipelineStub->stop(ipcController.get(), &request, &response, blockingClosure.get());
     430              : 
     431              :     // wait for the call to complete
     432            0 :     blockingClosure->wait();
     433              : 
     434              :     // check the result
     435            0 :     if (ipcController->Failed())
     436              :     {
     437            0 :         RIALTO_CLIENT_LOG_ERROR("failed to stop due to '%s'", ipcController->ErrorText().c_str());
     438            0 :         return false;
     439              :     }
     440              : 
     441            0 :     return true;
     442              : }
     443              : 
     444            4 : bool MediaPipelineIpc::haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t requestId)
     445              : {
     446            4 :     if (!reattachChannelIfRequired())
     447              :     {
     448            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     449            1 :         return false;
     450              :     }
     451              : 
     452            3 :     firebolt::rialto::HaveDataRequest request;
     453              : 
     454            3 :     request.set_session_id(m_sessionId);
     455            3 :     request.set_status(convertHaveDataRequestMediaSourceStatus(status));
     456            3 :     request.set_num_frames(numFrames);
     457            3 :     request.set_request_id(requestId);
     458              : 
     459            3 :     firebolt::rialto::HaveDataResponse response;
     460            3 :     auto ipcController = m_ipc.createRpcController();
     461            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     462            3 :     m_mediaPipelineStub->haveData(ipcController.get(), &request, &response, blockingClosure.get());
     463              : 
     464              :     // wait for the call to complete
     465            3 :     blockingClosure->wait();
     466              : 
     467              :     // check the result
     468            3 :     if (ipcController->Failed())
     469              :     {
     470            1 :         RIALTO_CLIENT_LOG_ERROR("failed to stop due to '%s'", ipcController->ErrorText().c_str());
     471            1 :         return false;
     472              :     }
     473              : 
     474            2 :     return true;
     475            3 : }
     476              : 
     477            4 : bool MediaPipelineIpc::setPosition(int64_t position)
     478              : {
     479            4 :     if (!reattachChannelIfRequired())
     480              :     {
     481            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     482            1 :         return false;
     483              :     }
     484              : 
     485            3 :     firebolt::rialto::SetPositionRequest request;
     486              : 
     487            3 :     request.set_session_id(m_sessionId);
     488            3 :     request.set_position(position);
     489              : 
     490            3 :     firebolt::rialto::SetPositionResponse response;
     491            3 :     auto ipcController = m_ipc.createRpcController();
     492            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     493            3 :     m_mediaPipelineStub->setPosition(ipcController.get(), &request, &response, blockingClosure.get());
     494              : 
     495              :     // wait for the call to complete
     496            3 :     blockingClosure->wait();
     497              : 
     498              :     // check the result
     499            3 :     if (ipcController->Failed())
     500              :     {
     501            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set position due to '%s'", ipcController->ErrorText().c_str());
     502            1 :         return false;
     503              :     }
     504              : 
     505            2 :     return true;
     506            3 : }
     507              : 
     508            4 : bool MediaPipelineIpc::getPosition(int64_t &position)
     509              : {
     510            4 :     if (!reattachChannelIfRequired())
     511              :     {
     512            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     513            1 :         return false;
     514              :     }
     515              : 
     516            3 :     firebolt::rialto::GetPositionRequest request;
     517              : 
     518            3 :     request.set_session_id(m_sessionId);
     519              : 
     520            3 :     firebolt::rialto::GetPositionResponse response;
     521            3 :     auto ipcController = m_ipc.createRpcController();
     522            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     523            3 :     m_mediaPipelineStub->getPosition(ipcController.get(), &request, &response, blockingClosure.get());
     524              : 
     525              :     // wait for the call to complete
     526            3 :     blockingClosure->wait();
     527              : 
     528              :     // check the result
     529            3 :     if (ipcController->Failed())
     530              :     {
     531            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get position due to '%s'", ipcController->ErrorText().c_str());
     532            1 :         return false;
     533              :     }
     534              : 
     535            2 :     position = response.position();
     536            2 :     return true;
     537            3 : }
     538              : 
     539            4 : bool MediaPipelineIpc::getDuration(int64_t &duration)
     540              : {
     541            4 :     if (!reattachChannelIfRequired())
     542              :     {
     543            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     544            1 :         return false;
     545              :     }
     546              : 
     547            3 :     firebolt::rialto::GetDurationRequest request;
     548              : 
     549            3 :     request.set_session_id(m_sessionId);
     550              : 
     551            3 :     firebolt::rialto::GetDurationResponse response;
     552            3 :     auto ipcController = m_ipc.createRpcController();
     553            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     554            3 :     m_mediaPipelineStub->getDuration(ipcController.get(), &request, &response, blockingClosure.get());
     555              : 
     556              :     // wait for the call to complete
     557            3 :     blockingClosure->wait();
     558              : 
     559              :     // check the result
     560            3 :     if (ipcController->Failed())
     561              :     {
     562            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get duration due to '%s'", ipcController->ErrorText().c_str());
     563            1 :         return false;
     564              :     }
     565              : 
     566            2 :     duration = response.duration();
     567            2 :     return true;
     568            3 : }
     569              : 
     570            4 : bool MediaPipelineIpc::setImmediateOutput(int32_t sourceId, bool immediateOutput)
     571              : {
     572            4 :     if (!reattachChannelIfRequired())
     573              :     {
     574            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     575            1 :         return false;
     576              :     }
     577              : 
     578            3 :     firebolt::rialto::SetImmediateOutputRequest request;
     579              : 
     580            3 :     request.set_session_id(m_sessionId);
     581            3 :     request.set_source_id(sourceId);
     582            3 :     request.set_immediate_output(immediateOutput);
     583              : 
     584            3 :     firebolt::rialto::SetImmediateOutputResponse response;
     585            3 :     auto ipcController = m_ipc.createRpcController();
     586            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     587            3 :     m_mediaPipelineStub->setImmediateOutput(ipcController.get(), &request, &response, blockingClosure.get());
     588              : 
     589              :     // wait for the call to complete
     590            3 :     blockingClosure->wait();
     591              : 
     592              :     // check the result
     593            3 :     if (ipcController->Failed())
     594              :     {
     595            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set immediate-output due to '%s'", ipcController->ErrorText().c_str());
     596            1 :         return false;
     597              :     }
     598              : 
     599            2 :     return true;
     600            3 : }
     601              : 
     602            4 : bool MediaPipelineIpc::getImmediateOutput(int32_t sourceId, bool &immediateOutput)
     603              : {
     604            4 :     if (!reattachChannelIfRequired())
     605              :     {
     606            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     607            1 :         return false;
     608              :     }
     609              : 
     610            3 :     firebolt::rialto::GetImmediateOutputRequest request;
     611              : 
     612            3 :     request.set_session_id(m_sessionId);
     613            3 :     request.set_source_id(sourceId);
     614              : 
     615            3 :     firebolt::rialto::GetImmediateOutputResponse response;
     616            3 :     auto ipcController = m_ipc.createRpcController();
     617            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     618            3 :     m_mediaPipelineStub->getImmediateOutput(ipcController.get(), &request, &response, blockingClosure.get());
     619              : 
     620              :     // wait for the call to complete
     621            3 :     blockingClosure->wait();
     622              : 
     623              :     // check the result
     624            3 :     if (ipcController->Failed())
     625              :     {
     626            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get immediate-output due to '%s'", ipcController->ErrorText().c_str());
     627            1 :         return false;
     628              :     }
     629              :     else
     630              :     {
     631            2 :         immediateOutput = response.immediate_output();
     632              :     }
     633              : 
     634            2 :     return true;
     635            3 : }
     636              : 
     637            4 : bool MediaPipelineIpc::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames)
     638              : {
     639            4 :     if (!reattachChannelIfRequired())
     640              :     {
     641            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     642            1 :         return false;
     643              :     }
     644              : 
     645            3 :     firebolt::rialto::GetStatsRequest request;
     646              : 
     647            3 :     request.set_session_id(m_sessionId);
     648            3 :     request.set_source_id(sourceId);
     649              : 
     650            3 :     firebolt::rialto::GetStatsResponse response;
     651            3 :     auto ipcController = m_ipc.createRpcController();
     652            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     653            3 :     m_mediaPipelineStub->getStats(ipcController.get(), &request, &response, blockingClosure.get());
     654              : 
     655              :     // wait for the call to complete
     656            3 :     blockingClosure->wait();
     657              : 
     658              :     // check the result
     659            3 :     if (ipcController->Failed())
     660              :     {
     661            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get stats due to '%s'", ipcController->ErrorText().c_str());
     662            1 :         return false;
     663              :     }
     664              : 
     665            2 :     renderedFrames = response.rendered_frames();
     666            2 :     droppedFrames = response.dropped_frames();
     667            2 :     return true;
     668            3 : }
     669              : 
     670            4 : bool MediaPipelineIpc::setPlaybackRate(double rate)
     671              : {
     672            4 :     if (!reattachChannelIfRequired())
     673              :     {
     674            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     675            1 :         return false;
     676              :     }
     677              : 
     678            3 :     firebolt::rialto::SetPlaybackRateRequest request;
     679              : 
     680            3 :     request.set_session_id(m_sessionId);
     681            3 :     request.set_rate(rate);
     682              : 
     683            3 :     firebolt::rialto::SetPlaybackRateResponse response;
     684            3 :     auto ipcController = m_ipc.createRpcController();
     685            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     686            3 :     m_mediaPipelineStub->setPlaybackRate(ipcController.get(), &request, &response, blockingClosure.get());
     687              : 
     688              :     // wait for the call to complete
     689            3 :     blockingClosure->wait();
     690              : 
     691              :     // check the result
     692            3 :     if (ipcController->Failed())
     693              :     {
     694            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set playback rate due to '%s'", ipcController->ErrorText().c_str());
     695            1 :         return false;
     696              :     }
     697              : 
     698            2 :     return true;
     699            3 : }
     700              : 
     701            4 : bool MediaPipelineIpc::renderFrame()
     702              : {
     703            4 :     if (!reattachChannelIfRequired())
     704              :     {
     705            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     706            1 :         return false;
     707              :     }
     708              : 
     709            3 :     firebolt::rialto::RenderFrameRequest request;
     710            3 :     request.set_session_id(m_sessionId);
     711              : 
     712            3 :     firebolt::rialto::RenderFrameResponse response;
     713            3 :     auto ipcController = m_ipc.createRpcController();
     714            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     715            3 :     m_mediaPipelineStub->renderFrame(ipcController.get(), &request, &response, blockingClosure.get());
     716              : 
     717              :     // wait for the call to complete
     718            3 :     blockingClosure->wait();
     719              : 
     720              :     // check the result
     721            3 :     if (ipcController->Failed())
     722              :     {
     723            1 :         RIALTO_CLIENT_LOG_ERROR("failed to render frame due to '%s'", ipcController->ErrorText().c_str());
     724            1 :         return false;
     725              :     }
     726              : 
     727            2 :     return true;
     728            3 : }
     729              : 
     730            4 : bool MediaPipelineIpc::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType)
     731              : {
     732            4 :     if (!reattachChannelIfRequired())
     733              :     {
     734            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     735            1 :         return false;
     736              :     }
     737              : 
     738            3 :     firebolt::rialto::SetVolumeRequest request;
     739              : 
     740            3 :     request.set_session_id(m_sessionId);
     741            3 :     request.set_volume(targetVolume);
     742            3 :     request.set_volume_duration(volumeDuration);
     743            3 :     request.set_ease_type(convertEaseType(easeType));
     744              : 
     745            3 :     firebolt::rialto::SetVolumeResponse response;
     746            3 :     auto ipcController = m_ipc.createRpcController();
     747            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     748            3 :     m_mediaPipelineStub->setVolume(ipcController.get(), &request, &response, blockingClosure.get());
     749              : 
     750              :     // wait for the call to complete
     751            3 :     blockingClosure->wait();
     752              : 
     753              :     // check the result
     754            3 :     if (ipcController->Failed())
     755              :     {
     756            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set volume due to '%s'", ipcController->ErrorText().c_str());
     757            1 :         return false;
     758              :     }
     759              : 
     760            2 :     return true;
     761            3 : }
     762              : 
     763            4 : bool MediaPipelineIpc::getVolume(double &volume)
     764              : {
     765            4 :     if (!reattachChannelIfRequired())
     766              :     {
     767            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     768            1 :         return false;
     769              :     }
     770              : 
     771            3 :     firebolt::rialto::GetVolumeRequest request;
     772              : 
     773            3 :     request.set_session_id(m_sessionId);
     774              : 
     775            3 :     firebolt::rialto::GetVolumeResponse response;
     776            3 :     auto ipcController = m_ipc.createRpcController();
     777            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     778            3 :     m_mediaPipelineStub->getVolume(ipcController.get(), &request, &response, blockingClosure.get());
     779              : 
     780              :     // wait for the call to complete
     781            3 :     blockingClosure->wait();
     782              : 
     783              :     // check the result
     784            3 :     if (ipcController->Failed())
     785              :     {
     786            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get volume due to '%s'", ipcController->ErrorText().c_str());
     787            1 :         return false;
     788              :     }
     789            2 :     volume = response.volume();
     790              : 
     791            2 :     return true;
     792            3 : }
     793              : 
     794            4 : bool MediaPipelineIpc::setMute(int32_t sourceId, bool mute)
     795              : {
     796            4 :     if (!reattachChannelIfRequired())
     797              :     {
     798            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     799            1 :         return false;
     800              :     }
     801              : 
     802            3 :     firebolt::rialto::SetMuteRequest request;
     803              : 
     804            3 :     request.set_session_id(m_sessionId);
     805            3 :     request.set_mute(mute);
     806            3 :     request.set_source_id(sourceId);
     807              : 
     808            3 :     firebolt::rialto::SetMuteResponse response;
     809            3 :     auto ipcController = m_ipc.createRpcController();
     810            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     811            3 :     m_mediaPipelineStub->setMute(ipcController.get(), &request, &response, blockingClosure.get());
     812              : 
     813              :     // waiting for call to complete
     814            3 :     blockingClosure->wait();
     815              : 
     816              :     // check the result
     817            3 :     if (ipcController->Failed())
     818              :     {
     819            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set mute due to '%s'", ipcController->ErrorText().c_str());
     820            1 :         return false;
     821              :     }
     822              : 
     823            2 :     return true;
     824            3 : }
     825              : 
     826            4 : bool MediaPipelineIpc::getMute(std::int32_t sourceId, bool &mute)
     827              : {
     828            4 :     if (!reattachChannelIfRequired())
     829              :     {
     830            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     831            1 :         return false;
     832              :     }
     833              : 
     834            3 :     firebolt::rialto::GetMuteRequest request;
     835              : 
     836            3 :     request.set_session_id(m_sessionId);
     837            3 :     request.set_source_id(sourceId);
     838              : 
     839            3 :     firebolt::rialto::GetMuteResponse response;
     840            3 :     auto ipcController = m_ipc.createRpcController();
     841            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     842            3 :     m_mediaPipelineStub->getMute(ipcController.get(), &request, &response, blockingClosure.get());
     843              : 
     844              :     // wait for the call to complete
     845            3 :     blockingClosure->wait();
     846              : 
     847              :     // check the result
     848            3 :     if (ipcController->Failed())
     849              :     {
     850            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get mute due to '%s'", ipcController->ErrorText().c_str());
     851            1 :         return false;
     852              :     }
     853              : 
     854            2 :     mute = response.mute();
     855              : 
     856            2 :     return true;
     857            3 : }
     858              : 
     859            4 : bool MediaPipelineIpc::setTextTrackIdentifier(const std::string &textTrackIdentifier)
     860              : {
     861            4 :     if (!reattachChannelIfRequired())
     862              :     {
     863            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     864            1 :         return false;
     865              :     }
     866              : 
     867            3 :     firebolt::rialto::SetTextTrackIdentifierRequest request;
     868              : 
     869            3 :     request.set_session_id(m_sessionId);
     870              :     request.set_text_track_identifier(textTrackIdentifier);
     871              : 
     872            3 :     firebolt::rialto::SetTextTrackIdentifierResponse response;
     873            3 :     auto ipcController = m_ipc.createRpcController();
     874            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     875            3 :     m_mediaPipelineStub->setTextTrackIdentifier(ipcController.get(), &request, &response, blockingClosure.get());
     876              : 
     877              :     // waiting for call to complete
     878            3 :     blockingClosure->wait();
     879              : 
     880              :     // check the result
     881            3 :     if (ipcController->Failed())
     882              :     {
     883            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set text track identifier due to '%s'", ipcController->ErrorText().c_str());
     884            1 :         return false;
     885              :     }
     886              : 
     887            2 :     return true;
     888            3 : }
     889              : 
     890            4 : bool MediaPipelineIpc::getTextTrackIdentifier(std::string &textTrackIdentifier)
     891              : {
     892            4 :     if (!reattachChannelIfRequired())
     893              :     {
     894            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     895            1 :         return false;
     896              :     }
     897              : 
     898            3 :     firebolt::rialto::GetTextTrackIdentifierRequest request;
     899              : 
     900            3 :     request.set_session_id(m_sessionId);
     901              : 
     902            3 :     firebolt::rialto::GetTextTrackIdentifierResponse response;
     903            3 :     auto ipcController = m_ipc.createRpcController();
     904            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     905            3 :     m_mediaPipelineStub->getTextTrackIdentifier(ipcController.get(), &request, &response, blockingClosure.get());
     906              : 
     907              :     // wait for the call to complete
     908            3 :     blockingClosure->wait();
     909              : 
     910              :     // check the result
     911            3 :     if (ipcController->Failed())
     912              :     {
     913            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get mute due to '%s'", ipcController->ErrorText().c_str());
     914            1 :         return false;
     915              :     }
     916              : 
     917            2 :     textTrackIdentifier = response.text_track_identifier();
     918              : 
     919            2 :     return true;
     920            3 : }
     921              : 
     922            4 : bool MediaPipelineIpc::setLowLatency(bool lowLatency)
     923              : {
     924            4 :     if (!reattachChannelIfRequired())
     925              :     {
     926            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     927            1 :         return false;
     928              :     }
     929              : 
     930            3 :     firebolt::rialto::SetLowLatencyRequest request;
     931              : 
     932            3 :     request.set_session_id(m_sessionId);
     933            3 :     request.set_low_latency(lowLatency);
     934              : 
     935            3 :     firebolt::rialto::SetLowLatencyResponse response;
     936            3 :     auto ipcController = m_ipc.createRpcController();
     937            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     938            3 :     m_mediaPipelineStub->setLowLatency(ipcController.get(), &request, &response, blockingClosure.get());
     939              :     // waiting for call to complete
     940            3 :     blockingClosure->wait();
     941              : 
     942              :     // check the result
     943            3 :     if (ipcController->Failed())
     944              :     {
     945            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set low-latency due to '%s'", ipcController->ErrorText().c_str());
     946            1 :         return false;
     947              :     }
     948              : 
     949            2 :     return true;
     950            3 : }
     951              : 
     952            4 : bool MediaPipelineIpc::setSync(bool sync)
     953              : {
     954            4 :     if (!reattachChannelIfRequired())
     955              :     {
     956            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     957            1 :         return false;
     958              :     }
     959              : 
     960            3 :     firebolt::rialto::SetSyncRequest request;
     961              : 
     962            3 :     request.set_session_id(m_sessionId);
     963            3 :     request.set_sync(sync);
     964              : 
     965            3 :     firebolt::rialto::SetSyncResponse response;
     966            3 :     auto ipcController = m_ipc.createRpcController();
     967            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     968            3 :     m_mediaPipelineStub->setSync(ipcController.get(), &request, &response, blockingClosure.get());
     969              : 
     970              :     // waiting for call to complete
     971            3 :     blockingClosure->wait();
     972              : 
     973              :     // check the result
     974            3 :     if (ipcController->Failed())
     975              :     {
     976            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set sync due to '%s'", ipcController->ErrorText().c_str());
     977            1 :         return false;
     978              :     }
     979              : 
     980            2 :     return true;
     981            3 : }
     982              : 
     983            4 : bool MediaPipelineIpc::getSync(bool &sync)
     984              : {
     985            4 :     if (!reattachChannelIfRequired())
     986              :     {
     987            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
     988            1 :         return false;
     989              :     }
     990              : 
     991            3 :     firebolt::rialto::GetSyncRequest request;
     992              : 
     993            3 :     request.set_session_id(m_sessionId);
     994              : 
     995            3 :     firebolt::rialto::GetSyncResponse response;
     996            3 :     auto ipcController = m_ipc.createRpcController();
     997            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
     998            3 :     m_mediaPipelineStub->getSync(ipcController.get(), &request, &response, blockingClosure.get());
     999              : 
    1000              :     // wait for the call to complete
    1001            3 :     blockingClosure->wait();
    1002              : 
    1003              :     // check the result
    1004            3 :     if (ipcController->Failed())
    1005              :     {
    1006            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get sync due to '%s'", ipcController->ErrorText().c_str());
    1007            1 :         return false;
    1008              :     }
    1009              : 
    1010            2 :     sync = response.sync();
    1011              : 
    1012            2 :     return true;
    1013            3 : }
    1014              : 
    1015            4 : bool MediaPipelineIpc::setSyncOff(bool syncOff)
    1016              : {
    1017            4 :     if (!reattachChannelIfRequired())
    1018              :     {
    1019            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1020            1 :         return false;
    1021              :     }
    1022              : 
    1023            3 :     firebolt::rialto::SetSyncOffRequest request;
    1024              : 
    1025            3 :     request.set_session_id(m_sessionId);
    1026            3 :     request.set_sync_off(syncOff);
    1027              : 
    1028            3 :     firebolt::rialto::SetSyncOffResponse response;
    1029            3 :     auto ipcController = m_ipc.createRpcController();
    1030            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1031            3 :     m_mediaPipelineStub->setSyncOff(ipcController.get(), &request, &response, blockingClosure.get());
    1032              : 
    1033              :     // waiting for call to complete
    1034            3 :     blockingClosure->wait();
    1035              : 
    1036              :     // check the result
    1037            3 :     if (ipcController->Failed())
    1038              :     {
    1039            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set sync-off due to '%s'", ipcController->ErrorText().c_str());
    1040            1 :         return false;
    1041              :     }
    1042              : 
    1043            2 :     return true;
    1044            3 : }
    1045              : 
    1046            4 : bool MediaPipelineIpc::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode)
    1047              : {
    1048            4 :     if (!reattachChannelIfRequired())
    1049              :     {
    1050            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1051            1 :         return false;
    1052              :     }
    1053              : 
    1054            3 :     firebolt::rialto::SetStreamSyncModeRequest request;
    1055              : 
    1056            3 :     request.set_session_id(m_sessionId);
    1057            3 :     request.set_source_id(sourceId);
    1058            3 :     request.set_stream_sync_mode(streamSyncMode);
    1059              : 
    1060            3 :     firebolt::rialto::SetStreamSyncModeResponse response;
    1061            3 :     auto ipcController = m_ipc.createRpcController();
    1062            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1063            3 :     m_mediaPipelineStub->setStreamSyncMode(ipcController.get(), &request, &response, blockingClosure.get());
    1064              : 
    1065              :     // waiting for call to complete
    1066            3 :     blockingClosure->wait();
    1067              : 
    1068              :     // check the result
    1069            3 :     if (ipcController->Failed())
    1070              :     {
    1071            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set stream-sync-mode due to '%s'", ipcController->ErrorText().c_str());
    1072            1 :         return false;
    1073              :     }
    1074              : 
    1075            2 :     return true;
    1076            3 : }
    1077              : 
    1078            4 : bool MediaPipelineIpc::getStreamSyncMode(int32_t &streamSyncMode)
    1079              : {
    1080            4 :     if (!reattachChannelIfRequired())
    1081              :     {
    1082            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1083            1 :         return false;
    1084              :     }
    1085              : 
    1086            3 :     firebolt::rialto::GetStreamSyncModeRequest request;
    1087              : 
    1088            3 :     request.set_session_id(m_sessionId);
    1089              : 
    1090            3 :     firebolt::rialto::GetStreamSyncModeResponse response;
    1091            3 :     auto ipcController = m_ipc.createRpcController();
    1092            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1093            3 :     m_mediaPipelineStub->getStreamSyncMode(ipcController.get(), &request, &response, blockingClosure.get());
    1094              : 
    1095              :     // wait for the call to complete
    1096            3 :     blockingClosure->wait();
    1097              : 
    1098              :     // check the result
    1099            3 :     if (ipcController->Failed())
    1100              :     {
    1101            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get stream-sync-mode due to '%s'", ipcController->ErrorText().c_str());
    1102            1 :         return false;
    1103              :     }
    1104              : 
    1105            2 :     streamSyncMode = response.stream_sync_mode();
    1106              : 
    1107            2 :     return true;
    1108            3 : }
    1109              : 
    1110            4 : bool MediaPipelineIpc::flush(int32_t sourceId, bool resetTime, bool &async)
    1111              : {
    1112            4 :     if (!reattachChannelIfRequired())
    1113              :     {
    1114            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1115            1 :         return false;
    1116              :     }
    1117              : 
    1118            3 :     firebolt::rialto::FlushRequest request;
    1119              : 
    1120            3 :     request.set_session_id(m_sessionId);
    1121            3 :     request.set_source_id(sourceId);
    1122            3 :     request.set_reset_time(resetTime);
    1123              : 
    1124            3 :     firebolt::rialto::FlushResponse response;
    1125            3 :     auto ipcController = m_ipc.createRpcController();
    1126            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1127            3 :     m_mediaPipelineStub->flush(ipcController.get(), &request, &response, blockingClosure.get());
    1128              : 
    1129              :     // wait for the call to complete
    1130            3 :     blockingClosure->wait();
    1131              : 
    1132              :     // check the result
    1133            3 :     if (ipcController->Failed())
    1134              :     {
    1135            1 :         RIALTO_CLIENT_LOG_ERROR("failed to flush due to '%s'", ipcController->ErrorText().c_str());
    1136            1 :         return false;
    1137              :     }
    1138              : 
    1139              :     // Async is true by default
    1140            2 :     async = response.has_async() ? response.async() : true;
    1141              : 
    1142            2 :     return true;
    1143            3 : }
    1144              : 
    1145            4 : bool MediaPipelineIpc::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate,
    1146              :                                          uint64_t stopPosition)
    1147              : {
    1148            4 :     if (!reattachChannelIfRequired())
    1149              :     {
    1150            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1151            1 :         return false;
    1152              :     }
    1153              : 
    1154            3 :     firebolt::rialto::SetSourcePositionRequest request;
    1155              : 
    1156            3 :     request.set_session_id(m_sessionId);
    1157            3 :     request.set_source_id(sourceId);
    1158            3 :     request.set_position(position);
    1159            3 :     request.set_reset_time(resetTime);
    1160            3 :     request.set_applied_rate(appliedRate);
    1161            3 :     request.set_stop_position(stopPosition);
    1162              : 
    1163            3 :     firebolt::rialto::SetSourcePositionResponse response;
    1164            3 :     auto ipcController = m_ipc.createRpcController();
    1165            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1166            3 :     m_mediaPipelineStub->setSourcePosition(ipcController.get(), &request, &response, blockingClosure.get());
    1167              : 
    1168              :     // wait for the call to complete
    1169            3 :     blockingClosure->wait();
    1170              : 
    1171              :     // check the result
    1172            3 :     if (ipcController->Failed())
    1173              :     {
    1174            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set source position due to '%s'", ipcController->ErrorText().c_str());
    1175            1 :         return false;
    1176              :     }
    1177              : 
    1178            2 :     return true;
    1179            3 : }
    1180              : 
    1181            3 : bool MediaPipelineIpc::setSubtitleOffset(int32_t sourceId, int64_t position)
    1182              : {
    1183            3 :     if (!reattachChannelIfRequired())
    1184              :     {
    1185            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1186            1 :         return false;
    1187              :     }
    1188              : 
    1189            2 :     firebolt::rialto::SetSubtitleOffsetRequest request;
    1190              : 
    1191            2 :     request.set_session_id(m_sessionId);
    1192            2 :     request.set_source_id(sourceId);
    1193            2 :     request.set_position(position);
    1194              : 
    1195            2 :     firebolt::rialto::SetSubtitleOffsetResponse response;
    1196            2 :     auto ipcController = m_ipc.createRpcController();
    1197            2 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1198            2 :     m_mediaPipelineStub->setSubtitleOffset(ipcController.get(), &request, &response, blockingClosure.get());
    1199              : 
    1200              :     // wait for the call to complete
    1201            2 :     blockingClosure->wait();
    1202              : 
    1203              :     // check the result
    1204            2 :     if (ipcController->Failed())
    1205              :     {
    1206            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set subtitle offset due to '%s'", ipcController->ErrorText().c_str());
    1207            1 :         return false;
    1208              :     }
    1209              : 
    1210            1 :     return true;
    1211            2 : }
    1212              : 
    1213            4 : bool MediaPipelineIpc::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac)
    1214              : {
    1215            4 :     if (!reattachChannelIfRequired())
    1216              :     {
    1217            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1218            1 :         return false;
    1219              :     }
    1220              : 
    1221            3 :     firebolt::rialto::ProcessAudioGapRequest request;
    1222              : 
    1223            3 :     request.set_session_id(m_sessionId);
    1224            3 :     request.set_position(position);
    1225            3 :     request.set_duration(duration);
    1226            3 :     request.set_discontinuity_gap(discontinuityGap);
    1227            3 :     request.set_audio_aac(audioAac);
    1228              : 
    1229            3 :     firebolt::rialto::ProcessAudioGapResponse response;
    1230            3 :     auto ipcController = m_ipc.createRpcController();
    1231            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1232            3 :     m_mediaPipelineStub->processAudioGap(ipcController.get(), &request, &response, blockingClosure.get());
    1233              : 
    1234              :     // wait for the call to complete
    1235            3 :     blockingClosure->wait();
    1236              : 
    1237              :     // check the result
    1238            3 :     if (ipcController->Failed())
    1239              :     {
    1240            1 :         RIALTO_CLIENT_LOG_ERROR("failed to process audio gap due to '%s'", ipcController->ErrorText().c_str());
    1241            1 :         return false;
    1242              :     }
    1243              : 
    1244            2 :     return true;
    1245            3 : }
    1246              : 
    1247            4 : bool MediaPipelineIpc::setBufferingLimit(uint32_t limitBufferingMs)
    1248              : {
    1249            4 :     if (!reattachChannelIfRequired())
    1250              :     {
    1251            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1252            1 :         return false;
    1253              :     }
    1254              : 
    1255            3 :     firebolt::rialto::SetBufferingLimitRequest request;
    1256              : 
    1257            3 :     request.set_session_id(m_sessionId);
    1258            3 :     request.set_limit_buffering_ms(limitBufferingMs);
    1259              : 
    1260            3 :     firebolt::rialto::SetBufferingLimitResponse response;
    1261            3 :     auto ipcController = m_ipc.createRpcController();
    1262            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1263            3 :     m_mediaPipelineStub->setBufferingLimit(ipcController.get(), &request, &response, blockingClosure.get());
    1264              : 
    1265              :     // wait for the call to complete
    1266            3 :     blockingClosure->wait();
    1267              : 
    1268              :     // check the result
    1269            3 :     if (ipcController->Failed())
    1270              :     {
    1271            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set buffering limit due to '%s'", ipcController->ErrorText().c_str());
    1272            1 :         return false;
    1273              :     }
    1274              : 
    1275            2 :     return true;
    1276            3 : }
    1277              : 
    1278            4 : bool MediaPipelineIpc::getBufferingLimit(uint32_t &limitBufferingMs)
    1279              : {
    1280            4 :     if (!reattachChannelIfRequired())
    1281              :     {
    1282            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1283            1 :         return false;
    1284              :     }
    1285              : 
    1286            3 :     firebolt::rialto::GetBufferingLimitRequest request;
    1287              : 
    1288            3 :     request.set_session_id(m_sessionId);
    1289              : 
    1290            3 :     firebolt::rialto::GetBufferingLimitResponse response;
    1291            3 :     auto ipcController = m_ipc.createRpcController();
    1292            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1293            3 :     m_mediaPipelineStub->getBufferingLimit(ipcController.get(), &request, &response, blockingClosure.get());
    1294              : 
    1295              :     // wait for the call to complete
    1296            3 :     blockingClosure->wait();
    1297              : 
    1298              :     // check the result
    1299            3 :     if (ipcController->Failed())
    1300              :     {
    1301            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get buffering limit due to '%s'", ipcController->ErrorText().c_str());
    1302            1 :         return false;
    1303              :     }
    1304              : 
    1305            2 :     limitBufferingMs = response.limit_buffering_ms();
    1306              : 
    1307            2 :     return true;
    1308            3 : }
    1309              : 
    1310            4 : bool MediaPipelineIpc::setUseBuffering(bool useBuffering)
    1311              : {
    1312            4 :     if (!reattachChannelIfRequired())
    1313              :     {
    1314            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1315            1 :         return false;
    1316              :     }
    1317              : 
    1318            3 :     firebolt::rialto::SetUseBufferingRequest request;
    1319              : 
    1320            3 :     request.set_session_id(m_sessionId);
    1321            3 :     request.set_use_buffering(useBuffering);
    1322              : 
    1323            3 :     firebolt::rialto::SetUseBufferingResponse response;
    1324            3 :     auto ipcController = m_ipc.createRpcController();
    1325            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1326            3 :     m_mediaPipelineStub->setUseBuffering(ipcController.get(), &request, &response, blockingClosure.get());
    1327              : 
    1328              :     // wait for the call to complete
    1329            3 :     blockingClosure->wait();
    1330              : 
    1331              :     // check the result
    1332            3 :     if (ipcController->Failed())
    1333              :     {
    1334            1 :         RIALTO_CLIENT_LOG_ERROR("failed to set use buffering due to '%s'", ipcController->ErrorText().c_str());
    1335            1 :         return false;
    1336              :     }
    1337              : 
    1338            2 :     return true;
    1339            3 : }
    1340              : 
    1341            4 : bool MediaPipelineIpc::getUseBuffering(bool &useBuffering)
    1342              : {
    1343            4 :     if (!reattachChannelIfRequired())
    1344              :     {
    1345            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1346            1 :         return false;
    1347              :     }
    1348              : 
    1349            3 :     firebolt::rialto::GetUseBufferingRequest request;
    1350              : 
    1351            3 :     request.set_session_id(m_sessionId);
    1352              : 
    1353            3 :     firebolt::rialto::GetUseBufferingResponse response;
    1354            3 :     auto ipcController = m_ipc.createRpcController();
    1355            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1356            3 :     m_mediaPipelineStub->getUseBuffering(ipcController.get(), &request, &response, blockingClosure.get());
    1357              : 
    1358              :     // wait for the call to complete
    1359            3 :     blockingClosure->wait();
    1360              : 
    1361              :     // check the result
    1362            3 :     if (ipcController->Failed())
    1363              :     {
    1364            1 :         RIALTO_CLIENT_LOG_ERROR("failed to get use buffering due to '%s'", ipcController->ErrorText().c_str());
    1365            1 :         return false;
    1366              :     }
    1367              : 
    1368            2 :     useBuffering = response.use_buffering();
    1369              : 
    1370            2 :     return true;
    1371            3 : }
    1372              : 
    1373            5 : bool MediaPipelineIpc::switchSource(const std::unique_ptr<IMediaPipeline::MediaSource> &source)
    1374              : {
    1375            5 :     if (!reattachChannelIfRequired())
    1376              :     {
    1377            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1378            1 :         return false;
    1379              :     }
    1380              : 
    1381            4 :     firebolt::rialto::AttachSourceRequest request;
    1382              : 
    1383            4 :     request.set_session_id(m_sessionId);
    1384            4 :     request.set_switch_source(true);
    1385            4 :     if (!buildAttachSourceRequest(request, source))
    1386              :     {
    1387            1 :         RIALTO_CLIENT_LOG_ERROR("Failed to parse source");
    1388            1 :         return false;
    1389              :     }
    1390              : 
    1391            3 :     firebolt::rialto::AttachSourceResponse response;
    1392            3 :     auto ipcController = m_ipc.createRpcController();
    1393            3 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1394            3 :     m_mediaPipelineStub->attachSource(ipcController.get(), &request, &response, blockingClosure.get());
    1395              : 
    1396              :     // wait for the call to complete
    1397            3 :     blockingClosure->wait();
    1398              : 
    1399              :     // check the result
    1400            3 :     if (ipcController->Failed())
    1401              :     {
    1402            1 :         RIALTO_CLIENT_LOG_ERROR("failed to attach source due to '%s'", ipcController->ErrorText().c_str());
    1403            1 :         return false;
    1404              :     }
    1405              : 
    1406            2 :     return true;
    1407            4 : }
    1408              : 
    1409            2 : void MediaPipelineIpc::onPlaybackStateUpdated(const std::shared_ptr<firebolt::rialto::PlaybackStateChangeEvent> &event)
    1410              : {
    1411              :     /* Ignore event if not for this session */
    1412            2 :     if (event->session_id() == m_sessionId)
    1413              :     {
    1414            1 :         PlaybackState playbackState = PlaybackState::UNKNOWN;
    1415            1 :         switch (event->state())
    1416              :         {
    1417            0 :         case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_IDLE:
    1418            0 :             playbackState = PlaybackState::IDLE;
    1419            0 :             break;
    1420            1 :         case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PLAYING:
    1421            1 :             playbackState = PlaybackState::PLAYING;
    1422            1 :             break;
    1423            0 :         case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PAUSED:
    1424            0 :             playbackState = PlaybackState::PAUSED;
    1425            0 :             break;
    1426            0 :         case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEKING:
    1427            0 :             playbackState = PlaybackState::SEEKING;
    1428            0 :             break;
    1429            0 :         case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEK_DONE:
    1430            0 :             playbackState = PlaybackState::SEEK_DONE;
    1431            0 :             break;
    1432            0 :         case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_STOPPED:
    1433            0 :             playbackState = PlaybackState::STOPPED;
    1434            0 :             break;
    1435            0 :         case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_END_OF_STREAM:
    1436            0 :             playbackState = PlaybackState::END_OF_STREAM;
    1437            0 :             break;
    1438            0 :         case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_FAILURE:
    1439            0 :             playbackState = PlaybackState::FAILURE;
    1440            0 :             break;
    1441            0 :         default:
    1442            0 :             RIALTO_CLIENT_LOG_WARN("Received unknown playback state");
    1443            0 :             break;
    1444              :         }
    1445              : 
    1446            1 :         m_mediaPipelineIpcClient->notifyPlaybackState(playbackState);
    1447              :     }
    1448            2 : }
    1449              : 
    1450            0 : void MediaPipelineIpc::onPositionUpdated(const std::shared_ptr<firebolt::rialto::PositionChangeEvent> &event)
    1451              : {
    1452              :     // Ignore event if not for this session
    1453            0 :     if (event->session_id() == m_sessionId)
    1454              :     {
    1455            0 :         int64_t position = event->position();
    1456            0 :         m_mediaPipelineIpcClient->notifyPosition(position);
    1457              :     }
    1458              : }
    1459              : 
    1460            2 : void MediaPipelineIpc::onNetworkStateUpdated(const std::shared_ptr<firebolt::rialto::NetworkStateChangeEvent> &event)
    1461              : {
    1462              :     // Ignore event if not for this session
    1463            2 :     if (event->session_id() == m_sessionId)
    1464              :     {
    1465            1 :         NetworkState networkState = NetworkState::UNKNOWN;
    1466            1 :         switch (event->state())
    1467              :         {
    1468            0 :         case firebolt::rialto::NetworkStateChangeEvent_NetworkState_IDLE:
    1469            0 :             networkState = NetworkState::IDLE;
    1470            0 :             break;
    1471            1 :         case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING:
    1472            1 :             networkState = NetworkState::BUFFERING;
    1473            1 :             break;
    1474            0 :         case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING_PROGRESS:
    1475            0 :             networkState = NetworkState::BUFFERING_PROGRESS;
    1476            0 :             break;
    1477            0 :         case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERED:
    1478            0 :             networkState = NetworkState::BUFFERED;
    1479            0 :             break;
    1480            0 :         case firebolt::rialto::NetworkStateChangeEvent_NetworkState_STALLED:
    1481            0 :             networkState = NetworkState::STALLED;
    1482            0 :             break;
    1483            0 :         case firebolt::rialto::NetworkStateChangeEvent_NetworkState_FORMAT_ERROR:
    1484            0 :             networkState = NetworkState::FORMAT_ERROR;
    1485            0 :             break;
    1486            0 :         case firebolt::rialto::NetworkStateChangeEvent_NetworkState_NETWORK_ERROR:
    1487            0 :             networkState = NetworkState::NETWORK_ERROR;
    1488            0 :             break;
    1489            0 :         default:
    1490            0 :             RIALTO_CLIENT_LOG_WARN("Received unknown network state");
    1491            0 :             break;
    1492              :         }
    1493              : 
    1494            1 :         m_mediaPipelineIpcClient->notifyNetworkState(networkState);
    1495              :     }
    1496            2 : }
    1497              : 
    1498            3 : void MediaPipelineIpc::onNeedMediaData(const std::shared_ptr<firebolt::rialto::NeedMediaDataEvent> &event)
    1499              : {
    1500              :     // Ignore event if not for this session
    1501            3 :     if (event->session_id() == m_sessionId)
    1502              :     {
    1503            2 :         std::shared_ptr<MediaPlayerShmInfo> shmInfo;
    1504            2 :         if (event->has_shm_info())
    1505              :         {
    1506            1 :             shmInfo = std::make_shared<MediaPlayerShmInfo>();
    1507            1 :             shmInfo->maxMetadataBytes = event->shm_info().max_metadata_bytes();
    1508            1 :             shmInfo->metadataOffset = event->shm_info().metadata_offset();
    1509            1 :             shmInfo->mediaDataOffset = event->shm_info().media_data_offset();
    1510            1 :             shmInfo->maxMediaBytes = event->shm_info().max_media_bytes();
    1511              :         }
    1512            2 :         m_mediaPipelineIpcClient->notifyNeedMediaData(event->source_id(), event->frame_count(), event->request_id(),
    1513              :                                                       shmInfo);
    1514              :     }
    1515            3 : }
    1516              : 
    1517            2 : void MediaPipelineIpc::onQos(const std::shared_ptr<firebolt::rialto::QosEvent> &event)
    1518              : {
    1519              :     // Ignore event if not for this session
    1520            2 :     if (event->session_id() == m_sessionId)
    1521              :     {
    1522            1 :         QosInfo qosInfo = {event->qos_info().processed(), event->qos_info().dropped()};
    1523            1 :         m_mediaPipelineIpcClient->notifyQos(event->source_id(), qosInfo);
    1524              :     }
    1525            2 : }
    1526              : 
    1527            0 : void MediaPipelineIpc::onBufferUnderflow(const std::shared_ptr<firebolt::rialto::BufferUnderflowEvent> &event)
    1528              : {
    1529              :     // Ignore event if not for this session
    1530            0 :     if (event->session_id() == m_sessionId)
    1531              :     {
    1532            0 :         m_mediaPipelineIpcClient->notifyBufferUnderflow(event->source_id());
    1533              :     }
    1534              : }
    1535              : 
    1536            2 : void MediaPipelineIpc::onPlaybackError(const std::shared_ptr<firebolt::rialto::PlaybackErrorEvent> &event)
    1537              : {
    1538              :     // Ignore event if not for this session
    1539            2 :     if (event->session_id() == m_sessionId)
    1540              :     {
    1541            1 :         PlaybackError playbackError = PlaybackError::UNKNOWN;
    1542            1 :         switch (event->error())
    1543              :         {
    1544            1 :         case firebolt::rialto::PlaybackErrorEvent_PlaybackError_DECRYPTION:
    1545            1 :             playbackError = PlaybackError::DECRYPTION;
    1546            1 :             break;
    1547            0 :         default:
    1548            0 :             RIALTO_CLIENT_LOG_WARN("Received unknown playback error");
    1549            0 :             break;
    1550              :         }
    1551              : 
    1552            1 :         m_mediaPipelineIpcClient->notifyPlaybackError(event->source_id(), playbackError);
    1553              :     }
    1554            2 : }
    1555              : 
    1556            2 : void MediaPipelineIpc::onSourceFlushed(const std::shared_ptr<firebolt::rialto::SourceFlushedEvent> &event)
    1557              : {
    1558              :     // Ignore event if not for this session
    1559            2 :     if (event->session_id() == m_sessionId)
    1560              :     {
    1561            1 :         m_mediaPipelineIpcClient->notifySourceFlushed(event->source_id());
    1562              :     }
    1563            2 : }
    1564              : 
    1565            1 : void MediaPipelineIpc::onPlaybackInfo(const std::shared_ptr<firebolt::rialto::PlaybackInfoEvent> &event)
    1566              : {
    1567            1 :     if (event->session_id() == m_sessionId)
    1568              :     {
    1569            1 :         PlaybackInfo playbackInfo;
    1570            1 :         playbackInfo.currentPosition = event->current_position();
    1571            1 :         playbackInfo.volume = event->volume();
    1572            1 :         m_mediaPipelineIpcClient->notifyPlaybackInfo(playbackInfo);
    1573              :     }
    1574              : }
    1575              : 
    1576          178 : bool MediaPipelineIpc::createSession(const VideoRequirements &videoRequirements)
    1577              : {
    1578          178 :     if (!reattachChannelIfRequired())
    1579              :     {
    1580            0 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1581            0 :         return false;
    1582              :     }
    1583              : 
    1584          178 :     firebolt::rialto::CreateSessionRequest request;
    1585              : 
    1586          178 :     request.set_max_width(videoRequirements.maxWidth);
    1587          178 :     request.set_max_height(videoRequirements.maxHeight);
    1588              : 
    1589          178 :     firebolt::rialto::CreateSessionResponse response;
    1590          178 :     auto ipcController = m_ipc.createRpcController();
    1591          178 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1592          178 :     m_mediaPipelineStub->createSession(ipcController.get(), &request, &response, blockingClosure.get());
    1593              : 
    1594              :     // wait for the call to complete
    1595          178 :     blockingClosure->wait();
    1596              : 
    1597              :     // check the result
    1598          178 :     if (ipcController->Failed())
    1599              :     {
    1600            1 :         RIALTO_CLIENT_LOG_ERROR("failed to create session due to '%s'", ipcController->ErrorText().c_str());
    1601            1 :         return false;
    1602              :     }
    1603              : 
    1604          177 :     m_sessionId = response.session_id();
    1605              : 
    1606          177 :     return true;
    1607          178 : }
    1608              : 
    1609          177 : void MediaPipelineIpc::destroySession()
    1610              : {
    1611          177 :     if (!reattachChannelIfRequired())
    1612              :     {
    1613            1 :         RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected");
    1614            1 :         return;
    1615              :     }
    1616              : 
    1617          176 :     firebolt::rialto::DestroySessionRequest request;
    1618          176 :     request.set_session_id(m_sessionId);
    1619              : 
    1620          176 :     firebolt::rialto::DestroySessionResponse response;
    1621          176 :     auto ipcController = m_ipc.createRpcController();
    1622          176 :     auto blockingClosure = m_ipc.createBlockingClosure();
    1623          176 :     m_mediaPipelineStub->destroySession(ipcController.get(), &request, &response, blockingClosure.get());
    1624              : 
    1625              :     // wait for the call to complete
    1626          176 :     blockingClosure->wait();
    1627              : 
    1628              :     // check the result
    1629          176 :     if (ipcController->Failed())
    1630              :     {
    1631            1 :         RIALTO_CLIENT_LOG_ERROR("failed to destroy session due to '%s'", ipcController->ErrorText().c_str());
    1632              :     }
    1633          176 : }
    1634              : 
    1635            3 : firebolt::rialto::LoadRequest_MediaType MediaPipelineIpc::convertLoadRequestMediaType(MediaType mediaType) const
    1636              : {
    1637            3 :     firebolt::rialto::LoadRequest_MediaType protoMediaType = firebolt::rialto::LoadRequest_MediaType_UNKNOWN;
    1638            3 :     switch (mediaType)
    1639              :     {
    1640            3 :     case MediaType::MSE:
    1641            3 :         protoMediaType = firebolt::rialto::LoadRequest_MediaType_MSE;
    1642            3 :         break;
    1643            0 :     default:
    1644            0 :         break;
    1645              :     }
    1646              : 
    1647            3 :     return protoMediaType;
    1648              : }
    1649              : 
    1650              : firebolt::rialto::HaveDataRequest_MediaSourceStatus
    1651            3 : MediaPipelineIpc::convertHaveDataRequestMediaSourceStatus(MediaSourceStatus status) const
    1652              : {
    1653            3 :     firebolt::rialto::HaveDataRequest_MediaSourceStatus protoMediaSourceStatus =
    1654              :         firebolt::rialto::HaveDataRequest_MediaSourceStatus_UNKNOWN;
    1655            3 :     switch (status)
    1656              :     {
    1657            3 :     case MediaSourceStatus::OK:
    1658            3 :         protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_OK;
    1659            3 :         break;
    1660            0 :     case MediaSourceStatus::EOS:
    1661            0 :         protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_EOS;
    1662            0 :         break;
    1663            0 :     case MediaSourceStatus::ERROR:
    1664            0 :         protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_ERROR;
    1665            0 :         break;
    1666            0 :     case MediaSourceStatus::CODEC_CHANGED:
    1667            0 :         protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_CODEC_CHANGED;
    1668            0 :         break;
    1669            0 :     case MediaSourceStatus::NO_AVAILABLE_SAMPLES:
    1670            0 :         protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_NO_AVAILABLE_SAMPLES;
    1671            0 :         break;
    1672            0 :     default:
    1673            0 :         break;
    1674              :     }
    1675              : 
    1676            3 :     return protoMediaSourceStatus;
    1677              : }
    1678              : 
    1679              : firebolt::rialto::AttachSourceRequest_ConfigType
    1680           17 : MediaPipelineIpc::convertConfigType(const firebolt::rialto::SourceConfigType &configType) const
    1681              : {
    1682           17 :     switch (configType)
    1683              :     {
    1684            0 :     case firebolt::rialto::SourceConfigType::UNKNOWN:
    1685              :     {
    1686            0 :         return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_UNKNOWN;
    1687              :     }
    1688            9 :     case firebolt::rialto::SourceConfigType::AUDIO:
    1689              :     {
    1690            9 :         return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_AUDIO;
    1691              :     }
    1692            3 :     case firebolt::rialto::SourceConfigType::VIDEO:
    1693              :     {
    1694            3 :         return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO;
    1695              :     }
    1696            3 :     case firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION:
    1697              :     {
    1698            3 :         return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO_DOLBY_VISION;
    1699              :     }
    1700            2 :     case firebolt::rialto::SourceConfigType::SUBTITLE:
    1701              :     {
    1702            2 :         return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_SUBTITLE;
    1703              :     }
    1704              :     }
    1705            0 :     return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_UNKNOWN;
    1706              : }
    1707              : 
    1708            3 : firebolt::rialto::SetVolumeRequest_EaseType MediaPipelineIpc::convertEaseType(const firebolt::rialto::EaseType &easeType) const
    1709              : {
    1710            3 :     switch (easeType)
    1711              :     {
    1712            3 :     case firebolt::rialto::EaseType::EASE_LINEAR:
    1713              :     {
    1714            3 :         return firebolt::rialto::SetVolumeRequest_EaseType_EASE_LINEAR;
    1715              :     }
    1716            0 :     case firebolt::rialto::EaseType::EASE_IN_CUBIC:
    1717              :     {
    1718            0 :         return firebolt::rialto::SetVolumeRequest_EaseType_EASE_IN_CUBIC;
    1719              :     }
    1720            0 :     case firebolt::rialto::EaseType::EASE_OUT_CUBIC:
    1721              :     {
    1722            0 :         return firebolt::rialto::SetVolumeRequest_EaseType_EASE_OUT_CUBIC;
    1723              :     }
    1724              :     }
    1725            0 :     return firebolt::rialto::SetVolumeRequest_EaseType_EASE_LINEAR;
    1726              : }
    1727              : 
    1728              : firebolt::rialto::AttachSourceRequest_SegmentAlignment
    1729           14 : MediaPipelineIpc::convertSegmentAlignment(const firebolt::rialto::SegmentAlignment &alignment) const
    1730              : {
    1731           14 :     switch (alignment)
    1732              :     {
    1733           14 :     case firebolt::rialto::SegmentAlignment::UNDEFINED:
    1734              :     {
    1735           14 :         return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_UNDEFINED;
    1736              :     }
    1737            0 :     case firebolt::rialto::SegmentAlignment::NAL:
    1738              :     {
    1739            0 :         return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_NAL;
    1740              :     }
    1741            0 :     case firebolt::rialto::SegmentAlignment::AU:
    1742              :     {
    1743            0 :         return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_AU;
    1744              :     }
    1745              :     }
    1746            0 :     return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_UNDEFINED;
    1747              : }
    1748              : 
    1749              : firebolt::rialto::AttachSourceRequest_StreamFormat
    1750           14 : MediaPipelineIpc::convertStreamFormat(const firebolt::rialto::StreamFormat &streamFormat) const
    1751              : {
    1752           14 :     switch (streamFormat)
    1753              :     {
    1754            8 :     case firebolt::rialto::StreamFormat::UNDEFINED:
    1755              :     {
    1756            8 :         return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_UNDEFINED;
    1757              :     }
    1758            6 :     case firebolt::rialto::StreamFormat::RAW:
    1759              :     {
    1760            6 :         return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_RAW;
    1761              :     }
    1762            0 :     case firebolt::rialto::StreamFormat::AVC:
    1763              :     {
    1764            0 :         return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_AVC;
    1765              :     }
    1766            0 :     case firebolt::rialto::StreamFormat::BYTE_STREAM:
    1767              :     {
    1768            0 :         return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_BYTE_STREAM;
    1769              :     }
    1770            0 :     case firebolt::rialto::StreamFormat::HVC1:
    1771              :     {
    1772            0 :         return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HVC1;
    1773              :     }
    1774            0 :     case firebolt::rialto::StreamFormat::HEV1:
    1775              :     {
    1776            0 :         return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HEV1;
    1777              :     }
    1778              :     }
    1779            0 :     return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_UNDEFINED;
    1780              : }
    1781              : 
    1782              : firebolt::rialto::AttachSourceRequest_CodecData_Type
    1783            3 : MediaPipelineIpc::convertCodecDataType(const firebolt::rialto::CodecDataType &codecDataType) const
    1784              : {
    1785            3 :     if (firebolt::rialto::CodecDataType::STRING == codecDataType)
    1786              :     {
    1787            0 :         return firebolt::rialto::AttachSourceRequest_CodecData_Type_STRING;
    1788              :     }
    1789            3 :     return firebolt::rialto::AttachSourceRequest_CodecData_Type_BUFFER;
    1790              : }
    1791              : 
    1792              : firebolt::rialto::AttachSourceRequest_AudioConfig_Format
    1793            0 : MediaPipelineIpc::convertFormat(const firebolt::rialto::Format &format) const
    1794              : {
    1795              :     static const std::unordered_map<firebolt::rialto::Format, firebolt::rialto::AttachSourceRequest_AudioConfig_Format>
    1796              :         kFormatConversionMap{
    1797              :             {firebolt::rialto::Format::S8, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S8},
    1798              :             {firebolt::rialto::Format::U8, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U8},
    1799              :             {firebolt::rialto::Format::S16LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16LE},
    1800              :             {firebolt::rialto::Format::S16BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16BE},
    1801              :             {firebolt::rialto::Format::U16LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16LE},
    1802              :             {firebolt::rialto::Format::U16BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16BE},
    1803              :             {firebolt::rialto::Format::S24_32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32LE},
    1804              :             {firebolt::rialto::Format::S24_32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32BE},
    1805              :             {firebolt::rialto::Format::U24_32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32LE},
    1806              :             {firebolt::rialto::Format::U24_32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32BE},
    1807              :             {firebolt::rialto::Format::S32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32LE},
    1808              :             {firebolt::rialto::Format::S32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32BE},
    1809              :             {firebolt::rialto::Format::U32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32LE},
    1810              :             {firebolt::rialto::Format::U32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32BE},
    1811              :             {firebolt::rialto::Format::S24LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24LE},
    1812              :             {firebolt::rialto::Format::S24BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24BE},
    1813              :             {firebolt::rialto::Format::U24LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24LE},
    1814              :             {firebolt::rialto::Format::U24BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24BE},
    1815              :             {firebolt::rialto::Format::S20LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20LE},
    1816              :             {firebolt::rialto::Format::S20BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20BE},
    1817              :             {firebolt::rialto::Format::U20LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20LE},
    1818              :             {firebolt::rialto::Format::U20BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20BE},
    1819              :             {firebolt::rialto::Format::S18LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18LE},
    1820              :             {firebolt::rialto::Format::S18BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18BE},
    1821              :             {firebolt::rialto::Format::U18LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18LE},
    1822              :             {firebolt::rialto::Format::U18BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18BE},
    1823              :             {firebolt::rialto::Format::F32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32LE},
    1824              :             {firebolt::rialto::Format::F32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32BE},
    1825              :             {firebolt::rialto::Format::F64LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64LE},
    1826            0 :             {firebolt::rialto::Format::F64BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64BE}};
    1827            0 :     const auto kIt = kFormatConversionMap.find(format);
    1828            0 :     if (kFormatConversionMap.end() != kIt)
    1829              :     {
    1830            0 :         return kIt->second;
    1831              :     }
    1832            0 :     return firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S8;
    1833              : }
    1834              : 
    1835              : firebolt::rialto::AttachSourceRequest_AudioConfig_Layout
    1836            0 : MediaPipelineIpc::convertLayout(const firebolt::rialto::Layout &layout) const
    1837              : {
    1838              :     static const std::unordered_map<firebolt::rialto::Layout, firebolt::rialto::AttachSourceRequest_AudioConfig_Layout>
    1839              :         kLayoutConversionMap{{firebolt::rialto::Layout::INTERLEAVED,
    1840              :                               firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_INTERLEAVED},
    1841              :                              {firebolt::rialto::Layout::NON_INTERLEAVED,
    1842            0 :                               firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_NON_INTERLEAVED}};
    1843            0 :     const auto kIt = kLayoutConversionMap.find(layout);
    1844            0 :     if (kLayoutConversionMap.end() != kIt)
    1845              :     {
    1846            0 :         return kIt->second;
    1847              :     }
    1848            0 :     return firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_INTERLEAVED;
    1849              : }
    1850              : 
    1851           17 : bool MediaPipelineIpc::buildAttachSourceRequest(firebolt::rialto::AttachSourceRequest &request,
    1852              :                                                 const std::unique_ptr<IMediaPipeline::MediaSource> &source) const
    1853              : {
    1854           17 :     SourceConfigType configType = source->getConfigType();
    1855           17 :     request.set_config_type(convertConfigType(configType));
    1856           34 :     request.set_mime_type(source->getMimeType());
    1857           17 :     request.set_has_drm(source->getHasDrm());
    1858              : 
    1859           17 :     if (configType == SourceConfigType::VIDEO_DOLBY_VISION || configType == SourceConfigType::VIDEO ||
    1860           11 :         configType == SourceConfigType::AUDIO)
    1861              :     {
    1862           15 :         IMediaPipeline::MediaSourceAV *mediaSourceAV = dynamic_cast<IMediaPipeline::MediaSourceAV *>(source.get());
    1863           15 :         if (!mediaSourceAV)
    1864              :         {
    1865            1 :             RIALTO_CLIENT_LOG_ERROR("Failed to get the audio video source");
    1866            1 :             return false;
    1867              :         }
    1868           14 :         request.set_segment_alignment(convertSegmentAlignment(mediaSourceAV->getSegmentAlignment()));
    1869              : 
    1870           14 :         if (mediaSourceAV->getCodecData())
    1871              :         {
    1872            6 :             request.mutable_codec_data()->set_data(mediaSourceAV->getCodecData()->data.data(),
    1873            3 :                                                    mediaSourceAV->getCodecData()->data.size());
    1874            3 :             request.mutable_codec_data()->set_type(convertCodecDataType(mediaSourceAV->getCodecData()->type));
    1875              :         }
    1876           14 :         request.set_stream_format(convertStreamFormat(mediaSourceAV->getStreamFormat()));
    1877              : 
    1878           14 :         if (configType == SourceConfigType::VIDEO_DOLBY_VISION)
    1879              :         {
    1880              :             IMediaPipeline::MediaSourceVideoDolbyVision *mediaSourceDolby =
    1881            2 :                 dynamic_cast<IMediaPipeline::MediaSourceVideoDolbyVision *>(source.get());
    1882            2 :             if (!mediaSourceDolby)
    1883              :             {
    1884            1 :                 RIALTO_CLIENT_LOG_ERROR("Failed to get the video dolby vision media source");
    1885            1 :                 return false;
    1886              :             }
    1887            1 :             request.set_width(mediaSourceDolby->getWidth());
    1888            1 :             request.set_height(mediaSourceDolby->getHeight());
    1889            1 :             request.set_dolby_vision_profile(mediaSourceDolby->getDolbyVisionProfile());
    1890              :         }
    1891           12 :         else if (configType == SourceConfigType::VIDEO)
    1892              :         {
    1893              :             IMediaPipeline::MediaSourceVideo *mediaSourceVideo =
    1894            3 :                 dynamic_cast<IMediaPipeline::MediaSourceVideo *>(source.get());
    1895            3 :             if (!mediaSourceVideo)
    1896              :             {
    1897            1 :                 RIALTO_CLIENT_LOG_ERROR("Failed to get the video media source");
    1898            1 :                 return false;
    1899              :             }
    1900            2 :             request.set_width(mediaSourceVideo->getWidth());
    1901            2 :             request.set_height(mediaSourceVideo->getHeight());
    1902              :         }
    1903            9 :         else if (configType == SourceConfigType::AUDIO)
    1904              :         {
    1905              :             IMediaPipeline::MediaSourceAudio *mediaSourceAudio =
    1906            9 :                 dynamic_cast<IMediaPipeline::MediaSourceAudio *>(source.get());
    1907            9 :             if (!mediaSourceAudio)
    1908              :             {
    1909            2 :                 RIALTO_CLIENT_LOG_ERROR("Failed to get the audio media source");
    1910            2 :                 return false;
    1911              :             }
    1912            7 :             request.mutable_audio_config()->set_number_of_channels(mediaSourceAudio->getAudioConfig().numberOfChannels);
    1913            7 :             request.mutable_audio_config()->set_sample_rate(mediaSourceAudio->getAudioConfig().sampleRate);
    1914            7 :             if (!mediaSourceAudio->getAudioConfig().codecSpecificConfig.empty())
    1915              :             {
    1916              :                 request.mutable_audio_config()
    1917            9 :                     ->set_codec_specific_config(mediaSourceAudio->getAudioConfig().codecSpecificConfig.data(),
    1918            3 :                                                 mediaSourceAudio->getAudioConfig().codecSpecificConfig.size());
    1919              :             }
    1920            7 :             if (mediaSourceAudio->getAudioConfig().format.has_value())
    1921              :             {
    1922            0 :                 request.mutable_audio_config()->set_format(
    1923            0 :                     convertFormat(mediaSourceAudio->getAudioConfig().format.value()));
    1924              :             }
    1925            7 :             if (mediaSourceAudio->getAudioConfig().layout.has_value())
    1926              :             {
    1927            0 :                 request.mutable_audio_config()->set_layout(
    1928            0 :                     convertLayout(mediaSourceAudio->getAudioConfig().layout.value()));
    1929              :             }
    1930            7 :             if (mediaSourceAudio->getAudioConfig().channelMask.has_value())
    1931              :             {
    1932            0 :                 request.mutable_audio_config()->set_channel_mask(mediaSourceAudio->getAudioConfig().channelMask.value());
    1933              :             }
    1934            7 :             for (auto &header : mediaSourceAudio->getAudioConfig().streamHeader)
    1935              :             {
    1936            0 :                 request.mutable_audio_config()->add_stream_header(header.data(), header.size());
    1937              :             }
    1938            7 :             if (mediaSourceAudio->getAudioConfig().framed.has_value())
    1939              :             {
    1940            0 :                 request.mutable_audio_config()->set_framed(mediaSourceAudio->getAudioConfig().framed.value());
    1941              :             }
    1942              :         }
    1943           10 :     }
    1944            2 :     else if (configType == SourceConfigType::SUBTITLE)
    1945              :     {
    1946              :         IMediaPipeline::MediaSourceSubtitle *mediaSourceSubtitle =
    1947            2 :             dynamic_cast<IMediaPipeline::MediaSourceSubtitle *>(source.get());
    1948            2 :         if (!mediaSourceSubtitle)
    1949              :         {
    1950            1 :             RIALTO_CLIENT_LOG_ERROR("Failed to get the subtitle source");
    1951            1 :             return false;
    1952              :         }
    1953            1 :         request.set_text_track_identifier(mediaSourceSubtitle->getTextTrackIdentifier());
    1954              :     }
    1955              :     else
    1956              :     {
    1957            0 :         RIALTO_CLIENT_LOG_ERROR("Unknown source type");
    1958            0 :         return false;
    1959              :     }
    1960           11 :     return true;
    1961              : }
    1962              : }; // namespace firebolt::rialto::client
        

Generated by: LCOV version 2.0-1