* @bug No known bugs except for NYI items
*
* This is the per-NN-framework plugin (Intel Movidius NCSDK2) for tensor_filter.
- * TODO: Fill in "GstTensorFilterFramework" for tensor_filter.h/c
- *
*/
+#include <fcntl.h>
#include <glib.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
#include <mvnc2/mvnc.h>
#include <nnstreamer_plugin_api_filter.h>
+#include <sys/types.h>
+#include <sys/stat.h>
void init_filter_mvncsdk2 (void) __attribute__ ((constructor));
void fini_filter_mvncsdk2 (void) __attribute__ ((destructor));
+enum _private_constants
+{
+ NNS_MVNCSDK2_SUPPORT_MAX_NUMS_DEVICES = 8,
+ NNS_MVNCSDK2_SUPPORT_API_MAJOR_VER = 2,
+ NNS_MVNCSDK2_API_VER_ARRAY_SIZE = NC_VERSION_MAX_SIZE,
+ NNS_MVNCSDK2_MAX_NUM_ELEM_IN_FIFO = 2,
+};
+
+static const char NNS_MVNCSDK2_NAME_INPUT_FIFO[] = "INPUT_FIFO";
+static const char NNS_MVNCSDK2_NAME_OUTPUT_FIFO[] = "OUTPUT_FIFO";
+
/**
* @brief internal data of mvncsdk2
*/
typedef struct _mvncsdk2_data
{
- void *private_data;
+ /* Variables of the data types from mvnc.h */
+ struct ncDeviceHandle_t *handle_device; /** handle for Intel Movidius device */
+ struct ncGraphHandle_t *handle_graph; /** handle for graph (model) */
+ struct ncTensorDescriptor_t tensor_desc_input; /** description of input tensor */
+ struct ncTensorDescriptor_t tensor_desc_output; /** description of output tenser */
+ struct ncFifoHandle_t *handle_fifo_input; /** handle for input fifo (buffer) */
+ struct ncFifoHandle_t *handle_fifo_output; /** handle for output fifo (buffer) */
+ /* Normal variables */
+ gint32 idx_device; /** index of device to use (Q. is it necessary?) */
} mvncsdk2_data;
/**
* @brief Free privateData and move on.
+ * @param prop : property of tensor_filter instance
+ * @param private_data : movidius-ncsdk2 plugin's private data
*/
static void
_mvncsdk2_close (const GstTensorFilterProperties * prop, void **private_data)
{
- return;
+ mvncsdk2_data *pdata = *private_data;
+
+ if (pdata != NULL) {
+ ncGraphDestroy (&(pdata->handle_graph));
+ ncFifoDestroy (&(pdata->handle_fifo_output));
+ ncFifoDestroy (&(pdata->handle_fifo_input));
+ ncDeviceDestroy (&(pdata->handle_device));
+
+ g_free (pdata);
+ *private_data = NULL;
+ }
}
/**
* @brief The open callback for GstTensorFilterFramework. Called before anything else
* @param prop : property of tensor_filter instance
- * @param private_data : movidius-ncsdk2 plugin's private data
- * @todo : fill this function
+ * @param private_data : movidius-ncsdk2 plugin's private data
+ * @return 0 if OK. -1 if error.
*/
static int
_mvncsdk2_open (const GstTensorFilterProperties * prop, void **private_data)
{
+ /* Variables of the data types from mvnc.h */
+ struct ncDeviceHandle_t *handle_device = NULL;
+ struct ncGraphHandle_t *handle_graph = NULL;
+ struct ncTensorDescriptor_t tensor_desc_input;
+ struct ncTensorDescriptor_t tensor_desc_output;
+ struct ncFifoHandle_t *handle_fifo_input;
+ struct ncFifoHandle_t *handle_fifo_output;
+ ncStatus_t ret_code;
+ /* Normal variables */
+ GMappedFile *file_model = NULL;
+ mvncsdk2_data *pdata = NULL;
+ gint32 sdk_ver[NNS_MVNCSDK2_API_VER_ARRAY_SIZE];
+ guint32 size_sdk_ver = sizeof (sdk_ver);
+ gint32 idx_dev = -1;
+ guint32 len_model_file;
+ void *buf_model_file;
+ guint32 len;
+ gint32 i;
+
+ /* 0. Check the API version */
+ ret_code = ncGlobalGetOption (NC_RO_API_VERSION, sdk_ver, &size_sdk_ver);
+ if ((ret_code != NC_OK) && (sdk_ver[0] != NNS_MVNCSDK2_SUPPORT_API_MAJOR_VER)) {
+ g_printerr
+ ("The major version number of the MVNCSDK API should be %d, not %d\n",
+ NNS_MVNCSDK2_SUPPORT_API_MAJOR_VER, sdk_ver[0]);
+ return -1;
+ }
+
+ /**
+ * 1. Initialize device handle:
+ * we do not know how many devices are plugged and used. Therefore,
+ * let's try all the possible device indices (currently,
+ * 0 ~ NNS_MVNCSDK2_SUPPORT_MAX_NUMS_DEVICES) here.
+ */
+ for (i = 0; i < NNS_MVNCSDK2_SUPPORT_MAX_NUMS_DEVICES; ++i) {
+ ret_code = ncDeviceCreate (i, &handle_device);
+ if (ret_code == NC_OK) {
+ idx_dev = i;
+ break;
+ } else {
+ GST_WARNING ("Failed to create device handle at index %d: "
+ "%d is returned\n", i, ret_code);
+ }
+ }
+ if ((ret_code != NC_OK) && (i == NNS_MVNCSDK2_SUPPORT_MAX_NUMS_DEVICES)) {
+ g_printerr ("Cannot create device handle: no available device found\n");
+ return -1;
+ }
+
+ /**
+ * 2. Initialize graph (model) handle
+ */
+ ret_code = ncGraphCreate (prop->model_file, &handle_graph);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot create graph handle for \"%s\"\n", prop->model_file);
+ goto err_destroy_device_h;
+ }
+
+ /**
+ * 3. Open device using device handle
+ */
+ ret_code = ncDeviceOpen (handle_device);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot open device at index %d\n", idx_dev);
+ goto err_destroy_graph_h;
+ }
+
+ /**
+ * 4. Send model (graph) to the device
+ */
+ file_model = g_mapped_file_new (prop->model_file, FALSE, NULL);
+ if (file_model == NULL) {
+ g_printerr ("Failed to g_mapped_file_new for the model file, \"%s\"\n",
+ prop->model_file);
+ goto err_destroy_graph_h;
+ }
+
+ /* Warning: conversion unsigned long to unsigned int */
+ len_model_file = g_mapped_file_get_length (file_model);
+ buf_model_file = (void *) g_mapped_file_get_contents (file_model);
+
+ /* Actually, send the model to the device */
+ ret_code = ncGraphAllocate (handle_device, handle_graph, buf_model_file,
+ len_model_file);
+ /** After allocating, we do not need file_model any more */
+ g_mapped_file_unref (file_model);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot send the model file to the device\n");
+ goto err_destroy_graph_h;
+ }
+
+ /**
+ * 5. Get the tensor desciptions for input and output form allocated model
+ */
+ len = sizeof (tensor_desc_input);
+ ret_code =
+ ncGraphGetOption (handle_graph, NC_RO_GRAPH_INPUT_TENSOR_DESCRIPTORS,
+ &tensor_desc_input, &len);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot get the tensor description for input\n");
+ goto err_destroy_graph_h;
+ }
+
+ len = sizeof (tensor_desc_output);
+ ret_code =
+ ncGraphGetOption (handle_graph, NC_RO_GRAPH_OUTPUT_TENSOR_DESCRIPTORS,
+ &tensor_desc_output, &len);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot get the tensor description for output\n");
+ goto err_destroy_graph_h;
+ }
+ /**
+ * 6. Create fifo handles for input and output tensors
+ */
+ ret_code = ncFifoCreate (NNS_MVNCSDK2_NAME_INPUT_FIFO,
+ NC_FIFO_HOST_WO, &handle_fifo_input);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot create FIFO handle for input tensor\n");
+ goto err_destroy_graph_h;
+ }
+
+ ret_code = ncFifoCreate (NNS_MVNCSDK2_NAME_OUTPUT_FIFO,
+ NC_FIFO_HOST_RO, &handle_fifo_output);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot create FIFO handle for output tensor\n");
+ goto err_destroy_graph_h;
+ }
+
+ /**
+ * 7. Allocate fifos for input and output tensors
+ */
+ ret_code = ncFifoAllocate (handle_fifo_input, handle_device,
+ &tensor_desc_input, NNS_MVNCSDK2_MAX_NUM_ELEM_IN_FIFO);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot allocate FIFO in the device for input tensor\n");
+ goto err_destroy_graph_h;
+ }
+
+ ret_code = ncFifoAllocate (handle_fifo_output, handle_device,
+ &tensor_desc_output, NNS_MVNCSDK2_MAX_NUM_ELEM_IN_FIFO);
+ if (ret_code != NC_OK) {
+ g_printerr ("Cannot allocate FIFO in the device for output tensor\n");
+ ncFifoDestroy (&handle_fifo_input);
+ goto err_destroy_graph_h;
+ }
+
+ /**
+ * 8. Create private data and fill it
+ */
+ pdata = g_try_new0 (mvncsdk2_data, 1);
+ if (pdata == NULL) {
+ g_printerr ("Cannot allocate memory for private data structure\n");
+ goto err_destroy_fifo_h;
+ }
+
+ pdata->handle_device = handle_device;
+ pdata->handle_graph = handle_graph;
+ pdata->handle_fifo_input = handle_fifo_input;
+ pdata->handle_fifo_output = handle_fifo_output;
+ pdata->tensor_desc_input = tensor_desc_input;
+ pdata->tensor_desc_output = tensor_desc_output;
+ *private_data = pdata;
+
return 0;
+
+err_destroy_fifo_h:
+ ncFifoDestroy (&handle_fifo_input);
+ ncFifoDestroy (&handle_fifo_output);
+err_destroy_graph_h:
+ ncGraphDestroy (&handle_graph);
+err_destroy_device_h:
+ ncDeviceDestroy (&handle_device);
+
+ g_printerr ("Failed to initialize %s tensor_filter framework", prop->fwname);
+
+ return -1;
}
/**
* @todo : fill this function
*/
static int
-_mvncsdk2_getInputDim (const GstTensorFilterProperties * prop, void **private_data,
- GstTensorsInfo * info)
+_mvncsdk2_getInputDim (const GstTensorFilterProperties * prop,
+ void **private_data, GstTensorsInfo * info)
{
return 0;
}