Error return instead of assert for external errors.
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Mon, 20 Apr 2020 07:16:22 +0000 (16:16 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Sat, 25 Apr 2020 13:48:55 +0000 (22:48 +0900)
If an error might occur by external reasons,
(invalid input/app behaviors and inappropriate environments)
it should not simply assert away, but should provide
appropriate error messages and handling.

Refactored everything except for tensor_filter_python.cc,
which will be refactored with exception throwing.

Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
24 files changed:
ext/nnstreamer/android_source/gstamcsrc_looper.cc
ext/nnstreamer/tensor_decoder/tensordec-boundingbox.c
ext/nnstreamer/tensor_decoder/tensordec-directvideo.c
ext/nnstreamer/tensor_decoder/tensordec-imagelabel.c
ext/nnstreamer/tensor_decoder/tensordec-imagesegment.c
ext/nnstreamer/tensor_decoder/tensordec-pose.c
ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc
gst/nnstreamer/nnstreamer_conf.c
gst/nnstreamer/nnstreamer_subplugin.c
gst/nnstreamer/tensor_aggregator/tensor_aggregator.c
gst/nnstreamer/tensor_common.c
gst/nnstreamer/tensor_common_pipeline.c
gst/nnstreamer/tensor_converter/tensor_converter.c
gst/nnstreamer/tensor_decoder/tensordec.c
gst/nnstreamer/tensor_filter/tensor_filter.c
gst/nnstreamer/tensor_filter/tensor_filter_common.c
gst/nnstreamer/tensor_filter/tensor_filter_custom.c
gst/nnstreamer/tensor_filter/tensor_filter_custom_easy.c
gst/nnstreamer/tensor_merge/gsttensormerge.c
gst/nnstreamer/tensor_mux/gsttensormux.c
gst/nnstreamer/tensor_repo/tensor_repo.c
gst/nnstreamer/tensor_repo/tensor_reposrc.c
gst/nnstreamer/tensor_split/gsttensorsplit.c
gst/nnstreamer/tensor_transform/tensor_transform.c

index c064752..5cf3c95 100644 (file)
@@ -26,7 +26,6 @@
 #include "gstamcsrc.h"
 #include "gstamcsrc_looper.h"
 
-#include <assert.h>
 #include <jni.h>
 #include <pthread.h>
 #include <stdio.h>
index 276b186..c9b8800 100644 (file)
@@ -56,6 +56,7 @@
 #include <math.h>               /* expf */
 #include <nnstreamer_plugin_api_decoder.h>
 #include <nnstreamer_plugin_api.h>
+#include <nnstreamer_log.h>
 #include "tensordecutil.h"
 
 void init_bb (void) __attribute__ ((constructor));
@@ -224,7 +225,12 @@ _tflite_ssd_loadBoxPrior (bounding_boxes * bdata)
   }
 
   priors = g_strsplit (contents, "\n", -1);
