LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/nnstreamer/elements - gsttensor_reposink.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer#eca68b8d050408568af95d831a8eef62aaee7784 Lines: 82.5 % 166 137
Test Date: 2025-03-14 05:36:58 Functions: 94.1 % 17 16

            Line data    Source code
       1              : /**
       2              :  * GStreamer
       3              :  * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
       4              :  * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
       5              :  * Copyright (C) 2018 Samsung Electronics Co., Ltd.
       6              :  *
       7              :  * This library is free software; you can redistribute it and/or
       8              :  * modify it under the terms of the GNU Library General Public
       9              :  * License as published by the Free Software Foundation;
      10              :  * version 2.1 of the License.
      11              :  *
      12              :  * This library is distributed in the hope that it will be useful,
      13              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15              :  * Library General Public License for more details.
      16              :  */
      17              : 
      18              : /**
      19              :  * SECTION: element-tensor_reposink
      20              :  *
      21              :  * Set element to handle tensor repo
      22              :  *
      23              :  * @file        gsttensor_reposink.c
      24              :  * @date        19 Nov 2018
      25              :  * @brief       GStreamer plugin to handle tensor repository
      26              :  * @see         https://github.com/nnstreamer/nnstreamer
      27              :  * @author      Jijoong Moon <jijoong.moon@samsung.com>
      28              :  * @bug         No known bugs except for NYI items
      29              :  */
      30              : 
      31              : #ifdef HAVE_CONFIG_H
      32              : #include <config.h>
      33              : #endif
      34              : #include <nnstreamer_util.h>
      35              : 
      36              : #include "gsttensor_repo.h"
      37              : #include "gsttensor_reposink.h"
      38              : 
      39              : GST_DEBUG_CATEGORY_STATIC (gst_tensor_reposink_debug);
      40              : #define GST_CAT_DEFAULT gst_tensor_reposink_debug
      41              : 
      42              : /**
      43              :  * @brief tensor_reposink properties
      44              :  */
      45              : enum
      46              : {
      47              :   PROP_0,
      48              :   PROP_SIGNAL_RATE,
      49              :   PROP_SLOT,
      50              :   PROP_SILENT
      51              : };
      52              : 
      53              : #define DEFAULT_SIGNAL_RATE 0
      54              : #define DEFAULT_SILENT TRUE
      55              : #define DEFAULT_QOS TRUE
      56              : #define DEFAULT_INDEX 0
      57              : 
      58              : static void gst_tensor_reposink_set_property (GObject * object, guint prop_id,
      59              :     const GValue * value, GParamSpec * pspec);
      60              : static void gst_tensor_reposink_get_property (GObject * object, guint prop_id,
      61              :     GValue * value, GParamSpec * pspec);
      62              : static void gst_tensor_reposink_dispose (GObject * object);
      63              : 
      64              : static gboolean gst_tensor_reposink_start (GstBaseSink * sink);
      65              : static gboolean gst_tensor_reposink_stop (GstBaseSink * sink);
      66              : static gboolean gst_tensor_reposink_event (GstBaseSink * sink,
      67              :     GstEvent * event);
      68              : static gboolean gst_tensor_reposink_query (GstBaseSink * sink,
      69              :     GstQuery * query);
      70              : static GstFlowReturn gst_tensor_reposink_render (GstBaseSink * sink,
      71              :     GstBuffer * buffer);
      72              : static GstFlowReturn gst_tensor_reposink_render_list (GstBaseSink * sink,
      73              :     GstBufferList * buffer_list);
      74              : static gboolean gst_tensor_reposink_set_caps (GstBaseSink * sink,
      75              :     GstCaps * caps);
      76              : static GstCaps *gst_tensor_reposink_get_caps (GstBaseSink * sink,
      77              :     GstCaps * filter);
      78              : 
      79              : #define gst_tensor_reposink_parent_class parent_class
      80         1417 : G_DEFINE_TYPE (GstTensorRepoSink, gst_tensor_reposink, GST_TYPE_BASE_SINK);
      81              : 
      82              : /**
      83              :  * @brief class initialization of tensor_reposink
      84              :  */
      85              : static void
      86           10 : gst_tensor_reposink_class_init (GstTensorRepoSinkClass * klass)
      87              : {
      88              :   GObjectClass *gobject_class;
      89              :   GstElementClass *element_class;
      90              :   GstBaseSinkClass *basesink_class;
      91              :   GstPadTemplate *pad_template;
      92              :   GstCaps *pad_caps;
      93              : 
      94           10 :   GST_DEBUG_CATEGORY_INIT (gst_tensor_reposink_debug, "tensor_reposink", 0,
      95              :       "Sink element to handle tensor repository");
      96              : 
      97           10 :   gobject_class = G_OBJECT_CLASS (klass);
      98           10 :   element_class = GST_ELEMENT_CLASS (klass);
      99           10 :   basesink_class = GST_BASE_SINK_CLASS (klass);
     100              : 
     101           10 :   gobject_class->set_property = gst_tensor_reposink_set_property;
     102           10 :   gobject_class->get_property = gst_tensor_reposink_get_property;
     103           10 :   gobject_class->dispose = gst_tensor_reposink_dispose;
     104              : 
     105           10 :   g_object_class_install_property (gobject_class, PROP_SIGNAL_RATE,
     106              :       g_param_spec_uint ("signal-rate", "Signal rate",
     107              :           "New data signals per second (0 for unlimited, max 500)", 0, 500,
     108              :           DEFAULT_SIGNAL_RATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     109              : 
     110           10 :   g_object_class_install_property (gobject_class, PROP_SLOT,
     111              :       g_param_spec_uint ("slot-index", "Slot Index", "repository slot index",
     112              :           0, UINT_MAX, DEFAULT_INDEX,
     113              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     114              : 
     115           10 :   g_object_class_install_property (gobject_class, PROP_SILENT,
     116              :       g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
     117              :           DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     118              : 
     119           10 :   gst_element_class_set_static_metadata (element_class,
     120              :       "TensorRepoSink",
     121              :       "Sink/Tensor/Repository",
     122              :       "Set element to handle tensor repository",
     123              :       "Samsung Electronics Co., Ltd.");
     124              : 
     125              :   /* pad template */
     126           10 :   pad_caps = gst_caps_from_string (GST_TENSOR_CAP_DEFAULT "; "
     127              :       GST_TENSORS_CAP_DEFAULT);
     128           10 :   pad_template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
     129              :       pad_caps);
     130           10 :   gst_element_class_add_pad_template (element_class, pad_template);
     131           10 :   gst_caps_unref (pad_caps);
     132              : 
     133           10 :   basesink_class->start = GST_DEBUG_FUNCPTR (gst_tensor_reposink_start);
     134           10 :   basesink_class->stop = GST_DEBUG_FUNCPTR (gst_tensor_reposink_stop);
     135           10 :   basesink_class->event = GST_DEBUG_FUNCPTR (gst_tensor_reposink_event);
     136           10 :   basesink_class->query = GST_DEBUG_FUNCPTR (gst_tensor_reposink_query);
     137           10 :   basesink_class->render = GST_DEBUG_FUNCPTR (gst_tensor_reposink_render);
     138           10 :   basesink_class->render_list =
     139           10 :       GST_DEBUG_FUNCPTR (gst_tensor_reposink_render_list);
     140           10 :   basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_tensor_reposink_set_caps);
     141           10 :   basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_tensor_reposink_get_caps);
     142           10 : }
     143              : 
     144              : /**
     145              :  * @brief initialization of tensor_reposink
     146              :  */
     147              : static void
     148           14 : gst_tensor_reposink_init (GstTensorRepoSink * self)
     149              : {
     150              :   GstBaseSink *basesink;
     151              : 
     152           14 :   basesink = GST_BASE_SINK (self);
     153              : 
     154           14 :   gst_tensor_repo_init ();
     155              : 
     156           14 :   GST_DEBUG_OBJECT (self, "GstTensorRepo is successfully initialized");
     157              : 
     158           14 :   self->silent = DEFAULT_SILENT;
     159           14 :   self->signal_rate = DEFAULT_SIGNAL_RATE;
     160           14 :   self->last_render_time = GST_CLOCK_TIME_NONE;
     161           14 :   self->set_startid = FALSE;
     162           14 :   self->in_caps = NULL;
     163              : 
     164           14 :   gst_base_sink_set_qos_enabled (basesink, DEFAULT_QOS);
     165              : 
     166              :   /* ignore sync and preroll in repo */
     167           14 :   gst_base_sink_set_sync (basesink, FALSE);
     168           14 :   gst_base_sink_set_async_enabled (basesink, FALSE);
     169           14 : }
     170              : 
     171              : /**
     172              :  * @brief set property vmethod
     173              :  */
     174              : static void
     175           29 : gst_tensor_reposink_set_property (GObject * object, guint prop_id,
     176              :     const GValue * value, GParamSpec * pspec)
     177              : {
     178              :   GstTensorRepoSink *self;
     179              : 
     180           29 :   self = GST_TENSOR_REPOSINK (object);
     181              : 
     182           29 :   switch (prop_id) {
     183            1 :     case PROP_SIGNAL_RATE:
     184            1 :       self->signal_rate = g_value_get_uint (value);
     185            1 :       break;
     186           14 :     case PROP_SILENT:
     187           14 :       self->silent = g_value_get_boolean (value);
     188           14 :       break;
     189           14 :     case PROP_SLOT:
     190           14 :       self->o_myid = self->myid;
     191           14 :       self->myid = g_value_get_uint (value);
     192              : 
     193           14 :       gst_tensor_repo_add_repodata (self->myid, TRUE);
     194              : 
     195           14 :       if (!self->set_startid) {
     196           14 :         self->o_myid = self->myid;
     197           14 :         self->set_startid = TRUE;
     198              :       }
     199              : 
     200           14 :       if (self->o_myid != self->myid)
     201            0 :         gst_tensor_repo_set_changed (self->o_myid, self->myid, TRUE);
     202           14 :       break;
     203            0 :     default:
     204            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     205            0 :       break;
     206              :   }
     207           29 : }
     208              : 
     209              : /**
     210              :  * @brief get property vmethod
     211              :  */
     212              : static void
     213            3 : gst_tensor_reposink_get_property (GObject * object, guint prop_id,
     214              :     GValue * value, GParamSpec * pspec)
     215              : {
     216              :   GstTensorRepoSink *self;
     217              : 
     218            3 :   self = GST_TENSOR_REPOSINK (object);
     219              : 
     220            3 :   switch (prop_id) {
     221            1 :     case PROP_SIGNAL_RATE:
     222            1 :       g_value_set_uint (value, self->signal_rate);
     223            1 :       break;
     224            1 :     case PROP_SILENT:
     225            1 :       g_value_set_boolean (value, self->silent);
     226            1 :       break;
     227            1 :     case PROP_SLOT:
     228            1 :       g_value_set_uint (value, self->myid);
     229            1 :       break;
     230            0 :     default:
     231            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     232            0 :       break;
     233              :   }
     234            3 : }
     235              : 
     236              : /**
     237              :  * @brief dispose vmethod implementation
     238              :  */
     239              : static void
     240           13 : gst_tensor_reposink_dispose (GObject * object)
     241              : {
     242              :   GstTensorRepoSink *self;
     243              : 
     244           13 :   self = GST_TENSOR_REPOSINK (object);
     245              : 
     246           13 :   if (self->in_caps)
     247           13 :     gst_caps_unref (self->in_caps);
     248              : 
     249           13 :   G_OBJECT_CLASS (parent_class)->dispose (object);
     250           13 : }
     251              : 
     252              : /**
     253              :  * @brief start vmethod implementation
     254              :  */
     255              : static gboolean
     256           14 : gst_tensor_reposink_start (GstBaseSink * sink)
     257              : {
     258              :   UNUSED (sink);
     259           14 :   return TRUE;
     260              : }
     261              : 
     262              : /**
     263              :  * @brief stop vmethod implementation
     264              :  */
     265              : static gboolean
     266           13 : gst_tensor_reposink_stop (GstBaseSink * sink)
     267              : {
     268              :   UNUSED (sink);
     269           13 :   return TRUE;
     270              : }
     271              : 
     272              : /**
     273              :  * @brief Handle events.
     274              :  *
     275              :  * GstBaseSink method implementation.
     276              :  */
     277              : static gboolean
     278           53 : gst_tensor_reposink_event (GstBaseSink * sink, GstEvent * event)
     279              : {
     280              :   GstTensorRepoSink *self;
     281              :   GstEventType type;
     282              : 
     283           53 :   self = GST_TENSOR_REPOSINK (sink);
     284           53 :   type = GST_EVENT_TYPE (event);
     285              : 
     286           53 :   GST_DEBUG_OBJECT (self, "received event %s", GST_EVENT_TYPE_NAME (event));
     287              : 
     288           53 :   switch (type) {
     289           11 :     case GST_EVENT_EOS:
     290           11 :       gst_tensor_repo_set_eos (self->myid);
     291           11 :       break;
     292           42 :     default:
     293           42 :       break;
     294              :   }
     295              : 
     296           53 :   return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
     297              : }
     298              : 
     299              : /**
     300              :  * @brief query vmethod implementation
     301              :  */
     302              : static gboolean
     303           97 : gst_tensor_reposink_query (GstBaseSink * sink, GstQuery * query)
     304              : {
     305              :   GstTensorRepoSink *self;
     306              :   GstQueryType type;
     307              :   GstFormat format;
     308              : 
     309           97 :   self = GST_TENSOR_REPOSINK (sink);
     310           97 :   type = GST_QUERY_TYPE (query);
     311              : 
     312           97 :   GST_DEBUG_OBJECT (self, "received query %s", GST_QUERY_TYPE_NAME (query));
     313              : 
     314           97 :   switch (type) {
     315            0 :     case GST_QUERY_SEEKING:
     316            0 :       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
     317            0 :       gst_query_set_seeking (query, format, FALSE, 0, -1);
     318           97 :       return TRUE;
     319           97 :     default:
     320           97 :       break;
     321              :   }
     322              : 
     323           97 :   return GST_BASE_SINK_CLASS (parent_class)->query (sink, query);
     324              : }
     325              : 
     326              : /**
     327              :  * @brief Push GstBuffer
     328              :  */
     329              : static gboolean
     330          119 : gst_tensor_reposink_render_buffer (GstTensorRepoSink * self, GstBuffer * buffer)
     331              : {
     332          119 :   GstClockTime now = GST_CLOCK_TIME_NONE;
     333              :   guint signal_rate;
     334          119 :   gboolean notify = FALSE;
     335          119 :   g_return_val_if_fail (GST_IS_TENSOR_REPOSINK (self), FALSE);
     336              : 
     337          119 :   signal_rate = self->signal_rate;
     338              : 
     339          119 :   if (signal_rate) {
     340              :     GstClock *clock;
     341              :     GstClockTime render_time;
     342              : 
     343            0 :     clock = gst_element_get_clock (GST_ELEMENT (self));
     344              : 
     345            0 :     if (clock) {
     346            0 :       now = gst_clock_get_time (clock);
     347            0 :       render_time = (1000 / signal_rate) * GST_MSECOND + self->last_render_time;
     348              : 
     349            0 :       if (!GST_CLOCK_TIME_IS_VALID (self->last_render_time) ||
     350            0 :           GST_CLOCK_DIFF (now, render_time) <= 0) {
     351            0 :         notify = TRUE;
     352              :       }
     353              : 
     354            0 :       gst_object_unref (clock);
     355              :     }
     356              :   } else {
     357          119 :     notify = TRUE;
     358              :   }
     359              : 
     360          119 :   if (notify) {
     361          119 :     self->last_render_time = now;
     362              : 
     363          119 :     if (!gst_tensor_repo_set_buffer (self->myid, buffer, self->in_caps)) {
     364            3 :       GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
     365              :           ("Cannot Set buffer into repo [key: %d]", self->myid), NULL);
     366            3 :       return FALSE;
     367              :     }
     368              :   }
     369              : 
     370          116 :   return TRUE;
     371              : }
     372              : 
     373              : /**
     374              :  * @brief render vmethod implementation
     375              :  */
     376              : static GstFlowReturn
     377          119 : gst_tensor_reposink_render (GstBaseSink * sink, GstBuffer * buffer)
     378              : {
     379              :   GstTensorRepoSink *self;
     380              : 
     381          119 :   self = GST_TENSOR_REPOSINK (sink);
     382              : 
     383          119 :   if (!gst_tensor_reposink_render_buffer (self, buffer))
     384            3 :     return GST_FLOW_ERROR;
     385          116 :   return GST_FLOW_OK;
     386              : }
     387              : 
     388              : /**
     389              :  * @brief render list vmethod implementation
     390              :  */
     391              : static GstFlowReturn
     392            0 : gst_tensor_reposink_render_list (GstBaseSink * sink,
     393              :     GstBufferList * buffer_list)
     394              : {
     395              :   GstTensorRepoSink *self;
     396              :   GstBuffer *buffer;
     397              :   guint i;
     398              :   guint num_buffers;
     399              : 
     400            0 :   self = GST_TENSOR_REPOSINK (sink);
     401            0 :   num_buffers = gst_buffer_list_length (buffer_list);
     402              : 
     403            0 :   for (i = 0; i < num_buffers; i++) {
     404            0 :     buffer = gst_buffer_list_get (buffer_list, i);
     405            0 :     if (!gst_tensor_reposink_render_buffer (self, buffer))
     406            0 :       return GST_FLOW_ERROR;
     407              :   }
     408              : 
     409            0 :   return GST_FLOW_OK;
     410              : }
     411              : 
     412              : /**
     413              :  * @brief set_caps vmethod implementation
     414              :  */
     415              : static gboolean
     416           14 : gst_tensor_reposink_set_caps (GstBaseSink * sink, GstCaps * caps)
     417              : {
     418              :   GstTensorRepoSink *self;
     419              : 
     420           14 :   self = GST_TENSOR_REPOSINK (sink);
     421           14 :   gst_caps_replace (&self->in_caps, caps);
     422              : 
     423              :   /* debug print caps */
     424           14 :   if (!self->silent) {
     425              :     GstStructure *structure;
     426              :     gchar *str;
     427              :     guint caps_size, i;
     428              : 
     429           14 :     caps_size = gst_caps_get_size (caps);
     430           14 :     GST_DEBUG_OBJECT (self, "set caps, size is %d", caps_size);
     431              : 
     432           28 :     for (i = 0; i < caps_size; i++) {
     433           14 :       structure = gst_caps_get_structure (caps, i);
     434           14 :       str = gst_structure_to_string (structure);
     435              : 
     436           14 :       GST_DEBUG_OBJECT (self, "[%d] %s", i, str);
     437           14 :       g_free (str);
     438              :     }
     439              :   }
     440              : 
     441           14 :   return TRUE;
     442              : }
     443              : 
     444              : /**
     445              :  * @brief get_caps vmethod implementation
     446              :  */
     447              : static GstCaps *
     448           96 : gst_tensor_reposink_get_caps (GstBaseSink * sink, GstCaps * filter)
     449              : {
     450              :   GstTensorRepoSink *self;
     451              :   GstCaps *caps;
     452              : 
     453           96 :   self = GST_TENSOR_REPOSINK (sink);
     454              : 
     455           96 :   caps = self->in_caps;
     456              : 
     457           96 :   if (caps) {
     458            0 :     if (filter) {
     459            0 :       caps = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
     460              :     } else {
     461            0 :       gst_caps_ref (caps);
     462              :     }
     463              :   }
     464              : 
     465           96 :   return caps;
     466              : }
        

Generated by: LCOV version 2.0-1