#include "gstamcsrc.h"
#include "gstamcsrc_looper.h"
-#include <assert.h>
#include <jni.h>
#include <pthread.h>
#include <stdio.h>
#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));
}
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;
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,
}
/* 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); */
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 */
}
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);
* 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];
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];
#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));
/* 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) {
} 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 */
#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));
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;
}
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);
#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));
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 */
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) {
}
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);
#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));
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);
}
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);
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
{
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);
/** 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;
}
/**
_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++;
}
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;
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,
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)) {
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);
}
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);
{
guint i;
- g_assert (info != NULL);
+ g_assert (info != NULL); /** Internal error. Caller should've checked it */
/**
* Check condition to concatenate data.
* @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)
{
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)
gst_buffer_unmap (outbuf, &dest_info);
gst_buffer_unref (srcbuf);
+
+ return TRUE;
}
/**
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);
{
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;
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)
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);
gst_tensor_info_init (&self->tensor_info);
self->adapter = gst_adapter_new ();
+ g_assert (self->adapter != NULL);
gst_tensor_converter_reset (self);
}
GstSegment seg;
guint64 start;
+ /** This is an internal logic error. */
g_assert (self->have_segment);
start = self->segment.start;
self = GST_TENSOR_CONVERTER (parent);
+ /** This is an internal logic error. */
g_assert (self->tensor_configured);
config = &self->tensor_config;
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);
}
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);
}
default:
GST_ERROR_OBJECT (self, "Unsupported type %d\n", self->in_media_type);
- g_assert (0);
return GST_FLOW_ERROR;
}
/** @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");
* @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?
*
*/
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)
const GstTensorDecoderDef *decoder;
const gchar *mode_string;
guint i;
- int status;
mode_string = g_value_get_string (value);
decoder = nnstreamer_decoder_find (mode_string);
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))
{
GstTensorDec *self;
GstFlowReturn res;
- gboolean status;
self = GST_TENSOR_DECODER_CAST (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;
/** @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;
}
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 =
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]);
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;
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;
/* 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;
}
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++) {
self = GST_TENSOR_FILTER_CAST (trans);
priv = &self->priv;
+ /** Internal Logic Error. Cannot proceed without configured pipeline */
g_assert (priv->configured);
/**
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;
}
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);
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. */
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)) {
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;
}
/**
/* 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;
}
/**
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;
}
/**
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);
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;
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;
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;
}
gsize element_size;
tensor_dim dim;
tensor_type type;
- gboolean status;
memcpy (&dim, &tensor_merge->tensors_config.info.info[0].dimension,
sizeof (tensor_dim));
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) {
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;
}
}
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,
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;
}
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);
/**
* @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;
}
/**
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 =
}
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,
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 ();
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);
int i;
gsize size, offset;
GstMapInfo src_info, dest_info;
- gboolean status;
size = 0;
offset = 0;
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);
/**
* @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);
}
default:
GST_ERROR_OBJECT (filter, "Cannot identify mode\n");
- g_assert (0);
- break;
+ ret = FALSE;
}
g_free (filter_name);
+ return ret;
}
/**
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);
* 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;
}
default:
GST_ERROR_OBJECT (filter, "Cannot identify mode\n");
- g_assert (0);
return GST_FLOW_ERROR;
}
{
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;