test: add task manager test case 00/310800/4
authorInki Dae <inki.dae@samsung.com>
Fri, 3 May 2024 02:26:07 +0000 (11:26 +0900)
committerInki Dae <inki.dae@samsung.com>
Thu, 9 May 2024 03:22:29 +0000 (12:22 +0900)
Change-Id: I5a56b83ff46da3e4484d8148ac979127d77e41ed
Signed-off-by: Inki Dae <inki.dae@samsung.com>
packaging/singleo.spec
services/task_manager/include/INode.h
services/task_manager/src/TaskManager.cpp
test/services/CMakeLists.txt
test/services/test_task_manager.cpp [new file with mode: 0644]

index 6d7e9aec0671e9f0f079eb43dbd4542343a85ef6..3e8f96b82e95006ba10823f56eee0ad83abbf7b7 100644 (file)
@@ -89,3 +89,4 @@ rm -rf %{buildroot}
 %files test
 %{_bindir}/test_singleo
 %{_bindir}/test_singleo_on_screen
+%{_bindir}/test_singleo_task_manger
index 11b0a5758d0da54f57c86f5fd7edb805088c4b36..945f144452498489a1280323037e65a302e0a9d5 100644 (file)
@@ -31,8 +31,8 @@ namespace services
 {
 enum class NodeType { NONE, INFERENCE, CB };
 
-using NodeCb = std::function<void(void *user_data, std::vector<BaseResultType *> &results,
-                                                                 std::shared_ptr<BaseDataType> input)>;
+using NodeCb = std::function<void(std::vector<BaseResultType *> &results, std::shared_ptr<BaseDataType> input,
+                                                                 void *user_data)>;
 
 class INode
 {
index 3cb7e4483d15bcc00ac052e404c36765bb776282..4e8f7bd6e0fa9912ea905af8367bd92c69bac7b3 100644 (file)
@@ -76,7 +76,7 @@ void TaskManager::threadCb(shared_ptr<INode> &node)
                // Call the callback function registered in this callback node.
                // In this callback, new data should be set by calling node->setOutput()
                // if new data is made. TODO. consider for multiple inputs later.
-               cb(user_data, results, _inputs[0]);
+               cb(results, _inputs[0], user_data);
        }
 
        // Wake up.
index 8b8fb5d38c626960f8772f18be7af1aee806ff5a..a67614e73819351b4e37df6060a6ae9b07b1fe7c 100644 (file)
@@ -27,3 +27,13 @@ TARGET_LINK_LIBRARIES(test_singleo_on_screen
     gtest gtest_main pthread singleo_service singleo_visualizer opencv_imgcodecs)
 
 INSTALL(TARGETS test_singleo_on_screen DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+SET(TEST_SOURCE_TASK_MANAGER_LIST test_task_manager.cpp)
+
+ADD_EXECUTABLE(test_singleo_task_manger ${TEST_SOURCE_TASK_MANAGER_LIST})
+TARGET_COMPILE_DEFINITIONS(test_singleo_task_manger PRIVATE -DTEST_RES_PATH="${TEST_RES_PATH}")
+TARGET_INCLUDE_DIRECTORIES(test_singleo_task_manger PRIVATE ../../capi/ ../../common/include ../../inference/include ../../services/task_manager/include ../../services/common/include ../../visualizer/include)
+TARGET_LINK_LIBRARIES(test_singleo_task_manger
+    gtest gtest_main pthread singleo_service singleo_visualizer opencv_imgcodecs)
+
+INSTALL(TARGETS test_singleo_task_manger DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/test/services/test_task_manager.cpp b/test/services/test_task_manager.cpp
new file mode 100644 (file)
index 0000000..e3d6320
--- /dev/null
@@ -0,0 +1,182 @@
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gtest/gtest.h"
+#include <iostream>
+#include <memory>
+#include <opencv2/opencv.hpp>
+
+#include "InferenceServiceFactory.h"
+#include "IInferenceServiceInterface.h"
+#include "SingleoCommonTypes.h"
+#include "TaskManager.h"
+#include "InferenceNode.h"
+#include "CallbackNode.h"
+
+#define IMG_FACE TEST_RES_PATH "/usr/share/capi-media-vision/res/inference/images/faceDetection.jpg"
+
+using namespace std;
+using namespace testing;
+using namespace singleo;
+using namespace singleo::inference;
+using namespace singleo::services;
+
+void ExampleNodeCallback(vector<BaseResultType *> &results, shared_ptr<BaseDataType> inputData, void *user_data)
+{
+       shared_ptr<ImageDataType> imageData = dynamic_pointer_cast<ImageDataType>(inputData);
+       size_t buffer_size = imageData->width * imageData->height * imageData->byte_per_pixel;
+       CallbackNode *node = static_cast<CallbackNode *>(user_data);
+       ImageDataType newImage;
+
+       newImage = *imageData;
+       newImage.ptr = new unsigned char[buffer_size];
+       memcpy(newImage.ptr, imageData->ptr, buffer_size);
+       newImage.custom = true;
+
+       cv::Mat cv_image(cv::Size(newImage.width, newImage.height), CV_MAKETYPE(CV_8U, 3), newImage.ptr);
+
+       cout << "Face detection result" << endl;
+       for (auto r : results) {
+               if (r->_type != ResultType::FACE_DETECTION) {
+                       cout << "invalid result type" << endl;
+                       continue;
+               }
+
+               FdResultType *f_r = dynamic_cast<FdResultType *>(r);
+
+               for (auto rect : f_r->_rects)
+                       cout << rect.left << " x " << rect.top << " ~ " << rect.right << " x " << rect.bottom << endl;
+       }
+
+       node->setOutput(make_shared<ImageDataType>(newImage));
+};
+
+// GraphA : input ----> face_detection ----> callback ----> face_landmark_detection ----> output
+TEST(SingloTaskManager, MultipleNodesBasedGraphAShouldWork)
+{
+       cv::Mat cv_image = cv::imread(IMG_FACE, cv::IMREAD_COLOR);
+       cv::cvtColor(cv_image, cv_image, cv::COLOR_BGR2RGB);
+
+       if (cv_image.empty()) {
+               cout << "Fail to read a given image file." << endl;
+               return;
+       }
+
+       ImageDataType image_data;
+
+       image_data.width = cv_image.cols;
+       image_data.height = cv_image.rows;
+       image_data.byte_per_pixel = cv_image.channels();
+       image_data.ptr = cv_image.data;
+
+       auto factory = InferenceServiceFactory::instance().create("MvInferenceServiceFactory");
+
+       auto taskManager = make_unique<TaskManager>();
+       const unsigned int maxIteration = 10;
+
+       for (unsigned int cnt = 0; cnt < maxIteration; ++cnt) {
+               taskManager->addInput(image_data);
+
+               auto face_detection_node = make_shared<InferenceNode>();
+               face_detection_node->setName("face_detection");
+               face_detection_node->setInferenceService(factory->createFaceDetection());
+               taskManager->addNode(face_detection_node);
+
+               auto callback_node = make_shared<CallbackNode>();
+               callback_node->setName("callback");
+               callback_node->setCb(&ExampleNodeCallback, callback_node.get());
+               callback_node->addDependency(face_detection_node);
+               taskManager->addNode(callback_node);
+
+               auto face_landmark_node = make_shared<InferenceNode>();
+               face_landmark_node->setName("face_landmark");
+               face_landmark_node->setInferenceService(factory->createFaceLandmarkDetection());
+               face_landmark_node->addDependency(callback_node);
+               taskManager->addNode(face_landmark_node);
+
+               taskManager->run();
+
+               cout << "Face landmark result" << endl;
+               auto result = dynamic_cast<FldResultType &>(taskManager->output());
+               for (auto &point : result._points)
+                       cout << point.x << " x " << point.y << endl;
+
+               taskManager->clear();
+       }
+}
+
+// GraphB:
+//                -----> face_detection
+//         input |                     |----> callback ----> face_landmark_detection ----> output
+//                -----> face_detection
+TEST(SingloTaskManager, MultipleNodesBasedGraphBShouldWork)
+{
+       cv::Mat cv_image = cv::imread(IMG_FACE, cv::IMREAD_COLOR);
+       cv::cvtColor(cv_image, cv_image, cv::COLOR_BGR2RGB);
+
+       if (cv_image.empty()) {
+               cout << "Fail to read a given image file." << endl;
+               return;
+       }
+
+       ImageDataType image_data;
+
+       image_data.width = cv_image.cols;
+       image_data.height = cv_image.rows;
+       image_data.byte_per_pixel = cv_image.channels();
+       image_data.ptr = cv_image.data;
+
+       auto factory = InferenceServiceFactory::instance().create("MvInferenceServiceFactory");
+
+       auto taskManager = make_unique<TaskManager>();
+       const unsigned int maxIteration = 10;
+
+       for (unsigned int cnt = 0; cnt < maxIteration; ++cnt) {
+               taskManager->addInput(image_data);
+
+               auto face_detection_node_a = make_shared<InferenceNode>();
+               face_detection_node_a->setName("face_detectionA");
+               face_detection_node_a->setInferenceService(factory->createFaceDetection());
+               taskManager->addNode(face_detection_node_a);
+
+               auto face_detection_node_b = make_shared<InferenceNode>();
+               face_detection_node_b->setName("face_detectionB");
+               face_detection_node_b->setInferenceService(factory->createFaceDetection());
+               taskManager->addNode(face_detection_node_b);
+
+               auto callback_node = make_shared<CallbackNode>();
+               callback_node->setName("callback");
+               callback_node->setCb(&ExampleNodeCallback, callback_node.get());
+               callback_node->addDependency(face_detection_node_a);
+               callback_node->addDependency(face_detection_node_b);
+               taskManager->addNode(callback_node);
+
+               auto face_landmark_node = make_shared<InferenceNode>();
+               face_landmark_node->setName("face_landmark");
+               face_landmark_node->setInferenceService(factory->createFaceLandmarkDetection());
+               face_landmark_node->addDependency(callback_node);
+               taskManager->addNode(face_landmark_node);
+
+               taskManager->run();
+
+               cout << "Face landmark result" << endl;
+               auto result = dynamic_cast<FldResultType &>(taskManager->output());
+               for (auto &point : result._points)
+                       cout << point.x << " x " << point.y << endl;
+
+               taskManager->clear();
+       }
+}