LCOV - code coverage report
Current view: top level - media/server/gstplayer/source - GstTextTrackSink.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 1.6 % 246 4
Test Date: 2025-10-07 14:22:52 Functions: 6.2 % 16 1

            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 2024 Sky UK
       6              :  *
       7              :  * Licensed under the Apache License, Version 2.0 (the "License");
       8              :  * you may not use this file except in compliance with the License.
       9              :  * You may obtain a copy of the License at
      10              :  *
      11              :  * http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  * Unless required by applicable law or agreed to in writing, software
      14              :  * distributed under the License is distributed on an "AS IS" BASIS,
      15              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  * See the License for the specific language governing permissions and
      17              :  * limitations under the License.
      18              :  */
      19              : 
      20              : #include "GstProtectionMetadataHelperFactory.h"
      21              : #include "GstRialtoTextTrackSinkPrivate.h"
      22              : #include "GstTextTrackSinkFactory.h"
      23              : #include "RialtoServerLogging.h"
      24              : #include <atomic>
      25              : #include <cinttypes>
      26              : #include <cstdlib>
      27              : #include <gst/base/gstbasetransform.h>
      28              : #include <gst/gst.h>
      29              : #include <stdexcept>
      30              : G_BEGIN_DECLS
      31              : 
      32              : enum
      33              : {
      34              :     PROP_0,
      35              :     PROP_MUTE,
      36              :     PROP_TEXT_TRACK_IDENTIFIER,
      37              :     PROP_VIDEO_DECODER,
      38              :     PROP_POSITION,
      39              :     PROP_OFFSET,
      40              :     PROP_LAST
      41              : };
      42              : 
      43              : #define GST_RIALTO_TEXT_TRACK_SINK_TYPE (gst_rialto_text_track_sink_get_type())
      44              : #define GST_RIALTO_TEXT_TRACK_SINK(obj)                                                                                \
      45              :     (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_RIALTO_TEXT_TRACK_SINK_TYPE, GstRialtoTextTrackSink))
      46              : #define GST_RIALTO_TEXT_TRACK_SINK_CLASS(klass)                                                                        \
      47              :     (G_TYPE_CHECK_CLASS_CAST((klass), GST_RIALTO_TEXT_TRACK_SINK_TYPE, GstRialtoTextTrackSinkClass))
      48              : 
      49              : typedef struct _GstRialtoTextTrackSink GstRialtoTextTrackSink;
      50              : typedef struct _GstRialtoTextTrackSinkClass GstRialtoTextTrackSinkClass;
      51              : typedef struct firebolt::rialto::server::GstRialtoTextTrackSinkPrivate GstRialtoTextTrackSinkPrivate;
      52              : 
      53              : GType gst_rialto_text_track_sink_get_type(void); // NOLINT(build/function_format)
      54              : 
      55              : struct _GstRialtoTextTrackSink
      56              : {
      57              :     GstBaseSink parent;
      58              :     GstRialtoTextTrackSinkPrivate *priv;
      59              : };
      60              : 
      61              : struct _GstRialtoTextTrackSinkClass
      62              : {
      63              :     GstBaseSink parentClass;
      64              : };
      65              : 
      66              : G_END_DECLS
      67              : 
      68              : static GstStaticPadTemplate sinkTemplate =
      69              :     GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
      70              :                             GST_STATIC_CAPS("application/ttml+xml; text/vtt; application/x-subtitle-vtt; text/x-raw; "
      71              :                                             "subtitle/x-subtitle-cc"));
      72              : 
      73              : GST_DEBUG_CATEGORY(gst_rialto_text_track_sink_debug_category);
      74              : #define GST_CAT_DEFAULT gst_rialto_text_track_sink_debug_category
      75              : 
      76              : #define gst_rialto_text_track_sink_parent_class parent_class
      77            0 : G_DEFINE_TYPE_WITH_PRIVATE(GstRialtoTextTrackSink, gst_rialto_text_track_sink, GST_TYPE_BASE_SINK);
      78              : 
      79              : static void gst_rialto_text_track_sink_finalize(GObject *object);         // NOLINT(build/function_format)
      80              : static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, // NOLINT(build/function_format)
      81              :                                                        GstBuffer *buffer);
      82              : static gboolean gst_rialto_text_track_sink_set_caps(GstBaseSink *sink, GstCaps *caps); // NOLINT(build/function_format)
      83              : static gboolean gst_rialto_text_track_sink_start(GstBaseSink *sink);                   // NOLINT(build/function_format)
      84              : static gboolean gst_rialto_text_track_sink_stop(GstBaseSink *sink);                    // NOLINT(build/function_format)
      85              : static gboolean gst_rialto_text_track_sink_event(GstBaseSink *sink, GstEvent *event);  // NOLINT(build/function_format)
      86              : static GstStateChangeReturn
      87              : gst_rialto_text_track_sink_change_state(GstElement *element, GstStateChange transition); // NOLINT(build/function_format)
      88              : static void gst_rialto_text_track_sink_get_property(GObject *object, guint propId, // NOLINT(build/function_format)
      89              :                                                     GValue *value, GParamSpec *pspec);
      90              : static void gst_rialto_text_track_sink_set_property(GObject *object, guint propId, // NOLINT(build/function_format)
      91              :                                                     const GValue *value, GParamSpec *pspec);
      92              : static gboolean gst_rialto_text_track_sink_query(GstElement *element, GstQuery *query); // NOLINT(build/function_format)
      93              : 
      94            0 : static void gst_rialto_text_track_sink_class_init(GstRialtoTextTrackSinkClass *klass) // NOLINT(build/function_format)
      95              : {
      96            0 :     GST_DEBUG_CATEGORY_INIT(gst_rialto_text_track_sink_debug_category, "rialto_text_track_sink", 0,
      97              :                             "TextTrack Sink for Rialto");
      98              : 
      99            0 :     GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
     100            0 :     GstElementClass *elementClass = GST_ELEMENT_CLASS(klass);
     101            0 :     GstBaseSinkClass *baseSinkClass = GST_BASE_SINK_CLASS(klass);
     102              : 
     103            0 :     gobjectClass->finalize = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_finalize);
     104            0 :     gobjectClass->get_property = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_get_property);
     105            0 :     gobjectClass->set_property = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_set_property);
     106            0 :     baseSinkClass->start = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_start);
     107            0 :     baseSinkClass->stop = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_stop);
     108            0 :     baseSinkClass->render = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_render);
     109            0 :     baseSinkClass->set_caps = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_set_caps);
     110            0 :     baseSinkClass->event = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_event);
     111            0 :     elementClass->change_state = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_change_state);
     112            0 :     elementClass->query = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_query);
     113              : 
     114            0 :     g_object_class_install_property(gobjectClass, PROP_MUTE,
     115              :                                     g_param_spec_boolean("mute", "Mute", "Mute subtitles", FALSE, G_PARAM_READWRITE));
     116              : 
     117            0 :     g_object_class_install_property(gobjectClass, PROP_TEXT_TRACK_IDENTIFIER,
     118              :                                     g_param_spec_string("text-track-identifier", "Text Track Identifier",
     119              :                                                         "Identifier of text track", nullptr,
     120              :                                                         GParamFlags(G_PARAM_READWRITE)));
     121              : 
     122            0 :     g_object_class_install_property(gobjectClass, PROP_VIDEO_DECODER,
     123              :                                     g_param_spec_uint64("video-decoder", "Video Decoder", "Video Decoder", 0,
     124              :                                                         G_MAXUINT64, 0, GParamFlags(G_PARAM_WRITABLE)));
     125              : 
     126            0 :     g_object_class_install_property(gobjectClass, PROP_POSITION,
     127              :                                     g_param_spec_uint64("position", "Position", "Position", 0, G_MAXUINT64, 0,
     128              :                                                         GParamFlags(G_PARAM_READWRITE)));
     129              : 
     130            0 :     g_object_class_install_property(gobjectClass, PROP_OFFSET,
     131              :                                     g_param_spec_uint64("offset", "Offset", "Offset", 0, G_MAXUINT64, 0,
     132              :                                                         GParamFlags(G_PARAM_WRITABLE)));
     133              : 
     134            0 :     gst_element_class_add_pad_template(elementClass, gst_static_pad_template_get(&sinkTemplate));
     135            0 :     gst_element_class_set_static_metadata(elementClass, "Rialto TextTrack Sink", "Sink/Parser/Subtitle",
     136              :                                           "Rialto TextTrack Sink", "SKY");
     137              : }
     138              : 
     139            0 : static void gst_rialto_text_track_sink_init(GstRialtoTextTrackSink *self) // NOLINT(build/function_format)
     140              : {
     141              :     GstRialtoTextTrackSinkPrivate *priv =
     142            0 :         reinterpret_cast<GstRialtoTextTrackSinkPrivate *>(gst_rialto_text_track_sink_get_instance_private(self));
     143              : 
     144            0 :     self->priv = new (priv) GstRialtoTextTrackSinkPrivate();
     145              : 
     146            0 :     gst_base_sink_set_async_enabled(GST_BASE_SINK(self), FALSE);
     147              : }
     148              : 
     149            0 : static void gst_rialto_text_track_sink_finalize(GObject *object) // NOLINT(build/function_format)
     150              : {
     151            0 :     GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(object);
     152              :     GstRialtoTextTrackSinkPrivate *priv =
     153            0 :         reinterpret_cast<GstRialtoTextTrackSinkPrivate *>(gst_rialto_text_track_sink_get_instance_private(self));
     154              : 
     155            0 :     priv->~GstRialtoTextTrackSinkPrivate();
     156              : 
     157            0 :     GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object));
     158              : }
     159              : 
     160            0 : static gboolean gst_rialto_text_track_sink_start(GstBaseSink *sink) // NOLINT(build/function_format)
     161              : {
     162            0 :     const char *wayland_display = std::getenv("WAYLAND_DISPLAY");
     163            0 :     if (!wayland_display)
     164              :     {
     165            0 :         GST_ERROR_OBJECT(sink, "Failed to get WAYLAND_DISPLAY env variable");
     166            0 :         return false;
     167              :     }
     168              : 
     169            0 :     std::string display{wayland_display};
     170            0 :     GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink);
     171              :     try
     172              :     {
     173            0 :         self->priv->m_textTrackSession =
     174            0 :             firebolt::rialto::server::ITextTrackSessionFactory::getFactory().createTextTrackSession(display);
     175              :     }
     176            0 :     catch (const std::exception &e)
     177              :     {
     178            0 :         GST_ERROR_OBJECT(sink, "Failed to create TextTrackSession. Reason '%s'", e.what());
     179            0 :         return false;
     180              :     }
     181              : 
     182            0 :     GST_INFO_OBJECT(sink, "Successfully started TextTrack sink");
     183            0 :     return true;
     184              : }
     185              : 
     186            0 : static gboolean gst_rialto_text_track_sink_stop(GstBaseSink *sink) // NOLINT(build/function_format)
     187              : {
     188            0 :     GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink);
     189            0 :     self->priv->m_textTrackSession.reset();
     190              : 
     191            0 :     GST_INFO_OBJECT(sink, "Successfully stopped TextTrack sink");
     192            0 :     return true;
     193              : }
     194              : 
     195            0 : static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, GstBuffer *buffer) // NOLINT(build/function_format)
     196              : {
     197            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink);
     198              : 
     199              :     GstMapInfo info;
     200            0 :     if (gst_buffer_map(buffer, &info, GST_MAP_READ))
     201              :     {
     202            0 :         std::string data(reinterpret_cast<char *>(info.data), info.size);
     203            0 :         int64_t displayOffset{0};
     204            0 :         if (GST_BUFFER_OFFSET_NONE != GST_BUFFER_OFFSET(buffer))
     205              :         {
     206            0 :             displayOffset = static_cast<int64_t>(GST_BUFFER_OFFSET(buffer));
     207              :         }
     208            0 :         textTrackSink->priv->m_textTrackSession->sendData(data, 0 - displayOffset);
     209              : 
     210            0 :         gst_buffer_unmap(buffer, &info);
     211              :     }
     212              :     else
     213              :     {
     214            0 :         GST_ERROR_OBJECT(textTrackSink, "Failed to map buffer");
     215            0 :         return GST_FLOW_ERROR;
     216              :     }
     217              : 
     218            0 :     return GST_FLOW_OK;
     219              : }
     220              : 
     221            0 : static gboolean gst_rialto_text_track_sink_set_position(GstRialtoTextTrackSink *textTrackSink) // NOLINT(build/function_format)
     222              : {
     223            0 :     if (!textTrackSink->priv->m_textTrackSession)
     224              :     {
     225            0 :         GST_ERROR_OBJECT(textTrackSink, "Session is NULL");
     226            0 :         return FALSE;
     227              :     }
     228              : 
     229            0 :     uint64_t positionWithOffset = textTrackSink->priv->m_position.value_or(0) + textTrackSink->priv->m_offset.value_or(0);
     230              : 
     231            0 :     GST_DEBUG_OBJECT(textTrackSink,
     232              :                      "Setting position to %" GST_TIME_FORMAT " (pts %" GST_TIME_FORMAT ", offset %" GST_TIME_FORMAT ")",
     233              :                      GST_TIME_ARGS(positionWithOffset), GST_TIME_ARGS(textTrackSink->priv->m_position.value_or(0)),
     234              :                      GST_TIME_ARGS(textTrackSink->priv->m_offset.value_or(0)));
     235              : 
     236            0 :     textTrackSink->priv->m_textTrackSession->setPosition(positionWithOffset / GST_MSECOND);
     237            0 :     return TRUE;
     238              : }
     239              : 
     240            0 : static gboolean gst_rialto_text_track_sink_set_caps(GstBaseSink *sink, GstCaps *caps) // NOLINT(build/function_format)
     241              : {
     242            0 :     GST_INFO_OBJECT(sink, "Setting caps %" GST_PTR_FORMAT, caps);
     243            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink);
     244              : 
     245            0 :     GstStructure *structure = gst_caps_get_structure(caps, 0);
     246            0 :     const gchar *mimeName = gst_structure_get_name(structure);
     247              : 
     248            0 :     if (g_str_has_prefix(mimeName, "text/vtt") || g_str_has_prefix(mimeName, "application/x-subtitle-vtt"))
     249              :     {
     250            0 :         GST_INFO_OBJECT(sink, "Setting session to WebVTT");
     251            0 :         textTrackSink->priv->m_textTrackSession->setSessionWebVTTSelection();
     252              :     }
     253            0 :     else if (g_str_has_prefix(mimeName, "application/ttml+xml"))
     254              :     {
     255            0 :         GST_INFO_OBJECT(sink, "Setting session to TTML");
     256            0 :         textTrackSink->priv->m_textTrackSession->setSessionTTMLSelection();
     257              :     }
     258            0 :     else if (g_str_has_prefix(mimeName, "subtitle/x-subtitle-cc"))
     259              :     {
     260            0 :         GST_INFO_OBJECT(sink, "Setting session to CC");
     261            0 :         std::string identifier = "CC1";
     262            0 :         if (textTrackSink->priv->m_textTrackIdentifier.empty())
     263              :         {
     264            0 :             GST_WARNING_OBJECT(sink, "No text track identifier set, defaulting to %s", identifier.c_str());
     265              :         }
     266              :         else
     267              :         {
     268            0 :             identifier = textTrackSink->priv->m_textTrackIdentifier;
     269              :         }
     270            0 :         textTrackSink->priv->m_textTrackSession->setSessionCCSelection(identifier);
     271              : 
     272            0 :         if (textTrackSink->priv->m_videoDecoderIdentifier)
     273              :         {
     274            0 :             textTrackSink->priv->m_textTrackSession->associateVideoDecoder(textTrackSink->priv->m_videoDecoderIdentifier);
     275              :         }
     276              :     }
     277              :     else
     278              :     {
     279            0 :         GST_ERROR_OBJECT(sink, "Invalid mime name '%s'", mimeName);
     280            0 :         return FALSE;
     281              :     }
     282              : 
     283            0 :     textTrackSink->priv->m_textTrackSession->mute(textTrackSink->priv->m_isMuted);
     284              : 
     285            0 :     std::unique_lock lock{textTrackSink->priv->m_mutex};
     286            0 :     textTrackSink->priv->m_capsSet = true;
     287            0 :     bool wasAnyQueued = textTrackSink->priv->m_queuedPosition.has_value() ||
     288            0 :                         textTrackSink->priv->m_queuedOffset.has_value();
     289            0 :     if (textTrackSink->priv->m_queuedPosition.has_value())
     290              :     {
     291            0 :         textTrackSink->priv->m_position = textTrackSink->priv->m_queuedPosition;
     292            0 :         textTrackSink->priv->m_queuedPosition.reset();
     293              :     }
     294            0 :     if (textTrackSink->priv->m_queuedOffset.has_value())
     295              :     {
     296            0 :         textTrackSink->priv->m_offset = textTrackSink->priv->m_queuedOffset;
     297            0 :         textTrackSink->priv->m_queuedOffset.reset();
     298              :     }
     299            0 :     if (wasAnyQueued)
     300              :     {
     301            0 :         gst_rialto_text_track_sink_set_position(textTrackSink);
     302              :     }
     303              : 
     304            0 :     return TRUE;
     305              : }
     306              : 
     307            0 : static gboolean gst_rialto_text_track_sink_event(GstBaseSink *sink, GstEvent *event) // NOLINT(build/function_format)
     308              : {
     309            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink);
     310            0 :     GST_DEBUG_OBJECT(textTrackSink, "handling event %" GST_PTR_FORMAT, event);
     311              : 
     312            0 :     switch (GST_EVENT_TYPE(event))
     313              :     {
     314            0 :     case GST_EVENT_FLUSH_START:
     315              :     {
     316            0 :         if (!textTrackSink->priv->m_textTrackSession->resetSession(textTrackSink->priv->m_isMuted))
     317              :         {
     318            0 :             GST_ERROR_OBJECT(textTrackSink, "Failed to reset TextTrack session");
     319              :         }
     320            0 :         break;
     321              :     }
     322            0 :     case GST_EVENT_FLUSH_STOP:
     323              :     {
     324            0 :         break;
     325              :     }
     326            0 :     case GST_EVENT_CUSTOM_DOWNSTREAM:
     327              :     case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
     328              :     {
     329            0 :         if (gst_event_has_name(event, "current-pts"))
     330              :         {
     331            0 :             uint64_t pts = 0;
     332            0 :             const GstStructure *structure = gst_event_get_structure(event);
     333            0 :             if (structure)
     334              :             {
     335            0 :                 if (gst_structure_get_uint64(structure, "pts", &pts))
     336              :                 {
     337            0 :                     if (pts == GST_CLOCK_TIME_NONE)
     338              :                     {
     339            0 :                         GST_ERROR_OBJECT(textTrackSink, "Invalid PTS value");
     340            0 :                         return FALSE;
     341              :                     }
     342              : 
     343            0 :                     std::unique_lock lock{textTrackSink->priv->m_mutex};
     344            0 :                     textTrackSink->priv->m_position = pts;
     345              : 
     346            0 :                     gst_rialto_text_track_sink_set_position(textTrackSink);
     347              :                 }
     348              :                 else
     349              :                 {
     350            0 :                     GST_ERROR_OBJECT(textTrackSink, "Failed to get PTS from structure");
     351            0 :                     return FALSE;
     352              :                 }
     353              :             }
     354              :             else
     355              :             {
     356            0 :                 GST_ERROR_OBJECT(textTrackSink, "Failed to get structure from event");
     357            0 :                 return FALSE;
     358              :             }
     359              :         }
     360            0 :         break;
     361              :     }
     362            0 :     default:
     363              :     {
     364            0 :         break;
     365              :     }
     366              :     }
     367              : 
     368            0 :     return GST_BASE_SINK_CLASS(parent_class)->event(sink, event);
     369              : }
     370              : 
     371              : static GstStateChangeReturn
     372            0 : gst_rialto_text_track_sink_change_state(GstElement *element, GstStateChange transition) // NOLINT(build/function_format)
     373              : {
     374            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(element);
     375              : 
     376            0 :     GstState current_state = GST_STATE_TRANSITION_CURRENT(transition);
     377            0 :     GstState next_state = GST_STATE_TRANSITION_NEXT(transition);
     378            0 :     GST_INFO_OBJECT(textTrackSink, "State change: (%s) -> (%s)", gst_element_state_get_name(current_state),
     379              :                     gst_element_state_get_name(next_state));
     380              : 
     381            0 :     switch (transition)
     382              :     {
     383            0 :     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
     384              :     {
     385            0 :         if (!textTrackSink->priv->m_textTrackSession->play())
     386              :         {
     387            0 :             GST_ERROR_OBJECT(textTrackSink, "Failed to play textTrack session");
     388            0 :             return GST_STATE_CHANGE_FAILURE;
     389              :         }
     390            0 :         break;
     391              :     }
     392            0 :     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
     393              :     {
     394            0 :         if (!textTrackSink->priv->m_textTrackSession->pause())
     395              :         {
     396            0 :             GST_ERROR_OBJECT(textTrackSink, "Failed to pause textTrack session");
     397            0 :             return GST_STATE_CHANGE_FAILURE;
     398              :         }
     399              : 
     400            0 :         break;
     401              :     }
     402            0 :     default:
     403            0 :         break;
     404              :     }
     405              : 
     406            0 :     GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
     407            0 :     if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE))
     408              :     {
     409            0 :         GST_WARNING_OBJECT(textTrackSink, "State change failed");
     410            0 :         return result;
     411              :     }
     412              : 
     413            0 :     return GST_STATE_CHANGE_SUCCESS;
     414              : }
     415              : 
     416            0 : static void gst_rialto_text_track_sink_get_property(GObject *object, guint propId, // NOLINT(build/function_format)
     417              :                                                     GValue *value, GParamSpec *pspec)
     418              : {
     419            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(object);
     420            0 :     if (!textTrackSink)
     421              :     {
     422            0 :         GST_ERROR_OBJECT(textTrackSink, "Sink not initalised");
     423            0 :         return;
     424              :     }
     425            0 :     GstRialtoTextTrackSinkPrivate *priv = textTrackSink->priv;
     426              : 
     427            0 :     switch (propId)
     428              :     {
     429            0 :     case PROP_MUTE:
     430              :     {
     431            0 :         g_value_set_boolean(value, priv->m_isMuted.load());
     432            0 :         break;
     433              :     }
     434            0 :     case PROP_TEXT_TRACK_IDENTIFIER:
     435              :     {
     436            0 :         g_value_set_string(value, priv->m_textTrackIdentifier.c_str());
     437            0 :         break;
     438              :     }
     439            0 :     case PROP_POSITION:
     440              :     {
     441              :         // Thunder ITextTrack does not provide getPosition API so we are unable to determine current position
     442            0 :         g_value_set_uint64(value, GST_CLOCK_TIME_NONE);
     443            0 :         break;
     444              :     }
     445            0 :     default:
     446            0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
     447            0 :         break;
     448              :     }
     449              : }
     450              : 
     451            0 : static void gst_rialto_text_track_sink_set_property(GObject *object, guint propId, // NOLINT(build/function_format)
     452              :                                                     const GValue *value, GParamSpec *pspec)
     453              : {
     454            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(object);
     455            0 :     if (!textTrackSink)
     456              :     {
     457            0 :         GST_ERROR_OBJECT(textTrackSink, "Sink not initalised");
     458            0 :         return;
     459              :     }
     460            0 :     GstRialtoTextTrackSinkPrivate *priv = textTrackSink->priv;
     461              : 
     462            0 :     switch (propId)
     463              :     {
     464            0 :     case PROP_MUTE:
     465              :     {
     466            0 :         priv->m_isMuted = g_value_get_boolean(value);
     467            0 :         if (priv->m_textTrackSession)
     468              :         {
     469            0 :             priv->m_textTrackSession->mute(priv->m_isMuted);
     470              :         }
     471            0 :         break;
     472              :     }
     473            0 :     case PROP_TEXT_TRACK_IDENTIFIER:
     474              :     {
     475            0 :         priv->m_textTrackIdentifier = g_value_get_string(value);
     476            0 :         if (priv->m_textTrackSession && priv->m_textTrackSession->isClosedCaptions())
     477              :         {
     478            0 :             priv->m_textTrackSession->setSessionCCSelection(priv->m_textTrackIdentifier);
     479              :         }
     480              : 
     481            0 :         break;
     482              :     }
     483            0 :     case PROP_VIDEO_DECODER:
     484              :     {
     485            0 :         priv->m_videoDecoderIdentifier = g_value_get_uint64(value);
     486            0 :         if (priv->m_textTrackSession && priv->m_textTrackSession->isClosedCaptions())
     487              :         {
     488            0 :             priv->m_textTrackSession->associateVideoDecoder(priv->m_videoDecoderIdentifier);
     489              :         }
     490              : 
     491            0 :         break;
     492              :     }
     493            0 :     case PROP_POSITION:
     494              :     {
     495            0 :         guint64 position = g_value_get_uint64(value);
     496            0 :         std::unique_lock lock{priv->m_mutex};
     497            0 :         if (priv->m_textTrackSession && priv->m_capsSet)
     498              :         {
     499            0 :             priv->m_position = position;
     500            0 :             gst_rialto_text_track_sink_set_position(textTrackSink);
     501              :         }
     502              :         else
     503              :         {
     504            0 :             priv->m_queuedPosition = position;
     505              :         }
     506            0 :         break;
     507              :     }
     508            0 :     case PROP_OFFSET:
     509              :     {
     510            0 :         uint64_t offset = g_value_get_uint64(value);
     511            0 :         std::unique_lock lock{priv->m_mutex};
     512            0 :         if (priv->m_textTrackSession && priv->m_capsSet)
     513              :         {
     514            0 :             priv->m_offset = offset;
     515            0 :             gst_rialto_text_track_sink_set_position(textTrackSink);
     516              :         }
     517              :         else
     518              :         {
     519            0 :             priv->m_queuedOffset = offset;
     520              :         }
     521            0 :         break;
     522              :     }
     523              : 
     524            0 :     default:
     525            0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
     526            0 :         break;
     527              :     }
     528              : }
     529              : 
     530            0 : static gboolean gst_rialto_text_track_sink_query(GstElement *element, GstQuery *query) // NOLINT(build/function_format)
     531              : {
     532            0 :     GstRialtoTextTrackSink *sink = GST_RIALTO_TEXT_TRACK_SINK(element);
     533            0 :     GST_DEBUG_OBJECT(sink, "handling query '%s'", GST_QUERY_TYPE_NAME(query));
     534            0 :     switch (GST_QUERY_TYPE(query))
     535              :     {
     536            0 :     case GST_QUERY_POSITION:
     537              :     {
     538              :         GstFormat fmt;
     539            0 :         gst_query_parse_position(query, &fmt, NULL);
     540            0 :         switch (fmt)
     541              :         {
     542            0 :         case GST_FORMAT_TIME:
     543              :         {
     544              :             // GST_CLOCK_TIME_NONE has to be returned here, because otherwise whole pipeline returns incorrect position
     545            0 :             gst_query_set_position(query, fmt, GST_CLOCK_TIME_NONE);
     546            0 :             break;
     547              :         }
     548            0 :         default:
     549            0 :             break;
     550              :         }
     551            0 :         return TRUE;
     552              :     }
     553            0 :     default:
     554            0 :         break;
     555              :     }
     556            0 :     GstElement *parent = GST_ELEMENT(&sink->parent);
     557            0 :     return GST_ELEMENT_CLASS(parent_class)->query(parent, query);
     558              : }
     559              : 
     560              : namespace firebolt::rialto::server
     561              : {
     562            1 : std::shared_ptr<IGstTextTrackSinkFactory> IGstTextTrackSinkFactory::createFactory()
     563              : {
     564            1 :     std::shared_ptr<IGstTextTrackSinkFactory> factory;
     565              : 
     566              :     try
     567              :     {
     568            1 :         factory = std::make_shared<GstTextTrackSinkFactory>();
     569              :     }
     570            0 :     catch (const std::exception &e)
     571              :     {
     572            0 :         RIALTO_SERVER_LOG_ERROR("Failed to create the textTrackSink element factory, reason: %s", e.what());
     573              :     }
     574              : 
     575            1 :     return factory;
     576              : }
     577              : 
     578            0 : GstElement *GstTextTrackSinkFactory::createGstTextTrackSink() const
     579              : {
     580            0 :     GstElement *elem = GST_ELEMENT(g_object_new(GST_RIALTO_TEXT_TRACK_SINK_TYPE, nullptr));
     581              : 
     582            0 :     return elem;
     583              : }
     584              : 
     585              : }; // namespace firebolt::rialto::server
        

Generated by: LCOV version 2.0-1