Each invoke callback gets/returns tensor data object including metadata.
To improve performance, Cache tensor metadata object and avoid duplicated conversion.
Signed-off-by: Jaeyun <jy1210.jung@samsung.com>
element_data_s *item = (element_data_s *) data;
if (item) {
+ /* release private data */
+ if (item->priv_data) {
+ JNIEnv *env = nns_get_jni_env (item->pipe_info);
+ item->priv_destroy_func (item->priv_data, env);
+ }
+
switch (item->type) {
#if !defined (NNS_SINGLE_ONLY)
case NNS_ELEMENT_TYPE_SRC:
pipe_info->priv_destroy_func (pipe_info->priv_data, env);
else
g_free (pipe_info->priv_data);
+
+ pipe_info->priv_data = NULL;
}
g_hash_table_destroy (pipe_info->element_handles);
*/
gboolean
nns_convert_tensors_data (pipeline_info_s * pipe_info, JNIEnv * env,
- ml_tensors_data_h data_h, ml_tensors_info_h info_h, jobject * result)
+ ml_tensors_data_h data_h, jobject obj_info, jobject * result)
{
guint i;
data_class_info_s *dcls_info;
goto done;
}
- if (info_h) {
- jobject obj_info = NULL;
-
- if (!nns_convert_tensors_info (pipe_info, env, info_h, &obj_info)) {
- nns_loge ("Failed to convert tensors info.");
- (*env)->DeleteLocalRef (env, obj_data);
- obj_data = NULL;
- goto done;
- }
-
+ /* set tensors info */
+ if (obj_info) {
(*env)->CallVoidMethod (env, obj_data, dcls_info->mid_set_info, obj_info);
- (*env)->DeleteLocalRef (env, obj_info);
}
for (i = 0; i < data->num_tensors; i++) {
{
jmethodID mid_invoke;
jmethodID mid_info;
+ ml_tensors_info_h in_info;
+ jobject in_info_obj;
} customfilter_priv_data_s;
/**
{
customfilter_priv_data_s *priv = (customfilter_priv_data_s *) data;
- /* nothing to free */
+ ml_tensors_info_destroy (priv->in_info);
+ if (priv->in_info_obj)
+ (*env)->DeleteGlobalRef (env, priv->in_info_obj);
+
g_free (priv);
}
/**
+ * @brief Update input info in private data.
+ */
+static gboolean
+nns_customfilter_priv_set_in_info (pipeline_info_s * pipe_info, JNIEnv * env,
+ ml_tensors_info_h in_info)
+{
+ customfilter_priv_data_s *priv;
+ jobject obj_info = NULL;
+
+ priv = (customfilter_priv_data_s *) pipe_info->priv_data;
+
+ if (priv->in_info && ml_tensors_info_is_equal (in_info, priv->in_info)) {
+ /* do nothing, tensors info is equal. */
+ return TRUE;
+ }
+
+ if (!nns_convert_tensors_info (pipe_info, env, in_info, &obj_info)) {
+ nns_loge ("Failed to convert tensors info.");
+ return FALSE;
+ }
+
+ if (priv->in_info_obj)
+ (*env)->DeleteGlobalRef (env, priv->in_info_obj);
+
+ if (priv->in_info)
+ ml_tensors_info_free (priv->in_info);
+ else
+ ml_tensors_info_create (&priv->in_info);
+
+ ml_tensors_info_clone (priv->in_info, in_info);
+ priv->in_info_obj = (*env)->NewGlobalRef (env, obj_info);
+ (*env)->DeleteLocalRef (env, obj_info);
+ return TRUE;
+}
+
+/**
* @brief The mandatory callback for GstTensorFilterFramework.
* @param prop The property of tensor_filter instance
* @param private_data Sub-plugin's private data
}
ml_tensors_info_copy_from_gst (in_info, &prop->input_meta);
+ if (!nns_customfilter_priv_set_in_info (pipe_info, env, in_info)) {
+ goto done;
+ }
/* convert to data object */
- if (!nns_convert_tensors_data (pipe_info, env, in_data, in_info,
+ if (!nns_convert_tensors_data (pipe_info, env, in_data, priv->in_info_obj,
&obj_in_data)) {
nns_loge ("Failed to convert input data to data-object.");
goto done;
} pipeline_priv_data_s;
/**
+ * @brief Private data for sink node.
+ */
+typedef struct
+{
+ ml_tensors_info_h out_info;
+ jobject out_info_obj;
+} pipeline_sink_priv_data_s;
+
+/**
* @brief Release private data in pipeline info.
*/
static void
}
/**
+ * @brief Release private data in sink node.
+ */
+static void
+nns_pipeline_sink_priv_free (gpointer data, JNIEnv * env)
+{
+ pipeline_sink_priv_data_s *priv = (pipeline_sink_priv_data_s *) data;
+
+ ml_tensors_info_destroy (priv->out_info);
+ if (priv->out_info_obj)
+ (*env)->DeleteGlobalRef (env, priv->out_info_obj);
+
+ g_free (priv);
+}
+
+/**
+ * @brief Update output info in sink node data.
+ */
+static gboolean
+nns_pipeline_sink_priv_set_out_info (element_data_s * item, JNIEnv * env,
+ const ml_tensors_info_h out_info)
+{
+ pipeline_sink_priv_data_s *priv;
+ jobject obj_info = NULL;
+
+ if ((priv = item->priv_data) == NULL) {
+ priv = g_new0 (pipeline_sink_priv_data_s, 1);
+
+ item->priv_data = priv;
+ item->priv_destroy_func = nns_pipeline_sink_priv_free;
+ }
+
+ if (priv->out_info && ml_tensors_info_is_equal (out_info, priv->out_info)) {
+ /* do nothing, tensors info is equal. */
+ return TRUE;
+ }
+
+ if (!nns_convert_tensors_info (item->pipe_info, env, out_info, &obj_info)) {
+ nns_loge ("Failed to convert output info.");
+ return FALSE;
+ }
+
+ if (priv->out_info_obj)
+ (*env)->DeleteGlobalRef (env, priv->out_info_obj);
+
+ if (priv->out_info)
+ ml_tensors_info_free (priv->out_info);
+ else
+ ml_tensors_info_create (&priv->out_info);
+
+ ml_tensors_info_clone (priv->out_info, out_info);
+ priv->out_info_obj = (*env)->NewGlobalRef (env, obj_info);
+ (*env)->DeleteLocalRef (env, obj_info);
+ return TRUE;
+}
+
+/**
* @brief Pipeline state change callback.
*/
static void
nns_sink_data_cb (const ml_tensors_data_h data, const ml_tensors_info_h info,
void *user_data)
{
- element_data_s *cb_data;
+ element_data_s *item;
pipeline_info_s *pipe_info;
pipeline_priv_data_s *priv;
+ pipeline_sink_priv_data_s *priv_sink;
jobject obj_data = NULL;
JNIEnv *env;
- cb_data = (element_data_s *) user_data;
- pipe_info = cb_data->pipe_info;
- priv = (pipeline_priv_data_s *) pipe_info->priv_data;
+ item = (element_data_s *) user_data;
+ pipe_info = item->pipe_info;
if ((env = nns_get_jni_env (pipe_info)) == NULL) {
nns_logw ("Cannot get jni env in the sink callback.");
return;
}
- if (nns_convert_tensors_data (pipe_info, env, data, info, &obj_data)) {
- jstring sink_name = (*env)->NewStringUTF (env, cb_data->name);
+ /* cache output tensors info */
+ if (!nns_pipeline_sink_priv_set_out_info (item, env, info)) {
+ return;
+ }
+
+ priv = (pipeline_priv_data_s *) pipe_info->priv_data;
+ priv_sink = (pipeline_sink_priv_data_s *) item->priv_data;
+
+ if (nns_convert_tensors_data (pipe_info, env, data, priv_sink->out_info_obj,
+ &obj_data)) {
+ jstring sink_name = (*env)->NewStringUTF (env, item->name);
(*env)->CallVoidMethod (env, pipe_info->instance, priv->mid_sink_cb,
sink_name, obj_data);
#include "nnstreamer-native.h"
/**
+ * @brief Private data for SingleShot class.
+ */
+typedef struct
+{
+ ml_tensors_info_h out_info;
+ jobject out_info_obj;
+} singleshot_priv_data_s;
+
+/**
+ * @brief Release private data in pipeline info.
+ */
+static void
+nns_singleshot_priv_free (gpointer data, JNIEnv * env)
+{
+ singleshot_priv_data_s *priv = (singleshot_priv_data_s *) data;
+
+ ml_tensors_info_destroy (priv->out_info);
+ if (priv->out_info_obj)
+ (*env)->DeleteGlobalRef (env, priv->out_info_obj);
+
+ g_free (priv);
+}
+
+/**
+ * @brief Update output info in private data.
+ */
+static gboolean
+nns_singleshot_priv_set_out_info (pipeline_info_s * pipe_info, JNIEnv * env,
+ ml_tensors_info_h out_info)
+{
+ singleshot_priv_data_s *priv;
+ jobject obj_info = NULL;
+
+ priv = (singleshot_priv_data_s *) pipe_info->priv_data;
+
+ if (priv->out_info && ml_tensors_info_is_equal (out_info, priv->out_info)) {
+ /* do nothing, tensors info is equal. */
+ return TRUE;
+ }
+
+ if (!nns_convert_tensors_info (pipe_info, env, out_info, &obj_info)) {
+ nns_loge ("Failed to convert output info.");
+ return FALSE;
+ }
+
+ if (priv->out_info_obj)
+ (*env)->DeleteGlobalRef (env, priv->out_info_obj);
+
+ if (priv->out_info)
+ ml_tensors_info_free (priv->out_info);
+ else
+ ml_tensors_info_create (&priv->out_info);
+
+ ml_tensors_info_clone (priv->out_info, out_info);
+ priv->out_info_obj = (*env)->NewGlobalRef (env, obj_info);
+ (*env)->DeleteLocalRef (env, obj_info);
+ return TRUE;
+}
+
+/**
* @brief Native method for single-shot API.
*/
jlong
g_free (info.models);
g_free (info.custom_option);
- if (!opened) {
+ if (opened) {
+ singleshot_priv_data_s *priv;
+ ml_tensors_info_h out_info;
+
+ priv = g_new0 (singleshot_priv_data_s, 1);
+ nns_set_priv_data (pipe_info, priv, nns_singleshot_priv_free);
+
+ /* set output info */
+ if (ml_single_get_output_info (single, &out_info) == ML_ERROR_NONE) {
+ nns_singleshot_priv_set_out_info (pipe_info, env, out_info);
+ ml_tensors_info_destroy (out_info);
+ }
+ } else {
nns_destroy_pipe_info (pipe_info, env);
pipe_info = NULL;
}
jobject thiz, jlong handle, jobject in)
{
pipeline_info_s *pipe_info;
+ singleshot_priv_data_s *priv;
ml_single_h single;
ml_tensors_info_h cur_info, in_info, out_info;
ml_tensors_data_h in_data, out_data;
jobject result = NULL;
pipe_info = CAST_TO_TYPE (handle, pipeline_info_s *);
+ priv = (singleshot_priv_data_s *) pipe_info->priv_data;
single = pipe_info->pipeline_handle;
cur_info = in_info = out_info = NULL;
in_data = out_data = NULL;
goto done;
}
- if (!nns_convert_tensors_data (pipe_info, env, out_data, out_info, &result)) {
- nns_loge ("Failed to convert the result to data.");
+ if (!nns_singleshot_priv_set_out_info (pipe_info, env, out_info)) {
+ goto done;
+ }
+
+ if (!nns_convert_tensors_data (pipe_info, env, out_data, priv->out_info_obj,
+ &result)) {
+ nns_loge ("Failed to convert the result to data-object.");
result = NULL;
}
nns_element_type_e type;
gpointer handle;
pipeline_info_s *pipe_info;
+
+ gpointer priv_data;
+ nns_priv_destroy priv_destroy_func;
} element_data_s;
/**
* @brief Convert tensors data to TensorsData object.
*/
extern gboolean
-nns_convert_tensors_data (pipeline_info_s * pipe_info, JNIEnv * env, ml_tensors_data_h data_h, ml_tensors_info_h info_h, jobject * result);
+nns_convert_tensors_data (pipeline_info_s * pipe_info, JNIEnv * env, ml_tensors_data_h data_h, jobject obj_info, jobject * result);
/**
* @brief Parse tensors data from TensorsData object.