LCOV - code coverage report
Current view: top level - media/server/gstplayer/source - GstTextTrackSink.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 1.7 % 242 4
Test Date: 2026-01-28 07:54:01 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_pointer("video-decoder", "Video Decoder", "Video Decoder",
     124              :                                                          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 std::string kDisplay{"westeros-asplayer-subtitles"};
     163            0 :     GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink);
     164              :     try
     165              :     {
     166            0 :         self->priv->m_textTrackSession =
     167            0 :             firebolt::rialto::server::ITextTrackSessionFactory::getFactory().createTextTrackSession(kDisplay);
     168              :     }
     169            0 :     catch (const std::exception &e)
     170              :     {
     171            0 :         GST_ERROR_OBJECT(sink, "Failed to create TextTrackSession. Reason '%s'", e.what());
     172            0 :         return false;
     173              :     }
     174              : 
     175            0 :     GST_INFO_OBJECT(sink, "Successfully started TextTrack sink");
     176            0 :     return true;
     177              : }
     178              : 
     179            0 : static gboolean gst_rialto_text_track_sink_stop(GstBaseSink *sink) // NOLINT(build/function_format)
     180              : {
     181            0 :     GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink);
     182            0 :     self->priv->m_textTrackSession.reset();
     183              : 
     184            0 :     GST_INFO_OBJECT(sink, "Successfully stopped TextTrack sink");
     185            0 :     return true;
     186              : }
     187              : 
     188            0 : static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, GstBuffer *buffer) // NOLINT(build/function_format)
     189              : {
     190            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink);
     191              : 
     192              :     GstMapInfo info;
     193            0 :     if (gst_buffer_map(buffer, &info, GST_MAP_READ))
     194              :     {
     195            0 :         std::string data(reinterpret_cast<char *>(info.data), info.size);
     196            0 :         int64_t displayOffset{0};
     197            0 :         if (GST_BUFFER_OFFSET_NONE != GST_BUFFER_OFFSET(buffer))
     198              :         {
     199            0 :             displayOffset = static_cast<int64_t>(GST_BUFFER_OFFSET(buffer));
     200              :         }
     201            0 :         textTrackSink->priv->m_textTrackSession->sendData(data, 0 - displayOffset);
     202              : 
     203            0 :         gst_buffer_unmap(buffer, &info);
     204              :     }
     205              :     else
     206              :     {
     207            0 :         GST_ERROR_OBJECT(textTrackSink, "Failed to map buffer");
     208            0 :         return GST_FLOW_ERROR;
     209              :     }
     210              : 
     211            0 :     return GST_FLOW_OK;
     212              : }
     213              : 
     214            0 : static gboolean gst_rialto_text_track_sink_set_position(GstRialtoTextTrackSink *textTrackSink) // NOLINT(build/function_format)
     215              : {
     216            0 :     if (!textTrackSink->priv->m_textTrackSession)
     217              :     {
     218            0 :         GST_ERROR_OBJECT(textTrackSink, "Session is NULL");
     219            0 :         return FALSE;
     220              :     }
     221              : 
     222            0 :     uint64_t positionWithOffset = textTrackSink->priv->m_position.value_or(0) + textTrackSink->priv->m_offset.value_or(0);
     223              : 
     224            0 :     GST_DEBUG_OBJECT(textTrackSink,
     225              :                      "Setting position to %" GST_TIME_FORMAT " (pts %" GST_TIME_FORMAT ", offset %" GST_TIME_FORMAT ")",
     226              :                      GST_TIME_ARGS(positionWithOffset), GST_TIME_ARGS(textTrackSink->priv->m_position.value_or(0)),
     227              :                      GST_TIME_ARGS(textTrackSink->priv->m_offset.value_or(0)));
     228              : 
     229            0 :     textTrackSink->priv->m_textTrackSession->setPosition(positionWithOffset / GST_MSECOND);
     230            0 :     return TRUE;
     231              : }
     232              : 
     233            0 : static gboolean gst_rialto_text_track_sink_set_caps(GstBaseSink *sink, GstCaps *caps) // NOLINT(build/function_format)
     234              : {
     235            0 :     GST_INFO_OBJECT(sink, "Setting caps %" GST_PTR_FORMAT, caps);
     236            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink);
     237              : 
     238            0 :     GstStructure *structure = gst_caps_get_structure(caps, 0);
     239            0 :     const gchar *mimeName = gst_structure_get_name(structure);
     240              : 
     241            0 :     if (g_str_has_prefix(mimeName, "text/vtt") || g_str_has_prefix(mimeName, "application/x-subtitle-vtt"))
     242              :     {
     243            0 :         GST_INFO_OBJECT(sink, "Setting session to WebVTT");
     244            0 :         textTrackSink->priv->m_textTrackSession->setSessionWebVTTSelection();
     245              :     }
     246            0 :     else if (g_str_has_prefix(mimeName, "application/ttml+xml"))
     247              :     {
     248            0 :         GST_INFO_OBJECT(sink, "Setting session to TTML");
     249            0 :         textTrackSink->priv->m_textTrackSession->setSessionTTMLSelection();
     250              :     }
     251            0 :     else if (g_str_has_prefix(mimeName, "subtitle/x-subtitle-cc"))
     252              :     {
     253            0 :         GST_INFO_OBJECT(sink, "Setting session to CC");
     254            0 :         std::string identifier = "CC1";
     255            0 :         if (textTrackSink->priv->m_textTrackIdentifier.empty())
     256              :         {
     257            0 :             GST_WARNING_OBJECT(sink, "No text track identifier set, defaulting to %s", identifier.c_str());
     258              :         }
     259              :         else
     260              :         {
     261            0 :             identifier = textTrackSink->priv->m_textTrackIdentifier;
     262              :         }
     263            0 :         textTrackSink->priv->m_textTrackSession->setSessionCCSelection(identifier);
     264              : 
     265            0 :         if (textTrackSink->priv->m_videoDecoderIdentifier)
     266              :         {
     267            0 :             textTrackSink->priv->m_textTrackSession->associateVideoDecoder(textTrackSink->priv->m_videoDecoderIdentifier);
     268              :         }
     269              :     }
     270              :     else
     271              :     {
     272            0 :         GST_ERROR_OBJECT(sink, "Invalid mime name '%s'", mimeName);
     273            0 :         return FALSE;
     274              :     }
     275              : 
     276            0 :     textTrackSink->priv->m_textTrackSession->mute(textTrackSink->priv->m_isMuted);
     277              : 
     278            0 :     std::unique_lock lock{textTrackSink->priv->m_mutex};
     279            0 :     textTrackSink->priv->m_capsSet = true;
     280            0 :     bool wasAnyQueued = textTrackSink->priv->m_queuedPosition.has_value() ||
     281            0 :                         textTrackSink->priv->m_queuedOffset.has_value();
     282            0 :     if (textTrackSink->priv->m_queuedPosition.has_value())
     283              :     {
     284            0 :         textTrackSink->priv->m_position = textTrackSink->priv->m_queuedPosition;
     285            0 :         textTrackSink->priv->m_queuedPosition.reset();
     286              :     }
     287            0 :     if (textTrackSink->priv->m_queuedOffset.has_value())
     288              :     {
     289            0 :         textTrackSink->priv->m_offset = textTrackSink->priv->m_queuedOffset;
     290            0 :         textTrackSink->priv->m_queuedOffset.reset();
     291              :     }
     292            0 :     if (wasAnyQueued)
     293              :     {
     294            0 :         gst_rialto_text_track_sink_set_position(textTrackSink);
     295              :     }
     296              : 
     297            0 :     return TRUE;
     298              : }
     299              : 
     300            0 : static gboolean gst_rialto_text_track_sink_event(GstBaseSink *sink, GstEvent *event) // NOLINT(build/function_format)
     301              : {
     302            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink);
     303            0 :     GST_DEBUG_OBJECT(textTrackSink, "handling event %" GST_PTR_FORMAT, event);
     304              : 
     305            0 :     switch (GST_EVENT_TYPE(event))
     306              :     {
     307            0 :     case GST_EVENT_FLUSH_START:
     308              :     {
     309            0 :         if (!textTrackSink->priv->m_textTrackSession->resetSession(textTrackSink->priv->m_isMuted))
     310              :         {
     311            0 :             GST_ERROR_OBJECT(textTrackSink, "Failed to reset TextTrack session");
     312              :         }
     313            0 :         break;
     314              :     }
     315            0 :     case GST_EVENT_FLUSH_STOP:
     316              :     {
     317            0 :         break;
     318              :     }
     319            0 :     case GST_EVENT_CUSTOM_DOWNSTREAM:
     320              :     case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
     321              :     {
     322            0 :         if (gst_event_has_name(event, "current-pts"))
     323              :         {
     324            0 :             uint64_t pts = 0;
     325            0 :             const GstStructure *structure = gst_event_get_structure(event);
     326            0 :             if (structure)
     327              :             {
     328            0 :                 if (gst_structure_get_uint64(structure, "pts", &pts))
     329              :                 {
     330            0 :                     if (pts == GST_CLOCK_TIME_NONE)
     331              :                     {
     332            0 :                         GST_ERROR_OBJECT(textTrackSink, "Invalid PTS value");
     333            0 :                         return FALSE;
     334              :                     }
     335              : 
     336            0 :                     std::unique_lock lock{textTrackSink->priv->m_mutex};
     337            0 :                     textTrackSink->priv->m_position = pts;
     338              : 
     339            0 :                     gst_rialto_text_track_sink_set_position(textTrackSink);
     340              :                 }
     341              :                 else
     342              :                 {
     343            0 :                     GST_ERROR_OBJECT(textTrackSink, "Failed to get PTS from structure");
     344            0 :                     return FALSE;
     345              :                 }
     346              :             }
     347              :             else
     348              :             {
     349            0 :                 GST_ERROR_OBJECT(textTrackSink, "Failed to get structure from event");
     350            0 :                 return FALSE;
     351              :             }
     352              :         }
     353            0 :         break;
     354              :     }
     355            0 :     default:
     356              :     {
     357            0 :         break;
     358              :     }
     359              :     }
     360              : 
     361            0 :     return GST_BASE_SINK_CLASS(parent_class)->event(sink, event);
     362              : }
     363              : 
     364              : static GstStateChangeReturn
     365            0 : gst_rialto_text_track_sink_change_state(GstElement *element, GstStateChange transition) // NOLINT(build/function_format)
     366              : {
     367            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(element);
     368              : 
     369            0 :     GstState current_state = GST_STATE_TRANSITION_CURRENT(transition);
     370            0 :     GstState next_state = GST_STATE_TRANSITION_NEXT(transition);
     371            0 :     GST_INFO_OBJECT(textTrackSink, "State change: (%s) -> (%s)", gst_element_state_get_name(current_state),
     372              :                     gst_element_state_get_name(next_state));
     373              : 
     374            0 :     switch (transition)
     375              :     {
     376            0 :     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
     377              :     {
     378            0 :         if (!textTrackSink->priv->m_textTrackSession->play())
     379              :         {
     380            0 :             GST_ERROR_OBJECT(textTrackSink, "Failed to play textTrack session");
     381            0 :             return GST_STATE_CHANGE_FAILURE;
     382              :         }
     383            0 :         break;
     384              :     }
     385            0 :     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
     386              :     {
     387            0 :         if (!textTrackSink->priv->m_textTrackSession->pause())
     388              :         {
     389            0 :             GST_ERROR_OBJECT(textTrackSink, "Failed to pause textTrack session");
     390            0 :             return GST_STATE_CHANGE_FAILURE;
     391              :         }
     392              : 
     393            0 :         break;
     394              :     }
     395            0 :     default:
     396            0 :         break;
     397              :     }
     398              : 
     399            0 :     GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
     400            0 :     if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE))
     401              :     {
     402            0 :         GST_WARNING_OBJECT(textTrackSink, "State change failed");
     403            0 :         return result;
     404              :     }
     405              : 
     406            0 :     return GST_STATE_CHANGE_SUCCESS;
     407              : }
     408              : 
     409            0 : static void gst_rialto_text_track_sink_get_property(GObject *object, guint propId, // NOLINT(build/function_format)
     410              :                                                     GValue *value, GParamSpec *pspec)
     411              : {
     412            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(object);
     413            0 :     if (!textTrackSink)
     414              :     {
     415            0 :         GST_ERROR_OBJECT(textTrackSink, "Sink not initalised");
     416            0 :         return;
     417              :     }
     418            0 :     GstRialtoTextTrackSinkPrivate *priv = textTrackSink->priv;
     419              : 
     420            0 :     switch (propId)
     421              :     {
     422            0 :     case PROP_MUTE:
     423              :     {
     424            0 :         g_value_set_boolean(value, priv->m_isMuted.load());
     425            0 :         break;
     426              :     }
     427            0 :     case PROP_TEXT_TRACK_IDENTIFIER:
     428              :     {
     429            0 :         g_value_set_string(value, priv->m_textTrackIdentifier.c_str());
     430            0 :         break;
     431              :     }
     432            0 :     case PROP_POSITION:
     433              :     {
     434              :         // Thunder ITextTrack does not provide getPosition API so we are unable to determine current position
     435            0 :         g_value_set_uint64(value, GST_CLOCK_TIME_NONE);
     436            0 :         break;
     437              :     }
     438            0 :     default:
     439            0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
     440            0 :         break;
     441              :     }
     442              : }
     443              : 
     444            0 : static void gst_rialto_text_track_sink_set_property(GObject *object, guint propId, // NOLINT(build/function_format)
     445              :                                                     const GValue *value, GParamSpec *pspec)
     446              : {
     447            0 :     GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(object);
     448            0 :     if (!textTrackSink)
     449              :     {
     450            0 :         GST_ERROR_OBJECT(textTrackSink, "Sink not initalised");
     451            0 :         return;
     452              :     }
     453            0 :     GstRialtoTextTrackSinkPrivate *priv = textTrackSink->priv;
     454              : 
     455            0 :     switch (propId)
     456              :     {
     457            0 :     case PROP_MUTE:
     458              :     {
     459            0 :         priv->m_isMuted = g_value_get_boolean(value);
     460            0 :         if (priv->m_textTrackSession)
     461              :         {
     462            0 :             priv->m_textTrackSession->mute(priv->m_isMuted);
     463              :         }
     464            0 :         break;
     465              :     }
     466            0 :     case PROP_TEXT_TRACK_IDENTIFIER:
     467              :     {
     468            0 :         priv->m_textTrackIdentifier = g_value_get_string(value);
     469            0 :         if (priv->m_textTrackSession && priv->m_textTrackSession->isClosedCaptions())
     470              :         {
     471            0 :             priv->m_textTrackSession->setSessionCCSelection(priv->m_textTrackIdentifier);
     472              :         }
     473              : 
     474            0 :         break;
     475              :     }
     476            0 :     case PROP_VIDEO_DECODER:
     477              :     {
     478            0 :         priv->m_videoDecoderIdentifier = g_value_get_pointer(value);
     479              : 
     480            0 :         if (priv->m_textTrackSession && priv->m_textTrackSession->isClosedCaptions())
     481              :         {
     482            0 :             priv->m_textTrackSession->associateVideoDecoder(priv->m_videoDecoderIdentifier);
     483              :         }
     484              : 
     485            0 :         break;
     486              :     }
     487            0 :     case PROP_POSITION:
     488              :     {
     489            0 :         guint64 position = g_value_get_uint64(value);
     490            0 :         std::unique_lock lock{priv->m_mutex};
     491            0 :         if (priv->m_textTrackSession && priv->m_capsSet)
     492              :         {
     493            0 :             priv->m_position = position;
     494            0 :             gst_rialto_text_track_sink_set_position(textTrackSink);
     495              :         }
     496              :         else
     497              :         {
     498            0 :             priv->m_queuedPosition = position;
     499              :         }
     500            0 :         break;
     501              :     }
     502            0 :     case PROP_OFFSET:
     503              :     {
     504            0 :         uint64_t offset = g_value_get_uint64(value);
     505            0 :         std::unique_lock lock{priv->m_mutex};
     506            0 :         if (priv->m_textTrackSession && priv->m_capsSet)
     507              :         {
     508            0 :             priv->m_offset = offset;
     509            0 :             gst_rialto_text_track_sink_set_position(textTrackSink);
     510              :         }
     511              :         else
     512              :         {
     513            0 :             priv->m_queuedOffset = offset;
     514              :         }
     515            0 :         break;
     516              :     }
     517              : 
     518            0 :     default:
     519            0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
     520            0 :         break;
     521              :     }
     522              : }
     523              : 
     524            0 : static gboolean gst_rialto_text_track_sink_query(GstElement *element, GstQuery *query) // NOLINT(build/function_format)
     525              : {
     526            0 :     GstRialtoTextTrackSink *sink = GST_RIALTO_TEXT_TRACK_SINK(element);
     527            0 :     GST_DEBUG_OBJECT(sink, "handling query '%s'", GST_QUERY_TYPE_NAME(query));
     528            0 :     switch (GST_QUERY_TYPE(query))
     529              :     {
     530            0 :     case GST_QUERY_POSITION:
     531              :     {
     532              :         GstFormat fmt;
     533            0 :         gst_query_parse_position(query, &fmt, NULL);
     534            0 :         switch (fmt)
     535              :         {
     536            0 :         case GST_FORMAT_TIME:
     537              :         {
     538              :             // GST_CLOCK_TIME_NONE has to be returned here, because otherwise whole pipeline returns incorrect position
     539            0 :             gst_query_set_position(query, fmt, GST_CLOCK_TIME_NONE);
     540            0 :             break;
     541              :         }
     542            0 :         default:
     543            0 :             break;
     544              :         }
     545            0 :         return TRUE;
     546              :     }
     547            0 :     default:
     548            0 :         break;
     549              :     }
     550            0 :     GstElement *parent = GST_ELEMENT(&sink->parent);
     551            0 :     return GST_ELEMENT_CLASS(parent_class)->query(parent, query);
     552              : }
     553              : 
     554              : namespace firebolt::rialto::server
     555              : {
     556            1 : std::shared_ptr<IGstTextTrackSinkFactory> IGstTextTrackSinkFactory::createFactory()
     557              : {
     558            1 :     std::shared_ptr<IGstTextTrackSinkFactory> factory;
     559              : 
     560              :     try
     561              :     {
     562            1 :         factory = std::make_shared<GstTextTrackSinkFactory>();
     563              :     }
     564            0 :     catch (const std::exception &e)
     565              :     {
     566            0 :         RIALTO_SERVER_LOG_ERROR("Failed to create the textTrackSink element factory, reason: %s", e.what());
     567              :     }
     568              : 
     569            1 :     return factory;
     570              : }
     571              : 
     572            0 : GstElement *GstTextTrackSinkFactory::createGstTextTrackSink() const
     573              : {
     574            0 :     GstElement *elem = GST_ELEMENT(g_object_new(GST_RIALTO_TEXT_TRACK_SINK_TYPE, nullptr));
     575              : 
     576            0 :     return elem;
     577              : }
     578              : 
     579              : }; // namespace firebolt::rialto::server
        

Generated by: LCOV version 2.0-1