LCOV - code coverage report
Current view: top level - source - RialtoGStreamerMSEVideoSink.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.0 % 271 252
Test Date: 2025-06-24 14:11:58 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2022 Sky UK
       3              :  *
       4              :  * This library is free software; you can redistribute it and/or
       5              :  * modify it under the terms of the GNU Lesser General Public
       6              :  * License as published by the Free Software Foundation;
       7              :  * version 2.1 of the License.
       8              :  *
       9              :  * This library is distributed in the hope that it will be useful,
      10              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12              :  * Lesser General Public License for more details.
      13              :  *
      14              :  * You should have received a copy of the GNU Lesser General Public
      15              :  * License along with this library; if not, write to the Free Software
      16              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
      17              :  */
      18              : 
      19              : #include <gst/gst.h>
      20              : #include <inttypes.h>
      21              : #include <stdint.h>
      22              : 
      23              : #include "GStreamerEMEUtils.h"
      24              : #include "GStreamerMSEUtils.h"
      25              : #include "IMediaPipelineCapabilities.h"
      26              : #include "RialtoGStreamerMSEBaseSinkPrivate.h"
      27              : #include "RialtoGStreamerMSEVideoSink.h"
      28              : #include "RialtoGStreamerMSEVideoSinkPrivate.h"
      29              : 
      30              : using namespace firebolt::rialto::client;
      31              : 
      32              : GST_DEBUG_CATEGORY_STATIC(RialtoMSEVideoSinkDebug);
      33              : #define GST_CAT_DEFAULT RialtoMSEVideoSinkDebug
      34              : 
      35              : #define rialto_mse_video_sink_parent_class parent_class
      36          244 : G_DEFINE_TYPE_WITH_CODE(RialtoMSEVideoSink, rialto_mse_video_sink, RIALTO_TYPE_MSE_BASE_SINK,
      37              :                         G_ADD_PRIVATE(RialtoMSEVideoSink)
      38              :                             GST_DEBUG_CATEGORY_INIT(RialtoMSEVideoSinkDebug, "rialtomsevideosink", 0,
      39              :                                                     "rialto mse video sink"));
      40              : 
      41              : enum
      42              : {
      43              :     PROP_0,
      44              :     PROP_WINDOW_SET,
      45              :     PROP_MAX_VIDEO_WIDTH,
      46              :     PROP_MAX_VIDEO_HEIGHT,
      47              :     PROP_MAX_VIDEO_WIDTH_DEPRECATED,
      48              :     PROP_MAX_VIDEO_HEIGHT_DEPRECATED,
      49              :     PROP_FRAME_STEP_ON_PREROLL,
      50              :     PROP_IMMEDIATE_OUTPUT,
      51              :     PROP_SYNCMODE_STREAMING,
      52              :     PROP_SHOW_VIDEO_WINDOW,
      53              :     PROP_LAST
      54              : };
      55              : 
      56          116 : static GstStateChangeReturn rialto_mse_video_sink_change_state(GstElement *element, GstStateChange transition)
      57              : {
      58          116 :     RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(element);
      59          116 :     RialtoMSEVideoSinkPrivate *priv = sink->priv;
      60          116 :     RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
      61              : 
      62          116 :     switch (transition)
      63              :     {
      64           28 :     case GST_STATE_CHANGE_READY_TO_PAUSED:
      65              :     {
      66              :         // Attach the media player client to media player manager.
      67              :         // maxWidth and maxHeight are used to set the video capabilities of the MediaPlayer.
      68              :         // If the mediaPlayer has already been created (ie. an audio sink on the same parent bus changed state first)
      69              :         // the video capabilities will NOT be set.
      70           28 :         if (!rialto_mse_base_sink_attach_to_media_client_and_set_streams_number(element, priv->maxWidth, priv->maxHeight))
      71              :         {
      72            1 :             return GST_STATE_CHANGE_FAILURE;
      73              :         }
      74              : 
      75           27 :         std::shared_ptr<GStreamerMSEMediaPlayerClient> client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
      76           27 :         if (!client)
      77              :         {
      78            0 :             GST_ERROR_OBJECT(sink, "MediaPlayerClient is nullptr");
      79            0 :             return GST_STATE_CHANGE_FAILURE;
      80              :         }
      81              : 
      82           27 :         std::unique_lock lock{priv->propertyMutex};
      83           27 :         if (priv->rectangleSettingQueued)
      84              :         {
      85            1 :             GST_DEBUG_OBJECT(sink, "Set queued video rectangle");
      86            1 :             priv->rectangleSettingQueued = false;
      87            1 :             client->setVideoRectangle(priv->videoRectangle);
      88              :         }
      89           27 :         break;
      90           54 :     }
      91           88 :     default:
      92           88 :         break;
      93              :     }
      94              : 
      95          115 :     GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
      96          115 :     if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE))
      97              :     {
      98            0 :         GST_WARNING_OBJECT(sink, "State change failed");
      99            0 :         return result;
     100              :     }
     101              : 
     102          115 :     return result;
     103              : }
     104              : 
     105              : static std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSource>
     106           27 : rialto_mse_video_sink_create_media_source(RialtoMSEBaseSink *sink, GstCaps *caps)
     107              : {
     108           27 :     GstStructure *structure = gst_caps_get_structure(caps, 0);
     109           27 :     const gchar *strct_name = gst_structure_get_name(structure);
     110              : 
     111           27 :     firebolt::rialto::SegmentAlignment alignment = rialto_mse_base_sink_get_segment_alignment(sink, structure);
     112           27 :     std::shared_ptr<firebolt::rialto::CodecData> codecData = rialto_mse_base_sink_get_codec_data(sink, structure);
     113           27 :     firebolt::rialto::StreamFormat format = rialto_mse_base_sink_get_stream_format(sink, structure);
     114              : 
     115           27 :     gint width = 0;
     116           27 :     gint height = 0;
     117           27 :     gst_structure_get_int(structure, "width", &width);
     118           27 :     gst_structure_get_int(structure, "height", &height);
     119              : 
     120           27 :     std::string mimeType;
     121           27 :     if (strct_name)
     122              :     {
     123           27 :         if (g_str_has_prefix(strct_name, "video/x-h264"))
     124              :         {
     125           22 :             mimeType = "video/h264";
     126              :         }
     127            5 :         else if (g_str_has_prefix(strct_name, "video/x-h265"))
     128              :         {
     129            4 :             mimeType = "video/h265";
     130              : 
     131            4 :             uint32_t dolbyVisionProfile = -1;
     132            4 :             if (rialto_mse_base_sink_get_dv_profile(sink, structure, dolbyVisionProfile))
     133              :             {
     134            1 :                 return std::make_unique<firebolt::rialto::IMediaPipeline::MediaSourceVideoDolbyVision>(mimeType,
     135              :                                                                                                        dolbyVisionProfile,
     136            1 :                                                                                                        sink->priv->m_hasDrm,
     137              :                                                                                                        width, height,
     138              :                                                                                                        alignment, format,
     139            1 :                                                                                                        codecData);
     140              :             }
     141              :         }
     142              :         else
     143              :         {
     144            1 :             mimeType = strct_name;
     145              :         }
     146              : 
     147           26 :         GST_INFO_OBJECT(sink, "%s video media source created", mimeType.c_str());
     148           52 :         return std::make_unique<firebolt::rialto::IMediaPipeline::MediaSourceVideo>(mimeType, sink->priv->m_hasDrm,
     149              :                                                                                     width, height, alignment, format,
     150           26 :                                                                                     codecData);
     151              :     }
     152              :     else
     153              :     {
     154            0 :         GST_ERROR_OBJECT(sink,
     155              :                          "Empty caps' structure name! Failed to set mime type when constructing video media source");
     156              :     }
     157              : 
     158            0 :     return nullptr;
     159           27 : }
     160              : 
     161           29 : static gboolean rialto_mse_video_sink_event(GstPad *pad, GstObject *parent, GstEvent *event)
     162              : {
     163           29 :     RialtoMSEBaseSink *baseSink = RIALTO_MSE_BASE_SINK(parent);
     164           29 :     RialtoMSEBaseSinkPrivate *basePriv = baseSink->priv;
     165           29 :     switch (GST_EVENT_TYPE(event))
     166              :     {
     167           28 :     case GST_EVENT_CAPS:
     168              :     {
     169              :         GstCaps *caps;
     170           28 :         gst_event_parse_caps(event, &caps);
     171           28 :         if (basePriv->m_sourceAttached)
     172              :         {
     173            1 :             GST_INFO_OBJECT(baseSink, "Source already attached. Skip calling attachSource");
     174            1 :             break;
     175              :         }
     176              : 
     177           27 :         GST_INFO_OBJECT(baseSink, "Attaching VIDEO source with caps %" GST_PTR_FORMAT, caps);
     178              : 
     179              :         std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSource> vsource =
     180           27 :             rialto_mse_video_sink_create_media_source(baseSink, caps);
     181           27 :         if (vsource)
     182              :         {
     183           27 :             std::shared_ptr<GStreamerMSEMediaPlayerClient> client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
     184           27 :             if ((!client) || (!client->attachSource(vsource, baseSink)))
     185              :             {
     186            1 :                 GST_ERROR_OBJECT(baseSink, "Failed to attach VIDEO source");
     187              :             }
     188              :             else
     189              :             {
     190           26 :                 basePriv->m_sourceAttached = true;
     191              : 
     192              :                 // check if READY -> PAUSED was requested before source was attached
     193           26 :                 if (GST_STATE_NEXT(baseSink) == GST_STATE_PAUSED)
     194              :                 {
     195           26 :                     client->pause(basePriv->m_sourceId);
     196              :                 }
     197           26 :                 RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(parent);
     198           26 :                 RialtoMSEVideoSinkPrivate *priv = sink->priv;
     199           26 :                 std::unique_lock lock{priv->propertyMutex};
     200           26 :                 if (priv->immediateOutputQueued)
     201              :                 {
     202            1 :                     GST_DEBUG_OBJECT(sink, "Set queued immediate-output");
     203            1 :                     priv->immediateOutputQueued = false;
     204            1 :                     if (!client->setImmediateOutput(basePriv->m_sourceId, priv->immediateOutput))
     205              :                     {
     206            0 :                         GST_ERROR_OBJECT(sink, "Could not set immediate-output");
     207              :                     }
     208              :                 }
     209           26 :                 if (priv->syncmodeStreamingQueued)
     210              :                 {
     211            2 :                     GST_DEBUG_OBJECT(sink, "Set queued syncmode-streaming");
     212            2 :                     priv->syncmodeStreamingQueued = false;
     213            2 :                     if (!client->setStreamSyncMode(basePriv->m_sourceId, priv->syncmodeStreaming))
     214              :                     {
     215            1 :                         GST_ERROR_OBJECT(sink, "Could not set syncmode-streaming");
     216              :                     }
     217              :                 }
     218           26 :                 if (priv->showVideoWindowQueued)
     219              :                 {
     220            1 :                     GST_DEBUG_OBJECT(sink, "Set queued show-video-window");
     221            1 :                     priv->showVideoWindowQueued = false;
     222            1 :                     client->setMute(priv->showVideoWindow, basePriv->m_sourceId);
     223              :                 }
     224           26 :             }
     225           27 :         }
     226              :         else
     227              :         {
     228            0 :             GST_ERROR_OBJECT(baseSink, "Failed to create VIDEO source");
     229              :         }
     230              : 
     231           27 :         break;
     232              :     }
     233            1 :     default:
     234            1 :         break;
     235              :     }
     236              : 
     237           29 :     return rialto_mse_base_sink_event(pad, parent, event);
     238              : }
     239              : 
     240           14 : static void rialto_mse_video_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec)
     241              : {
     242           14 :     RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(object);
     243           14 :     if (!sink)
     244              :     {
     245            0 :         GST_ERROR_OBJECT(object, "Sink not initalised");
     246            0 :         return;
     247              :     }
     248           14 :     RialtoMSEVideoSinkPrivate *priv = sink->priv;
     249           14 :     RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
     250           14 :     if (!priv || !basePriv)
     251              :     {
     252            0 :         GST_ERROR_OBJECT(object, "Private Sink not initalised");
     253            0 :         return;
     254              :     }
     255              : 
     256           14 :     switch (propId)
     257              :     {
     258            5 :     case PROP_WINDOW_SET:
     259              :     {
     260            5 :         std::unique_lock lock{priv->propertyMutex};
     261            5 :         auto client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
     262            5 :         if (!client)
     263              :         {
     264              :             // Return the default value and
     265              :             // queue a setting event (for the default value) so that it will become true when
     266              :             // the client connects...
     267            2 :             GST_DEBUG_OBJECT(object, "Return default rectangle setting, and queue an event to set the default upon "
     268              :                                      "client connect");
     269            2 :             priv->rectangleSettingQueued = true;
     270            2 :             g_value_set_string(value, priv->videoRectangle.c_str());
     271              :         }
     272              :         else
     273              :         {
     274            3 :             lock.unlock();
     275            3 :             g_value_set_string(value, client->getVideoRectangle().c_str());
     276              :         }
     277            5 :         break;
     278              :     }
     279            1 :     case PROP_MAX_VIDEO_WIDTH_DEPRECATED:
     280            1 :         GST_WARNING_OBJECT(object, "MaxVideoWidth property is deprecated. Use 'max-video-width' instead");
     281              :     case PROP_MAX_VIDEO_WIDTH:
     282              :     {
     283            2 :         g_value_set_uint(value, priv->maxWidth);
     284            2 :         break;
     285              :     }
     286            1 :     case PROP_MAX_VIDEO_HEIGHT_DEPRECATED:
     287            1 :         GST_WARNING_OBJECT(object, "MaxVideoHeight property is deprecated. Use 'max-video-height' instead");
     288              :     case PROP_MAX_VIDEO_HEIGHT:
     289              :     {
     290            2 :         g_value_set_uint(value, priv->maxHeight);
     291            2 :         break;
     292              :     }
     293            1 :     case PROP_FRAME_STEP_ON_PREROLL:
     294              :     {
     295            1 :         g_value_set_boolean(value, priv->stepOnPrerollEnabled);
     296            1 :         break;
     297              :     }
     298            3 :     case PROP_IMMEDIATE_OUTPUT:
     299              :     {
     300            3 :         std::unique_lock lock{priv->propertyMutex};
     301            3 :         auto client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
     302            3 :         if (!client)
     303              :         {
     304              :             // Return the default value and
     305              :             // queue a setting event (for the default value) so that it will become true when
     306              :             // the client connects...
     307            1 :             GST_DEBUG_OBJECT(object, "Return default immediate-output setting, and queue an event to set the default "
     308              :                                      "upon client connect");
     309            1 :             priv->immediateOutputQueued = true;
     310            1 :             g_value_set_boolean(value, priv->immediateOutput);
     311              :         }
     312              :         else
     313              :         {
     314            2 :             bool immediateOutput{priv->immediateOutput};
     315            2 :             lock.unlock();
     316            2 :             if (!client->getImmediateOutput(sink->parent.priv->m_sourceId, immediateOutput))
     317              :             {
     318            1 :                 GST_ERROR_OBJECT(sink, "Could not get immediate-output");
     319              :             }
     320            2 :             g_value_set_boolean(value, immediateOutput);
     321              :         }
     322            3 :         break;
     323              :     }
     324            1 :     default:
     325            1 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
     326            1 :         break;
     327              :     }
     328              : }
     329              : 
     330           20 : static void rialto_mse_video_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec)
     331              : {
     332           20 :     RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(object);
     333           20 :     if (!sink)
     334              :     {
     335            0 :         GST_ERROR_OBJECT(object, "Sink not initalised");
     336            0 :         return;
     337              :     }
     338           20 :     RialtoMSEVideoSinkPrivate *priv = sink->priv;
     339           20 :     RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
     340           20 :     if (!priv || !basePriv)
     341              :     {
     342            0 :         GST_ERROR_OBJECT(object, "Private sink not initalised");
     343            0 :         return;
     344              :     }
     345              : 
     346           20 :     std::shared_ptr<GStreamerMSEMediaPlayerClient> client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
     347              : 
     348           20 :     switch (propId)
     349              :     {
     350            4 :     case PROP_WINDOW_SET:
     351              :     {
     352            4 :         const gchar *rectangle = g_value_get_string(value);
     353            4 :         if (!rectangle)
     354              :         {
     355            1 :             GST_WARNING_OBJECT(object, "Rectangle string not valid");
     356            1 :             break;
     357              :         }
     358            6 :         std::string videoRectangle{rectangle};
     359            3 :         std::unique_lock lock{priv->propertyMutex};
     360            3 :         priv->videoRectangle = videoRectangle;
     361            3 :         if (!client)
     362              :         {
     363            2 :             GST_DEBUG_OBJECT(object, "Rectangle setting enqueued");
     364            2 :             priv->rectangleSettingQueued = true;
     365              :         }
     366              :         else
     367              :         {
     368            1 :             lock.unlock();
     369            1 :             client->setVideoRectangle(videoRectangle);
     370              :         }
     371            3 :         break;
     372              :     }
     373            1 :     case PROP_MAX_VIDEO_WIDTH:
     374              :     case PROP_MAX_VIDEO_WIDTH_DEPRECATED:
     375            1 :         priv->maxWidth = g_value_get_uint(value);
     376            1 :         break;
     377            1 :     case PROP_MAX_VIDEO_HEIGHT:
     378              :     case PROP_MAX_VIDEO_HEIGHT_DEPRECATED:
     379            1 :         priv->maxHeight = g_value_get_uint(value);
     380            1 :         break;
     381            4 :     case PROP_FRAME_STEP_ON_PREROLL:
     382              :     {
     383            4 :         bool stepOnPrerollEnabled = g_value_get_boolean(value);
     384            4 :         if (client && stepOnPrerollEnabled && !priv->stepOnPrerollEnabled)
     385              :         {
     386            2 :             GST_INFO_OBJECT(object, "Frame stepping on preroll");
     387            2 :             client->renderFrame(RIALTO_MSE_BASE_SINK(sink));
     388              :         }
     389            4 :         priv->stepOnPrerollEnabled = stepOnPrerollEnabled;
     390            4 :         break;
     391              :     }
     392            3 :     case PROP_IMMEDIATE_OUTPUT:
     393              :     {
     394            3 :         bool immediateOutput = (g_value_get_boolean(value) != FALSE);
     395            3 :         std::unique_lock lock{priv->propertyMutex};
     396            3 :         priv->immediateOutput = immediateOutput;
     397            3 :         if (!client)
     398              :         {
     399            1 :             GST_DEBUG_OBJECT(sink, "Immediate output setting enqueued");
     400            1 :             priv->immediateOutputQueued = true;
     401              :         }
     402              :         else
     403              :         {
     404            2 :             lock.unlock();
     405            2 :             if (!client->setImmediateOutput(basePriv->m_sourceId, immediateOutput))
     406              :             {
     407            1 :                 GST_ERROR_OBJECT(sink, "Could not set immediate-output");
     408              :             }
     409              :         }
     410            3 :         break;
     411              :     }
     412            4 :     case PROP_SYNCMODE_STREAMING:
     413              :     {
     414            4 :         bool syncmodeStreaming = (g_value_get_boolean(value) != FALSE);
     415            4 :         std::unique_lock lock{priv->propertyMutex};
     416            4 :         priv->syncmodeStreaming = syncmodeStreaming;
     417            4 :         if (!client)
     418              :         {
     419            2 :             GST_DEBUG_OBJECT(sink, "Syncmode streaming setting enqueued");
     420            2 :             priv->syncmodeStreamingQueued = true;
     421              :         }
     422              :         else
     423              :         {
     424            2 :             lock.unlock();
     425            2 :             if (!client->setStreamSyncMode(basePriv->m_sourceId, syncmodeStreaming))
     426              :             {
     427            1 :                 GST_ERROR_OBJECT(sink, "Could not set syncmode-streaming");
     428              :             }
     429              :         }
     430            4 :         break;
     431              :     }
     432            2 :     case PROP_SHOW_VIDEO_WINDOW:
     433              :     {
     434            2 :         bool showVideoWindow = (g_value_get_boolean(value) == TRUE);
     435            2 :         std::unique_lock lock{priv->propertyMutex};
     436            2 :         priv->showVideoWindow = showVideoWindow;
     437            2 :         if (!client)
     438              :         {
     439            1 :             GST_DEBUG_OBJECT(sink, "Show video window setting enqueued");
     440            1 :             priv->showVideoWindowQueued = true;
     441              :         }
     442              :         else
     443              :         {
     444            1 :             lock.unlock();
     445            1 :             client->setMute(showVideoWindow, basePriv->m_sourceId);
     446              :         }
     447            2 :         break;
     448              :     }
     449            1 :     default:
     450            1 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
     451            1 :         break;
     452              :     }
     453           20 : }
     454              : 
     455            1 : static void rialto_mse_video_sink_qos_handle(GstElement *element, uint64_t processed, uint64_t dropped)
     456              : {
     457            1 :     GstBus *bus = gst_element_get_bus(element);
     458              :     /* Hardcode isLive to FALSE and set invalid timestamps */
     459            1 :     GstMessage *message = gst_message_new_qos(GST_OBJECT(element), FALSE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE,
     460              :                                               GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE);
     461              : 
     462            1 :     gst_message_set_qos_stats(message, GST_FORMAT_BUFFERS, processed, dropped);
     463            1 :     gst_bus_post(bus, message);
     464            1 :     gst_object_unref(bus);
     465              : }
     466              : 
     467           57 : static void rialto_mse_video_sink_init(RialtoMSEVideoSink *sink)
     468              : {
     469           57 :     RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
     470              : 
     471           57 :     sink->priv = static_cast<RialtoMSEVideoSinkPrivate *>(rialto_mse_video_sink_get_instance_private(sink));
     472           57 :     new (sink->priv) RialtoMSEVideoSinkPrivate();
     473              : 
     474           57 :     if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink)))
     475              :     {
     476            0 :         GST_ERROR_OBJECT(sink, "Failed to initialise VIDEO sink. Sink pad initialisation failed.");
     477            0 :         return;
     478              :     }
     479              : 
     480           57 :     basePriv->m_mediaSourceType = firebolt::rialto::MediaSourceType::VIDEO;
     481           57 :     basePriv->m_isAsync = true;
     482           57 :     gst_pad_set_chain_function(basePriv->m_sinkPad, rialto_mse_base_sink_chain);
     483           57 :     gst_pad_set_event_function(basePriv->m_sinkPad, rialto_mse_video_sink_event);
     484              : 
     485          114 :     basePriv->m_callbacks.qosCallback = std::bind(rialto_mse_video_sink_qos_handle, GST_ELEMENT_CAST(sink),
     486           57 :                                                   std::placeholders::_1, std::placeholders::_2);
     487              : }
     488              : 
     489            1 : static void rialto_mse_video_sink_class_init(RialtoMSEVideoSinkClass *klass)
     490              : {
     491            1 :     GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
     492            1 :     GstElementClass *elementClass = GST_ELEMENT_CLASS(klass);
     493            1 :     gobjectClass->get_property = rialto_mse_video_sink_get_property;
     494            1 :     gobjectClass->set_property = rialto_mse_video_sink_set_property;
     495            1 :     elementClass->change_state = rialto_mse_video_sink_change_state;
     496              : 
     497            1 :     g_object_class_install_property(gobjectClass, PROP_WINDOW_SET,
     498              :                                     g_param_spec_string("rectangle", "rectangle", "Window Set Format: x,y,width,height",
     499              :                                                         nullptr, GParamFlags(G_PARAM_READWRITE)));
     500              : 
     501            1 :     g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_WIDTH,
     502              :                                     g_param_spec_uint("max-video-width",
     503              :                                                       "max video width", "Maximum width of video frames to be decoded. Should only be set for video only streams.",
     504              :                                                       0, 3840, DEFAULT_MAX_VIDEO_WIDTH, GParamFlags(G_PARAM_READWRITE)));
     505              : 
     506            1 :     g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_HEIGHT,
     507              :                                     g_param_spec_uint("max-video-height",
     508              :                                                       "max video height", "Maximum height of video frames to be decoded. should only be set for video only streams.",
     509              :                                                       0, 2160, DEFAULT_MAX_VIDEO_HEIGHT, GParamFlags(G_PARAM_READWRITE)));
     510              : 
     511            1 :     g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_WIDTH_DEPRECATED,
     512              :                                     g_param_spec_uint("maxVideoWidth", "maxVideoWidth", "[DEPRECATED] Use max-video-width",
     513              :                                                       0, 3840, DEFAULT_MAX_VIDEO_WIDTH, GParamFlags(G_PARAM_READWRITE)));
     514              : 
     515            1 :     g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_HEIGHT_DEPRECATED,
     516              :                                     g_param_spec_uint("maxVideoHeight", "maxVideoHeight", "[DEPRECATED] max-video-height",
     517              :                                                       0, 2160, DEFAULT_MAX_VIDEO_HEIGHT, GParamFlags(G_PARAM_READWRITE)));
     518              : 
     519            1 :     g_object_class_install_property(gobjectClass, PROP_FRAME_STEP_ON_PREROLL,
     520              :                                     g_param_spec_boolean("frame-step-on-preroll", "frame step on preroll",
     521              :                                                          "allow frame stepping on preroll into pause", FALSE,
     522              :                                                          G_PARAM_READWRITE));
     523              : 
     524              :     std::unique_ptr<firebolt::rialto::IMediaPipelineCapabilities> mediaPlayerCapabilities =
     525            1 :         firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities();
     526            1 :     if (mediaPlayerCapabilities)
     527              :     {
     528              :         std::vector<std::string> supportedMimeTypes =
     529            1 :             mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::VIDEO);
     530              : 
     531            1 :         rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes);
     532              : 
     533            2 :         const std::string kImmediateOutputPropertyName{"immediate-output"};
     534            2 :         const std::string kSyncmodeStreamingPropertyName{"syncmode-streaming"};
     535            1 :         const std::string kShowVideoWindowPropertyName{"show-video-window"};
     536              :         const std::vector<std::string> kPropertyNamesToSearch{kImmediateOutputPropertyName,
     537              :                                                               kSyncmodeStreamingPropertyName,
     538            5 :                                                               kShowVideoWindowPropertyName};
     539              :         std::vector<std::string> supportedProperties{
     540            1 :             mediaPlayerCapabilities->getSupportedProperties(firebolt::rialto::MediaSourceType::VIDEO,
     541            1 :                                                             kPropertyNamesToSearch)};
     542              : 
     543            4 :         for (const auto &propertyName : supportedProperties)
     544              :         {
     545            3 :             if (kImmediateOutputPropertyName == propertyName)
     546              :             {
     547            1 :                 g_object_class_install_property(gobjectClass, PROP_IMMEDIATE_OUTPUT,
     548              :                                                 g_param_spec_boolean(kImmediateOutputPropertyName.c_str(),
     549              :                                                                      "immediate output", "immediate output", TRUE,
     550              :                                                                      GParamFlags(G_PARAM_READWRITE)));
     551              :             }
     552            2 :             else if (kSyncmodeStreamingPropertyName == propertyName)
     553              :             {
     554            1 :                 g_object_class_install_property(gobjectClass, PROP_SYNCMODE_STREAMING,
     555              :                                                 g_param_spec_boolean("syncmode-streaming", "Streaming Sync Mode",
     556              :                                                                      "Enable/disable OTT streaming sync mode", FALSE,
     557              :                                                                      G_PARAM_WRITABLE));
     558              :             }
     559            1 :             else if (kShowVideoWindowPropertyName == propertyName)
     560              :             {
     561            1 :                 g_object_class_install_property(gobjectClass, PROP_SHOW_VIDEO_WINDOW,
     562              :                                                 g_param_spec_boolean(kShowVideoWindowPropertyName.c_str(),
     563              :                                                                      "make video window visible",
     564              :                                                                      "true: visible, false: hidden", TRUE,
     565              :                                                                      G_PARAM_WRITABLE));
     566              :             }
     567              :         }
     568              :     }
     569              :     else
     570              :     {
     571            0 :         GST_ERROR("Failed to get supported mime types for VIDEO");
     572              :     }
     573              : 
     574            1 :     gst_element_class_set_details_simple(elementClass, "Rialto Video Sink", "Decoder/Video/Sink/Video",
     575              :                                          "Communicates with Rialto Server", "Sky");
     576            2 : }
        

Generated by: LCOV version 2.0-1