LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/datarepo - gstdatareposrc.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer.git#5d55fc62547faa02e861af5ef93cc1c89800934a Lines: 79.1 % 867 686
Test Date: 2024-09-25 09:08:39 Functions: 100.0 % 29 29

            Line data    Source code
       1              : /* SPDX-License-Identifier: LGPL-2.1-only */
       2              : /**
       3              :  * Copyright (C) 2022 Samsung Electronics Co., Ltd.
       4              :  *
       5              :  * @file        gstdatareposrc.c
       6              :  * @date        31 January 2023
       7              :  * @brief       GStreamer plugin to read file in MLOps Data repository into buffers
       8              :  * @see         https://github.com/nnstreamer/nnstreamer
       9              :  * @author      Hyunil Park <hyunil46.park@samsung.com>
      10              :  * @bug         No known bugs except for NYI items
      11              :  *
      12              :  *
      13              :  * ## Example launch line
      14              :  * |[
      15              :  * gst-launch-1.0 datareposrc location=mnist.data json=mnist.json start-sample-index=3 stop-sample-index=202 epochs=5 ! \
      16              :  * ! tensor_sink
      17              :  * gst-launch-1.0 datareposrc location=image_%02ld.png json=image.json start-sample-index=3 stop-sample-index=9 epochs=2 ! fakesink
      18              :  * gst-launch-1.0 datareposrc location=audiofile json=audio.json ! fakesink
      19              :  * gst-launch-1.0 datareposrc location=videofile json=video.json ! fakesink
      20              :  * |]
      21              :  * |[ Unknown sample file(has not JSON) need to set caps and blocksize or set caps to tensors type without blocksize
      22              :  * gst-launch-1.0 datareposrc blocksize=3176 location=unknown.data start-sample-index=3 stop-sample-index=202 epochs=5 \
      23              :  * caps ="application/octet-stream" ! tensor_converter input-dim=1:1:784:1,1:1:10:1 input-type=float32,float32 ! fakesink
      24              :  * |]
      25              :  * or
      26              :  * |[
      27              :  * gst-launch-1.0 datareposrc location=unknown.data start-sample-index=3 stop-sample-index=202 epochs=5 \
      28              :  * caps ="other/tensors, format=(string)static, framerate=(fraction)0/1, num_tensors=(int)2, dimensions=(string)1:1:784:1.1:1:10:1, types=(string)float32.float32" \
      29              :  * ! fakesink
      30              :  * ]|
      31              :  */
      32              : 
      33              : #ifdef HAVE_CONFIG_H
      34              : #include <config.h>
      35              : #endif
      36              : #include <gst/gst.h>
      37              : #include <gst/video/video-info.h>
      38              : #include <gst/audio/audio-info.h>
      39              : #include <glib/gstdio.h>
      40              : #include <nnstreamer_plugin_api.h>
      41              : #include <nnstreamer_util.h>
      42              : #include <stdio.h>
      43              : #include <fcntl.h>
      44              : #include <unistd.h>
      45              : #include <errno.h>
      46              : #include <string.h>
      47              : #include <sys/types.h>
      48              : #include <sys/stat.h>
      49              : #include <inttypes.h>
      50              : #include "gstdatareposrc.h"
      51              : 
      52              : #define struct_stat struct stat
      53              : #ifndef S_ISREG
      54              : /* regular file */
      55              : #define S_ISREG(mode) ((mode)&_S_IFREG)
      56              : #endif
      57              : #ifndef S_ISDIR
      58              : #define S_ISDIR(mode) ((mode)&_S_IFDIR)
      59              : #endif
      60              : /* socket */
      61              : #ifndef S_ISSOCK
      62              : #define S_ISSOCK(x) (0)
      63              : #endif
      64              : #ifndef O_BINARY
      65              : #define O_BINARY (0)
      66              : #endif
      67              : 
      68              : static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
      69              :     GST_PAD_SRC,
      70              :     GST_PAD_ALWAYS,
      71              :     GST_STATIC_CAPS_ANY);
      72              : 
      73              : GST_DEBUG_CATEGORY_STATIC (gst_data_repo_src_debug);
      74              : #define GST_CAT_DEFAULT gst_data_repo_src_debug
      75              : 
      76              : /* datareposrc signals and args */
      77              : enum
      78              : {
      79              :   PROP_0,
      80              :   PROP_LOCATION,
      81              :   PROP_JSON,
      82              :   PROP_START_SAMPLE_INDEX,
      83              :   PROP_STOP_SAMPLE_INDEX,
      84              :   PROP_EPOCHS,
      85              :   PROP_IS_SHUFFLE,
      86              :   PROP_TENSORS_SEQUENCE,
      87              :   PROP_CAPS,                    /* for setting caps of sample data directly */
      88              : };
      89              : 
      90              : #define DEFAULT_INDEX 0
      91              : #define DEFAULT_EPOCHS 1
      92              : #define DEFAULT_IS_SHUFFLE TRUE
      93              : 
      94              : static void gst_data_repo_src_finalize (GObject * object);
      95              : static GstStateChangeReturn gst_data_repo_src_change_state (GstElement *
      96              :     element, GstStateChange transition);
      97              : static void gst_data_repo_src_set_property (GObject * object, guint prop_id,
      98              :     const GValue * value, GParamSpec * pspec);
      99              : static void gst_data_repo_src_get_property (GObject * object, guint prop_id,
     100              :     GValue * value, GParamSpec * pspec);
     101              : static gboolean gst_data_repo_src_stop (GstBaseSrc * basesrc);
     102              : static GstCaps *gst_data_repo_src_get_caps (GstBaseSrc * basesrc,
     103              :     GstCaps * filter);
     104              : static gboolean gst_data_repo_src_set_caps (GstBaseSrc * basesrc,
     105              :     GstCaps * caps);
     106              : static GstFlowReturn gst_data_repo_src_create (GstPushSrc * pushsrc,
     107              :     GstBuffer ** buffer);
     108              : #define _do_init \
     109              :   GST_DEBUG_CATEGORY_INIT (gst_data_repo_src_debug, "datareposrc", 0, "datareposrc element");
     110              : 
     111              : #define gst_data_repo_src_parent_class parent_class
     112          926 : G_DEFINE_TYPE_WITH_CODE (GstDataRepoSrc, gst_data_repo_src, GST_TYPE_PUSH_SRC,
     113              :     _do_init);
     114              : 
     115              : /**
     116              :  * @brief initialize the datareposrc's class
     117              :  */
     118              : static void
     119           23 : gst_data_repo_src_class_init (GstDataRepoSrcClass * klass)
     120              : {
     121           23 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     122           23 :   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
     123           23 :   GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
     124           23 :   GstPushSrcClass *gstpushsrc_class = GST_PUSH_SRC_CLASS (klass);
     125              : 
     126           23 :   gobject_class->set_property =
     127           23 :       GST_DEBUG_FUNCPTR (gst_data_repo_src_set_property);
     128           23 :   gobject_class->get_property =
     129           23 :       GST_DEBUG_FUNCPTR (gst_data_repo_src_get_property);
     130              : 
     131           23 :   g_object_class_install_property (gobject_class, PROP_LOCATION,
     132              :       g_param_spec_string ("location", "File Location",
     133              :           "Location of the file to read that is stored in MLOps Data Repository, "
     134              :           "if the files are images, write the index of filename name "
     135              :           "like %04ld or %04lld (e.g., filenmae%04ld.png)",
     136              :           NULL,
     137              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
     138              :           GST_PARAM_MUTABLE_READY));
     139              : 
     140           23 :   g_object_class_install_property (gobject_class, PROP_JSON,
     141              :       g_param_spec_string ("json", "Json file path",
     142              :           "Json file path containing the meta information of the file "
     143              :           "specified as location", NULL,
     144              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
     145              :           GST_PARAM_MUTABLE_READY));
     146              : 
     147           23 :   g_object_class_install_property (gobject_class, PROP_START_SAMPLE_INDEX,
     148              :       g_param_spec_uint ("start-sample-index", "Start index of samples",
     149              :           "Start index of sample to read, in case of image, "
     150              :           "the starting index of the numbered files. start at 0."
     151              :           "Set start index of range of samples or files to read",
     152              :           0, G_MAXINT, DEFAULT_INDEX,
     153              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
     154              :           GST_PARAM_MUTABLE_READY));
     155              : 
     156           23 :   g_object_class_install_property (gobject_class, PROP_STOP_SAMPLE_INDEX,
     157              :       g_param_spec_uint ("stop-sample-index", "Stop index of samples",
     158              :           "Stop index of sample to read, in case of image, "
     159              :           "the stopping index of the numbered files. start at 0."
     160              :           "Set stop index of range of samples or files to read",
     161              :           0, G_MAXINT, DEFAULT_INDEX,
     162              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
     163              :           GST_PARAM_MUTABLE_READY));
     164              : 
     165           23 :   g_object_class_install_property (gobject_class, PROP_EPOCHS,
     166              :       g_param_spec_uint ("epochs", "Epochs",
     167              :           "Repetition of range of files or samples to read, set number of repetitions",
     168              :           0, G_MAXINT, DEFAULT_EPOCHS,
     169              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
     170              :           GST_PARAM_MUTABLE_READY));
     171              : 
     172           23 :   g_object_class_install_property (gobject_class, PROP_TENSORS_SEQUENCE,
     173              :       g_param_spec_string ("tensors-sequence", "Tensors sequence",
     174              :           "Tensors in a sample are read into gstBuffer according to tensors-sequence."
     175              :           "Only read the set tensors among all tensors in a sample"
     176              :           "e.g, if a sample has '1:1:1:1','1:1:10:1','1:1:784:1' and each index is '0,1,2', "
     177              :           "'tensors-sequence=2,1' means that only '1:1:784:1' then '1:1:10:1' are read. "
     178              :           "Use for other/tensors and the default value is NULL"
     179              :           "(all tensors are read in the order stored in a sample).",
     180              :           NULL,
     181              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
     182              :           GST_PARAM_MUTABLE_READY));
     183              : 
     184           23 :   g_object_class_install_property (gobject_class, PROP_IS_SHUFFLE,
     185              :       g_param_spec_boolean ("is-shuffle", "Is shuffle",
     186              :           "If the value is true, samples are shuffled",
     187              :           DEFAULT_IS_SHUFFLE,
     188              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
     189              :           GST_PARAM_MUTABLE_READY));
     190              : 
     191           23 :   g_object_class_install_property (gobject_class, PROP_CAPS,
     192              :       g_param_spec_boxed ("caps", "Caps",
     193              :           "Optional property, Caps describing the format of the sample data.",
     194              :           GST_TYPE_CAPS,
     195              :           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
     196              :           GST_PARAM_MUTABLE_READY));
     197              : 
     198           23 :   gobject_class->finalize = gst_data_repo_src_finalize;
     199           23 :   gstelement_class->change_state = gst_data_repo_src_change_state;
     200              : 
     201           23 :   gst_element_class_set_static_metadata (gstelement_class,
     202              :       "NNStreamer MLOps Data Repository Source",
     203              :       "Source/File",
     204              :       "Read files in MLOps Data Repository into buffers",
     205              :       "Samsung Electronics Co., Ltd.");
     206           23 :   gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
     207              : 
     208           23 :   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_data_repo_src_stop);
     209           23 :   gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_data_repo_src_get_caps);
     210           23 :   gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_data_repo_src_set_caps);
     211           23 :   gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_data_repo_src_create);
     212              : 
     213              :   if (sizeof (off_t) < 8) {
     214              :     GST_LOG ("No large file support, sizeof (off_t) = %" G_GSIZE_FORMAT "!",
     215              :         sizeof (off_t));
     216              :   }
     217           23 : }
     218              : 
     219              : /**
     220              :  * @brief Initialize datareposrc
     221              :  */
     222              : static void
     223           38 : gst_data_repo_src_init (GstDataRepoSrc * src)
     224              : {
     225           38 :   src->filename = NULL;
     226           38 :   src->json_filename = NULL;
     227           38 :   src->tensors_seq_str = NULL;
     228           38 :   src->file_size = 0;
     229           38 :   src->fd = 0;
     230           38 :   src->data_type = GST_DATA_REPO_DATA_UNKNOWN;
     231           38 :   src->fd_offset = 0;
     232           38 :   src->start_offset = 0;
     233           38 :   src->last_offset = 0;
     234           38 :   src->successful_read = FALSE;
     235           38 :   src->is_start = FALSE;
     236           38 :   src->current_sample_index = 0;
     237           38 :   src->start_sample_index = 0;
     238           38 :   src->stop_sample_index = 0;
     239           38 :   src->epochs = DEFAULT_EPOCHS;
     240           38 :   src->shuffled_index_array = g_array_new (FALSE, FALSE, sizeof (guint));
     241           38 :   src->array_index = 0;
     242           38 :   src->sample_offset_array = NULL;
     243           38 :   src->sample_offset_array_len = 0;
     244           38 :   src->tensor_size_array = NULL;
     245           38 :   src->tensor_size_array_len = 0;
     246           38 :   src->tensor_count_array = NULL;
     247           38 :   src->tensor_count_array_len = 0;
     248           38 :   src->first_epoch_is_done = FALSE;
     249           38 :   src->is_shuffle = DEFAULT_IS_SHUFFLE;
     250           38 :   src->num_samples = 0;
     251           38 :   src->total_samples = 0;
     252           38 :   src->tensors_seq_cnt = 0;
     253           38 :   src->caps = NULL;
     254           38 :   src->sample_size = 0;
     255           38 :   src->need_changed_caps = FALSE;
     256           38 :   src->n_frame = 0;
     257           38 :   src->running_time = 0;
     258           38 :   src->parser = NULL;
     259           38 :   gst_tensors_config_init (&src->config);
     260              : 
     261              :   /* Filling the buffer should be pending until set_caps() */
     262           38 :   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
     263           38 :   gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
     264           38 : }
     265              : 
     266              : /**
     267              :  * @brief Function to finalize instance.
     268              :  */
     269              : static void
     270           35 : gst_data_repo_src_finalize (GObject * object)
     271              : {
     272           35 :   GstDataRepoSrc *src = GST_DATA_REPO_SRC (object);
     273              : 
     274           35 :   g_free (src->filename);
     275           35 :   g_free (src->json_filename);
     276           35 :   g_free (src->tensors_seq_str);
     277              : 
     278              :   /* close the file */
     279           35 :   if (src->fd) {
     280            0 :     g_close (src->fd, NULL);
     281            0 :     src->fd = 0;
     282              :   }
     283              : 
     284           35 :   if (src->parser)
     285           27 :     g_object_unref (src->parser);
     286              : 
     287           35 :   if (src->shuffled_index_array)
     288           35 :     g_array_free (src->shuffled_index_array, TRUE);
     289              : 
     290           35 :   if (src->caps)
     291           28 :     gst_caps_replace (&src->caps, NULL);
     292              : 
     293           35 :   gst_tensors_config_free (&src->config);
     294              : 
     295           35 :   G_OBJECT_CLASS (parent_class)->finalize (object);
     296           35 : }
     297              : 
     298              : /**
     299              :  * @brief Parse gst-caps to get media type and data size.
     300              :  * @note This function always takes the ownership of gst-caps.
     301              :  */
     302              : static gboolean
     303           48 : gst_data_repo_src_parse_caps (GstDataRepoSrc * src, GstCaps * caps)
     304              : {
     305              :   GstStructure *s;
     306              : 
     307           48 :   g_return_val_if_fail (src != NULL, FALSE);
     308           48 :   g_return_val_if_fail (caps != NULL, FALSE);
     309              : 
     310           48 :   src->data_type = gst_data_repo_get_data_type_from_caps (caps);
     311           48 :   s = gst_caps_get_structure (caps, 0);
     312              : 
     313           48 :   switch (src->data_type) {
     314            1 :     case GST_DATA_REPO_DATA_VIDEO:
     315              :     {
     316              :       GstVideoInfo video_info;
     317              : 
     318            1 :       gst_video_info_init (&video_info);
     319            1 :       gst_video_info_from_caps (&video_info, caps);
     320              : 
     321              :       /* https://gstreamer.freedesktop.org/documentation/additional/design/mediatype-video-raw.html?gi-language=c */
     322            1 :       src->sample_size = (guint) GST_VIDEO_INFO_SIZE (&video_info);
     323              : 
     324            1 :       GST_DEBUG_OBJECT (src, "format(%s), width(%d), height(%d): %zd byte/frame",
     325              :           gst_structure_get_string (s, "format"),
     326              :           GST_VIDEO_INFO_WIDTH (&video_info),
     327              :           GST_VIDEO_INFO_HEIGHT (&video_info), src->sample_size);
     328            1 :       break;
     329              :     }
     330            1 :     case GST_DATA_REPO_DATA_AUDIO:
     331              :     {
     332              :       GstAudioInfo audio_info;
     333              :       gint rate, channel, depth;
     334              : 
     335            1 :       gst_audio_info_init (&audio_info);
     336            1 :       gst_audio_info_from_caps (&audio_info, caps);
     337              : 
     338            1 :       rate = GST_AUDIO_INFO_RATE (&audio_info);
     339            1 :       channel = GST_AUDIO_INFO_CHANNELS (&audio_info);
     340            1 :       depth = GST_AUDIO_INFO_DEPTH (&audio_info);
     341              : 
     342            1 :       src->sample_size = (gsize) channel * (depth / 8) * rate;
     343              : 
     344            1 :       GST_DEBUG_OBJECT (src,
     345              :           "format(%s), depth(%d), rate(%d), channel(%d): %zd bps",
     346              :           gst_structure_get_string (s, "format"), depth, rate, channel,
     347              :           src->sample_size);
     348            1 :       break;
     349              :     }
     350           45 :     case GST_DATA_REPO_DATA_TENSOR:
     351              :     {
     352              :       GstTensorInfo *_info;
     353              :       guint i;
     354              : 
     355              :       /* Set current tensors information if given data type is tensor. */
     356           45 :       gst_tensors_config_free (&src->config);
     357           45 :       gst_tensors_config_from_structure (&src->config, s);
     358           45 :       src->sample_size = 0;
     359              : 
     360          123 :       for (i = 0; i < src->config.info.num_tensors; i++) {
     361           78 :         src->tensors_offset[i] = src->sample_size;
     362           78 :         _info = gst_tensors_info_get_nth_info (&src->config.info, i);
     363           78 :         src->tensors_size[i] = gst_tensor_info_get_size (_info);
     364           78 :         GST_DEBUG_OBJECT (src, "offset[%u]: %zd", i, src->tensors_offset[i]);
     365           78 :         GST_DEBUG_OBJECT (src, "size[%u]: %zd", i, src->tensors_size[i]);
     366           78 :         src->sample_size += src->tensors_size[i];
     367              :       }
     368           45 :       break;
     369              :     }
     370            1 :     default:
     371            1 :       break;
     372              :   }
     373              : 
     374           48 :   src->rate_n = 0;
     375           48 :   src->rate_d = 1;
     376           48 :   if (gst_structure_has_field (s, "framerate")) {
     377           47 :     gst_structure_get_fraction (s, "framerate", &src->rate_n, &src->rate_d);
     378              :   }
     379              : 
     380           48 :   GST_LOG_OBJECT (src, "framerate %d/%d", src->rate_n, src->rate_d);
     381           48 :   GST_LOG_OBJECT (src, "data type: %d", src->data_type);
     382              : 
     383              :   /* This function always takes caps. */
     384           48 :   if (src->data_type != GST_DATA_REPO_DATA_UNKNOWN)
     385           48 :     gst_caps_take (&src->caps, caps);
     386              :   else
     387            0 :     gst_caps_unref (caps);
     388              : 
     389           48 :   return (src->data_type != GST_DATA_REPO_DATA_UNKNOWN);
     390              : }
     391              : 
     392              : /**
     393              :  * @brief Function to set file path.
     394              :  */
     395              : static gboolean
     396           74 : gst_data_repo_src_set_file_path (GstDataRepoSrc * src, const int prop,
     397              :     const gchar * file_path, GError ** err)
     398              : {
     399           74 :   gchar *filename = NULL;
     400              :   GstState state;
     401              : 
     402           74 :   g_return_val_if_fail (prop == PROP_LOCATION || prop == PROP_JSON, FALSE);
     403              : 
     404              :   /* the element must be stopped in order to do this */
     405           74 :   GST_OBJECT_LOCK (src);
     406           74 :   state = GST_STATE (src);
     407           74 :   if (state != GST_STATE_READY && state != GST_STATE_NULL)
     408            0 :     goto wrong_state;
     409           74 :   GST_OBJECT_UNLOCK (src);
     410              : 
     411              :   /* clear the filename if we get a NULL */
     412           74 :   if (file_path == NULL) {
     413            2 :     filename = NULL;
     414              :   } else {
     415              :     /* should be UTF8 */
     416           72 :     filename = g_strdup (file_path);
     417           72 :     GST_INFO_OBJECT (src, "%sname : %s",
     418              :         (prop == PROP_LOCATION) ? "file" : "json_file", filename);
     419              :   }
     420              : 
     421           74 :   if (prop == PROP_LOCATION) {
     422           38 :     g_free (src->filename);
     423           38 :     src->filename = filename;
     424              :   } else {                      /* PROP_JSON */
     425           36 :     g_free (src->json_filename);
     426           36 :     src->json_filename = filename;
     427              :   }
     428              : 
     429           74 :   return TRUE;
     430              : 
     431              :   /* ERROR */
     432            0 : wrong_state:
     433              :   {
     434            0 :     g_warning
     435              :         ("Changing the `location or json' property on datareposrc when a file is "
     436              :         "open is not supported.");
     437            0 :     if (err)
     438            0 :       g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_STATE,
     439              :           "Changing the `location or json' property on datareposrc when a file is "
     440              :           "open is not supported.");
     441            0 :     GST_OBJECT_UNLOCK (src);
     442            0 :     return FALSE;
     443              :   }
     444              : }
     445              : 
     446              : /**
     447              :  * @brief Function to set tensors sequence
     448              :  */
     449              : static gboolean
     450           21 : gst_data_repo_src_set_tensors_sequence (GstDataRepoSrc * src)
     451              : {
     452           21 :   g_auto (GStrv) strv = NULL;
     453              :   guint length;
     454           21 :   guint i = 0;
     455              : 
     456           21 :   g_return_val_if_fail (src != NULL, FALSE);
     457           21 :   g_return_val_if_fail (src->tensors_seq_str != NULL, FALSE);
     458              : 
     459           21 :   GST_INFO_OBJECT (src, "tensors sequence = %s", src->tensors_seq_str);
     460              : 
     461              :   /* not use NNS_TENSOR_SIZE_LIMIT */
     462           21 :   strv = g_strsplit (src->tensors_seq_str, ",", -1);
     463              : 
     464           21 :   length = g_strv_length (strv);
     465           21 :   if (length > NNS_TENSOR_SIZE_LIMIT) {
     466            0 :     GST_ERROR_OBJECT (src, "The total number of indices exceeded %d.",
     467              :         NNS_TENSOR_SIZE_LIMIT);
     468            0 :     goto error;
     469              :   }
     470              : 
     471           63 :   while (strv[i] != NULL && strlen (strv[i]) > 0) {
     472           43 :     src->tensors_seq[i] = (guint) g_ascii_strtoull (strv[i], NULL, 10);
     473           43 :     if (src->tensors_seq[i] > src->config.info.num_tensors - 1) {
     474            1 :       GST_ERROR_OBJECT (src, "Invalid index %d, max is %d", src->tensors_seq[i],
     475              :           src->config.info.num_tensors - 1);
     476            1 :       goto error;
     477              :     }
     478           42 :     GST_INFO_OBJECT (src, "%d", src->tensors_seq[i]);
     479           42 :     i++;
     480              :   }
     481           20 :   src->tensors_seq_cnt = i;
     482           20 :   GST_INFO_OBJECT (src, "The number of selected tensors is %d",
     483              :       src->tensors_seq_cnt);
     484              : 
     485              :   /* num_tensors was calculated from JSON file */
     486           20 :   if (src->config.info.num_tensors < src->tensors_seq_cnt) {
     487            3 :     GST_ERROR_OBJECT (src,
     488              :         "The number of tensors selected(%d) "
     489              :         "is greater than the total number of tensors(%d) in a sample.",
     490              :         src->tensors_seq_cnt, src->config.info.num_tensors);
     491            3 :     goto error;
     492              :   }
     493           17 :   return TRUE;
     494              : 
     495            4 : error:
     496            4 :   src->tensors_seq_cnt = 0;
     497            4 :   return FALSE;
     498              : }
     499              : 
     500              : /**
     501              :  * @brief Function to get file offset with sample index
     502              :  */
     503              : static guint64
     504          119 : gst_data_repo_src_get_file_offset (GstDataRepoSrc * src, guint sample_index)
     505              : {
     506              :   guint64 offset;
     507              : 
     508          119 :   g_return_val_if_fail (src != NULL, 0);
     509          119 :   g_return_val_if_fail (src->data_type != GST_DATA_REPO_DATA_IMAGE, 0);
     510          119 :   g_return_val_if_fail (src->fd != 0, 0);
     511              : 
     512          119 :   offset = src->sample_size * sample_index;
     513              : 
     514          119 :   return offset;
     515              : }
     516              : 
     517              : /**
     518              :  * @brief Function to shuffle samples index
     519              :  */
     520              : static void
     521            2 : gst_data_repo_src_shuffle_samples_index (GstDataRepoSrc * src)
     522              : {
     523              :   guint i, j;
     524              :   guint value_i, value_j;
     525            2 :   g_return_if_fail (src != NULL);
     526            2 :   g_return_if_fail (src->shuffled_index_array != NULL);
     527              : 
     528            2 :   GST_LOG_OBJECT (src, "samples index are shuffled");
     529              :   /* Fisher-Yates algorithm */
     530              :   /* The last index is the number of samples - 1. */
     531           20 :   for (i = src->num_samples - 1; i > 0; i--) {
     532           18 :     j = g_random_int_range (0, src->num_samples);
     533           18 :     value_i = g_array_index (src->shuffled_index_array, guint, i);
     534           18 :     value_j = g_array_index (src->shuffled_index_array, guint, j);
     535              : 
     536              :     /* shuffled_index_array->data type is gchar * */
     537           18 :     *(guint *) (src->shuffled_index_array->data + (sizeof (guint) * i)) =
     538              :         value_j;
     539           18 :     *(guint *) (src->shuffled_index_array->data + (sizeof (guint) * j)) =
     540              :         value_i;
     541              :   }
     542              : 
     543           22 :   for (i = 0; i < src->shuffled_index_array->len; i++) {
     544           20 :     GST_DEBUG_OBJECT (src, "%u -> %u", i,
     545              :         g_array_index (src->shuffled_index_array, guint, i));
     546              :   }
     547              : }
     548              : 
     549              : /**
     550              :  * @brief Function to check epoch and EOS
     551              :  */
     552              : static gboolean
     553          211 : gst_data_repo_src_epoch_is_done (GstDataRepoSrc * src)
     554              : {
     555          211 :   g_return_val_if_fail (src != NULL, FALSE);
     556          211 :   if (src->num_samples != src->array_index)
     557          196 :     return FALSE;
     558              : 
     559           15 :   src->first_epoch_is_done = TRUE;
     560           15 :   src->array_index = 0;
     561           15 :   src->epochs--;
     562              : 
     563           15 :   return TRUE;
     564              : }
     565              : 
     566              : /**
     567              :  * @brief Function to read tensors
     568              :  */
     569              : static GstFlowReturn
     570           86 : gst_data_repo_src_read_tensors (GstDataRepoSrc * src, GstBuffer ** buffer)
     571              : {
     572           86 :   GstFlowReturn ret = GST_FLOW_OK;
     573           86 :   guint i = 0, seq_idx = 0;
     574           86 :   GstBuffer *buf = NULL;
     575              :   gsize to_read, byte_read;
     576              :   gssize read_size;
     577              :   guint8 *data;
     578           86 :   GstMemory *mem = NULL;
     579              :   GstMapInfo info;
     580           86 :   guint shuffled_index = 0;
     581           86 :   guint64 sample_offset = 0;
     582           86 :   guint64 offset = 0;           /* offset from 0 */
     583              : 
     584          172 :   g_return_val_if_fail (src->fd != 0, GST_FLOW_ERROR);
     585           86 :   g_return_val_if_fail (src->shuffled_index_array != NULL, GST_FLOW_ERROR);
     586              : 
     587           86 :   if (gst_data_repo_src_epoch_is_done (src)) {
     588            8 :     if (src->epochs == 0) {
     589            6 :       GST_LOG_OBJECT (src, "send EOS");
     590            6 :       return GST_FLOW_EOS;
     591              :     }
     592            2 :     if (src->is_shuffle)
     593            2 :       gst_data_repo_src_shuffle_samples_index (src);
     594              :   }
     595              : 
     596              :   /* only do for first epoch */
     597           80 :   if (!src->first_epoch_is_done) {
     598              :     /* append samples index to array */
     599           60 :     g_array_append_val (src->shuffled_index_array, src->current_sample_index);
     600           60 :     src->current_sample_index++;
     601              :   }
     602           80 :   shuffled_index =
     603           80 :       g_array_index (src->shuffled_index_array, guint, src->array_index++);
     604           80 :   GST_LOG_OBJECT (src, "shuffled_index [%d] -> %d", src->array_index - 1,
     605              :       shuffled_index);
     606              : 
     607              :   /* sample offset from 0 */
     608           80 :   sample_offset = gst_data_repo_src_get_file_offset (src, shuffled_index);
     609           80 :   GST_LOG_OBJECT (src, "sample offset 0x%" G_GINT64_MODIFIER "x (%d size)",
     610              :       sample_offset, (guint) sample_offset);
     611              : 
     612           80 :   buf = gst_buffer_new ();
     613              : 
     614          240 :   for (i = 0; i < src->tensors_seq_cnt; i++) {
     615          160 :     seq_idx = src->tensors_seq[i];
     616          160 :     mem = gst_allocator_alloc (NULL, src->tensors_size[seq_idx], NULL);
     617              : 
     618          160 :     if (!gst_memory_map (mem, &info, GST_MAP_WRITE)) {
     619            0 :       GST_ERROR_OBJECT (src, "Could not map GstMemory[%d]", i);
     620            0 :       ret = GST_FLOW_ERROR;
     621            0 :       goto error;
     622              :     }
     623              : 
     624          160 :     GST_INFO_OBJECT (src, "sequence index: %d", seq_idx);
     625          160 :     GST_INFO_OBJECT (src, "tensor_size[%d]: %zd", seq_idx,
     626              :         src->tensors_size[seq_idx]);
     627          160 :     GST_INFO_OBJECT (src, "tensors_offset[%d]: %zd", seq_idx,
     628              :         src->tensors_offset[seq_idx]);
     629              : 
     630              :     /** offset and sample_offset(byte size) are from 0.
     631              :       if the size of one sample is 6352 and num_tensors is 4,
     632              :       dimensions are  '1:1:784:1' , '1:1:10:1',  '1:1:784:1' and '1:1:10:1' with float32.
     633              :       the offset of the second sample is as follows.
     634              :         -------------------------------------------------
     635              :           sample_offset: 6352
     636              :           tensors index: [ 0    | 1    | 2    | 3     ]
     637              :            tensors_size: [ 3136 | 40   | 3136 | 40    ]
     638              :          tensors_offset: [ 0    | 3136 | 3176 | 6312  ]
     639              :               fd offset: [ 6352 | 9488 | 9528 | 12664 ]
     640              :         -------------------------------------------------
     641              :       if user sets "tensor-sequence=2,1", datareposrc read offset 9528 then 9488.
     642              :     */
     643              : 
     644          160 :     data = info.data;
     645              : 
     646          160 :     byte_read = 0;
     647          160 :     to_read = src->tensors_size[seq_idx];
     648          160 :     offset = sample_offset + src->tensors_offset[seq_idx];
     649          160 :     src->fd_offset = lseek (src->fd, offset, SEEK_SET);
     650              : 
     651          320 :     while (to_read > 0) {
     652          160 :       GST_LOG_OBJECT (src,
     653              :           "Reading %zd bytes at offset 0x%" G_GINT64_MODIFIER "x (%zd size)",
     654              :           to_read, src->fd_offset + byte_read,
     655              :           (guint) src->fd_offset + byte_read);
     656          160 :       errno = 0;
     657          160 :       read_size = read (src->fd, data + byte_read, to_read);
     658          160 :       GST_LOG_OBJECT (src, "Read: %zd", read_size);
     659          160 :       if (read_size < 0) {
     660            0 :         if (errno == EAGAIN || errno == EINTR)
     661            0 :           continue;
     662            0 :         GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
     663            0 :         ret = GST_FLOW_ERROR;
     664            0 :         goto error;
     665              :       }
     666              :       /* files should eos if they read 0 and more was requested */
     667          160 :       if (read_size == 0) {
     668              :         /* .. but first we should return any remaining data */
     669            0 :         if (byte_read > 0)
     670            0 :           break;
     671            0 :         GST_DEBUG_OBJECT (src, "EOS");
     672            0 :         ret = GST_FLOW_EOS;
     673            0 :         goto error;
     674              :       }
     675          160 :       to_read -= read_size;
     676          160 :       byte_read += read_size;
     677              : 
     678          160 :       src->read_position += read_size;
     679          160 :       src->fd_offset += read_size;
     680              :     }
     681              : 
     682          160 :     gst_memory_unmap (mem, &info);
     683              : 
     684          160 :     gst_tensor_buffer_append_memory (buf, mem,
     685          160 :         gst_tensors_info_get_nth_info (&src->config.info, i));
     686          160 :     mem = NULL;
     687              :   }
     688              : 
     689           80 :   *buffer = buf;
     690              : 
     691           80 :   return GST_FLOW_OK;
     692              : 
     693            0 : error:
     694            0 :   if (mem) {
     695            0 :     gst_memory_unmap (mem, &info);
     696            0 :     gst_memory_unref (mem);
     697              :   }
     698            0 :   if (buf)
     699            0 :     gst_buffer_unref (buf);
     700              : 
     701            0 :   return ret;
     702              : }
     703              : 
     704              : /**
     705              :  * @brief Function to get num_tensors from tensor_count_array
     706              :  */
     707              : static guint
     708          102 : gst_data_repo_src_get_num_tensors (GstDataRepoSrc * src, guint shuffled_index)
     709              : {
     710          102 :   guint num_tensors = 0;
     711          102 :   guint cur_idx_tensor_cnt = 0;
     712          102 :   guint next_idx_tensor_cnt = 0;
     713              :   gint64 val;
     714              : 
     715          102 :   g_return_val_if_fail (src != NULL, 0);
     716              : 
     717          102 :   val = json_array_get_int_element (src->tensor_count_array, shuffled_index);
     718          102 :   g_return_val_if_fail (val >= 0, 0);
     719              : 
     720          102 :   cur_idx_tensor_cnt = (guint) val;
     721          102 :   GST_DEBUG_OBJECT (src, "cur_idx_tensor_cnt:%u", cur_idx_tensor_cnt);
     722              : 
     723          102 :   if (shuffled_index + 1 == src->tensor_count_array_len) {
     724            4 :     next_idx_tensor_cnt = src->tensor_size_array_len;
     725              :   } else {
     726           98 :     val = json_array_get_int_element (src->tensor_count_array,
     727              :         shuffled_index + 1);
     728           98 :     g_return_val_if_fail (val >= 0, 0);
     729              : 
     730           98 :     next_idx_tensor_cnt = (guint) val;
     731              :   }
     732          102 :   GST_DEBUG_OBJECT (src, "next_idx_tensor_cnt:%u", next_idx_tensor_cnt);
     733              : 
     734          102 :   num_tensors = next_idx_tensor_cnt - cur_idx_tensor_cnt;
     735          102 :   GST_DEBUG_OBJECT (src, "num_tensors:%u", num_tensors);
     736              : 
     737          102 :   return num_tensors;
     738              : }
     739              : 
     740              : /**
     741              :  * @brief Function to read flexible or sparse tensors
     742              :  */
     743              : static GstFlowReturn
     744          106 : gst_data_repo_src_read_flexible_or_sparse_tensors (GstDataRepoSrc * src,
     745              :     GstBuffer ** buffer)
     746              : {
     747          106 :   GstFlowReturn ret = GST_FLOW_OK;
     748              :   guint i;
     749          106 :   guint shuffled_index = 0;
     750              :   gint64 val;
     751          106 :   guint num_tensors = 0;
     752          106 :   GstBuffer *buf = NULL;
     753          106 :   GstMemory *mem = NULL;
     754              :   GstMapInfo info;
     755              :   GstTensorMetaInfo meta;
     756              :   GstTensorInfo tinfo;
     757              :   gsize to_read, byte_read;
     758              :   gssize read_size;
     759              :   guint8 *data;
     760              :   guint tensor_count;
     761              :   gsize tensor_size;
     762              : 
     763          212 :   g_return_val_if_fail (src->fd != 0, GST_FLOW_ERROR);
     764          106 :   g_return_val_if_fail (src->shuffled_index_array != NULL, GST_FLOW_ERROR);
     765              : 
     766          106 :   if (gst_data_repo_src_epoch_is_done (src)) {
     767            4 :     if (src->epochs == 0) {
     768            4 :       GST_LOG_OBJECT (src, "send EOS");
     769            4 :       return GST_FLOW_EOS;
     770              :     }
     771            0 :     if (src->is_shuffle)
     772            0 :       gst_data_repo_src_shuffle_samples_index (src);
     773              :   }
     774              : 
     775              :   /* only do for first epoch */
     776          102 :   if (!src->first_epoch_is_done) {
     777              :     /* append samples index to array */
     778          102 :     g_array_append_val (src->shuffled_index_array, src->current_sample_index);
     779          102 :     src->current_sample_index++;
     780              :   }
     781              : 
     782          102 :   shuffled_index =
     783          102 :       g_array_index (src->shuffled_index_array, guint, src->array_index++);
     784          102 :   GST_LOG_OBJECT (src, "shuffled_index [%d] -> %d", src->array_index - 1,
     785              :       shuffled_index);
     786              : 
     787              :   /* sample offset from 0 */
     788          102 :   val = json_array_get_int_element (src->sample_offset_array, shuffled_index);
     789          102 :   if (val < 0) {
     790            0 :     GST_ERROR_OBJECT (src, "Could not get the sample offset from json.");
     791            0 :     return GST_FLOW_ERROR;
     792              :   }
     793              : 
     794          102 :   GST_LOG_OBJECT (src, "sample offset 0x%" G_GINT64_MODIFIER "x (%d size)",
     795              :       val, (guint) val);
     796              : 
     797          102 :   src->fd_offset = lseek (src->fd, val, SEEK_SET);
     798              : 
     799          102 :   val = json_array_get_int_element (src->tensor_count_array, shuffled_index);
     800          102 :   if (val < 0) {
     801            0 :     GST_ERROR_OBJECT (src, "Could not get the tensor count from json.");
     802            0 :     return GST_FLOW_ERROR;
     803              :   }
     804          102 :   tensor_count = (guint) val;
     805              : 
     806          102 :   num_tensors = gst_data_repo_src_get_num_tensors (src, shuffled_index);
     807              : 
     808          102 :   buf = gst_buffer_new ();
     809              : 
     810          212 :   for (i = 0; i < num_tensors; i++) {
     811          112 :     val = json_array_get_int_element (src->tensor_size_array, tensor_count + i);
     812          112 :     if (val < 0) {
     813            0 :       GST_ERROR_OBJECT (src, "Could not get the size of tensor from json.");
     814            0 :       ret = GST_FLOW_ERROR;
     815            0 :       goto error;
     816              :     }
     817              : 
     818          112 :     tensor_size = (gsize) val;
     819          112 :     mem = gst_allocator_alloc (NULL, tensor_size, NULL);
     820              : 
     821          112 :     if (!gst_memory_map (mem, &info, GST_MAP_WRITE)) {
     822            0 :       GST_ERROR_OBJECT (src, "Could not map GstMemory[%d]", i);
     823            0 :       ret = GST_FLOW_ERROR;
     824            0 :       goto error;
     825              :     }
     826              : 
     827          112 :     data = info.data;
     828          112 :     byte_read = 0;
     829          112 :     to_read = tensor_size;
     830          224 :     while (to_read > 0) {
     831          112 :       GST_LOG_OBJECT (src,
     832              :           "Reading %zd bytes at offset 0x%" G_GINT64_MODIFIER "x (%lld size)",
     833              :           to_read, src->fd_offset + byte_read, (long long) src->fd_offset);
     834          112 :       errno = 0;
     835          112 :       read_size = read (src->fd, data + byte_read, to_read);
     836          112 :       GST_LOG_OBJECT (src, "Read: %zd", read_size);
     837          112 :       if (read_size < 0) {
     838            0 :         if (errno == EAGAIN || errno == EINTR)
     839            0 :           continue;
     840            0 :         GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
     841            0 :         ret = GST_FLOW_ERROR;
     842            0 :         goto error;
     843              :       }
     844              :       /* files should eos if they read 0 and more was requested */
     845          112 :       if (read_size == 0) {
     846              :         /* .. but first we should return any remaining data */
     847            0 :         if (byte_read > 0)
     848            0 :           break;
     849            0 :         GST_DEBUG_OBJECT (src, "EOS");
     850            0 :         ret = GST_FLOW_EOS;
     851            0 :         goto error;
     852              :       }
     853          112 :       to_read -= read_size;
     854          112 :       byte_read += read_size;
     855              : 
     856          112 :       src->read_position += read_size;
     857          112 :       src->fd_offset += read_size;
     858              :     }
     859              : 
     860              :     /* check invalid flexible tensor */
     861          112 :     if (!gst_tensor_meta_info_parse_header (&meta, info.data)) {
     862            2 :       GST_ERROR_OBJECT (src, "Invalid flexible tensors");
     863            2 :       ret = GST_FLOW_ERROR;
     864            2 :       goto error;
     865              :     }
     866              : 
     867          110 :     gst_memory_unmap (mem, &info);
     868              : 
     869          110 :     gst_tensor_meta_info_convert (&meta, &tinfo);
     870          110 :     gst_tensor_buffer_append_memory (buf, mem, &tinfo);
     871          110 :     gst_tensor_info_free (&tinfo);
     872          110 :     mem = NULL;
     873              :   }
     874              : 
     875          100 :   *buffer = buf;
     876              : 
     877          100 :   return GST_FLOW_OK;
     878              : 
     879            2 : error:
     880            2 :   if (mem) {
     881            2 :     gst_memory_unmap (mem, &info);
     882            2 :     gst_memory_unref (mem);
     883              :   }
     884            2 :   if (buf)
     885            2 :     gst_buffer_unref (buf);
     886              : 
     887            2 :   return ret;
     888              : }
     889              : 
     890              : /**
     891              :  * @brief Get image filename
     892              :  */
     893              : static gchar *
     894            6 : gst_data_repo_src_get_image_filename (GstDataRepoSrc * src)
     895              : {
     896            6 :   gchar *filename = NULL;
     897            6 :   guint shuffled_index = 0;
     898            6 :   g_return_val_if_fail (src != NULL, NULL);
     899            6 :   g_return_val_if_fail (src->data_type == GST_DATA_REPO_DATA_IMAGE, NULL);
     900            6 :   g_return_val_if_fail (src->filename != NULL, NULL);
     901            6 :   g_return_val_if_fail (src->shuffled_index_array != NULL, NULL);
     902              : 
     903              :   /* GST_DATA_REPO_DATA_IMAGE must have %d in src->filename */
     904            6 :   if (src->shuffled_index_array->len > 0)
     905            5 :     shuffled_index =
     906            5 :         g_array_index (src->shuffled_index_array, guint, src->array_index);
     907              :   else
     908            1 :     shuffled_index = 0;         /* Used for initial file open verification */
     909              : 
     910              : #ifdef __GNUC__
     911              : #pragma GCC diagnostic push
     912              : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
     913              : #endif
     914              :   /* let's set value by property */
     915            6 :   filename = g_strdup_printf (src->filename, shuffled_index);
     916              : #ifdef __GNUC__
     917              : #pragma GCC diagnostic pop
     918              : #endif
     919              : 
     920            6 :   return filename;
     921              : }
     922              : 
     923              : /**
     924              :  * @brief Function to read multi image files
     925              :  */
     926              : static GstFlowReturn
     927            6 : gst_data_repo_src_read_multi_images (GstDataRepoSrc * src, GstBuffer ** buffer)
     928              : {
     929            6 :   g_autofree gchar *filename = NULL;
     930              :   gsize size;
     931              :   gchar *data;
     932              :   GstBuffer *buf;
     933              :   gboolean read_size;
     934            6 :   GError *error = NULL;
     935              : 
     936            6 :   g_return_val_if_fail (src->shuffled_index_array != NULL, GST_FLOW_ERROR);
     937              : 
     938            6 :   if (gst_data_repo_src_epoch_is_done (src)) {
     939            1 :     if (src->epochs == 0) {
     940            1 :       GST_LOG_OBJECT (src, "send EOS");
     941            1 :       return GST_FLOW_EOS;
     942              :     }
     943            0 :     if (src->is_shuffle)
     944            0 :       gst_data_repo_src_shuffle_samples_index (src);
     945              :   }
     946              : 
     947              :   /* only do for first epoch */
     948            5 :   if (!src->first_epoch_is_done) {
     949              :     /* append samples index to array */
     950            5 :     g_array_append_val (src->shuffled_index_array, src->current_sample_index);
     951            5 :     src->current_sample_index++;
     952              :   }
     953              : 
     954            5 :   filename = gst_data_repo_src_get_image_filename (src);
     955            5 :   GST_DEBUG_OBJECT (src, "Reading from file \"%s\".", filename);
     956            5 :   src->array_index++;
     957              : 
     958              :   /* Try to read one image */
     959            5 :   read_size = g_file_get_contents (filename, &data, &size, &error);
     960            5 :   if (!read_size) {
     961            0 :     if (src->successful_read) {
     962              :       /* If we've read at least one buffer successfully, not finding the next file is EOS. */
     963            0 :       if (error != NULL)
     964            0 :         g_error_free (error);
     965            0 :       return GST_FLOW_EOS;
     966              :     }
     967            0 :     goto handle_error;
     968              :   }
     969              : 
     970              :   /* Success reading on image */
     971            5 :   src->successful_read = TRUE;
     972            5 :   GST_DEBUG_OBJECT (src, "file size is %zd", size);
     973              : 
     974            5 :   buf = gst_buffer_new ();
     975            5 :   gst_buffer_append_memory (buf,
     976              :       gst_memory_new_wrapped (0, data, size, 0, size, data, g_free));
     977              : 
     978            5 :   *buffer = buf;
     979              : 
     980            5 :   return GST_FLOW_OK;
     981              : 
     982            0 : handle_error:
     983              :   {
     984            0 :     if (error != NULL) {
     985            0 :       GST_ELEMENT_ERROR (src, RESOURCE, READ,
     986              :           ("Error while reading from file \"%s\".", filename),
     987              :           ("%s", error->message));
     988            0 :       g_error_free (error);
     989              :     } else {
     990            0 :       GST_ELEMENT_ERROR (src, RESOURCE, READ,
     991              :           ("Error while reading from file \"%s\".", filename),
     992              :           ("%s", g_strerror (errno)));
     993              :     }
     994            0 :     return GST_FLOW_ERROR;
     995              :   }
     996              : }
     997              : 
     998              : /**
     999              :  * @brief Function to read others media type (video, audio, octet and text)
    1000              :  */
    1001              : static GstFlowReturn
    1002           13 : gst_data_repo_src_read_others (GstDataRepoSrc * src, GstBuffer ** buffer)
    1003              : {
    1004           13 :   GstFlowReturn ret = GST_FLOW_OK;
    1005              :   GstBuffer *buf;
    1006              :   gsize to_read, byte_read;
    1007              :   gssize read_size;
    1008              :   guint8 *data;
    1009              :   GstMemory *mem;
    1010              :   GstMapInfo info;
    1011           13 :   guint shuffled_index = 0;
    1012           13 :   guint64 offset = 0;
    1013              : 
    1014           26 :   g_return_val_if_fail (src->fd != 0, GST_FLOW_ERROR);
    1015           13 :   g_return_val_if_fail (src->shuffled_index_array != NULL, GST_FLOW_ERROR);
    1016              : 
    1017           13 :   if (gst_data_repo_src_epoch_is_done (src)) {
    1018            2 :     if (src->epochs == 0) {
    1019            2 :       GST_LOG_OBJECT (src, "send EOS");
    1020            2 :       return GST_FLOW_EOS;
    1021              :     }
    1022            0 :     if (src->is_shuffle)
    1023            0 :       gst_data_repo_src_shuffle_samples_index (src);
    1024              :   }
    1025              : 
    1026              :   /* only do for first epoch */
    1027           11 :   if (!src->first_epoch_is_done) {
    1028              :     /* append samples index to array */
    1029           11 :     g_array_append_val (src->shuffled_index_array, src->current_sample_index);
    1030           11 :     src->current_sample_index++;
    1031              :   }
    1032              : 
    1033           11 :   shuffled_index =
    1034           11 :       g_array_index (src->shuffled_index_array, guint, src->array_index++);
    1035           11 :   GST_LOG_OBJECT (src, "shuffled_index [%d] -> %d", src->array_index - 1,
    1036              :       shuffled_index);
    1037           11 :   offset = gst_data_repo_src_get_file_offset (src, shuffled_index);
    1038           11 :   src->fd_offset = lseek (src->fd, offset, SEEK_SET);
    1039              : 
    1040           11 :   mem = gst_allocator_alloc (NULL, src->sample_size, NULL);
    1041              : 
    1042           11 :   if (!gst_memory_map (mem, &info, GST_MAP_WRITE)) {
    1043            0 :     GST_ERROR_OBJECT (src, "Could not map GstMemory");
    1044            0 :     gst_memory_unref (mem);
    1045            0 :     return GST_FLOW_ERROR;
    1046              :   }
    1047              : 
    1048           11 :   data = info.data;
    1049              : 
    1050           11 :   byte_read = 0;
    1051           11 :   to_read = src->sample_size;
    1052           22 :   while (to_read > 0) {
    1053           11 :     GST_LOG_OBJECT (src, "Reading %zd bytes at offset 0x%" G_GINT64_MODIFIER "x",
    1054              :         to_read, src->fd_offset + byte_read);
    1055           11 :     errno = 0;
    1056           11 :     read_size = read (src->fd, data + byte_read, to_read);
    1057           11 :     GST_LOG_OBJECT (src, "Read: %zd", read_size);
    1058           11 :     if (read_size < 0) {
    1059            0 :       if (errno == EAGAIN || errno == EINTR)
    1060            0 :         continue;
    1061            0 :       GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
    1062            0 :       ret = GST_FLOW_ERROR;
    1063            0 :       goto error;
    1064              :     }
    1065              :     /* files should eos if they read 0 and more was requested */
    1066           11 :     if (read_size == 0) {
    1067              :       /* .. but first we should return any remaining data */
    1068            0 :       if (byte_read > 0)
    1069            0 :         break;
    1070            0 :       GST_DEBUG_OBJECT (src, "EOS");
    1071            0 :       ret = GST_FLOW_EOS;
    1072            0 :       goto error;
    1073              :     }
    1074           11 :     to_read -= read_size;
    1075           11 :     byte_read += read_size;
    1076              : 
    1077           11 :     src->read_position += read_size;
    1078           11 :     src->fd_offset += read_size;
    1079              :   }
    1080              : 
    1081           11 :   gst_memory_unmap (mem, &info);
    1082              : 
    1083           11 :   buf = gst_buffer_new ();
    1084           11 :   gst_buffer_append_memory (buf, mem);
    1085              : 
    1086           11 :   *buffer = buf;
    1087           11 :   return GST_FLOW_OK;
    1088              : 
    1089            0 : error:
    1090            0 :   if (mem) {
    1091            0 :     gst_memory_unmap (mem, &info);
    1092            0 :     gst_memory_unref (mem);
    1093              :   }
    1094              : 
    1095            0 :   return ret;
    1096              : }
    1097              : 
    1098              : /**
    1099              :  * @brief Start datareposrc, open the file
    1100              :  */
    1101              : static gboolean
    1102           15 : gst_data_repo_src_start (GstDataRepoSrc * src)
    1103              : {
    1104           15 :   g_autofree gchar *filename = NULL;
    1105              :   struct_stat stat_results;
    1106           15 :   int flags = O_RDONLY | O_BINARY;
    1107              : 
    1108           15 :   g_return_val_if_fail (src != NULL, FALSE);
    1109              : 
    1110           15 :   if (src->filename == NULL || src->filename[0] == '\0')
    1111            0 :     goto no_filename;
    1112              : 
    1113           15 :   src->current_sample_index = src->start_sample_index;
    1114           15 :   src->num_samples = src->stop_sample_index - src->start_sample_index + 1;
    1115           15 :   GST_INFO_OBJECT (src,
    1116              :       "The number of samples to be used out of the total samples in the file is %d, [%d] ~ [%d]",
    1117              :       src->num_samples, src->start_sample_index, src->stop_sample_index);
    1118           15 :   GST_INFO_OBJECT (src, "data type: %d", src->data_type);
    1119           15 :   if (src->data_type == GST_DATA_REPO_DATA_IMAGE) {
    1120            1 :     filename = gst_data_repo_src_get_image_filename (src);
    1121              :   } else {
    1122           28 :     filename = g_strdup (src->filename);
    1123              :   }
    1124              : 
    1125           15 :   GST_INFO_OBJECT (src, "opening file %s", filename);
    1126              : 
    1127              :   /* open the file */
    1128           15 :   src->fd = g_open (filename, flags, 0);
    1129              : 
    1130           15 :   if (src->fd < 0)
    1131            0 :     goto open_failed;
    1132              : 
    1133              :   /* check if it is a regular file, otherwise bail out */
    1134           15 :   if (fstat (src->fd, &stat_results) < 0)
    1135            0 :     goto no_stat;
    1136              : 
    1137           15 :   src->file_size = stat_results.st_size;
    1138           15 :   if (src->file_size == 0)
    1139            0 :     goto error_close;
    1140              : 
    1141           15 :   if (S_ISDIR (stat_results.st_mode))
    1142            0 :     goto was_directory;
    1143              : 
    1144           15 :   if (S_ISSOCK (stat_results.st_mode))
    1145            0 :     goto was_socket;
    1146              : 
    1147              :   /* record if it's a regular (hence seekable and lengthable) file */
    1148           15 :   if (!S_ISREG (stat_results.st_mode))
    1149            0 :     goto error_close;
    1150              : 
    1151           15 :   src->read_position = 0;
    1152              : 
    1153           15 :   if (src->data_type == GST_DATA_REPO_DATA_IMAGE) {
    1154              :     /* no longer used */
    1155            1 :     g_close (src->fd, NULL);
    1156            1 :     src->fd = 0;
    1157              :   } else {
    1158              :     /* set start offset and last offset */
    1159           14 :     src->start_offset =
    1160           14 :         gst_data_repo_src_get_file_offset (src, src->start_sample_index);
    1161              : 
    1162              :     /* If the user does not set stop_sample_index, datareposrc need to calculate the last offset */
    1163           14 :     src->last_offset =
    1164           14 :         gst_data_repo_src_get_file_offset (src, src->stop_sample_index);
    1165              : 
    1166           14 :     src->fd_offset = lseek (src->fd, src->start_offset, SEEK_SET);
    1167           14 :     GST_LOG_OBJECT (src, "Start file offset 0x%" G_GINT64_MODIFIER "x",
    1168              :         src->fd_offset);
    1169              :   }
    1170              : 
    1171           15 :   return TRUE;
    1172              : 
    1173              :   /* ERROR */
    1174            0 : no_filename:
    1175              :   {
    1176            0 :     GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
    1177              :         ("No file name specified for reading."), (NULL));
    1178            0 :     goto error_exit;
    1179              :   }
    1180            0 : open_failed:
    1181              :   {
    1182            0 :     switch (errno) {
    1183            0 :       case ENOENT:
    1184            0 :         GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
    1185              :             ("No such file \"%s\"", src->filename));
    1186            0 :         break;
    1187            0 :       default:
    1188            0 :         GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
    1189              :             (("Could not open file \"%s\" for reading."), src->filename),
    1190              :             GST_ERROR_SYSTEM);
    1191            0 :         break;
    1192              :     }
    1193            0 :     goto error_exit;
    1194              :   }
    1195            0 : no_stat:
    1196              :   {
    1197            0 :     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
    1198              :         (("Could not get info on \"%s\"."), src->filename), (NULL));
    1199            0 :     goto error_close;
    1200              :   }
    1201            0 : was_directory:
    1202              :   {
    1203            0 :     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
    1204              :         (("\"%s\" is a directory."), src->filename), (NULL));
    1205            0 :     goto error_close;
    1206              :   }
    1207            0 : was_socket:
    1208              :   {
    1209            0 :     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
    1210              :         (("File \"%s\" is a socket."), src->filename), (NULL));
    1211            0 :     goto error_close;
    1212              :   }
    1213              : 
    1214            0 : error_close:
    1215            0 :   g_close (src->fd, NULL);
    1216            0 :   src->fd = 0;
    1217            0 : error_exit:
    1218            0 :   return FALSE;
    1219              : }
    1220              : 
    1221              : /**
    1222              :  * @brief Set timestamp
    1223              :  */
    1224              : static void
    1225          105 : gst_data_repo_src_set_timestamp (GstDataRepoSrc * src, GstBuffer * buffer)
    1226              : {
    1227              : 
    1228              :   GstClockTime next_time;
    1229          105 :   GstClockTime duration = GST_CLOCK_TIME_NONE;
    1230              : 
    1231          105 :   g_return_if_fail (src != NULL);
    1232          105 :   g_return_if_fail (buffer != NULL);
    1233              : 
    1234              :   /* Unlike video, audio should control one sample by framerate. */
    1235          105 :   if (src->data_type == GST_DATA_REPO_DATA_AUDIO) {
    1236            0 :     GST_WARNING_OBJECT (src,
    1237              :         "Use audiorate element for the framerate of audio");
    1238            0 :     return;
    1239              :   }
    1240              : 
    1241          105 :   duration = gst_util_uint64_scale_int (GST_SECOND, src->rate_d, src->rate_n);
    1242          105 :   GST_BUFFER_DURATION (buffer) = duration;
    1243          105 :   GST_BUFFER_TIMESTAMP (buffer) = src->running_time;
    1244          105 :   gst_object_sync_values (GST_OBJECT (src), GST_BUFFER_TIMESTAMP (buffer));
    1245              : 
    1246              :   next_time =
    1247          210 :       gst_util_uint64_scale (src->n_frame++, src->rate_d * GST_SECOND,
    1248          105 :       src->rate_n);
    1249          105 :   src->running_time = next_time;
    1250              : 
    1251          105 :   GST_LOG_OBJECT (src, "next_time %" GST_TIME_FORMAT "",
    1252              :       GST_TIME_ARGS (next_time));
    1253          105 :   GST_LOG_OBJECT (src,
    1254              :       "timestamp [%" GST_TIME_FORMAT " dur %" GST_TIME_FORMAT "]",
    1255              :       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
    1256              :       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
    1257              : }
    1258              : 
    1259              : /**
    1260              :  * @brief Function to create a buffer
    1261              :  */
    1262              : static GstFlowReturn
    1263          211 : gst_data_repo_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer)
    1264              : {
    1265          211 :   GstFlowReturn ret = GST_FLOW_OK;
    1266              :   GstDataRepoSrc *src;
    1267          211 :   src = GST_DATA_REPO_SRC (pushsrc);
    1268              : 
    1269              :   /** set_caps is completed after PAUSED_TO_PLAYING, so we cannot use change_state.
    1270              :       datareposrc can get type and size after set_caps() */
    1271          211 :   if (!src->is_start) {
    1272           15 :     if (!gst_data_repo_src_start (src)) {
    1273            0 :       return GST_FLOW_ERROR;
    1274              :     }
    1275           15 :     src->is_start = TRUE;
    1276              :   }
    1277              : 
    1278          211 :   switch (src->data_type) {
    1279           13 :     case GST_DATA_REPO_DATA_VIDEO:
    1280              :     case GST_DATA_REPO_DATA_AUDIO:
    1281              :     case GST_DATA_REPO_DATA_TEXT:
    1282              :     case GST_DATA_REPO_DATA_OCTET:
    1283           13 :       ret = gst_data_repo_src_read_others (src, buffer);
    1284           13 :       break;
    1285          192 :     case GST_DATA_REPO_DATA_TENSOR:
    1286          192 :       if (gst_tensors_config_is_static (&src->config))
    1287           86 :         ret = gst_data_repo_src_read_tensors (src, buffer);
    1288              :       else
    1289          106 :         ret = gst_data_repo_src_read_flexible_or_sparse_tensors (src, buffer);
    1290          192 :       break;
    1291            6 :     case GST_DATA_REPO_DATA_IMAGE:
    1292            6 :       ret = gst_data_repo_src_read_multi_images (src, buffer);
    1293            6 :       break;
    1294            0 :     default:
    1295            0 :       return GST_FLOW_ERROR;
    1296              :   }
    1297              : 
    1298          211 :   if (ret != GST_FLOW_OK)
    1299           15 :     return ret;
    1300              : 
    1301          196 :   if (src->rate_n)
    1302          105 :     gst_data_repo_src_set_timestamp (src, *buffer);
    1303              : 
    1304          196 :   return GST_FLOW_OK;
    1305              : }
    1306              : 
    1307              : /**
    1308              :  * @brief Stop datareposrc, unmap and close the file
    1309              :  */
    1310              : static gboolean
    1311           16 : gst_data_repo_src_stop (GstBaseSrc * basesrc)
    1312              : {
    1313           16 :   GstDataRepoSrc *src = GST_DATA_REPO_SRC (basesrc);
    1314              : 
    1315              :   /* close the file */
    1316           16 :   g_close (src->fd, NULL);
    1317           16 :   src->fd = 0;
    1318              : 
    1319           16 :   return TRUE;
    1320              : }
    1321              : 
    1322              : /**
    1323              :  * @brief Get caps with tensors_sequence applied
    1324              :  */
    1325              : static gboolean
    1326           17 : gst_data_repo_get_caps_by_tensors_sequence (GstDataRepoSrc * src)
    1327              : {
    1328              :   GstStructure *s;
    1329              :   GstTensorsConfig src_config, dst_config;
    1330              :   GstTensorInfo *_src_info, *_dst_info;
    1331              :   guint i;
    1332           17 :   guint seq_num = 0;
    1333              :   GstCaps *new_caps;
    1334              : 
    1335           34 :   g_return_val_if_fail (src != NULL, FALSE);
    1336           17 :   g_return_val_if_fail (src->caps != NULL, FALSE);
    1337              : 
    1338           17 :   s = gst_caps_get_structure (src->caps, 0);
    1339           17 :   if (!gst_tensors_config_from_structure (&src_config, s))
    1340            0 :     return FALSE;
    1341              : 
    1342           17 :   gst_tensors_config_init (&dst_config);
    1343              : 
    1344              :   /* Copy selected tensors in sequence */
    1345           51 :   for (i = 0; i < src->tensors_seq_cnt; i++) {
    1346           34 :     seq_num = src->tensors_seq[i];
    1347           34 :     _src_info = gst_tensors_info_get_nth_info (&src_config.info, seq_num);
    1348           34 :     _dst_info = gst_tensors_info_get_nth_info (&dst_config.info, i);
    1349           34 :     gst_tensor_info_copy (_dst_info, _src_info);
    1350              :   }
    1351           17 :   dst_config.rate_n = src_config.rate_n;
    1352           17 :   dst_config.rate_d = src_config.rate_d;
    1353           17 :   dst_config.info.format = src_config.info.format;
    1354           17 :   dst_config.info.num_tensors = src->tensors_seq_cnt;
    1355              : 
    1356           17 :   new_caps = gst_tensors_caps_from_config (&dst_config);
    1357              : 
    1358           17 :   GST_DEBUG_OBJECT (src,
    1359              :       "datareposrc caps by tensors_sequence %" GST_PTR_FORMAT, new_caps);
    1360              : 
    1361           17 :   gst_tensors_config_free (&dst_config);
    1362           17 :   gst_tensors_config_free (&src_config);
    1363              : 
    1364           17 :   return gst_data_repo_src_parse_caps (src, new_caps);
    1365              : }
    1366              : 
    1367              : /**
    1368              :  * @brief Get caps for caps negotiation
    1369              :  */
    1370              : static GstCaps *
    1371          112 : gst_data_repo_src_get_caps (GstBaseSrc * basesrc, GstCaps * filter)
    1372              : {
    1373          112 :   GstDataRepoSrc *src = GST_DATA_REPO_SRC (basesrc);
    1374              : 
    1375          112 :   if (src->data_type == GST_DATA_REPO_DATA_TENSOR && src->need_changed_caps) {
    1376           17 :     gst_data_repo_get_caps_by_tensors_sequence (src);
    1377           17 :     src->need_changed_caps = FALSE;
    1378              :   }
    1379              : 
    1380          112 :   GST_DEBUG_OBJECT (src, "Current datareposrc caps %" GST_PTR_FORMAT,
    1381              :       src->caps);
    1382              : 
    1383          112 :   if (src->caps) {
    1384           98 :     if (filter)
    1385            0 :       return gst_caps_intersect_full (filter, src->caps,
    1386              :           GST_CAPS_INTERSECT_FIRST);
    1387              :     else
    1388           98 :       return gst_caps_ref (src->caps);
    1389              :   } else {
    1390           14 :     if (filter)
    1391            0 :       return gst_caps_ref (filter);
    1392              :     else
    1393           14 :       return gst_caps_new_any ();
    1394              :   }
    1395              : }
    1396              : 
    1397              : /**
    1398              :  * @brief caps after caps negotiation
    1399              :  */
    1400              : static gboolean
    1401           18 : gst_data_repo_src_set_caps (GstBaseSrc * basesrc, GstCaps * caps)
    1402              : {
    1403           18 :   GstDataRepoSrc *src = GST_DATA_REPO_SRC (basesrc);
    1404              : 
    1405           18 :   GST_INFO_OBJECT (src, "set caps: %" GST_PTR_FORMAT, caps);
    1406              : 
    1407           18 :   return TRUE;
    1408              : }
    1409              : 
    1410              : /**
    1411              :  * @brief Read JSON file
    1412              :  */
    1413              : static gboolean
    1414           36 : gst_data_repo_src_read_json_file (GstDataRepoSrc * src)
    1415              : {
    1416           36 :   g_autofree gchar *contents = NULL;
    1417           36 :   GError *error = NULL;
    1418              :   GFile *file;
    1419              :   JsonNode *root;
    1420              :   JsonObject *object;
    1421           36 :   const gchar *caps_str = NULL;
    1422              :   GstCaps *new_caps;
    1423              :   gint64 val;
    1424              : 
    1425           36 :   g_return_val_if_fail (src != NULL, FALSE);
    1426           36 :   g_return_val_if_fail (src->json_filename != NULL, FALSE);
    1427              : 
    1428           35 :   if ((file = g_file_new_for_path (src->json_filename)) == NULL) {
    1429            0 :     GST_ERROR_OBJECT (src, "Failed to get file object of %s.",
    1430              :         src->json_filename);
    1431            0 :     return FALSE;
    1432              :   }
    1433              : 
    1434           35 :   if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, &error)) {
    1435            5 :     GST_ERROR_OBJECT (src, "Failed to open %s: %s", src->json_filename,
    1436              :         error ? error->message : "Unknown error");
    1437            5 :     g_clear_error (&error);
    1438            5 :     g_object_unref (file);
    1439            5 :     return FALSE;
    1440              :   }
    1441              : 
    1442           30 :   if (src->parser)
    1443            0 :     g_object_unref (src->parser);
    1444           30 :   src->parser = json_parser_new ();
    1445              : 
    1446           30 :   if (!json_parser_load_from_data (src->parser, contents, -1, NULL)) {
    1447            0 :     GST_ERROR_OBJECT (src, "Failed to load data from %s", src->json_filename);
    1448            0 :     goto error;
    1449              :   }
    1450              : 
    1451           30 :   root = json_parser_get_root (src->parser);
    1452           30 :   if (!JSON_NODE_HOLDS_OBJECT (root)) {
    1453            0 :     GST_ERROR_OBJECT (src, "it does not contain a JsonObject: %s", contents);
    1454            0 :     goto error;
    1455              :   }
    1456              : 
    1457           30 :   object = json_node_get_object (root);
    1458              : 
    1459           30 :   GST_INFO_OBJECT (src, ">>>>>>> Start parsing JSON file(%s)",
    1460              :       src->json_filename);
    1461              : 
    1462           30 :   if (!json_object_has_member (object, "gst_caps")) {
    1463            0 :     GST_ERROR_OBJECT (src, "There is no gst_caps field: %s", contents);
    1464            0 :     goto error;
    1465              :   }
    1466              : 
    1467           30 :   caps_str = json_object_get_string_member (object, "gst_caps");
    1468           30 :   GST_INFO_OBJECT (src, "caps_str : %s", caps_str);
    1469              : 
    1470           30 :   new_caps = gst_caps_from_string (caps_str);
    1471              : 
    1472              :   /* calculate media size from gst caps */
    1473           30 :   if (!gst_data_repo_src_parse_caps (src, new_caps))
    1474            0 :     goto error;
    1475              : 
    1476           30 :   GST_INFO_OBJECT (src, "gst_caps : %" GST_PTR_FORMAT, src->caps);
    1477              : 
    1478              :   /* In the case of below media type, get sample_size from JSON */
    1479           30 :   if (src->data_type == GST_DATA_REPO_DATA_TEXT
    1480           30 :       || src->data_type == GST_DATA_REPO_DATA_OCTET
    1481           30 :       || src->data_type == GST_DATA_REPO_DATA_IMAGE) {
    1482            1 :     if (!json_object_has_member (object, "sample_size")) {
    1483            0 :       GST_ERROR_OBJECT (src, "There is not sample_size field: %s", contents);
    1484            0 :       goto error;
    1485              :     }
    1486              : 
    1487            1 :     val = json_object_get_int_member (object, "sample_size");
    1488            1 :     if (val < 0) {
    1489            0 :       GST_ERROR_OBJECT (src, "Invalid sample_size: %" G_GINT64_FORMAT, val);
    1490            0 :       goto error;
    1491              :     }
    1492              : 
    1493            1 :     src->sample_size = (gsize) val;
    1494            1 :     GST_INFO_OBJECT (src, "sample_size: %zd", src->sample_size);
    1495              :   }
    1496              : 
    1497           30 :   if (src->data_type == GST_DATA_REPO_DATA_TENSOR &&
    1498           27 :       !gst_tensors_config_is_static (&src->config)) {
    1499            6 :     if (!json_object_has_member (object, "sample_offset")) {
    1500            0 :       GST_ERROR_OBJECT (src, "There is no sample_offset field: %s", contents);
    1501            0 :       goto error;
    1502              :     }
    1503            6 :     src->sample_offset_array =
    1504            6 :         json_object_get_array_member (object, "sample_offset");
    1505            6 :     src->sample_offset_array_len =
    1506            6 :         json_array_get_length (src->sample_offset_array);
    1507              : 
    1508            6 :     if (!json_object_has_member (object, "tensor_size")) {
    1509            0 :       GST_ERROR_OBJECT (src, "There is no tensor_size field: %s", contents);
    1510            0 :       goto error;
    1511              :     }
    1512            6 :     src->tensor_size_array =
    1513            6 :         json_object_get_array_member (object, "tensor_size");
    1514            6 :     src->tensor_size_array_len = json_array_get_length (src->tensor_size_array);
    1515            6 :     GST_INFO_OBJECT (src, "tensor_size_array_len:%u",
    1516              :         src->tensor_size_array_len);
    1517              : 
    1518            6 :     if (!json_object_has_member (object, "tensor_count")) {
    1519            0 :       GST_ERROR_OBJECT (src, "There is no tensor_count field: %s", contents);
    1520            0 :       goto error;
    1521              :     }
    1522            6 :     src->tensor_count_array =
    1523            6 :         json_object_get_array_member (object, "tensor_count");
    1524            6 :     src->tensor_count_array_len =
    1525            6 :         json_array_get_length (src->tensor_count_array);
    1526            6 :     GST_INFO_OBJECT (src, "tensor_count_array_len:%u",
    1527              :         src->tensor_count_array_len);
    1528              :   } else {
    1529           24 :     if (src->sample_size == 0)
    1530            0 :       goto error;
    1531              :   }
    1532              : 
    1533           30 :   if (!json_object_has_member (object, "total_samples")) {
    1534            0 :     GST_ERROR_OBJECT (src, "There is no total_samples field: %s", contents);
    1535            0 :     goto error;
    1536              :   }
    1537              : 
    1538           30 :   val = json_object_get_int_member (object, "total_samples");
    1539           30 :   if (val <= 0) {
    1540            0 :     GST_ERROR_OBJECT (src, "Invalid total_samples: %" G_GINT64_FORMAT, val);
    1541            0 :     goto error;
    1542              :   }
    1543              : 
    1544           30 :   src->total_samples = (guint) val;
    1545           30 :   GST_INFO_OBJECT (src, "total_samples: %u", src->total_samples);
    1546              : 
    1547           30 :   g_object_unref (file);
    1548              : 
    1549           30 :   return TRUE;
    1550            0 : error:
    1551            0 :   src->data_type = GST_DATA_REPO_DATA_UNKNOWN;
    1552            0 :   GST_ERROR_OBJECT (src, "Failed to parse %s", src->json_filename);
    1553            0 :   g_object_unref (file);
    1554              : 
    1555            0 :   return FALSE;
    1556              : }
    1557              : 
    1558              : /**
    1559              :  * @brief Setter for datareposrc properties.
    1560              :  */
    1561              : static void
    1562          160 : gst_data_repo_src_set_property (GObject * object, guint prop_id,
    1563              :     const GValue * value, GParamSpec * pspec)
    1564              : {
    1565              :   GstDataRepoSrc *src;
    1566              :   const GstCaps *caps;
    1567              : 
    1568          160 :   g_return_if_fail (GST_IS_DATA_REPO_SRC (object));
    1569              : 
    1570          160 :   src = GST_DATA_REPO_SRC (object);
    1571              : 
    1572          160 :   switch (prop_id) {
    1573           38 :     case PROP_LOCATION:
    1574           38 :       gst_data_repo_src_set_file_path (src, PROP_LOCATION,
    1575              :           g_value_get_string (value), NULL);
    1576           38 :       break;
    1577           36 :     case PROP_JSON:
    1578           36 :       gst_data_repo_src_set_file_path (src, PROP_JSON,
    1579              :           g_value_get_string (value), NULL);
    1580              :       /** To get caps, read JSON before Caps negotiation,
    1581              :           to get information on sample data */
    1582           36 :       if (!gst_data_repo_src_read_json_file (src)) {
    1583            6 :         GST_ERROR_OBJECT (src, "Failed to get data format");
    1584              :       }
    1585           36 :       break;
    1586           22 :     case PROP_START_SAMPLE_INDEX:
    1587           22 :       src->start_sample_index = g_value_get_uint (value);
    1588           22 :       break;
    1589           24 :     case PROP_STOP_SAMPLE_INDEX:
    1590           24 :       src->stop_sample_index = g_value_get_uint (value);
    1591           24 :       break;
    1592           18 :     case PROP_EPOCHS:
    1593           18 :       src->epochs = g_value_get_uint (value);
    1594           18 :       break;
    1595            0 :     case PROP_IS_SHUFFLE:
    1596            0 :       src->is_shuffle = g_value_get_boolean (value);
    1597            0 :       break;
    1598           20 :     case PROP_TENSORS_SEQUENCE:
    1599           20 :       g_free (src->tensors_seq_str);
    1600           20 :       src->tensors_seq_str = g_value_dup_string (value);
    1601           20 :       if (!gst_data_repo_src_set_tensors_sequence (src)) {
    1602            4 :         GST_ERROR_OBJECT (src, "Failed to set tensors sequence");
    1603              :       } else {
    1604           16 :         src->need_changed_caps = TRUE;
    1605              :       }
    1606           20 :       break;
    1607            2 :     case PROP_CAPS:
    1608            2 :       caps = gst_value_get_caps (value);
    1609            2 :       if (caps) {
    1610            1 :         gst_data_repo_src_parse_caps (src, gst_caps_copy (caps));
    1611              :       }
    1612              :       /** let's retry set tensors-sequence.
    1613              :           if caps property is set later than tensors-sequence property,
    1614              :           setting tensors-sequence fails because caps information is unknown.*/
    1615            2 :       if (src->tensors_seq_str) {
    1616            1 :         if (gst_data_repo_src_set_tensors_sequence (src))
    1617            1 :           src->need_changed_caps = TRUE;
    1618              :       }
    1619            2 :       break;
    1620            0 :     default:
    1621            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    1622            0 :       break;
    1623              :   }
    1624              : }
    1625              : 
    1626              : /**
    1627              :  * @brief Getter datareposrc properties
    1628              :  */
    1629              : static void
    1630           10 : gst_data_repo_src_get_property (GObject * object, guint prop_id, GValue * value,
    1631              :     GParamSpec * pspec)
    1632              : {
    1633              :   GstDataRepoSrc *src;
    1634              : 
    1635           10 :   g_return_if_fail (GST_IS_DATA_REPO_SRC (object));
    1636              : 
    1637           10 :   src = GST_DATA_REPO_SRC (object);
    1638              : 
    1639           10 :   switch (prop_id) {
    1640            2 :     case PROP_LOCATION:
    1641            2 :       g_value_set_string (value, src->filename);
    1642            2 :       break;
    1643            1 :     case PROP_JSON:
    1644            1 :       g_value_set_string (value, src->json_filename);
    1645            1 :       break;
    1646            1 :     case PROP_START_SAMPLE_INDEX:
    1647            1 :       g_value_set_uint (value, src->start_sample_index);
    1648            1 :       break;
    1649            1 :     case PROP_STOP_SAMPLE_INDEX:
    1650            1 :       g_value_set_uint (value, src->stop_sample_index);
    1651            1 :       break;
    1652            1 :     case PROP_EPOCHS:
    1653            1 :       g_value_set_uint (value, src->epochs);
    1654            1 :       break;
    1655            2 :     case PROP_IS_SHUFFLE:
    1656            2 :       g_value_set_boolean (value, src->is_shuffle);
    1657            2 :       break;
    1658            2 :     case PROP_TENSORS_SEQUENCE:
    1659            2 :       g_value_set_string (value, src->tensors_seq_str);
    1660            2 :       break;
    1661            0 :     case PROP_CAPS:
    1662            0 :       gst_value_set_caps (value, src->caps);
    1663            0 :       break;
    1664            0 :     default:
    1665            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    1666            0 :       break;
    1667              :   }
    1668              : }
    1669              : 
    1670              : /**
    1671              :  * @brief Change state of datareposrc.
    1672              :  */
    1673              : static GstStateChangeReturn
    1674          125 : gst_data_repo_src_change_state (GstElement * element, GstStateChange transition)
    1675              : {
    1676              :   guint i;
    1677          125 :   GstDataRepoSrc *src = GST_DATA_REPO_SRC (element);
    1678          125 :   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
    1679          125 :   GstBaseSrc *basesrc = NULL;
    1680              :   guint blocksize;
    1681              : 
    1682          125 :   switch (transition) {
    1683           30 :     case GST_STATE_CHANGE_NULL_TO_READY:
    1684           30 :       GST_INFO_OBJECT (src, "NULL_TO_READY");
    1685              : 
    1686           30 :       if (src->data_type == GST_DATA_REPO_DATA_UNKNOWN)
    1687            7 :         goto state_change_failed;
    1688              : 
    1689              :       /** if data_type is not GST_DATA_REPO_DATA_UNKNOWN and sample_size is 0 then
    1690              :           'caps' is set by property and sample size needs to be set by blocksize
    1691              :           (in the case of otect and text) */
    1692           23 :       if (src->sample_size == 0 && (src->data_type == GST_DATA_REPO_DATA_OCTET
    1693            6 :               || src->data_type == GST_DATA_REPO_DATA_TEXT)) {
    1694            0 :         basesrc = GST_BASE_SRC (src);
    1695            0 :         g_object_get (G_OBJECT (basesrc), "blocksize", &blocksize, NULL);
    1696            0 :         GST_DEBUG_OBJECT (src, "blocksize = %u", blocksize);
    1697            0 :         if (blocksize == 0) {
    1698            0 :           GST_ERROR_OBJECT (src, "Please set the 'blocksize' property "
    1699              :               "when using the 'caps' property to set the sample format without JSON.");
    1700            0 :           goto state_change_failed;
    1701              :         }
    1702            0 :         src->sample_size = blocksize;
    1703              :       }
    1704              : 
    1705              :       /** A case of importing a sample format using 'caps' property without JSON. */
    1706           23 :       if (src->total_samples == 0 && src->stop_sample_index == 0) {
    1707            0 :         GST_ERROR_OBJECT (src, "Please set the 'stop-sample-index' property "
    1708              :             "when using the 'caps' property to set the sample format without JSON.");
    1709            0 :         goto state_change_failed;
    1710              :       }
    1711              : 
    1712              :       /* total_samples -1 is the default value of 'stop-sample-index' property */
    1713           23 :       if (src->stop_sample_index == 0)
    1714            8 :         src->stop_sample_index = src->total_samples - 1;
    1715              : 
    1716              :       /* Check invalid property value */
    1717           23 :       if (src->start_sample_index > (src->total_samples - 1)
    1718           22 :           || src->stop_sample_index > (src->total_samples - 1)
    1719           21 :           || src->epochs == 0) {
    1720            3 :         GST_ERROR_OBJECT (src, "Check for invalid range values");
    1721              : 
    1722            3 :         goto state_change_failed;
    1723              :       }
    1724              : 
    1725              :       /* If tensors-sequence properties is set */
    1726           20 :       if (src->tensors_seq_str != NULL) {
    1727            7 :         if (src->data_type != GST_DATA_REPO_DATA_TENSOR) {
    1728            0 :           GST_ERROR_OBJECT (src,
    1729              :               "tensors-sequence properties is only for tensor/others type(%d), current type(%d)",
    1730              :               GST_DATA_REPO_DATA_TENSOR, src->data_type);
    1731            0 :           goto state_change_failed;
    1732              :         }
    1733              :         /* After gst_data_repo_src_set_tensors_sequence() */
    1734            7 :         if (src->tensors_seq_cnt == 0)
    1735            1 :           goto state_change_failed;
    1736              :       } else {
    1737           21 :         for (i = 0; i < src->config.info.num_tensors; i++)
    1738            8 :           src->tensors_seq[i] = i;
    1739           13 :         src->tensors_seq_cnt = i;
    1740              :       }
    1741              : 
    1742           19 :       break;
    1743              : 
    1744           19 :     case GST_STATE_CHANGE_READY_TO_PAUSED:
    1745           19 :       GST_INFO_OBJECT (src, "READY_TO_PAUSED");
    1746           19 :       break;
    1747              : 
    1748           15 :     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
    1749           15 :       GST_INFO_OBJECT (src, "PAUSED_TO_PLAYING");
    1750           15 :       break;
    1751              : 
    1752           61 :     default:
    1753           61 :       break;
    1754              :   }
    1755              : 
    1756          114 :   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
    1757              : 
    1758          114 :   switch (transition) {
    1759           15 :     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
    1760           15 :       GST_INFO_OBJECT (src, "PLAYING_TO_PAUSED");
    1761           15 :       break;
    1762              : 
    1763           16 :     case GST_STATE_CHANGE_PAUSED_TO_READY:
    1764           16 :       GST_INFO_OBJECT (src, "PAUSED_TO_READY");
    1765           16 :       break;
    1766              : 
    1767           16 :     case GST_STATE_CHANGE_READY_TO_NULL:
    1768           16 :       GST_INFO_OBJECT (src, "READY_TO_NULL");
    1769           16 :       break;
    1770              : 
    1771           67 :     default:
    1772           67 :       break;
    1773              :   }
    1774              : 
    1775          125 :   return ret;
    1776              : 
    1777           11 : state_change_failed:
    1778           11 :   GST_ERROR_OBJECT (src, "state change failed");
    1779              : 
    1780           11 :   return GST_STATE_CHANGE_FAILURE;
    1781              : }
        

Generated by: LCOV version 2.0-1