From: Wook Song Date: Thu, 23 May 2019 08:55:22 +0000 (+0900) Subject: [Filter/MvNCSDK] Implement callbacks for open/close of filter framework X-Git-Tag: v0.2.0~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=82ab96d53c6634b42bea5bd6fc0b39ce90cd15b7;p=platform%2Fupstream%2Fnnstreamer.git [Filter/MvNCSDK] Implement callbacks for open/close of filter framework This patch implements callback functions for opening and closing GstTensorFilterFramework for the Intel Movidius Neural Compute Stick sub-plugin of tensor_filter. Signed-off-by: Wook Song --- diff --git a/ext/nnstreamer/tensor_filter/tensor_filter_movidius_ncsdk2.c b/ext/nnstreamer/tensor_filter/tensor_filter_movidius_ncsdk2.c index 625cb4a..82afc2f 100644 --- a/ext/nnstreamer/tensor_filter/tensor_filter_movidius_ncsdk2.c +++ b/ext/nnstreamer/tensor_filter/tensor_filter_movidius_ncsdk2.c @@ -24,44 +24,253 @@ * @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 #include +#include +#include #include #include +#include +#include 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; } /** @@ -88,8 +297,8 @@ _mvncsdk2_invoke (const GstTensorFilterProperties * prop, void **private_data, * @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; }