-  g_assert (g_strv_length (priors) >= BOX_SIZE);
+  /* If given prior file is inappropriate, report back to tensor-decoder */
+  if (g_strv_length (priors) < BOX_SIZE) {
+    ml_loge ("The given prior file, %s, should have at least %d lines.\n",
+        tflite_ssd->box_prior_path, BOX_SIZE);
+    return FALSE;
+  }
 
   for (row = 0; row < BOX_SIZE; row++) {
     gint column = 0, registered = 0;
@@ -762,6 +768,12 @@ draw (GstMapInfo * out_info, bounding_boxes * bdata, GArray * results)
     int label_len;
     detectedObject *a = &g_array_index (results, detectedObject, i);
 
+    if (a->class_id <= 0 || a->class_id >= bdata->labeldata.total_labels) {
+      /** @todo make it "logw_once" after we get logw_once API. */
+      ml_logw ("Invalid class found with tensordec-boundingbox.c.\n");
+      continue;
+    }
+
     /* 1. Draw Boxes */
     x1 = (bdata->width * a->x) / bdata->i_width;
     x2 = MIN (bdata->width - 1,
@@ -792,7 +804,6 @@ draw (GstMapInfo * out_info, bounding_boxes * bdata, GArray * results)
     }
 
     /* 2. Write Labels */
-    g_assert (a->class_id > 0 && a->class_id < bdata->labeldata.total_labels);
     label = bdata->labeldata.labels[a->class_id];
     label_len = strlen (label);
     /* x1 is the same: x1 = MAX (0, (bdata->width * a->x) / bdata->i_width); */
@@ -828,7 +839,6 @@ bb_decode (void **pdata, const GstTensorsConfig * config,
   GstMemory *out_mem;
   GArray *results = NULL;
   const int num_tensors = config->info.num_tensors;
-  gboolean status;
 
   g_assert (outbuf);
   /* Ensure we have outbuf properly allocated */
@@ -840,8 +850,10 @@ bb_decode (void **pdata, const GstTensorsConfig * config,
     }
     out_mem = gst_buffer_get_all_memory (outbuf);
   }
-  status = gst_memory_map (out_mem, &out_info, GST_MAP_WRITE);
-  g_assert (status);
+  if (FALSE == gst_memory_map (out_mem, &out_info, GST_MAP_WRITE)) {
+    ml_loge ("Cannot map output memory / tensordec-bounding_boxes.\n");
+    return GST_FLOW_ERROR;
+  }
 
   /** reset the buffer with alpha 0 / black */
   memset (out_info.data, 0, size);
@@ -855,6 +867,7 @@ bb_decode (void **pdata, const GstTensorsConfig * config,
      *       For the sake of performance, don't make it too small.
      */
 
+    /* Already checked with getOutCaps. Thus, this is an internal bug */
     g_assert (num_tensors >= TFLITE_SSD_MAX_TENSORS);
 
     boxes = &input[0];
@@ -882,6 +895,7 @@ bb_decode (void **pdata, const GstTensorsConfig * config,
         g_array_sized_new (FALSE, TRUE, sizeof (detectedObject),
         TF_SSD_DETECTION_MAX);
 
+    /* Already checked with getOutCaps. Thus, this is an internal bug */
     g_assert (num_tensors >= TF_SSD_MAX_TENSORS);
 
     mem_num = &input[0];
index 28f527f..91eae36 100644 (file)
@@ -30,6 +30,7 @@
 #include <glib.h>
 #include <gst/video/video-format.h>
 #include <nnstreamer_plugin_api_decoder.h>
+#include <nnstreamer_log.h>
 
 void init_dv (void) __attribute__ ((constructor));
 void fini_dv (void) __attribute__ ((destructor));
@@ -150,7 +151,6 @@ dv_decode (void **pdata, const GstTensorsConfig * config,
   /* Direct video uses the first tensor only even if it's multi-tensor */
   const uint32_t *dim = &(config->info.info[0].dimension[0]);
   size_t size = _get_video_xraw_bufsize (dim);
-  gboolean status;
 
   g_assert (outbuf);
   if (gst_buffer_get_size (outbuf) > 0 && gst_buffer_get_size (outbuf) != size) {
@@ -164,8 +164,10 @@ dv_decode (void **pdata, const GstTensorsConfig * config,
   } else {
     out_mem = gst_allocator_alloc (NULL, size, NULL);
   }
-  status = gst_memory_map (out_mem, &out_info, GST_MAP_WRITE);
-  g_assert (status);
+  if (FALSE == gst_memory_map (out_mem, &out_info, GST_MAP_WRITE)) {
+    ml_loge ("Cannot map output memory / tensordec-directvideo.\n");
+    return GST_FLOW_ERROR;
+  }
 
   if (0 == ((dim[0] * dim[1]) % 4)) {
     /* No Padding Required */
index e420dc3..e163d15 100644 (file)
@@ -33,6 +33,7 @@
 #include <gst/gstinfo.h>
 #include <nnstreamer_plugin_api_decoder.h>
 #include <nnstreamer_plugin_api.h>
+#include <nnstreamer_log.h>
 #include "tensordecutil.h"
 
 void init_il (void) __attribute__ ((constructor));
@@ -161,7 +162,6 @@ il_decode (void **pdata, const GstTensorsConfig * config,
   ImageLabelData *data = *pdata;
   GstMapInfo out_info;
   GstMemory *out_mem;
-  gboolean status;
 
   gsize bpe = gst_tensor_get_element_size (config->info.info[0].type);
   tensor_element max_val;
@@ -208,8 +208,10 @@ il_decode (void **pdata, const GstTensorsConfig * config,
     }
     out_mem = gst_buffer_get_all_memory (outbuf);
   }
-  status = gst_memory_map (out_mem, &out_info, GST_MAP_WRITE);
-  g_assert (status);
+  if (FALSE == gst_memory_map (out_mem, &out_info, GST_MAP_WRITE)) {
+    ml_loge ("Cannot map output memory / tensordec-imagelabel.\n");
+    return GST_FLOW_ERROR;
+  }
 
   memcpy (out_info.data, str, size);
 
index a6cebae..f87cac7 100644 (file)
@@ -61,6 +61,7 @@
 #include <gst/video/video-format.h>
 #include <nnstreamer_plugin_api_decoder.h>
 #include <nnstreamer_plugin_api.h>
+#include <nnstreamer_log.h>
 
 void init_is (void) __attribute__ ((constructor));
 void fini_is (void) __attribute__ ((destructor));
@@ -262,7 +263,8 @@ set_color_according_to_label (image_segments * idata, GstMapInfo * out_info)
   for (i = 0; i < idata->height; i++) {
     for (j = 0; j < idata->width; j++) {
       int label_idx = idata->segment_map[i][j];
-      g_assert (label_idx >= 0 && label_idx <= 20);
+      if (label_idx > 20)       /* If out-of-range, don't draw it */
+        continue;
       pos = &frame[i * idata->width + j];
       if (label_idx == 0)
         continue;               /*Do not set color for background */
@@ -314,7 +316,6 @@ is_decode (void **pdata, const GstTensorsConfig * config,
   const size_t size = idata->width * idata->height * RGBA_CHANNEL;
   GstMapInfo out_info;
   GstMemory *out_mem;
-  gboolean status;
 
   /* init image segments if seg map is null */
   if (idata->segment_map == NULL) {
@@ -331,8 +332,10 @@ is_decode (void **pdata, const GstTensorsConfig * config,
     }
     out_mem = gst_buffer_get_all_memory (outbuf);
   }
-  status = gst_memory_map (out_mem, &out_info, GST_MAP_WRITE);
-  g_assert (status);
+  if (FALSE == gst_memory_map (out_mem, &out_info, GST_MAP_WRITE)) {
+    ml_loge ("Cannot map output memory / tensordec-imagesegment.\n");
+    return GST_FLOW_ERROR;
+  }
 
   memset (out_info.data, 0, size);
 
index cd5fdd7..8b92a90 100644 (file)
@@ -37,6 +37,7 @@
 #include <gst/gst.h>
 #include <nnstreamer_plugin_api_decoder.h>
 #include <nnstreamer_plugin_api.h>
+#include <nnstreamer_log.h>
 #include "tensordecutil.h"
 
 void init_pose (void) __attribute__ ((constructor));
@@ -437,9 +438,8 @@ pose_decode (void **pdata, const GstTensorsConfig * config,
   const GstTensorMemory *detections = NULL;
   float *arr;
   int index, i, j;
-  gboolean status;
 
-  g_assert (outbuf);
+  g_assert (outbuf); /** GST Internal Bug */
   /* Ensure we have outbuf properly allocated */
   if (gst_buffer_get_size (outbuf) == 0) {
     out_mem = gst_allocator_alloc (NULL, size, NULL);
@@ -449,8 +449,10 @@ pose_decode (void **pdata, const GstTensorsConfig * config,
     }
     out_mem = gst_buffer_get_all_memory (outbuf);
   }
-  status = gst_memory_map (out_mem, &out_info, GST_MAP_WRITE);
-  g_assert (status);
+  if (FALSE == gst_memory_map (out_mem, &out_info, GST_MAP_WRITE)) {
+    ml_loge ("Cannot map output memory / tensordec-pose.\n");
+    return GST_FLOW_ERROR;
+  }
   /** reset the buffer with alpha 0 / black */
   memset (out_info.data, 0, size);
 
index d5cd98f..174d37d 100644 (file)
@@ -908,6 +908,13 @@ tflite_getOutputDim (const GstTensorFilterProperties * prop,
   return core->getOutputTensorDim (info);
 }
 
+#define tryRecovery(failedAt, status, location, exp) do { \
+      status = (exp); \
+      if (status != 0) { \
+        failedAt = location; \
+        goto recovery_fail; \
+      } \
+    } while (0)
 /**
  * @brief The optional callback for GstTensorFilterFramework
  * @param prop property of tensor_filter instance
@@ -922,7 +929,7 @@ tflite_setInputDim (const GstTensorFilterProperties * prop, void **private_data,
 {
   TFLiteCore *core = static_cast<TFLiteCore *>(*private_data);
   GstTensorsInfo cur_in_info;
-  int status;
+  int status, failedAt, recoveryStatus;
 
   g_return_val_if_fail (core, -EINVAL);
   g_return_val_if_fail (in_info, -EINVAL);
@@ -936,35 +943,48 @@ tflite_setInputDim (const GstTensorFilterProperties * prop, void **private_data,
   /** set new input tensor info */
   status = core->setInputTensorDim (in_info);
   if (status != 0) {
-    g_assert (core->setInputTensorDim (&cur_in_info) == 0);
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setInputTensorDim (&cur_in_info));
     return status;
   }
 
   /** update input tensor info */
   if ((status = core->setInputTensorProp ()) != 0) {
-    g_assert (core->setInputTensorDim (&cur_in_info) == 0);
-    g_assert (core->setInputTensorProp () == 0);
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setInputTensorDim (&cur_in_info));
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setInputTensorProp ());
     return status;
   }
 
   /** update output tensor info */
   if ((status = core->setOutputTensorProp ()) != 0) {
-    g_assert (core->setInputTensorDim (&cur_in_info) == 0);
-    g_assert (core->setInputTensorProp () == 0);
-    g_assert (core->setOutputTensorProp () == 0);
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setInputTensorDim (&cur_in_info));
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setInputTensorProp ());
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setOutputTensorProp ());
     return status;
   }
 
   /** get output tensor info to be returned */
   status = core->getOutputTensorDim (out_info);
   if (status != 0) {
-    g_assert (core->setInputTensorDim (&cur_in_info) == 0);
-    g_assert (core->setInputTensorProp () == 0);
-    g_assert (core->setOutputTensorProp () == 0);
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setInputTensorDim (&cur_in_info));
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setInputTensorProp ());
+    tryRecovery (failedAt, recoveryStatus, __LINE__,
+        core->setOutputTensorProp ());
     return status;
   }
 
   return 0;
+recovery_fail:
+  ml_logf
+      ("tensorflow-lite's setInputDim failed (%d) and its recovery failed, too. The behavior will be unstable.\n", failedAt);
+  return status;
 }
 
 /**
index 3f38739..0c1451d 100644 (file)
@@ -241,7 +241,7 @@ static void
 _g_list_foreach_vstr_helper (gpointer data, gpointer user_data)
 {
   vstr_helper *helper = (vstr_helper *) user_data;
-  g_assert (helper->cursor < helper->size);
+  g_assert (helper->cursor < helper->size); /** library error? internal logic error? */
   helper->vstr[helper->cursor] = data;
   helper->cursor++;
 }
