Beyond_eval use generic discovery api
authorJuyeon Lee <juyeonne.lee@samsung.com>
Tue, 28 Sep 2021 03:00:51 +0000 (12:00 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Thu, 28 Oct 2021 10:25:13 +0000 (19:25 +0900)
Change-Id: Ief0f84903bc097649b37d502bb48062ffeb687b8

tools/evaluation/tasks/inference_peer/generic/image_classification.cc

index 290d1f311b3daf822ed63ccba1ba72ddabf4d1ef..a17eedfb4963b74be142e39b7785010ab94b661f 100644 (file)
 #include <opencv2/opencv.hpp>
 #include <beyond/beyond.h>
 #include <beyond/plugin/peer_nn_plugin.h>
+#include <beyond/plugin/discovery_dns_sd_plugin.h>
 #include "task_runner.h"
 #include "task_options.h"
 
+#define DEBUG false
+
 static enum beyond_handler_return stdin_handler(beyond_object_h object, int type, void *data)
 {
     if ((type & BEYOND_EVENT_TYPE_ERROR) == BEYOND_EVENT_TYPE_ERROR) {
@@ -54,8 +57,13 @@ namespace evaluation {
 // command line options
 constexpr char RunAsOpt[] = "run";
 constexpr char UseConfigOpt[] = "use_config";
+
+// for edge
+constexpr char EdgeNameOpt[]= "service_name";
 constexpr char EdgeStorageOpt[] = "storage";
 constexpr char EdgePortOpt[] = "port";
+
+// for device
 constexpr char DeviceModelFileOpt[] = "model_file";
 constexpr char DeviceImagePathOpt[] = "image_path";
 constexpr char DeviceOutputLabelsOpt[] = "output_labels";
@@ -71,10 +79,11 @@ const int OUTPUT_LABELS_NUM = 1001;
 const int IMG_HEIGHT = 100;
 const int IMG_WIDTH = 100;
 
-enum class Mode {
+enum class TargetMode {
     UNKNOWN,
     DEVICE,
-    EDGE
+    EDGE,
+    EDGELIST,
 };
 
 class ImageClassification : public TaskRunner {
@@ -86,16 +95,23 @@ public:
         , rep_port_(3001)
         , service_port_(3000)
         , use_config_(0)
-        , mode_(Mode::UNKNOWN)
+        , discovered_(0)
+        , target_(TargetMode::UNKNOWN)
         , session_h_(nullptr)
         , evt_h_(nullptr)
         , inference_h_(nullptr)
         , peer_h_(nullptr)
+        , discovery_h_(nullptr)
     {
     }
 
     ~ImageClassification() override
     {
+        if (discovery_h_ != nullptr) {
+            beyond_discovery_deactivate(discovery_h_);
+            beyond_discovery_destroy(discovery_h_);
+        }
+
         if (peer_h_ != nullptr) {
             if (inference_h_ != nullptr) {
                 beyond_inference_remove_peer(inference_h_, peer_h_);
@@ -125,14 +141,21 @@ protected:
 private:
     bool ReadytoRun();
     bool CheckCmdline();
-    bool CheckDevice();
-    bool LoadLabels(std::vector<std::string> *labels);
-    bool CheckEdge();
+    bool CheckDevice_InferencePeer();
+    bool CheckDevice_Discovery();
+    bool LoadLabels();
+    bool CheckEdge_Peer();
+    bool CheckEdge_Discovery();
     bool Run();
     bool RunMobilenet();
     bool RunEdge();
+    bool PrintResult();
+
+    static int DeviceDiscoveryCallback(beyond_discovery_h handle, beyond_event_info *event, void *data);
+    static int EdgeDiscoveryCallback(beyond_discovery_h handle, beyond_event_info *event, void *data);
 
-    std::string target_mode_;
+    std::string run_as_;
+    std::string service_name_;
     std::string storage_;
     std::string model_file_path_;
     std::string input_image_path_;
@@ -143,22 +166,25 @@ private:
     unsigned short rep_port_;
     unsigned short service_port_;
     int use_config_;
+    int discovered_;
 
-    Mode mode_;
+    TargetMode target_;
+    std::vector<std::string> image_labels_;
 
     beyond_session_h session_h_;
     beyond_event_handler_h evt_h_;
     beyond_inference_h inference_h_;
     beyond_peer_h peer_h_;
+    beyond_discovery_h discovery_h_;
 };
 
 std::vector<Option> ImageClassification::GetOptions()
 {
     std::vector<Option> opt_list = {
-        Option::CreateOption(RunAsOpt, &target_mode_,
-                             "Target to run as ('device' or 'edge')"),
+        Option::CreateOption(RunAsOpt, &run_as_,
+                             "Target to run as ('device', 'edge' or 'edgelist')"),
         Option::CreateOption(UseConfigOpt, &use_config_,
-                             "Peer configuration On:1, Off:0 (default: 0)"),
+                             "Peer configuration On:1, Off:0 (default: 0)\n"),
         Option::CreateOption(DeviceModelFileOpt, &model_file_path_,
                              "Path to tflite model file"),
         Option::CreateOption(DeviceImagePathOpt, &input_image_path_,
@@ -171,6 +197,8 @@ std::vector<Option> ImageClassification::GetOptions()
                              "Request Port (default: 3000)"),
         Option::CreateOption(DeviceRepPortOpt, &rep_port_,
                              "Response Port (default: 3001)\n"),
+        Option::CreateOption(EdgeNameOpt, &service_name_,
+                             "Service name to be registered"),
         Option::CreateOption(EdgeStorageOpt, &storage_,
                              "Path to storage for edge service"),
         Option::CreateOption(EdgePortOpt, &service_port_,
@@ -195,14 +223,17 @@ bool ImageClassification::ReadytoRun()
     bool result = CheckCmdline();
 
     if (result == true) {
-        switch (mode_) {
-        case Mode::DEVICE:
-            result = CheckDevice();
+        switch (target_) {
+        case TargetMode::DEVICE:
+            result = CheckDevice_InferencePeer();
             break;
-        case Mode::EDGE:
-            result = CheckEdge();
+        case TargetMode::EDGE:
+            result = (CheckEdge_Peer() & CheckEdge_Discovery());
             break;
-        case Mode::UNKNOWN:
+        case TargetMode::EDGELIST:
+            result = CheckDevice_Discovery();
+            break;
+        case TargetMode::UNKNOWN:
         default:
             result = false;
             break;
@@ -218,35 +249,45 @@ bool ImageClassification::CheckCmdline()
 {
     bool result = true;
 
-    if (target_mode_.compare("device") == 0) {
-        mode_ = Mode::DEVICE;
-    } else if (target_mode_.compare("edge") == 0) {
-        mode_ = Mode::EDGE;
+    if (run_as_.compare("device") == 0) {
+        target_ = TargetMode::DEVICE;
+    } else if (run_as_.compare("edge") == 0) {
+        target_ = TargetMode::EDGE;
+    } else if (run_as_.compare("edgelist") == 0) {
+        target_ = TargetMode::EDGELIST;
     } else {
         printf("Target is incorrect\n");
         result = false;
     }
 
-    if (mode_ == Mode::DEVICE) {
+    if (target_ == TargetMode::DEVICE) {
         std::ifstream model_check(model_file_path_);
         if (model_check.good() == false) {
             printf("Incorrect Model file\n");
             result = false;
         }
+        model_check.close();
+
         std::ifstream input_check(input_image_path_);
         if (input_check.good() == false) {
             printf("Incorrect Input Image file\n");
             result = false;
         }
+        input_check.close();
+
         std::ifstream output_check(output_label_path_);
         if (output_check.good() == false) {
             printf("Incorrect Output Label file\n");
             result = false;
         }
+        output_check.close();
 
+        if (LoadLabels() == false) {
+            printf("Failed to load labels\n");
+        }
         if (result == true) {
             printf("------------------------------\n");
-            printf("Target : %s \n", target_mode_.c_str());
+            printf("Target : %s \n", run_as_.c_str());
             printf("Model File : %s \n", model_file_path_.c_str());
             printf("Input Image File : %s \n", input_image_path_.c_str());
             printf("Output Label File : %s \n", output_label_path_.c_str());
@@ -256,7 +297,7 @@ bool ImageClassification::CheckCmdline()
             printf("Peer name : %s (configuration: %d) \n", peer_name_.c_str(), use_config_);
             printf("------------------------------\n");
         }
-    } else if (mode_ == Mode::EDGE) {
+    } else if (target_ == TargetMode::EDGE) {
         std::ifstream storage_check(storage_);
         if (storage_check.good() == false) {
             printf("Incorrect storage path %s\n", storage_.c_str());
@@ -265,7 +306,8 @@ bool ImageClassification::CheckCmdline()
 
         if (result == true) {
             printf("------------------------------\n");
-            printf("Target : %s \n", target_mode_.c_str());
+            printf("Target : %s \n", run_as_.c_str());
+            printf("Service Name : %s \n", service_name_.c_str());
             printf("Storage Path : %s \n", storage_.c_str());
             printf("Service Port : %d \n", service_port_);
             printf("Peer name : %s (configuration: %d) \n", peer_name_.c_str(), use_config_);
@@ -276,10 +318,8 @@ bool ImageClassification::CheckCmdline()
     return result;
 }
 
-bool ImageClassification::CheckDevice()
+bool ImageClassification::CheckDevice_InferencePeer()
 {
-    bool result = true;
-
     session_h_ = beyond_session_create(0, 0);
     if (session_h_ == nullptr) {
         printf("Failed to create session handle\n");
@@ -354,7 +394,9 @@ bool ImageClassification::CheckDevice()
 
     int ret = beyond_peer_set_event_callback(
         peer_h_, [](beyond_peer_h peer, struct beyond_event_info *event, void *data) -> int {
-            printf("Peer event callback for 0x%.8X (%p)\n", event->type, event->data);
+            if (DEBUG == true) {
+                printf("Peer event callback for 0x%.8X (%p)\n", event->type, event->data);
+            }
             return BEYOND_HANDLER_RETURN_RENEW;
         },
         nullptr);
@@ -396,28 +438,54 @@ bool ImageClassification::CheckDevice()
         return false;
     }
 
-    return result;
+    return true;
 }
 
-bool ImageClassification::LoadLabels(std::vector<std::string> *labels)
+bool ImageClassification::CheckDevice_Discovery()
 {
-    if (labels == nullptr) {
+    int ret;
+    const char *s_device_argv = BEYOND_PLUGIN_DISCOVERY_DNS_SD_NAME;
+    beyond_argument discovery_option = {
+        .argc = 1,
+        .argv = (char **)&s_device_argv,
+    };
+
+    discovery_h_ = beyond_discovery_create(session_h_, &discovery_option);
+
+    ret = beyond_discovery_set_event_callback(discovery_h_, DeviceDiscoveryCallback, static_cast<void *>(this));
+    if (ret < 0) {
+        printf("Failed beyond_discovery_set_event_callback : %d\n", ret);
+        return false;
+    }
+
+    ret = beyond_discovery_activate(discovery_h_);
+    if (ret < 0) {
+        printf("Failed beyond_discovery_activate : %d\n", ret);
         return false;
     }
+
+    return true;
+}
+
+bool ImageClassification::LoadLabels()
+{
     std::ifstream stream(output_label_path_.c_str());
     if (!stream) {
         return false;
     }
+
+    image_labels_.clear();
+
     std::string line;
     while (std::getline(stream, line)) {
-        labels->push_back(line);
+        image_labels_.push_back(line);
     }
     return true;
 }
 
-bool ImageClassification::CheckEdge()
+bool ImageClassification::CheckEdge_Peer()
 {
-    bool result = true;
+    int ret;
 
     session_h_ = beyond_session_create(0, 0);
     if (session_h_ == nullptr) {
@@ -453,9 +521,10 @@ bool ImageClassification::CheckEdge()
     if (use_config_ == 1) {
         // NO implementation yet for service config
         struct beyond_config config = { 's', nullptr };
-        if (beyond_peer_configure(peer_h_, &config) < 0) {
-            printf("Failed to config input\n");
-            result = false;
+        ret = beyond_peer_configure(peer_h_, &config);
+        if (ret < 0) {
+            printf("Failed to config input : %d\n", ret);
+            return false;
         }
     }
 
@@ -466,43 +535,89 @@ bool ImageClassification::CheckEdge()
         .free_memory = 0llu,
         .free_storage = 0llu,
     };
-    if (beyond_peer_set_info(peer_h_, &info) < 0) {
-        printf("Failed to set peer info\n");
+    ret = beyond_peer_set_info(peer_h_, &info);
+    if (ret < 0) {
+        printf("Failed to set peer info : %d\n", ret);
         return false;
     }
 
-    int ret = beyond_peer_set_event_callback(
+    ret = beyond_peer_set_event_callback(
         peer_h_, [](beyond_peer_h peer, struct beyond_event_info *event, void *data) -> int {
-            printf("Peer event callback for 0x%.8X (%p)\n", event->type, event->data);
+            if (DEBUG == true) {
+                printf("Peer event callback for 0x%.8X (%p)\n", event->type, event->data);
+            }
             return BEYOND_HANDLER_RETURN_RENEW;
         },
         nullptr);
     if (ret < 0) {
-        printf("peer_set_event_callback : %d", ret);
+        printf("Failed peer_set_event_callback : %d\n", ret);
+        return false;
     }
 
     // create connection & prepare communication channel
     ret = beyond_peer_activate(peer_h_);
     if (ret < 0) {
-        printf("beyond_peer_activate : %d\n", ret);
-        result = false;
+        printf("Failed beyond_peer_activate : %d\n", ret);
+        return false;
     }
 
-    return result;
+    return true;
 }
 
+bool ImageClassification::CheckEdge_Discovery()
+{
+    int ret;
+
+    const char *service = service_name_.c_str();
+    const char *s_edge_argv[] = {
+        BEYOND_PLUGIN_DISCOVERY_DNS_SD_NAME,
+        BEYOND_PLUGIN_DISCOVERY_DNS_SD_ARGUMENT_SERVER,
+        BEYOND_PLUGIN_DISCOVERY_DNS_SD_ARGUMENT_NAME,
+        const_cast<char *>(service)
+    };
+    beyond_argument discovery_option = {
+        .argc = sizeof(s_edge_argv) / sizeof(char *),
+        .argv = const_cast<char **>(s_edge_argv)
+    };
+
+    discovery_h_ = beyond_discovery_create(session_h_, &discovery_option);
+    if (discovery_h_ == nullptr) {
+        printf("Failed beyond_discovery_create\n");
+        return false;
+    }
+
+    // TODO. key,val should be passed by cmdline
+    ret = beyond_discovery_set_item(discovery_h_, "uuid", "1234", 4);
+    if (ret < 0) {
+        printf("Failed beyond_discovery_set_item : %d\n", ret);
+        return false;
+    }
+
+    ret = beyond_discovery_set_event_callback(discovery_h_, EdgeDiscoveryCallback, nullptr);
+    if (ret < 0) {
+        printf("Failed beyond_discovery_set_event_callback : %d\n", ret);
+        return false;
+    }
+
+    ret = beyond_discovery_activate(discovery_h_);
+    if (ret < 0) {
+        printf("Failed beyond_discovery_activate : %d\n", ret);
+        return false;
+    }
+
+    return true;
+}
 bool ImageClassification::Run()
 {
     bool result = true;
 
-    switch (mode_) {
-    case Mode::DEVICE:
-        result = RunMobilenet();
+    switch (target_) {
+    case TargetMode::DEVICE:
         break;
-    case Mode::EDGE:
-        result = RunEdge();
+    case TargetMode::EDGE:
+    case TargetMode::EDGELIST:
         break;
-    case Mode::UNKNOWN:
+    case TargetMode::UNKNOWN:
     default:
         result = false;
         break;
@@ -524,7 +639,7 @@ bool ImageClassification::RunMobilenet()
 
     cv::Mat inputImage = cv::imread(input_image_path_, cv::IMREAD_COLOR);
     if (inputImage.empty()) {
-        printf("Failed to read image");
+        printf("Failed to read image\n");
         return false;
     }
     cv::Mat resizedImage;
@@ -569,50 +684,53 @@ bool ImageClassification::RunMobilenet()
 
     // print label if invoke success
     if (result == true) {
-        beyond_tensor_h out_tensor_h;
-        int count; // dummy: Could not get count in this api beyond_inference_get_output
-        if (beyond_inference_get_output(inference_h_, &out_tensor_h, &count) < 0) {
-            printf("Failed beyond_inference_get_output\n");
-            return false;
-        }
+        result = PrintResult();
+    }
 
-        beyond_tensor *tensors = BEYOND_TENSOR(out_tensor_h);
-        if ((tensors[0].type != BEYOND_TENSOR_TYPE_UINT8) ||
-            (tensors[0].size != OUTPUT_LABELS_NUM)) {
-            printf("incorrect output( type : %d, size : %d)\n", tensors[0].type, tensors[0].size);
-            printf("expected result( type : %d, size : %d)\n", BEYOND_TENSOR_TYPE_UINT8, OUTPUT_LABELS_NUM);
-        }
+    return result;
+}
 
-        uint8_t max_score = 0;
-        uint8_t scores[OUTPUT_LABELS_NUM];
-        int index = -1;
+bool ImageClassification::PrintResult()
+{
+    beyond_tensor_h out_tensor_h;
+    int count; // dummy: Could not get count in this api beyond_inference_get_output
+    if (beyond_inference_get_output(inference_h_, &out_tensor_h, &count) < 0) {
+        printf("Failed beyond_inference_get_output\n");
+        return false;
+    }
 
-        memcpy(&scores, tensors[0].data, tensors[0].size);
+    beyond_tensor *tensors = BEYOND_TENSOR(out_tensor_h);
+    if ((tensors[0].type != BEYOND_TENSOR_TYPE_UINT8) ||
+        (tensors[0].size != OUTPUT_LABELS_NUM)) {
+        printf("incorrect output( type : %d, size : %d)\n", tensors[0].type, tensors[0].size);
+        printf("expected result( type : %d, size : %d)\n", BEYOND_TENSOR_TYPE_UINT8, OUTPUT_LABELS_NUM);
+    }
 
-        for (int i = 0; i < tensors[0].size; i++) {
-            if (scores[i] > 0 && scores[i] > max_score) {
-                index = i;
-                max_score = scores[i];
-            }
-        }
+    uint8_t max_score = 0;
+    uint8_t scores[OUTPUT_LABELS_NUM];
+    int index = -1;
+    int loaded = image_labels_.size();
 
-        if (index == -1) {
-            printf("Failed to get label from output\n");
-        }
+    memcpy(&scores, tensors[0].data, tensors[0].size);
 
-        std::vector<std::string> image_labels;
-        if (LoadLabels(&image_labels) == false) {
-            printf("Failed to load labels\n");
+    for (int i = 0; i < tensors[0].size; i++) {
+        if (scores[i] > 0 && scores[i] > max_score) {
+            index = i;
+            max_score = scores[i];
         }
+    }
 
-        printf("\n%s\n", image_labels[index].c_str());
+    beyond_inference_unref_tensor(out_tensor_h);
 
-        beyond_inference_unref_tensor(out_tensor_h);
+    if ((index == -1) ||
+        (loaded < index)) {
+        printf("Failed to get label from output\n");
+        return false;
     }
 
-    beyond_session_run(session_h_, 10, -1, -1);
+    printf("\n%s\n", image_labels_[index].c_str());
 
-    return result;
+    return true;
 }
 
 bool ImageClassification::RunEdge()
@@ -627,6 +745,68 @@ bool ImageClassification::RunEdge()
     return result;
 }
 
+int ImageClassification::DeviceDiscoveryCallback(beyond_discovery_h handle, beyond_event_info *event, void *data)
+{
+    if ((event->type & BEYOND_EVENT_TYPE_ERROR) == BEYOND_EVENT_TYPE_ERROR) {
+        return BEYOND_HANDLER_RETURN_CANCEL;
+    }
+
+    if (DEBUG == true) {
+        printf("Discovery event callback for 0x%.8X (%p)\n", event->type, event->data);
+    }
+
+    auto info = static_cast<beyond_peer_info *>(event->data);
+    if (info == nullptr) {
+        return BEYOND_HANDLER_RETURN_CANCEL;
+    }
+
+    if (data == nullptr) {
+        return BEYOND_HANDLER_RETURN_CANCEL;
+    }
+    auto _this = static_cast<ImageClassification *>(data);
+
+    switch (event->type) {
+    case BEYOND_EVENT_TYPE_DISCOVERY_DISCOVERED:
+        _this->discovered_++;
+        printf("[%d] ", _this->discovered_);
+
+        printf("name: %s , ", info->name);
+        printf("host: %s , ", info->host);
+        printf("port: %d , ", info->port[0]);
+        printf("uuid: %s\n", info->uuid);
+        break;
+    case BEYOND_EVENT_TYPE_DISCOVERY_REMOVED:
+        printf("service %s is removed\n", info->name ? info->name : "unknown");
+        break;
+    default:
+        break;
+    }
+
+    return BEYOND_HANDLER_RETURN_RENEW;
+}
+
+int ImageClassification::EdgeDiscoveryCallback(beyond_discovery_h handle, beyond_event_info *event, void *data)
+{
+    if ((event->type & BEYOND_EVENT_TYPE_ERROR) == BEYOND_EVENT_TYPE_ERROR) {
+        return BEYOND_HANDLER_RETURN_CANCEL;
+    }
+
+    if (DEBUG == true) {
+        printf("Discovery event callback for 0x%.8X (%p)\n", event->type, event->data);
+    }
+
+    auto info = static_cast<char *>(event->data);
+    if (info == nullptr) {
+        return BEYOND_HANDLER_RETURN_CANCEL;
+    }
+
+    if (event->type == BEYOND_EVENT_TYPE_DISCOVERY_REGISTERED) {
+        printf("service %s is registered\n", info);
+    }
+
+    return BEYOND_HANDLER_RETURN_RENEW;
+}
+
 std::unique_ptr<TaskRunner> CreateTaskRunner()
 {
     return std::unique_ptr<TaskRunner>(new ImageClassification());