LCOV - code coverage report
Current view: top level - media/client/ipc/source - MediaPipelineIpc.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.9 % 1046 898
Test Date: 2025-12-19 09:03:31 Functions: 90.4 % 73 66

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

Generated by: LCOV version 2.0-1