@@ -276,9 +276,9 @@ _fill_in_vstr (gchar *** fullpath_vstr, gchar *** basename_vstr,
   lstB = g_slist_reverse (lstB);
 
   *fullpath_vstr = g_malloc0_n (counter + 1, sizeof (gchar *));
-  g_assert (*fullpath_vstr != NULL);
+  g_assert (*fullpath_vstr != NULL);    /* This won't happen, but doesn't hurt either */
   *basename_vstr = g_malloc0_n (counter + 1, sizeof (gchar *));
-  g_assert (*basename_vstr != NULL);
+  g_assert (*basename_vstr != NULL);    /* This won't happen, but doesn't hurt either */
 
   vstrF.vstr = *fullpath_vstr;
   vstrB.vstr = *basename_vstr;
@@ -360,7 +360,7 @@ nnsconf_loadconf (gboolean force_reload)
 
   if (conf.conffile) {
     key_file = g_key_file_new ();
-    g_assert (key_file != NULL);
+    g_assert (key_file != NULL); /** Internal lib error? out-of-memory? */
 
     /* Read the conf file. It's ok even if we cannot load it. */
     if (g_key_file_load_from_file (key_file, conf.conffile, G_KEY_FILE_NONE,
@@ -536,7 +536,7 @@ nnsconf_get_custom_value_string (const gchar * group, const gchar * key)
     if (NULL == value && conf.conffile) {
       g_autoptr (GKeyFile) key_file = g_key_file_new ();
 
-      g_assert (key_file != NULL);
+      g_assert (key_file != NULL); /** Internal lib error? out-of-memory? */
 
       if (g_key_file_load_from_file (key_file, conf.conffile, G_KEY_FILE_NONE,
               NULL)) {
index d5770d4..4d8a068 100644 (file)
@@ -253,7 +253,7 @@ static void
 init_subplugin (void)
 {
   G_LOCK (splock);
-  g_assert (NULL == handles);
+  g_assert (NULL == handles); /** Internal error (duplicated init call?) */
   handles = g_ptr_array_new_full (16, _close_handle);
   G_UNLOCK (splock);
 }
@@ -263,7 +263,7 @@ static void
 fini_subplugin (void)
 {
   G_LOCK (splock);
-  g_assert (handles);
+  g_assert (handles); /** Internal error (init not called?) */
 
   /* iterate and call close by calling g_array_clear */
   g_ptr_array_free (handles, TRUE);
index ea91a7d..f17844a 100644 (file)
@@ -534,7 +534,7 @@ gst_tensor_aggregator_check_concat_axis (GstTensorAggregator * self,
 {
   guint i;
 
-  g_assert (info != NULL);
+  g_assert (info != NULL); /** Internal error. Caller should've checked it */
 
   /**
    * Check condition to concatenate data.
@@ -557,7 +557,7 @@ gst_tensor_aggregator_check_concat_axis (GstTensorAggregator * self,
  * @param outbuf buffer to be concatenated
  * @param info tensor info for one frame
  */
-static void
+static gboolean
 gst_tensor_aggregator_concat (GstTensorAggregator * self, GstBuffer * outbuf,
     const GstTensorInfo * info)
 {
@@ -567,18 +567,24 @@ gst_tensor_aggregator_concat (GstTensorAggregator * self, GstBuffer * outbuf,
   gsize block_size;
   gsize src_idx, dest_idx;
   gsize frame_size;
-  gboolean status;
 
   frame_size = gst_tensor_info_get_size (info);
-  g_assert (frame_size > 0);
+  g_assert (frame_size > 0); /** Internal error */
 
   srcbuf = gst_buffer_copy (outbuf);
   outbuf = gst_buffer_make_writable (outbuf);
 
-  status = gst_buffer_map (srcbuf, &src_info, GST_MAP_READ);
-  g_assert (status);
-  status = gst_buffer_map (outbuf, &dest_info, GST_MAP_WRITE);
-  g_assert (status);
+  if (FALSE == gst_buffer_map (srcbuf, &src_info, GST_MAP_READ)) {
+    ml_logf ("Failed to map source buffer with tensor_aggregator.\n");
+    gst_buffer_unref (srcbuf);
+    return FALSE;
+  }
+  if (FALSE == gst_buffer_map (outbuf, &dest_info, GST_MAP_WRITE)) {
+    ml_logf ("Failed to map destination buffer with tensor_aggregator.\n");
+    gst_buffer_unmap (srcbuf, &src_info);
+    gst_buffer_unref (srcbuf);
+    return FALSE;
+  }
 
   /**
    * Concatenate output buffer with given axis (frames-dim)
@@ -780,6 +786,8 @@ gst_tensor_aggregator_concat (GstTensorAggregator * self, GstBuffer * outbuf,
   gst_buffer_unmap (outbuf, &dest_info);
 
   gst_buffer_unref (srcbuf);
+
+  return TRUE;
 }
 
 /**
@@ -796,11 +804,17 @@ gst_tensor_aggregator_push (GstTensorAggregator * self, GstBuffer * outbuf,
   g_assert (self->frames_dim < NNS_TENSOR_RANK_LIMIT);
   info.dimension[self->frames_dim] /= self->frames_out;
 
-  g_assert (frame_size == gst_tensor_info_get_size (&info));
+  if (frame_size != gst_tensor_info_get_size (&info) || frame_size == 0U) {
+    ml_logf
+        ("Invalid output capability of tensor_aggregator. Frame size = %"
+        G_GSIZE_FORMAT "\n", frame_size);
+    return GST_FLOW_ERROR;
+  }
 
   if (gst_tensor_aggregator_check_concat_axis (self, &info)) {
     /** change data in buffer with given axis */
-    gst_tensor_aggregator_concat (self, outbuf, &info);
+    if (FALSE == gst_tensor_aggregator_concat (self, outbuf, &info))
+      return GST_FLOW_ERROR;
   }
 
   return gst_pad_push (self->srcpad, outbuf);
index 5de01f7..b566151 100644 (file)
@@ -1082,7 +1082,11 @@ find_key_strv (const gchar ** strv, const gchar * key)
 {
   gint cursor = 0;
 
-  g_assert (strv != NULL);
+  if (strv == NULL) {
+    ml_logf_stacktrace
+        ("find_key_strv is called with a null pointer. Possible internal logic errors.\n");
+    return -1;
+  }
   while (strv[cursor]) {
     if (g_ascii_strcasecmp (strv[cursor], key) == 0)
       return cursor;
index 742d370..b0a1c23 100644 (file)
@@ -236,6 +236,10 @@ gst_tensor_time_sync_buffer_from_collectpad (GstCollectPads * collect,
     GstBuffer *buf;
 
     gst_tensors_config_from_structure (&in_configs, s);
+    /** This is an internal logic error.
+        in_configs should be already confirmed valid at
+        the negotiation phase and this function should be
+        called in a running pipeline */
     g_assert (gst_tensors_config_validate (&in_configs));
 
     if (in_configs.rate_d < old_denominator)
@@ -271,6 +275,8 @@ gst_tensor_time_sync_buffer_from_collectpad (GstCollectPads * collect,
     if (GST_IS_BUFFER (buf)) {
       guint n_mem = gst_buffer_n_memory (buf);
 
+      /** These are internal logic error. If given inputs are incorrect,
+          the negotiation should have been failed before this stage. */
       g_assert (n_mem == in_configs.info.num_tensors);
       g_assert ((counting + n_mem) < NNS_TENSOR_SIZE_LIMIT);
 
index 9a6eb28..7c2ad63 100644 (file)
@@ -332,6 +332,7 @@ gst_tensor_converter_init (GstTensorConverter * self)
   gst_tensor_info_init (&self->tensor_info);
 
   self->adapter = gst_adapter_new ();
+  g_assert (self->adapter != NULL);
   gst_tensor_converter_reset (self);
 }
 
@@ -607,6 +608,7 @@ _gst_tensor_converter_chain_segment (GstTensorConverter * self,
     GstSegment seg;
     guint64 start;
 
+    /** This is an internal logic error. */
     g_assert (self->have_segment);
     start = self->segment.start;
 
@@ -697,6 +699,7 @@ gst_tensor_converter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 
   self = GST_TENSOR_CONVERTER (parent);
 
+  /** This is an internal logic error. */
   g_assert (self->tensor_configured);
   config = &self->tensor_config;
 
@@ -728,22 +731,28 @@ gst_tensor_converter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
         int d0, d1;
         unsigned int src_idx = 0, dest_idx = 0;
         size_t size, offset;
-        gboolean status;
 
         inbuf = gst_buffer_new_and_alloc (frame_size);
         gst_buffer_memset (inbuf, 0, 0, frame_size);
 
-        status = gst_buffer_map (buf, &src_info, GST_MAP_READ);
-        g_assert (status);
-        status = gst_buffer_map (inbuf, &dest_info, GST_MAP_WRITE);
-        g_assert (status);
+        if (FALSE == gst_buffer_map (buf, &src_info, GST_MAP_READ)) {
+          ml_logf ("Cannot map src buffer at tensor_converter/video.\n");
+          gst_buffer_unref (inbuf);     /* the new buffer is wasted. */
+          return GST_FLOW_ERROR;
+        }
+        if (FALSE == gst_buffer_map (inbuf, &dest_info, GST_MAP_WRITE)) {
+          ml_logf ("Cannot map dest buffer at tensor_converter/video.\n");
+          gst_buffer_unmap (buf, &src_info);
+          gst_buffer_unref (inbuf);     /* the new buffer is wasted. */
+          return GST_FLOW_ERROR;
+        }
 
         /**
          * Refer: https://gstreamer.freedesktop.org/documentation/design/mediatype-video-raw.html
          */
         size = offset = color * width * type;
 
-        g_assert (offset % 4);
+        g_assert (offset % 4); /** Internal logic error! */
         if (offset % 4) {
           offset += 4 - (offset % 4);
         }
@@ -777,17 +786,22 @@ gst_tensor_converter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
       frames_in = 1;
 
       if (buf_size != frame_size) {
-        gboolean status;
         GstMapInfo src_info, dest_info;
         gsize block_size = MIN (buf_size, frame_size);
 
         inbuf = gst_buffer_new_and_alloc (frame_size);
         gst_buffer_memset (inbuf, 0, 0, frame_size);
 
-        status = gst_buffer_map (buf, &src_info, GST_MAP_READ);
-        g_assert (status);
-        status = gst_buffer_map (inbuf, &dest_info, GST_MAP_WRITE);
-        g_assert (status);
+        if (FALSE == gst_buffer_map (buf, &src_info, GST_MAP_READ)) {
+          ml_logf ("Cannot map src buffer at tensor_converter/text.\n");
+          return GST_FLOW_ERROR;
+        }
+        if (FALSE == gst_buffer_map (inbuf, &dest_info, GST_MAP_WRITE)) {
+          ml_logf ("Cannot map dest buffer at tensor_converter/text.\n");
+          gst_buffer_unmap (buf, &src_info);
+          gst_buffer_unref (inbuf);     /* the new buffer is wasted. */
+          return GST_FLOW_ERROR;
+        }
 
         memcpy (dest_info.data, src_info.data, block_size);
 
@@ -822,7 +836,6 @@ gst_tensor_converter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
     }
     default:
       GST_ERROR_OBJECT (self, "Unsupported type %d\n", self->in_media_type);
-      g_assert (0);
       return GST_FLOW_ERROR;
   }
 
@@ -1381,7 +1394,12 @@ gst_tensor_converter_get_possible_media_caps (GstTensorConverter * self)
 
             /** @todo What if this is inconsistent with self->ex? */
 
-            g_assert (ex->query_caps);
+            if (NULL == ex->query_caps) {
+              ml_logf
+                  ("The given conveter subplugin, \"%s\", does not have a valid query_caps callback.\n",
+                  name);
+              break;
+            }
             if (ex->query_caps (self, &config, st) == FALSE) {
               GST_ERROR_OBJECT (self,
                   "Failed to filter GstCap structure with the given config");
index bac8963..5908c96 100644 (file)
@@ -22,6 +22,7 @@
  * @see        https://github.com/nnstreamer/nnstreamer
  * @author      Jijoong Moon <jijoong.moon@samsung.com>
  * @bug         gst_tensordec_transform_size () may be incorrect if direction is SINK.
+ * @bug         If configured = TRUE, it holds TRUE until exit. What if configuration changes in run-time?
  *
  */
 
@@ -416,7 +417,7 @@ gst_tensordec_init (GstTensorDec * self)
 static gboolean
 gst_tensordec_process_plugin_options (GstTensorDec * self, guint opnum)
 {
-  g_assert (opnum < TensorDecMaxOpNum);
+  g_assert (opnum < TensorDecMaxOpNum); /* Internal logic error! */
   if (self->decoder == NULL)
     return TRUE;                /* decoder plugin not available. */
   if (self->decoder->setOption == NULL)
@@ -460,7 +461,6 @@ gst_tensordec_set_property (GObject * object, guint prop_id,
       const GstTensorDecoderDef *decoder;
       const gchar *mode_string;
       guint i;
-      int status;
 
       mode_string = g_value_get_string (value);
       decoder = nnstreamer_decoder_find (mode_string);
@@ -480,9 +480,11 @@ gst_tensordec_set_property (GObject * object, guint prop_id,
           self->decoder = decoder;
         }
 
-        status = self->decoder->init (&self->plugin_data);
-        /** @todo Do proper error handling */
-        g_assert (status);
+        if (0 == self->decoder->init (&self->plugin_data)) {
+          ml_loge ("Failed to intialize a decode subplugin, \"%s\".\n",
+              mode_string);
+          break;
+        }
 
         for (i = 0; i < TensorDecMaxOpNum; i++)
           if (!gst_tensordec_process_plugin_options (self, i))
@@ -659,7 +661,6 @@ gst_tensordec_transform (GstBaseTransform * trans,
 {
   GstTensorDec *self;
   GstFlowReturn res;
-  gboolean status;
 
   self = GST_TENSOR_DECODER_CAST (trans);
 
@@ -675,12 +676,19 @@ gst_tensordec_transform (GstBaseTransform * trans,
     guint i, num_tensors;
 
     num_tensors = self->tensor_config.info.num_tensors;
+    /** Internal logic error. Negotation process should prevent this! */
     g_assert (gst_buffer_n_memory (inbuf) == num_tensors);
 
     for (i = 0; i < num_tensors; i++) {
       in_mem[i] = gst_buffer_peek_memory (inbuf, i);
-      status = gst_memory_map (in_mem[i], &in_info[i], GST_MAP_READ);
-      g_assert (status);
+      if (FALSE == gst_memory_map (in_mem[i], &in_info[i], GST_MAP_READ)) {
+        guint j;
+        ml_logf ("Failed to map in_mem[%u].\n", i);
+
+        for (j = 0; j < i; j++)
+          gst_memory_unmap (in_mem[j], &in_info[j]);
+        return GST_FLOW_ERROR;
+      }
 
       input[i].data = in_info[i].data;
       input[i].size = in_info[i].size;
@@ -748,7 +756,7 @@ gst_tensordec_transform_caps (GstBaseTransform * trans,
     /** @todo We may do more specific actions here */
     result = gst_caps_from_string (CAPS_STRING);
   } else {
-    g_assert (0);
+    g_assert (0);               /* Internal logic error! */
     return NULL;
   }
 
@@ -788,8 +796,16 @@ gst_tensordec_fixate_caps (GstBaseTransform * trans,
   GST_DEBUG_OBJECT (self, "trying to fixate othercaps %" GST_PTR_FORMAT
       " based on caps %" GST_PTR_FORMAT, othercaps, caps);
 
-  /** @todo The code below assumes that direction is GST_PAD_SINK */
-  g_assert (direction == GST_PAD_SINK);
+  /**
+   * In gst_tensordec_transform_caps, we have refused to specify caps
+   * if the direction is GST_PAD_SRC. Thus, gstreamer sholdn't fixate
+   * it with GST_PAD_SRC. If this happens, it's either internal logic
+   * error or GST bUG.
+   */
+  if (direction != GST_PAD_SINK) {
+    ml_logf_stacktrace ("Invalid direction for tensor-decoder fixate caps.\n");
+    return NULL;
+  }
 
   if (gst_tensordec_configure (self, caps)) {
     supposed =
index 5f4d2ff..2c8bdbd 100644 (file)
@@ -257,6 +257,7 @@ gst_tensor_filter_get_output_size (GstTensorFilter * self, guint index)
 
   priv = &self->priv;
   info = &priv->prop.output_meta;
+  /* Internal Logic Error */
   g_assert (index < info->num_tensors);
 
   return gst_tensor_info_get_size (&info->info[index]);
@@ -372,14 +373,18 @@ gst_tensor_filter_transform (GstBaseTransform * trans,
   allocate_in_invoke = gst_tensor_filter_allocate_in_invoke (priv);
 
   /* 1. Set input tensors from inbuf. */
+  /* Internal Logic Error or GST Bug (sinkcap changed!) */
   g_assert (gst_buffer_n_memory (inbuf) == prop->input_meta.num_tensors);
 
   for (i = 0; i < prop->input_meta.num_tensors; i++) {
-    gboolean status;
     in_mem[i] = gst_buffer_peek_memory (inbuf, i);
-    status = gst_memory_map (in_mem[i], &in_info[i], GST_MAP_READ);
-    g_assert (status);
-    /** @todo Do proper error handling (clean up and error return) */
+    if (FALSE == gst_memory_map (in_mem[i], &in_info[i], GST_MAP_READ)) {
+      guint j;
+      for (j = 0; j < i; j++)
+        gst_memory_unmap (in_mem[j], &in_info[j]);
+      ml_logf ("Cannot map input memory buffer(%d)\n", i);
+      return GST_FLOW_ERROR;
+    }
 
     in_tensors[i].data = in_info[i].data;
     in_tensors[i].size = in_info[i].size;
@@ -391,7 +396,6 @@ gst_tensor_filter_transform (GstBaseTransform * trans,
   g_assert (gst_buffer_get_size (outbuf) == 0);
 
   for (i = 0; i < prop->output_meta.num_tensors; i++) {
-    gboolean status;
     out_tensors[i].data = NULL;
     out_tensors[i].size = gst_tensor_filter_get_output_size (self, i);
     out_tensors[i].type = prop->output_meta.info[i].type;
@@ -399,8 +403,15 @@ gst_tensor_filter_transform (GstBaseTransform * trans,
     /* allocate memory if allocate_in_invoke is FALSE */
     if (allocate_in_invoke == FALSE) {
       out_mem[i] = gst_allocator_alloc (NULL, out_tensors[i].size, NULL);
-      status = gst_memory_map (out_mem[i], &out_info[i], GST_MAP_WRITE);
-      g_assert (status);
+      if (FALSE == gst_memory_map (out_mem[i], &out_info[i], GST_MAP_WRITE)) {
+        guint j;
+        for (j = 0; j < i; j++)
+          gst_memory_unmap (out_mem[j], &out_info[j]);
+        for (j = 0; j < prop->input_meta.num_tensors; j++)
+          gst_memory_unmap (in_mem[j], &in_info[i]);
+        ml_logf ("Cannot map output memory buffer(%d)\n", i);
+        return GST_FLOW_ERROR;
+      }
 
       out_tensors[i].data = out_info[i].data;
     }
@@ -410,7 +421,11 @@ gst_tensor_filter_transform (GstBaseTransform * trans,
   GST_TF_FW_INVOKE_COMPAT (priv, ret, in_tensors, out_tensors);
 
   /** @todo define enum to indicate status code */
-  g_assert (ret >= 0);
+
+  if (ret < 0) {
+    ml_loge ("Tensor-filter invoke failed (error code = %d).\n", ret);
+    return GST_FLOW_ERROR;
+  }
 
   /* 4. Update result and free map info. */
   for (i = 0; i < prop->output_meta.num_tensors; i++) {
@@ -838,6 +853,7 @@ gst_tensor_filter_transform_size (GstBaseTransform * trans,
   self = GST_TENSOR_FILTER_CAST (trans);
   priv = &self->priv;
 
+  /** Internal Logic Error. Cannot proceed without configured pipeline */
   g_assert (priv->configured);
 
   /**
index 82657ba..49f3548 100644 (file)
@@ -447,7 +447,10 @@ nnstreamer_filter_probe (GstTensorFilterFramework * tfsp)
     name = tfsp->name;
   } else if (GST_TF_FW_V1 (tfsp)) {
     gst_tensor_filter_properties_init (&prop);
-    g_assert (tfsp->getFrameworkInfo (tfsp, &prop, NULL, &info) == 0);
+    if (0 != tfsp->getFrameworkInfo (tfsp, &prop, NULL, &info)) {
+      ml_loge ("getFrameworkInfo() failed.\n");
+      return FALSE;
+    }
     name = info.name;
   }
 
@@ -1882,7 +1885,12 @@ parse_accl_hw (const gchar * accelerators,
   accl_hw hw;
 
   match_accl = parse_accl_hw_all (accelerators, supported_accelerators);
-  g_assert (g_list_length (match_accl) > 0);
+
+  if (NULL == match_accl) {
+    ml_loge ("There is no match hardware accelerators from {%s}.\n",
+        accelerators);
+    return ACCL_NONE;
+  }
 
   hw = GPOINTER_TO_INT (match_accl->data);
   g_list_free (match_accl);
index b9fc56d..db00cb3 100644 (file)
@@ -68,25 +68,28 @@ custom_loadlib (const GstTensorFilterProperties * prop, void **private_data)
 
   if (*private_data != NULL) {
     /** @todo : Check the integrity of filter->data and filter->model_file, nnfw */
-    return 1;
+    ml_loge ("Init is called but it is already initialized.\n");
+    return -EINVAL;
   }
 
   if (!prop->model_files || prop->num_models != 1 ||
       !prop->model_files[0] || prop->model_files[0][0] == '\0') {
     /* The .so file path is not given */
-    return -1;
+    ml_logw ("Custom filter file is not given.\n");
+    return -EINVAL;
   }
 
   if (!nnsconf_validate_file (NNSCONF_PATH_CUSTOM_FILTERS,
           prop->model_files[0])) {
     /* Cannot load the library */
-    return -1;
+    ml_logw ("Custom filter file %s is invalid.\n", prop->model_files[0]);
+    return -EINVAL;
   }
 
   ptr = *private_data = g_new0 (internal_data, 1);
   if (ptr == NULL) {
-    ml_loge ("Failed to allocate memory for custom filter.");
-    return -1;
+    ml_loge ("Failed to allocate memory for custom filter.\n");
+    return -ENOMEM;
   }
 
   /* Load .so if this is the first time for this instance. */
@@ -94,7 +97,8 @@ custom_loadlib (const GstTensorFilterProperties * prop, void **private_data)
   if (!ptr->module) {
     g_free (ptr);
     *private_data = NULL;
-    return -1;
+    ml_logw ("Cannot load custom filter file %s.\n", prop->model_files[0]);
+    return -EINVAL;
   }
 
   if (!g_module_symbol (ptr->module, "NNStreamer_custom", &custom_cls)) {
@@ -102,20 +106,29 @@ custom_loadlib (const GstTensorFilterProperties * prop, void **private_data)
     g_module_close (ptr->module);
     g_free (ptr);
     *private_data = NULL;
-    return -1;
+    return -EINVAL;
   }
 
   ptr->methods = *(NNStreamer_custom_class **) custom_cls;
 
-  g_assert (ptr->methods->initfunc);
+  if (NULL == ptr->methods->initfunc) {
+    ml_loge ("tensor_filter_custom (%s) requires a valid 'initfunc'.",
+        prop->model_files[0]);
+    return -EINVAL;
+  }
+
   ptr->customFW_private_data = ptr->methods->initfunc (prop);
 
   /* After init func, (getInput XOR setInput) && (getOutput XOR setInput) must hold! */
   /** @todo Double check if this check is really required and safe */
-  g_assert (!ptr->methods->getInputDim != !ptr->methods->setInputDim &&
-      !ptr->methods->getOutputDim != !ptr->methods->setInputDim);
+  if (!ptr->methods->getInputDim != !ptr->methods->setInputDim &&
+      !ptr->methods->getOutputDim != !ptr->methods->setInputDim)
+    return 0;                   /* it holds! */
 
-  return 0;
+  ml_loge
+      ("tensor_filter_custom (%s) requires input/output dimension callbacks.",
+      prop->model_files[0]);
+  return -EINVAL;
 }
 
 /**
@@ -129,12 +142,18 @@ custom_open (const GstTensorFilterProperties * prop, void **private_data)
 
   /* This must be called only once */
   if (retval != 0)
-    return -1;
+    return retval;
 
   ptr = *private_data;
-  g_assert (!ptr->methods->invoke != !ptr->methods->allocate_invoke);   /* XOR! */
 
-  return 0;
+  /* One of the two is defined. (but not both) */
+  if (!ptr->methods->invoke != !ptr->methods->allocate_invoke)
+    return 0;
+
+  ml_loge
+      ("An invoke callback is not given or both invoke functions are given. Cannot load %s.\n",
+      prop->model_files[0]);
+  return -EINVAL;
 }
 
 /**
index 0bcd321..1e4b6c8 100644 (file)
@@ -101,16 +101,33 @@ custom_open (const GstTensorFilterProperties * prop, void **private_data)
     ml_loge
         ("Cannot find the easy-custom model, \"%s\". You should provide a valid model name of easy-custom.",
         prop->model_files[0]);
-    g_free (rd);
-    return -EINVAL;
+    goto errorreturn;
   }
 
-  g_assert (rd->model->func);
-  g_assert (rd->model->in_info);
-  g_assert (rd->model->out_info);
+  if (NULL == rd->model->func) {
+    ml_logf
+        ("A custom-easy filter, \"%s\", should provide invoke function body, 'func'. A null-ptr is supplied instead.\n",
+        prop->model_files[0]);
+    goto errorreturn;
+  }
+  if (NULL == rd->model->in_info) {
+    ml_logf
+        ("A custom-easy filter, \"%s\", should provide input stream metadata, 'in_info'.\n",
+        prop->model_files[0]);
+    goto errorreturn;
+  }
+  if (NULL == rd->model->out_info) {
+    ml_logf
+        ("A custom-easy filter, \"%s\", should provide output stream metadata, 'out_info'.\n",
+        prop->model_files[0]);
+    goto errorreturn;
+  }
 
   *private_data = rd;
   return 0;
+errorreturn:
+  g_free (rd);
+  return -EINVAL;
 }
 
 /**
@@ -122,6 +139,7 @@ custom_invoke (const GstTensorFilterProperties * prop,
     GstTensorMemory * output)
 {
   runtime_data *rd = *private_data;
+  /* Internal Logic Error */
   g_assert (rd && rd->model && rd->model->func);
 
   return rd->model->func (rd->model->data, prop, input, output);
@@ -135,6 +153,7 @@ custom_getInputDim (const GstTensorFilterProperties * prop,
     void **private_data, GstTensorsInfo * info)
 {
   runtime_data *rd = *private_data;
+  /* Internal Logic Error */
   g_assert (rd && rd->model && rd->model->in_info);
   gst_tensors_info_copy (info, rd->model->in_info);
   return 0;
@@ -148,6 +167,7 @@ custom_getOutputDim (const GstTensorFilterProperties * prop,
     void **private_data, GstTensorsInfo * info)
 {
   runtime_data *rd = *private_data;
+  /* Internal Logic Error */
   g_assert (rd && rd->model && rd->model->out_info);
   gst_tensors_info_copy (info, rd->model->out_info);
   return 0;
index 3cde482..efcb43d 100644 (file)
@@ -297,8 +297,7 @@ gst_tensor_merge_request_new_pad (GstElement * element, GstPadTemplate * templ,
 
   if (tensor_merge->tensors_config.info.num_tensors >= NNS_TENSOR_SIZE_LIMIT) {
     GST_ERROR_OBJECT (tensor_merge,
-        "supposed max size is " NNS_TENSOR_SIZE_LIMIT_STR);
-    g_assert (0);
+        "supposed max number of tensors is " NNS_TENSOR_SIZE_LIMIT_STR);
     return NULL;
   }
 
@@ -479,7 +478,6 @@ gst_tensor_merge_generate_mem (GstTensorMerge * tensor_merge,
   gsize element_size;
   tensor_dim dim;
   tensor_type type;
-  gboolean status;
 
   memcpy (&dim, &tensor_merge->tensors_config.info.info[0].dimension,
       sizeof (tensor_dim));
@@ -488,14 +486,24 @@ gst_tensor_merge_generate_mem (GstTensorMerge * tensor_merge,
 
   for (i = 0; i < num_mem; i++) {
     mem[i] = gst_buffer_peek_memory (tensors_buf, i);
-    status = gst_memory_map (mem[i], &mInfo[i], GST_MAP_READ);
-    g_assert (status); /** @todo Do proper error handling */
+    if (FALSE == gst_memory_map (mem[i], &mInfo[i], GST_MAP_READ)) {
+      for (j = 0; j < i; j++) {
+        gst_memory_unmap (mem[j], &mInfo[j]);
+        ml_logf ("Cannot map input memory buffers (%d)\n", i);
+        ret = GST_FLOW_ERROR;
+        goto error_ret;
+      }
+    }
     outSize += mInfo[i].size;
   }
 
   outMem = gst_allocator_alloc (NULL, outSize, NULL);
-  status = gst_memory_map (outMem, &outInfo, GST_MAP_WRITE);
-  g_assert (status); /** @todo Do proper error handling */
+  if (FALSE == gst_memory_map (outMem, &outInfo, GST_MAP_WRITE)) {
+    gst_allocator_free (NULL, outMem);
+    ml_logf ("Cannot map output memory buffer\n");
+    ret = GST_FLOW_ERROR;
+    goto error_unmap_inmem;
+  }
   outptr = outInfo.data;
 
   switch (tensor_merge->mode) {
@@ -599,10 +607,11 @@ gst_tensor_merge_generate_mem (GstTensorMerge * tensor_merge,
   gst_buffer_append_memory (tensor_buf, outMem);
   gst_buffer_copy_into (tensor_buf, tensors_buf, GST_BUFFER_COPY_TIMESTAMPS, 0,
       -1);
+  gst_memory_unmap (outMem, &outInfo);
+error_unmap_inmem:
   for (i = 0; i < num_mem; i++)
     gst_memory_unmap (mem[i], &mInfo[i]);
-  gst_memory_unmap (outMem, &outInfo);
-
+error_ret:
   return ret;
 }
 
@@ -632,7 +641,11 @@ gst_tensor_merge_collected (GstCollectPads * pads,
   }
 
   tensors_buf = gst_buffer_new ();
-  g_assert (tensors_buf != NULL);
+
+  if (NULL == tensors_buf) {
+    ml_logf ("gst_buffer_new() returns NULL. Out of memory?\n");
+    return GST_FLOW_ERROR;
+  }
 
   isEOS =
       gst_tensor_merge_collect_buffer (tensor_merge, tensors_buf, &pts_time,
@@ -656,8 +669,8 @@ gst_tensor_merge_collected (GstCollectPads * pads,
 
     if (gst_tensor_merge_get_merged_config (tensor_merge,
             &tensor_merge->tensors_config, &config)) {
+      /** Internal Logic Error? */
       g_assert (gst_tensor_config_validate (&config));
-      /** @todo Do proper error handling */
       newcaps = gst_tensor_caps_from_config (&config);
     } else {
       goto nego_error;
@@ -690,7 +703,10 @@ gst_tensor_merge_collected (GstCollectPads * pads,
   }
 
   tensor_buf = gst_buffer_new ();
-  g_assert (tensor_buf != NULL);
+  if (NULL == tensors_buf) {
+    ml_logf ("gst_buffer_new() returns NULL. Out of memory?\n");
+    return GST_FLOW_ERROR;
+  }
 
   gst_tensor_merge_generate_mem (tensor_merge, tensors_buf, tensor_buf);
 
@@ -761,26 +777,29 @@ gst_tensor_merge_change_state (GstElement * element, GstStateChange transition)
 /**
  * @brief Setup internal data (data_* in GstTensor_Merge)
  * @param[in/out] filter "this" pointer. mode & option MUST BE set already.
+ * @retval TRUE if ok or not configured, yet.
+ * @retval FALSE if given input is configured invalid.
  */
-static void
+static gboolean
 gst_tensor_merge_set_option_data (GstTensorMerge * filter)
 {
   if (filter->mode == GTT_END || filter->option == NULL)
-    return;
+    return TRUE;
   switch (filter->mode) {
     case GTT_LINEAR:
     {
       filter->data_linear.direction =
           find_key_strv (gst_tensor_merge_linear_string, filter->option);
-      g_assert (filter->data_linear.direction >= 0);
+      if (filter->data_linear.direction < 0)
+        return FALSE;
       filter->loaded = TRUE;
     }
       break;
     default:
       GST_ERROR_OBJECT (filter, "Cannot identify mode\n");
-      g_assert (0);
-      break;
+      return FALSE;
   }
+  return TRUE;
 }
 
 /**
@@ -797,12 +816,22 @@ gst_tensor_merge_set_property (GObject * object, guint prop_id,
       break;
     case PROP_MODE:
       filter->mode = gst_tensor_merge_get_mode (g_value_get_string (value));
-      g_assert (filter->mode != GTT_END);
-      gst_tensor_merge_set_option_data (filter);
+      if (filter->mode == GTT_END) {
+        ml_logw ("Given mode property is not recognized: %s\n",
+            g_value_get_string (value));
+        break;
+      }
+      if (FALSE == gst_tensor_merge_set_option_data (filter)) {
+        filter->loaded = FALSE;
+        ml_logw ("Given mode property is not consistent with its options.\n");
+      }
       break;
     case PROP_OPTION:
       filter->option = g_value_dup_string (value);
-      gst_tensor_merge_set_option_data (filter);
+      if (FALSE == gst_tensor_merge_set_option_data (filter)) {
+        filter->loaded = FALSE;
+        ml_logw ("Given option property is not consistent with its mode.\n");
+      }
       break;
     case PROP_SYNC_MODE:
       filter->sync.mode =
index 00cdb7a..286e06e 100644 (file)
@@ -382,7 +382,10 @@ gst_tensor_mux_collected (GstCollectPads * pads, GstTensorMux * tensor_mux)
   }
 
   tensors_buf = gst_buffer_new ();
-  g_assert (tensors_buf);
+  if (NULL == tensors_buf) {
+    ml_logf ("gst_buffer_new() returns NULL. Out of memory?\n");
+    return GST_FLOW_ERROR;
+  }
 
   isEOS =
       gst_tensor_mux_collect_buffer (tensor_mux, tensors_buf, &pts_time,
index 6ee33f5..1981d49 100644 (file)
@@ -228,13 +228,14 @@ gst_tensor_repo_add_repodata (guint nth, gboolean is_sink)
 
   GST_REPO_LOCK ();
   ret = g_hash_table_insert (_repo.hash, GINT_TO_POINTER (nth), data);
-  g_assert (ret);
 
   if (ret) {
     _repo.num_data++;
 
     if (DBG)
       GST_DEBUG ("Successfully added in hash table with key[%d]", nth);
+  } else {
+    ml_logf ("The key[%d] is duplicated. Cannot proceed.\n", nth);
   }
 
   GST_REPO_UNLOCK ();
index 5de831b..23b4a32 100644 (file)
@@ -310,12 +310,15 @@ gst_tensor_reposrc_gen_dummy_buffer (GstTensorRepoSrc * self)
   num_tensors = self->config.info.num_tensors;
 
   for (i = 0; i < num_tensors; i++) {
-    gboolean status;
     size = gst_tensor_info_get_size (&self->config.info.info[i]);
     mem = gst_allocator_alloc (NULL, size, NULL);
 
-    status = gst_memory_map (mem, &info, GST_MAP_WRITE);
-    g_assert (status); /** @todo Do proper error handling (err return) */
+    if (FALSE == gst_memory_map (mem, &info, GST_MAP_WRITE)) {
+      gst_allocator_free (NULL, mem);
+      ml_logf ("Cannot mep gst memory (tensor-repo-src)\n");
+      gst_buffer_unref (buf);
+      return NULL;
+    }
     memset (info.data, 0, size);
     gst_memory_unmap (mem, &info);
 
index 9bd728d..7d1f097 100644 (file)
@@ -412,7 +412,6 @@ gst_tensor_split_get_splited (GstTensorSplit * split, GstBuffer * buffer,
   int i;
   gsize size, offset;
   GstMapInfo src_info, dest_info;
-  gboolean status;
 
   size = 0;
   offset = 0;
@@ -421,10 +420,15 @@ gst_tensor_split_get_splited (GstTensorSplit * split, GstBuffer * buffer,
   size += gst_tensor_get_element_count (*dim) *
       gst_tensor_get_element_size (split->sink_tensor_conf.info.type);
   mem = gst_allocator_alloc (NULL, size, NULL);
-  status = gst_memory_map (mem, &dest_info, GST_MAP_WRITE);
-  g_assert (status);
-  status = gst_buffer_map (buffer, &src_info, GST_MAP_READ);
-  g_assert (status);
+  if (FALSE == gst_memory_map (mem, &dest_info, GST_MAP_WRITE)) {
+    ml_logf ("Cannot map memory for destination buffer.\n");
+    return NULL;
+  }
+  if (FALSE == gst_buffer_map (buffer, &src_info, GST_MAP_READ)) {
+    ml_logf ("Cannot map src-memory to gst buffer at tensor-split.\n");
+    gst_memory_unmap (mem, &dest_info);
+    return NULL;
+  }
 
   for (i = 0; i < nth; i++) {
     dim = g_array_index (split->tensorseg, tensor_dim *, i);
index acef920..f158a92 100644 (file)
@@ -724,13 +724,16 @@ gst_tensor_transform_typecast_value (GstTensorTransform * filter,
 /**
  * @brief Setup internal data (data_* in GstTensorTransform)
  * @param[in/out] filter "this" pointer. mode & option MUST BE set already.
+ * @retval TRUE if OK or operation-skipped, FALSE if fatal-error.
  */
-static void
+static gboolean
 gst_tensor_transform_set_option_data (GstTensorTransform * filter)
 {
   gchar *filter_name;
+  gboolean ret = TRUE;
+
   if (filter->mode == GTT_UNKNOWN || filter->option == NULL)
-    return;
+    return TRUE;
 
   filter_name = gst_object_get_name ((GstObject *) filter);
 
@@ -923,11 +926,11 @@ gst_tensor_transform_set_option_data (GstTensorTransform * filter)
     }
     default:
       GST_ERROR_OBJECT (filter, "Cannot identify mode\n");
-      g_assert (0);
-      break;
+      ret = FALSE;
   }
 
   g_free (filter_name);
+  return ret;
 }
 
 /**
@@ -947,10 +950,19 @@ gst_tensor_transform_set_property (GObject * object, guint prop_id,
       filter->mode = g_value_get_enum (value);
       break;
     case PROP_OPTION:
+    {
+      gchar *backup_option = filter->option;
       filter->option = g_value_dup_string (value);
-      silent_debug ("Option = %s\n", filter->option);
-      gst_tensor_transform_set_option_data (filter);
+      if (TRUE == gst_tensor_transform_set_option_data (filter)) {
+        silent_debug ("Option = %s --> %s\n", backup_option, filter->option);
+        g_free (backup_option);
+      } else {
+        /* ERROR! Revert the change! */
+        g_free (filter->option);
+        filter->option = backup_option;
+      }
       break;
+    }
     case PROP_ACCELERATION:
 #ifdef HAVE_ORC
       filter->acceleration = g_value_get_boolean (value);
@@ -1090,7 +1102,9 @@ gst_tensor_transform_dimchg (GstTensorTransform * filter,
      * E.g., [N][c][H][W] (W:H:c:N) --> [N][H][W][c] (c:W:H:N)
      * @todo NYI
      */
-    g_assert (0);
+    ml_loge
+        ("tensor-transform/dimchg operation is not permitted if from >= to.\n");
+    return GST_FLOW_ERROR;
   }
 
   return GST_FLOW_OK;
@@ -1368,7 +1382,6 @@ gst_tensor_transform_stand (GstTensorTransform * filter,
     }
     default:
       GST_ERROR_OBJECT (filter, "Cannot identify mode\n");
-      g_assert (0);
       return GST_FLOW_ERROR;
   }
 
@@ -1388,17 +1401,21 @@ gst_tensor_transform_transform (GstBaseTransform * trans,
 {
   GstFlowReturn res;
   GstTensorTransform *filter = GST_TENSOR_TRANSFORM_CAST (trans);
-  gboolean status;
 
   uint8_t *inptr, *outptr;
   GstMapInfo inInfo, outInfo;
 
   g_return_val_if_fail (filter->loaded, GST_FLOW_ERROR);
 
-  status = gst_buffer_map (inbuf, &inInfo, GST_MAP_READ);
-  g_assert (status);
-  status = gst_buffer_map (outbuf, &outInfo, GST_MAP_WRITE);
-  g_assert (status);
+  if (FALSE == gst_buffer_map (inbuf, &inInfo, GST_MAP_READ)) {
+    ml_loge ("Cannot map input buffer to gst-buf at tensor-transform.\n");
+    return GST_FLOW_ERROR;
+  }
+  if (FALSE == gst_buffer_map (outbuf, &outInfo, GST_MAP_WRITE)) {
+    gst_buffer_unmap (inbuf, &inInfo);
+    ml_loge ("Cannot map output buffer to gst-buf at tensor-transform.\n");
+    return GST_FLOW_ERROR;
+  }
 
   inptr = inInfo.data;
   outptr = outInfo.data;