1. Fix wrong conversion of byte buffer in native.
2. Add methods to allocate buffer with native byte order.
3. Fix invalid condition to close handle.
Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
{
g_assert (pipe_info);
+ g_mutex_lock (&pipe_info->lock);
+ g_hash_table_destroy (pipe_info->element_handles);
+ pipe_info->element_handles = NULL;
+ g_mutex_unlock (&pipe_info->lock);
+
if (g_str_equal (pipe_info->pipeline_type, NNS_PIPE_TYPE_PIPELINE)) {
ml_pipeline_destroy (pipe_info->pipeline_handle);
} else if (g_str_equal (pipe_info->pipeline_type, NNS_PIPE_TYPE_SINGLE)) {
ml_single_close (pipe_info->pipeline_handle);
} else {
nns_logw ("Given pipe type %s is unknown.", pipe_info->pipeline_type);
- g_free (pipe_info->pipeline_handle);
+ if (pipe_info->pipeline_handle)
+ g_free (pipe_info->pipeline_handle);
}
- g_mutex_lock (&pipe_info->lock);
- g_hash_table_destroy (pipe_info->element_handles);
- pipe_info->element_handles = NULL;
- g_mutex_unlock (&pipe_info->lock);
-
g_mutex_clear (&pipe_info->lock);
(*env)->DeleteGlobalRef (env, pipe_info->instance);
/* method to generate tensors data */
jmethodID mid_init = (*env)->GetMethodID (env, pipe_info->cls_tensors_data, "<init>", "()V");
- jmethodID mid_add = (*env)->GetMethodID (env, pipe_info->cls_tensors_data, "addTensorData", "(Ljava/lang/Object;)V");
+ jmethodID mid_add = (*env)->GetMethodID (env, pipe_info->cls_tensors_data, "addTensorData", "([B)V");
jobject obj_data = (*env)->NewObject (env, pipe_info->cls_tensors_data, mid_init);
if (!obj_data) {
}
for (i = 0; i < data->num_tensors; i++) {
- jobject item = (*env)->NewDirectByteBuffer (env, data->tensors[i].tensor,
- (jlong) data->tensors[i].size);
+ jsize buffer_size = (jsize) data->tensors[i].size;
+ jbyteArray buffer = (*env)->NewByteArray (env, buffer_size);
- (*env)->CallVoidMethod (env, obj_data, mid_add, item);
- (*env)->DeleteLocalRef (env, item);
+ (*env)->SetByteArrayRegion (env, buffer, 0, buffer_size, (jbyte *) data->tensors[i].tensor);
+
+ (*env)->CallVoidMethod (env, obj_data, mid_add, buffer);
+ (*env)->DeleteLocalRef (env, buffer);
}
done:
gpointer data_ptr = (*env)->GetDirectBufferAddress (env, tensor_data);
data->tensors[i].tensor = g_malloc (data_size);
+ if (!data->tensors[i].tensor) {
+ nns_loge ("Failed to allocate memory %zd, data index %d.", data_size, i);
+ (*env)->DeleteLocalRef (env, tensor_data);
+ goto failed;
+ }
+
memcpy (data->tensors[i].tensor, data_ptr, data_size);
data->tensors[i].size = data_size;
(*env)->DeleteLocalRef (env, cls_arraylist);
(*env)->DeleteLocalRef (env, obj_arraylist);
return TRUE;
+
+failed:
+ for (i = 0; i < data->num_tensors; i++) {
+ if (data->tensors[i].tensor) {
+ g_free (data->tensors[i].tensor);
+ data->tensors[i].tensor = NULL;
+ }
+
+ data->tensors[i].size = 0;
+ }
+
+ data->num_tensors = 0;
+ return FALSE;
}
/**
mStateCallback = null;
}
- if (mHandle > 0) {
+ if (mHandle != 0) {
nativeDestroy(mHandle);
mHandle = 0;
}
@Override
public void close() {
- if (mHandle > 0) {
+ if (mHandle != 0) {
nativeClose(mHandle);
mHandle = 0;
}
private ArrayList<ByteBuffer> mDataList = new ArrayList<>();
/**
+ * Allocates a new direct byte buffer with the native byte order.
+ *
+ * @param size The byte size of the buffer
+ *
+ * @return The new byte buffer
+ */
+ public static ByteBuffer allocateByteBuffer(int size) {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(size);
+
+ buffer.order(ByteOrder.nativeOrder());
+
+ return buffer;
+ }
+
+ /**
+ * Allocates a new <code>TensorsData</code> instance with the given tensors information.
+ *
+ * @param info The tensors information
+ *
+ * @return The allocated tensors data instance
+ *
+ * @throws IllegalArgumentException if given param is invalid
+ */
+ public static TensorsData allocate(@NonNull TensorsInfo info) {
+ if (info == null) {
+ throw new IllegalArgumentException("The param info is null");
+ }
+
+ TensorsData data = new TensorsData();
+ int count = info.getTensorsCount();
+
+ for (int i = 0; i < count; i++) {
+ int type = info.getTesorType(i);
+ int[] dimension = info.getTesorDimension(i);
+
+ int size = 0;
+
+ switch (type) {
+ case NNStreamer.TENSOR_TYPE_INT32:
+ case NNStreamer.TENSOR_TYPE_UINT32:
+ case NNStreamer.TENSOR_TYPE_FLOAT32:
+ size = 4;
+ break;
+ case NNStreamer.TENSOR_TYPE_INT16:
+ case NNStreamer.TENSOR_TYPE_UINT16:
+ size = 2;
+ break;
+ case NNStreamer.TENSOR_TYPE_INT8:
+ case NNStreamer.TENSOR_TYPE_UINT8:
+ size = 1;
+ break;
+ case NNStreamer.TENSOR_TYPE_FLOAT64:
+ case NNStreamer.TENSOR_TYPE_INT64:
+ case NNStreamer.TENSOR_TYPE_UINT64:
+ size = 8;
+ break;
+ default:
+ /* unknown type */
+ break;
+ }
+
+ for (int j = 0; j < NNStreamer.TENSOR_RANK_LIMIT; j++) {
+ size *= dimension[j];
+ }
+
+ data.addTensorData(allocateByteBuffer(size));
+ }
+
+ return data;
+ }
+
+ /**
* Gets the number of tensors in tensors data.
*
* @return The number of tensors
*
* @param data The data object to be added
*
- * @throws IllegalArgumentException if the data is not a byte buffer
+ * @throws IllegalArgumentException if the data is not a byte buffer or the buffer is invalid
* @throws IndexOutOfBoundsException when the maximum number of tensors in the list
*/
public void addTensorData(@NonNull Object data) {
/**
* Adds a new tensor data.
*
+ * @param data The byte array to be added
+ *
+ * @throws IllegalArgumentException if given data is invalid
+ * @throws IndexOutOfBoundsException when the maximum number of tensors in the list
+ */
+ public void addTensorData(@NonNull byte[] data) {
+ if (data == null) {
+ throw new IllegalArgumentException("Given data is null");
+ }
+
+ ByteBuffer buffer = allocateByteBuffer(data.length);
+ buffer.put(data);
+
+ addTensorData(buffer);
+ }
+
+ /**
+ * Adds a new tensor data.
+ *
* @param data The tensor data to be added
*
+ * @throws IllegalArgumentException if given data is invalid
* @throws IndexOutOfBoundsException when the maximum number of tensors in the list
*/
public void addTensorData(@NonNull ByteBuffer data) {
+ checkByteBuffer(data);
+
int index = getTensorsCount();
if (index >= NNStreamer.TENSOR_SIZE_LIMIT) {
throw new IndexOutOfBoundsException("Max size of the tensors is " + NNStreamer.TENSOR_SIZE_LIMIT);
}
- mDataList.add(convertBuffer(data));
+ mDataList.add(data);
}
/**
* @param data The tensor data
*
* @throws IndexOutOfBoundsException if the given index is invalid
+ * @throws IllegalArgumentException if given data is invalid
*/
public void setTensorData(int index, @NonNull ByteBuffer data) {
checkIndexBounds(index);
- mDataList.set(index, convertBuffer(data));
+ checkByteBuffer(data);
+
+ mDataList.set(index, data);
}
/**
}
/**
- * Internal method to convert the given data to direct buffer.
- *
- * @param data The tensor data
+ * Internal method to check byte buffer.
*
- * @return The converted buffer
- *
- * @throws IllegalArgumentException if given data is null
+ * @throws IllegalArgumentException if given data is invalid
*/
- private ByteBuffer convertBuffer(ByteBuffer data) {
+ private void checkByteBuffer(ByteBuffer data) {
if (data == null) {
throw new IllegalArgumentException("Given data is null");
}
- if (data.isDirect() && data.order() == ByteOrder.nativeOrder()) {
- return data;
+ if (!data.isDirect()) {
+ throw new IllegalArgumentException("Given data is not a direct buffer");
}
- ByteBuffer allocated = ByteBuffer.allocateDirect(data.capacity());
-
- allocated.order(ByteOrder.nativeOrder());
- allocated.put(data);
-
- return allocated;
+ if (data.order() != ByteOrder.nativeOrder()) {
+ /* Default byte order of ByteBuffer in java is big-endian, it should be a little-endian. */
+ throw new IllegalArgumentException("Given data has invalid byte order");
+ }
}
@Override
try {
SingleShot single = new SingleShot(model);
+ Log.d(TAG, "Get input tensors info");
+ TensorsInfo inInfo = single.getInputInfo();
+ printTensorsInfo(inInfo);
+
+ Log.d(TAG, "Get output tensors info");
+ TensorsInfo outInfo = single.getOutputInfo();
+ printTensorsInfo(outInfo);
+
/* single-shot invoke */
for (int i = 0; i < 15; i++) {
/* dummy input */
- TensorsData in = new TensorsData();
- in.addTensorData(ByteBuffer.allocateDirect(3 * 224 * 224));
+ TensorsData in = TensorsData.allocate(inInfo);
Log.d(TAG, "Try to invoke data " + (i + 1));
Thread.sleep(50);
}
- Log.d(TAG, "Get input tensors info");
- printTensorsInfo(single.getInputInfo());
-
- Log.d(TAG, "Get output tensors info");
- printTensorsInfo(single.getOutputInfo());
-
single.close();
} catch (Exception e) {
e.printStackTrace();
for (int i = 0; i < 15; i++) {
/* dummy input */
TensorsData in = new TensorsData();
- in.addTensorData(ByteBuffer.allocateDirect(3 * 224 * 224));
+ in.addTensorData(TensorsData.allocateByteBuffer(3 * 224 * 224));
Log.d(TAG, "Push input data " + (i + 1));
for (int i = 0; i < 15; i++) {
/* dummy input */
TensorsData in = new TensorsData();
- in.addTensorData(ByteBuffer.allocateDirect(3 * 100 * 100));
+ in.addTensorData(TensorsData.allocateByteBuffer(3 * 100 * 100));
Log.d(TAG, "Push input data " + (i + 1));
for (int i = 0; i < 15; i++) {
/* dummy input */
TensorsData in = new TensorsData();
- in.addTensorData(ByteBuffer.allocateDirect(3 * 100 * 100));
+ in.addTensorData(TensorsData.allocateByteBuffer(3 * 100 * 100));
Log.d(TAG, "Push input data " + (i + 1));