LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/nnstreamer/elements - gsttensor_reposrc.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer#eca68b8d050408568af95d831a8eef62aaee7784 Lines: 88.8 % 160 142
Test Date: 2025-03-14 05:36:58 Functions: 100.0 % 11 11

            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_reposrc
      20              :  *
      21              :  * Pop element to handle tensor repo
      22              :  *
      23              :  * @file        gsttensor_reposrc.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              : 
      35              : #include <string.h>
      36              : #include "gsttensor_repo.h"
      37              : #include "gsttensor_reposrc.h"
      38              : 
      39              : GST_DEBUG_CATEGORY_STATIC (gst_tensor_reposrc_debug);
      40              : #define GST_CAT_DEFAULT gst_tensor_reposrc_debug
      41              : #define CAPS_STRING GST_TENSOR_CAP_DEFAULT "; " GST_TENSORS_CAP_DEFAULT
      42              : 
      43              : /**
      44              :  * @brief tensor_reposrc properties
      45              :  */
      46              : enum
      47              : {
      48              :   PROP_0,
      49              :   PROP_CAPS,
      50              :   PROP_SLOT_ID,
      51              :   PROP_SILENT
      52              : };
      53              : 
      54              : #define DEFAULT_SILENT TRUE
      55              : #define DEFAULT_INDEX 0
      56              : #define INVALID_INDEX G_MAXUINT
      57              : 
      58              : static void gst_tensor_reposrc_set_property (GObject * object, guint prop_id,
      59              :     const GValue * value, GParamSpec * pspec);
      60              : static void gst_tensor_reposrc_get_property (GObject * object, guint prop_id,
      61              :     GValue * value, GParamSpec * pspec);
      62              : static void gst_tensor_reposrc_dispose (GObject * object);
      63              : static GstCaps *gst_tensor_reposrc_getcaps (GstBaseSrc * src, GstCaps * filter);
      64              : static GstFlowReturn gst_tensor_reposrc_create (GstPushSrc * src,
      65              :     GstBuffer ** buffer);
      66              : 
      67              : #define gst_tensor_reposrc_parent_class parent_class
      68         1108 : G_DEFINE_TYPE (GstTensorRepoSrc, gst_tensor_reposrc, GST_TYPE_PUSH_SRC);
      69              : 
      70              : /**
      71              :  * @brief class initialization of tensor_reposrc
      72              :  */
      73              : static void
      74           10 : gst_tensor_reposrc_class_init (GstTensorRepoSrcClass * klass)
      75              : {
      76           10 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
      77           10 :   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
      78           10 :   GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
      79           10 :   GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass);
      80              :   GstPadTemplate *pad_template;
      81              :   GstCaps *pad_caps;
      82              : 
      83           10 :   GST_DEBUG_CATEGORY_INIT (gst_tensor_reposrc_debug, "tensor_reposrc", 0,
      84              :       "Source element to handle tensor repository");
      85              : 
      86           10 :   gobject_class->set_property = gst_tensor_reposrc_set_property;
      87           10 :   gobject_class->get_property = gst_tensor_reposrc_get_property;
      88           10 :   gobject_class->dispose = gst_tensor_reposrc_dispose;
      89              : 
      90           10 :   g_object_class_install_property (gobject_class, PROP_CAPS,
      91              :       g_param_spec_boxed ("caps", "Caps",
      92              :           "Caps describing the format of the data.",
      93              :           GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      94              : 
      95           10 :   g_object_class_install_property (gobject_class, PROP_SILENT,
      96              :       g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
      97              :           DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      98              : 
      99           10 :   g_object_class_install_property (gobject_class, PROP_SLOT_ID,
     100              :       g_param_spec_uint ("slot-index", "Slot Index", "repository slot index",
     101              :           0, INVALID_INDEX - 1, DEFAULT_INDEX,
     102              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     103              : 
     104           10 :   basesrc_class->get_caps = gst_tensor_reposrc_getcaps;
     105           10 :   pushsrc_class->create = gst_tensor_reposrc_create;
     106              : 
     107           10 :   gst_element_class_set_static_metadata (element_class,
     108              :       "TensorRepoSrc",
     109              :       "Source/Tensor/Repository",
     110              :       "Pop element to handle tensor repository",
     111              :       "Samsung Electronics Co., Ltd.");
     112              : 
     113              :   /* pad template */
     114           10 :   pad_caps = gst_caps_from_string (GST_TENSOR_CAP_DEFAULT "; "
     115              :       GST_TENSORS_CAP_DEFAULT);
     116           10 :   pad_template = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
     117              :       pad_caps);
     118           10 :   gst_element_class_add_pad_template (element_class, pad_template);
     119           10 :   gst_caps_unref (pad_caps);
     120           10 : }
     121              : 
     122              : /**
     123              :  * @brief object initialization of tensor_reposrc
     124              :  */
     125              : static void
     126           14 : gst_tensor_reposrc_init (GstTensorRepoSrc * self)
     127              : {
     128           14 :   self->silent = TRUE;
     129           14 :   self->ini = FALSE;
     130           14 :   self->negotiation = FALSE;
     131           14 :   gst_tensors_config_init (&self->config);
     132           14 :   self->caps = NULL;
     133           14 :   self->set_startid = FALSE;
     134           14 :   self->myid = INVALID_INDEX;
     135           14 : }
     136              : 
     137              : /**
     138              :  * @brief object dispose of tensor_reposrc
     139              :  */
     140              : static void
     141           13 : gst_tensor_reposrc_dispose (GObject * object)
     142              : {
     143           13 :   GstTensorRepoSrc *self = GST_TENSOR_REPOSRC (object);
     144              : 
     145           13 :   if (self->myid != INVALID_INDEX
     146           13 :       && !gst_tensor_repo_remove_repodata (self->myid))
     147            0 :     GST_ELEMENT_ERROR (self, RESOURCE, WRITE,
     148              :         ("Cannot remove [key: %d] in repo", self->myid), NULL);
     149              : 
     150           13 :   if (self->caps)
     151           13 :     gst_caps_unref (self->caps);
     152              : 
     153           13 :   G_OBJECT_CLASS (parent_class)->dispose (object);
     154           13 : }
     155              : 
     156              : /**
     157              :  * @brief get cap of tensor_reposrc
     158              :  */
     159              : static GstCaps *
     160           41 : gst_tensor_reposrc_getcaps (GstBaseSrc * src, GstCaps * filter)
     161              : {
     162           41 :   GstTensorRepoSrc *self = GST_TENSOR_REPOSRC (src);
     163              :   GstCaps *cap, *check, *result;
     164           41 :   GstStructure *st = NULL;
     165              : 
     166           41 :   GST_DEBUG_OBJECT (self, "returning %" GST_PTR_FORMAT, self->caps);
     167              : 
     168           41 :   if (self->caps) {
     169           41 :     if (filter) {
     170            0 :       cap = gst_caps_intersect_full (filter, self->caps,
     171              :           GST_CAPS_INTERSECT_FIRST);
     172              :     } else
     173           41 :       cap = gst_caps_ref (self->caps);
     174              :   } else {
     175            0 :     if (filter) {
     176            0 :       cap = gst_caps_ref (filter);
     177              :     } else
     178            0 :       cap = gst_caps_new_any ();
     179              :   }
     180              : 
     181           41 :   check = gst_caps_from_string (CAPS_STRING);
     182           41 :   result = gst_caps_intersect_full (cap, check, GST_CAPS_INTERSECT_FIRST);
     183              : 
     184           41 :   if (!result) {
     185            0 :     GST_ELEMENT_ERROR (GST_ELEMENT (self), STREAM, WRONG_TYPE,
     186              :         ("Only Tensor/Tensors MIME are supported for now"), (NULL));
     187              :   }
     188           41 :   gst_caps_unref (check);
     189           41 :   gst_caps_unref (cap);
     190              : 
     191           41 :   st = gst_caps_get_structure (result, 0);
     192           41 :   gst_tensors_config_from_structure (&self->config, st);
     193              : 
     194           41 :   return result;
     195              : }
     196              : 
     197              : /**
     198              :  * @brief set property of tensor_reposrc
     199              :  */
     200              : static void
     201           42 : gst_tensor_reposrc_set_property (GObject * object, guint prop_id,
     202              :     const GValue * value, GParamSpec * pspec)
     203              : {
     204           42 :   GstTensorRepoSrc *self = GST_TENSOR_REPOSRC (object);
     205              : 
     206           42 :   switch (prop_id) {
     207           14 :     case PROP_SILENT:
     208           14 :       self->silent = g_value_get_boolean (value);
     209           14 :       break;
     210           14 :     case PROP_SLOT_ID:
     211           14 :       self->o_myid = self->myid;
     212           14 :       self->myid = g_value_get_uint (value);
     213           14 :       self->negotiation = FALSE;
     214              : 
     215           14 :       gst_tensor_repo_add_repodata (self->myid, FALSE);
     216              : 
     217           14 :       if (!self->set_startid) {
     218           14 :         self->o_myid = self->myid;
     219           14 :         self->set_startid = TRUE;
     220              :       }
     221              : 
     222           14 :       if (self->o_myid != self->myid)
     223            0 :         gst_tensor_repo_set_changed (self->o_myid, self->myid, FALSE);
     224           14 :       break;
     225           14 :     case PROP_CAPS:
     226              :     {
     227           14 :       GstStructure *st = NULL;
     228           14 :       const GstCaps *caps = gst_value_get_caps (value);
     229              :       GstCaps *new_caps;
     230              : 
     231           14 :       if (caps == NULL) {
     232            0 :         new_caps = gst_caps_new_any ();
     233              :       } else {
     234           14 :         new_caps = gst_caps_copy (caps);
     235              :       }
     236           14 :       gst_caps_replace (&self->caps, new_caps);
     237           14 :       gst_pad_set_caps (GST_BASE_SRC_PAD (self), new_caps);
     238           14 :       st = gst_caps_get_structure (new_caps, 0);
     239              : 
     240           14 :       if (new_caps && gst_caps_get_size (new_caps) == 1 && st
     241           14 :           && gst_structure_get_fraction (st, "framerate", &self->fps_n,
     242              :               &self->fps_d)) {
     243           14 :         GST_INFO_OBJECT (self, "Setting framerate to %d/%d", self->fps_n,
     244              :             self->fps_d);
     245              :       } else {
     246            0 :         self->fps_n = -1;
     247            0 :         self->fps_d = -1;
     248              :       }
     249              : 
     250           14 :       if (new_caps)
     251           14 :         gst_caps_unref (new_caps);
     252           14 :       self->negotiation = FALSE;
     253           14 :       break;
     254              :     }
     255            0 :     default:
     256            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     257            0 :       break;
     258              :   }
     259           42 : }
     260              : 
     261              : /**
     262              :  * @brief get property of tensor_reposrc
     263              :  */
     264              : static void
     265            3 : gst_tensor_reposrc_get_property (GObject * object, guint prop_id,
     266              :     GValue * value, GParamSpec * pspec)
     267              : {
     268            3 :   GstTensorRepoSrc *self = GST_TENSOR_REPOSRC (object);
     269              : 
     270            3 :   switch (prop_id) {
     271            1 :     case PROP_SILENT:
     272            1 :       g_value_set_boolean (value, self->silent);
     273            1 :       break;
     274            1 :     case PROP_SLOT_ID:
     275            1 :       g_value_set_uint (value, self->myid);
     276            1 :       break;
     277            1 :     case PROP_CAPS:
     278            1 :       gst_value_set_caps (value, self->caps);
     279            1 :       break;
     280            0 :     default:
     281            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     282            0 :       break;
     283              :   }
     284            3 : }
     285              : 
     286              : /**
     287              :  * @brief create dummy buffer for initialization
     288              :  */
     289              : static GstBuffer *
     290           14 : gst_tensor_reposrc_gen_dummy_buffer (GstTensorRepoSrc * self)
     291              : {
     292           14 :   GstBuffer *buf = NULL;
     293              :   GstTensorInfo *_info;
     294              :   GstMemory *mem;
     295              :   GstMapInfo map;
     296              :   guint i, num_tensors;
     297           14 :   gsize size = 0;
     298              : 
     299           14 :   buf = gst_buffer_new ();
     300           14 :   num_tensors = self->config.info.num_tensors;
     301              : 
     302           28 :   for (i = 0; i < num_tensors; i++) {
     303           14 :     _info = gst_tensors_info_get_nth_info (&self->config.info, i);
     304           14 :     size = gst_tensor_info_get_size (_info);
     305           14 :     mem = gst_allocator_alloc (NULL, size, NULL);
     306           14 :     gst_tensor_buffer_append_memory (buf, mem, _info);
     307              : 
     308           14 :     if (!gst_memory_map (mem, &map, GST_MAP_WRITE)) {
     309            0 :       gst_buffer_unref (buf);
     310            0 :       ml_logf ("Cannot map gst memory (tensor-repo-src).");
     311           14 :       return NULL;
     312              :     }
     313              : 
     314           14 :     memset (map.data, 0, map.size);
     315           14 :     gst_memory_unmap (mem, &map);
     316              :   }
     317              : 
     318           14 :   return buf;
     319              : }
     320              : 
     321              : /**
     322              :  * @brief create func of tensor_reposrc
     323              :  */
     324              : static GstFlowReturn
     325          135 : gst_tensor_reposrc_create (GstPushSrc * src, GstBuffer ** buffer)
     326              : {
     327              :   GstTensorRepoSrc *self;
     328          135 :   GstBuffer *buf = NULL;
     329          135 :   GstCaps *caps = NULL;
     330          135 :   gboolean eos = FALSE;
     331              :   guint newid;
     332              : 
     333          135 :   self = GST_TENSOR_REPOSRC (src);
     334          135 :   gst_tensor_repo_wait ();
     335              : 
     336          135 :   if (!self->ini) {
     337           14 :     buf = gst_tensor_reposrc_gen_dummy_buffer (self);
     338           14 :     self->ini = TRUE;
     339              :   } else {
     340          242 :     while (!buf && !eos) {
     341          121 :       buf = gst_tensor_repo_get_buffer (self->myid, &eos, &newid, &caps);
     342              :     }
     343              : 
     344          121 :     if (eos)
     345            8 :       goto handle_eos;
     346              : 
     347          113 :     if (!self->negotiation && buf != NULL) {
     348           14 :       if (!gst_tensor_caps_can_intersect (self->caps, caps)) {
     349            3 :         GST_ELEMENT_ERROR (GST_ELEMENT (self), CORE, NEGOTIATION,
     350              :             ("Negotiation Failed! : repo_sink & repos_src"), (NULL));
     351              : 
     352            3 :         gst_tensor_repo_set_eos (self->myid);
     353            3 :         goto handle_eos;
     354              :       }
     355              : 
     356           11 :       self->negotiation = TRUE;
     357              :     }
     358              : 
     359          110 :     if (caps)
     360          110 :       gst_caps_unref (caps);
     361              :   }
     362              : 
     363          124 :   *buffer = buf;
     364          135 :   return GST_FLOW_OK;
     365              : 
     366           11 : handle_eos:
     367           11 :   if (buf)
     368            3 :     gst_buffer_unref (buf);
     369           11 :   if (caps)
     370            3 :     gst_caps_unref (caps);
     371           11 :   return GST_FLOW_EOS;
     372              : }
        

Generated by: LCOV version 2.0-1