LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/nnstreamer/tensor_query - tensor_query_serversink.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer#eca68b8d050408568af95d831a8eef62aaee7784 Lines: 79.8 % 129 103
Test Date: 2025-03-13 05:38:21 Functions: 92.3 % 13 12

            Line data    Source code
       1              : /* SPDX-License-Identifier: LGPL-2.1-only */
       2              : /**
       3              :  * Copyright (C) 2021 Samsung Electronics Co., Ltd.
       4              :  *
       5              :  * @file    tensor_query_serversink.c
       6              :  * @date    09 Jul 2021
       7              :  * @brief   GStreamer plugin to handle tensor query server sink
       8              :  * @author  Junhwan Kim <jejudo.kim@samsung.com>
       9              :  * @see     http://github.com/nnstreamer/nnstreamer
      10              :  * @bug     No known bugs
      11              :  *
      12              :  */
      13              : #ifdef HAVE_CONFIG_H
      14              : #include <config.h>
      15              : #endif
      16              : 
      17              : #include <string.h>
      18              : #include "tensor_query_serversink.h"
      19              : 
      20              : GST_DEBUG_CATEGORY_STATIC (gst_tensor_query_serversink_debug);
      21              : #define GST_CAT_DEFAULT gst_tensor_query_serversink_debug
      22              : 
      23              : #define DEFAULT_METALESS_FRAME_LIMIT 1
      24              : 
      25              : /**
      26              :  * @brief the capabilities of the inputs.
      27              :  */
      28              : static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
      29              :     GST_PAD_SINK,
      30              :     GST_PAD_ALWAYS,
      31              :     GST_STATIC_CAPS_ANY);
      32              : 
      33              : enum
      34              : {
      35              :   PROP_0,
      36              :   PROP_CONNECT_TYPE,
      37              :   PROP_ID,
      38              :   PROP_TIMEOUT,
      39              :   PROP_METALESS_FRAME_LIMIT
      40              : };
      41              : 
      42              : #define gst_tensor_query_serversink_parent_class parent_class
      43          904 : G_DEFINE_TYPE (GstTensorQueryServerSink, gst_tensor_query_serversink,
      44              :     GST_TYPE_BASE_SINK);
      45              : static GstStateChangeReturn gst_tensor_query_serversink_change_state (GstElement
      46              :     * element, GstStateChange transition);
      47              : static void gst_tensor_query_serversink_set_property (GObject * object,
      48              :     guint prop_id, const GValue * value, GParamSpec * pspec);
      49              : static void gst_tensor_query_serversink_get_property (GObject * object,
      50              :     guint prop_id, GValue * value, GParamSpec * pspec);
      51              : static void gst_tensor_query_serversink_finalize (GObject * object);
      52              : 
      53              : static GstFlowReturn gst_tensor_query_serversink_render (GstBaseSink * bsink,
      54              :     GstBuffer * buf);
      55              : static gboolean gst_tensor_query_serversink_set_caps (GstBaseSink * basesink,
      56              :     GstCaps * caps);
      57              : 
      58              : /**
      59              :  * @brief initialize the class
      60              :  */
      61              : static void
      62            1 : gst_tensor_query_serversink_class_init (GstTensorQueryServerSinkClass * klass)
      63              : {
      64              :   GObjectClass *gobject_class;
      65              :   GstElementClass *gstelement_class;
      66              :   GstBaseSinkClass *gstbasesink_class;
      67              : 
      68            1 :   gstbasesink_class = (GstBaseSinkClass *) klass;
      69            1 :   gstelement_class = (GstElementClass *) gstbasesink_class;
      70            1 :   gobject_class = (GObjectClass *) gstelement_class;
      71              : 
      72            1 :   gstelement_class->change_state = gst_tensor_query_serversink_change_state;
      73            1 :   gobject_class->set_property = gst_tensor_query_serversink_set_property;
      74            1 :   gobject_class->get_property = gst_tensor_query_serversink_get_property;
      75            1 :   gobject_class->finalize = gst_tensor_query_serversink_finalize;
      76              : 
      77            1 :   g_object_class_install_property (gobject_class, PROP_CONNECT_TYPE,
      78              :       g_param_spec_enum ("connect-type", "Connect Type",
      79              :           "The connection type",
      80              :           GST_TYPE_QUERY_CONNECT_TYPE, DEFAULT_CONNECT_TYPE,
      81              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      82            1 :   g_object_class_install_property (gobject_class, PROP_TIMEOUT,
      83              :       g_param_spec_uint ("timeout", "Timeout",
      84              :           "The timeout as seconds to maintain connection", 0,
      85              :           3600, QUERY_DEFAULT_TIMEOUT_SEC,
      86              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      87            1 :   g_object_class_install_property (gobject_class, PROP_ID,
      88              :       g_param_spec_uint ("id", "ID",
      89              :           "ID for distinguishing query servers.", 0,
      90              :           G_MAXUINT, DEFAULT_SERVER_ID,
      91              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      92            1 :   g_object_class_install_property (gobject_class, PROP_METALESS_FRAME_LIMIT,
      93              :       g_param_spec_int ("limit", "Limit",
      94              :           "Limits of the number of the buffers that the server cannot handle. "
      95              :           "e.g., If the received buffer does not have a GstMetaQuery, the server cannot handle the buffer.",
      96              :           0, 65535, DEFAULT_METALESS_FRAME_LIMIT,
      97              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      98              : 
      99            1 :   gst_element_class_add_pad_template (gstelement_class,
     100              :       gst_static_pad_template_get (&sinktemplate));
     101              : 
     102            1 :   gst_element_class_set_static_metadata (gstelement_class,
     103              :       "TensorQueryServerSink", "Sink/Tensor/Query",
     104              :       "Send tensor data as a server over the network",
     105              :       "Samsung Electronics Co., Ltd.");
     106              : 
     107            1 :   gstbasesink_class->set_caps = gst_tensor_query_serversink_set_caps;
     108            1 :   gstbasesink_class->render = gst_tensor_query_serversink_render;
     109              : 
     110            1 :   GST_DEBUG_CATEGORY_INIT (gst_tensor_query_serversink_debug,
     111              :       "tensor_query_serversink", 0, "Tensor Query Server Sink");
     112            1 : }
     113              : 
     114              : /**
     115              :  * @brief initialize the new element
     116              :  */
     117              : static void
     118            3 : gst_tensor_query_serversink_init (GstTensorQueryServerSink * sink)
     119              : {
     120            3 :   sink->connect_type = DEFAULT_CONNECT_TYPE;
     121            3 :   sink->timeout = QUERY_DEFAULT_TIMEOUT_SEC;
     122            3 :   sink->sink_id = DEFAULT_SERVER_ID;
     123            3 :   sink->metaless_frame_count = 0;
     124            3 : }
     125              : 
     126              : /**
     127              :  * @brief finalize the object
     128              :  */
     129              : static void
     130            2 : gst_tensor_query_serversink_finalize (GObject * object)
     131              : {
     132            2 :   GstTensorQueryServerSink *sink = GST_TENSOR_QUERY_SERVERSINK (object);
     133            2 :   gst_tensor_query_server_remove_data (sink->sink_id);
     134            2 :   G_OBJECT_CLASS (parent_class)->finalize (object);
     135            2 : }
     136              : 
     137              : /**
     138              :  * @brief start processing of query_serversink
     139              :  */
     140              : static gboolean
     141            5 : _gst_tensor_query_serversink_start (GstTensorQueryServerSink * sink)
     142              : {
     143              :   gboolean ret;
     144              : 
     145            5 :   ret = gst_tensor_query_server_add_data (sink->sink_id);
     146            5 :   if (ret)
     147            5 :     gst_tensor_query_server_set_configured (sink->sink_id);
     148              : 
     149            5 :   return ret;
     150              : }
     151              : 
     152              : /**
     153              :  * @brief start processing of query_serversink
     154              :  */
     155              : static gboolean
     156            4 : _gst_tensor_query_serversink_playing (GstTensorQueryServerSink * sink)
     157              : {
     158              :   gboolean ret;
     159              : 
     160            4 :   ret = gst_tensor_query_server_prepare (sink->sink_id, sink->connect_type,
     161              :       NULL);
     162              : 
     163            4 :   return ret;
     164              : }
     165              : 
     166              : /**
     167              :  * @brief Change state of query server sink.
     168              :  */
     169              : static GstStateChangeReturn
     170           24 : gst_tensor_query_serversink_change_state (GstElement * element,
     171              :     GstStateChange transition)
     172              : {
     173           24 :   GstTensorQueryServerSink *sink = GST_TENSOR_QUERY_SERVERSINK (element);
     174           24 :   GstBaseSink *bsink = GST_BASE_SINK (element);
     175           24 :   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
     176              :   GstCaps *caps;
     177              : 
     178           24 :   switch (transition) {
     179            4 :     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
     180            4 :       if (!_gst_tensor_query_serversink_playing (sink)) {
     181            0 :         nns_loge ("Failed to change state from PAUSED to PLAYING.");
     182            0 :         return GST_STATE_CHANGE_FAILURE;
     183              :       }
     184              : 
     185            4 :       caps = gst_pad_peer_query_caps (GST_BASE_SINK_PAD (bsink), NULL);
     186            4 :       gst_tensor_query_serversink_set_caps (bsink, caps);
     187            4 :       gst_caps_unref (caps);
     188            4 :       break;
     189            5 :     case GST_STATE_CHANGE_READY_TO_PAUSED:
     190            5 :       if (!_gst_tensor_query_serversink_start (sink)) {
     191            0 :         nns_loge ("Failed to change state from READY to PAUSED.");
     192            0 :         return GST_STATE_CHANGE_FAILURE;
     193              :       }
     194            5 :       break;
     195           15 :     default:
     196           15 :       break;
     197              :   }
     198              : 
     199           24 :   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
     200           24 :   if (ret == GST_STATE_CHANGE_FAILURE) {
     201            0 :     nns_loge ("Failed to change state");
     202            0 :     return ret;
     203              :   }
     204              : 
     205           24 :   switch (transition) {
     206            4 :     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
     207            4 :       gst_tensor_query_server_release_edge_handle (sink->sink_id);
     208            4 :       break;
     209           20 :     default:
     210           20 :       break;
     211              :   }
     212              : 
     213           24 :   return ret;
     214              : }
     215              : 
     216              : /**
     217              :  * @brief set property
     218              :  */
     219              : static void
     220            4 : gst_tensor_query_serversink_set_property (GObject * object, guint prop_id,
     221              :     const GValue * value, GParamSpec * pspec)
     222              : {
     223            4 :   GstTensorQueryServerSink *serversink = GST_TENSOR_QUERY_SERVERSINK (object);
     224              : 
     225            4 :   switch (prop_id) {
     226            1 :     case PROP_CONNECT_TYPE:
     227            1 :       serversink->connect_type = g_value_get_enum (value);
     228            1 :       break;
     229            1 :     case PROP_TIMEOUT:
     230            1 :       serversink->timeout = g_value_get_uint (value);
     231            1 :       break;
     232            1 :     case PROP_ID:
     233            1 :       serversink->sink_id = g_value_get_uint (value);
     234            1 :       break;
     235            1 :     case PROP_METALESS_FRAME_LIMIT:
     236            1 :       serversink->metaless_frame_limit = g_value_get_int (value);
     237            1 :       break;
     238            0 :     default:
     239            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     240            0 :       break;
     241              :   }
     242            4 : }
     243              : 
     244              : /**
     245              :  * @brief get property
     246              :  */
     247              : static void
     248            6 : gst_tensor_query_serversink_get_property (GObject * object, guint prop_id,
     249              :     GValue * value, GParamSpec * pspec)
     250              : {
     251            6 :   GstTensorQueryServerSink *serversink = GST_TENSOR_QUERY_SERVERSINK (object);
     252              : 
     253            6 :   switch (prop_id) {
     254            2 :     case PROP_CONNECT_TYPE:
     255            2 :       g_value_set_enum (value, serversink->connect_type);
     256            2 :       break;
     257            2 :     case PROP_TIMEOUT:
     258            2 :       g_value_set_uint (value, serversink->timeout);
     259            2 :       break;
     260            1 :     case PROP_ID:
     261            1 :       g_value_set_uint (value, serversink->sink_id);
     262            1 :       break;
     263            1 :     case PROP_METALESS_FRAME_LIMIT:
     264            1 :       g_value_set_int (value, serversink->metaless_frame_limit);
     265            1 :       break;
     266            0 :     default:
     267            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     268            0 :       break;
     269              :   }
     270            6 : }
     271              : 
     272              : /**
     273              :  * @brief An implementation of the set_caps vmethod in GstBaseSinkClass
     274              :  */
     275              : static gboolean
     276            5 : gst_tensor_query_serversink_set_caps (GstBaseSink * bsink, GstCaps * caps)
     277              : {
     278            5 :   GstTensorQueryServerSink *sink = GST_TENSOR_QUERY_SERVERSINK (bsink);
     279              :   gchar *caps_str, *new_caps_str;
     280              : 
     281            5 :   caps_str = gst_caps_to_string (caps);
     282              : 
     283            5 :   new_caps_str = g_strdup_printf ("@query_server_sink_caps@%s", caps_str);
     284            5 :   gst_tensor_query_server_set_caps (sink->sink_id, new_caps_str);
     285              : 
     286            5 :   g_free (new_caps_str);
     287            5 :   g_free (caps_str);
     288              : 
     289            5 :   return TRUE;
     290              : }
     291              : 
     292              : /**
     293              :  * @brief render buffer, send buffer to client
     294              :  */
     295              : static GstFlowReturn
     296            0 : gst_tensor_query_serversink_render (GstBaseSink * bsink, GstBuffer * buf)
     297              : {
     298            0 :   GstTensorQueryServerSink *sink = GST_TENSOR_QUERY_SERVERSINK (bsink);
     299              :   GstMetaQuery *meta_query;
     300              : 
     301            0 :   meta_query = gst_buffer_get_meta_query (buf);
     302            0 :   if (meta_query) {
     303            0 :     sink->metaless_frame_count = 0;
     304              : 
     305            0 :     if (!gst_tensor_query_server_send_buffer (sink->sink_id, buf)) {
     306            0 :       nns_loge ("Failed to send buffer to edge device in server sink.");
     307            0 :       return GST_FLOW_ERROR;
     308              :     }
     309              :   } else {
     310            0 :     nns_logw ("Cannot get tensor query meta. Drop buffers!\n");
     311            0 :     sink->metaless_frame_count++;
     312              : 
     313            0 :     if (sink->metaless_frame_count >= sink->metaless_frame_limit) {
     314            0 :       nns_logw ("Cannot get tensor query meta. Stop the query server!\n"
     315              :           "There are elements that are not available on the query server.\n"
     316              :           "Please check available elements on the server."
     317              :           "See: https://github.com/nnstreamer/nnstreamer/wiki/Available-elements-on-query-server");
     318            0 :       return GST_FLOW_ERROR;
     319              :     }
     320              :   }
     321              : 
     322            0 :   return GST_FLOW_OK;
     323              : }
        

Generated by: LCOV version 2.0-1