#include "../nodes/vp_file_src_node.h" #include "../nodes/infers/vp_trt_vehicle_detector.h" #include "../nodes/infers/vp_trt_vehicle_color_classifier.h" #include "../nodes/track/vp_sort_track_node.h" #include "../nodes/osd/vp_osd_node.h" #include "../nodes/broker/vp_json_console_broker_node.h" #include "../nodes/vp_split_node.h" #include "../nodes/vp_screen_des_node.h" #include "../utils/analysis_board/vp_analysis_board.h" /* * ## dynamic_pipeline_sample ## * 1. insert and remove channels(SRC & DES nodes) to/from existing pipeline. * 2. insert and remove MID nodes to/from existing pipeline. * 3. all nodes destroy and process exit normally after user press enter from console. * 4. no need to stop the pipeline and all operations in multi-threads, it works with hot-plug mode. */ int main() { VP_SET_LOG_LEVEL(vp_utils::vp_log_level::INFO); VP_LOGGER_INIT(); // create nodes auto file_src_0 = std::make_shared("file_src_0", 0, "./vp_data/test_video/vehicle_stop.mp4", 0.4); auto trt_vehicle_detector = std::make_shared("trt_vehicle_detector", "./vp_data/models/trt/vehicle/vehicle_v8.5.trt"); auto osd = std::make_shared("osd", "./vp_data/font/NotoSansCJKsc-Medium.otf"); auto split = std::make_shared("split", true); auto screen_des_0 = std::make_shared("screen_des_0", 0); // construct pipeline the first time trt_vehicle_detector->attach_to({file_src_0}); osd->attach_to({trt_vehicle_detector}); split->attach_to({osd}); screen_des_0->attach_to({split}); // start pipeline file_src_0->start(); // visualize pipeline for debug std::vector> src_nodes = {file_src_0}; vp_utils::vp_analysis_board board(src_nodes); board.display(1, false); // no block /* the original format of pipeline is: file_src_0 -> trt_vehicle_detector -> osd -> split -> screen_des_0 */ // simulation function for dynamically operating on piepline bool exit = false; auto simulate_run = [&]() { while (!exit) { // 1. wait for 5 seconds then insert the 2nd channel(input and output) to pipeline std::this_thread::sleep_for(std::chrono::seconds(5)); auto file_src_1 = std::make_shared("file_src_1", 1, "./vp_data/test_video/vehicle_stop.mp4", 0.4); auto screen_des_1 = std::make_shared("screen_des_1", 1); trt_vehicle_detector->attach_to({file_src_1}); screen_des_1->attach_to({split}); // start 2nd channel file_src_1->start(); // reload board using 2 SRC nodes src_nodes.push_back(file_src_1); board.reload(src_nodes); /* now the format of pipeline is: file_src_0 \ / screen_des_0 -> trt_vehicle_detector -> osd -> split -> file_src_1 / \ screen_des_1 */ // 2. wait for 5 seconds then insert the 3rd channel(input and output) to pipeline std::this_thread::sleep_for(std::chrono::seconds(5)); auto file_src_2 = std::make_shared("file_src_2", 2, "./vp_data/test_video/vehicle_stop.mp4", 0.4); auto screen_des_2 = std::make_shared("screen_des_2", 2); trt_vehicle_detector->attach_to({file_src_2}); screen_des_2->attach_to({split}); // start 3rd channel file_src_2->start(); // reload board using 3 SRC nodes src_nodes.push_back(file_src_2); board.reload(src_nodes); /* now the format of pipeline is: file_src_0 \ / screen_des_0 file_src_1 -> trt_vehicle_detector -> osd -> split -> screen_des_1 file_src_2 / \ screen_des_2 */ // 3. wait for 5 seconds then remove the DES node(output) of 3rd channel from pipeline std::this_thread::sleep_for(std::chrono::seconds(5)); screen_des_2->detach(); // call detach() since there is only 1 previous node for screen_des_2 screen_des_2 = nullptr; // force call destructor immediately // reload board using previous SRC nodes board.reload(); /* now the format of pipeline is: file_src_0 \ / screen_des_0 file_src_1 -> trt_vehicle_detector -> osd -> split -> screen_des_1 file_src_2 / */ // 4. wait for 5 seconds then remove the SRC node(input) of 3rd channel from pipeline std::this_thread::sleep_for(std::chrono::seconds(5)); trt_vehicle_detector->detach_from({"file_src_2"}); // call detach_from(...) since there are many previous nodes for trt_vehicle_detector file_src_2->stop(); // call stop() on SRC node which is not reused later file_src_2 = nullptr; // force call destructor immediately // reload board using 2 SRC nodes src_nodes.pop_back(); board.reload(src_nodes); /* now the format of pipeline is: file_src_0 \ / screen_des_0 -> trt_vehicle_detector -> osd -> split -> file_src_1 / \ screen_des_1 */ // 5. wait for 5 seconds then insert a secondary classifier node, track node and broker node into pipeline std::this_thread::sleep_for(std::chrono::seconds(5)); auto trt_color_cls = std::make_shared("trt_color_cls", "./vp_data/models/trt/vehicle/vehicle_color_v8.5.trt", std::vector{0, 1, 2}); auto track = std::make_shared("track"); auto console_broker = std::make_shared("console_broker"); osd->detach(); // first detach osd node from pipeline osd->attach_to({console_broker}); // then attach osd node to broker node console_broker->attach_to({track}); // attach broker node to track node track->attach_to({trt_color_cls}); // attach track node to classifier node trt_color_cls->attach_to({trt_vehicle_detector}); // attach classifier node into pipeline // reload board using previous SRC nodes board.reload(); /* now the format of pipeline is: file_src_0 \ / screen_des_0 -> trt_vehicle_detector -> trt_color_cls -> track -> console_broker -> osd -> split -> file_src_1 / \ screen_des_1 */ // 6. wait for 10 seconds then remove the 2nd channel (both SRC node and DES node) from pipeline std::this_thread::sleep_for(std::chrono::seconds(10)); screen_des_1->detach(); // call detach() since there is only 1 previous node for screen_des_1 trt_vehicle_detector->detach_from({"file_src_1"}); // call detach_from(...) since there are many previous nodes for trt_vehicle_detector file_src_1->stop(); // call stop() on SRC node which is not reused later screen_des_1 = nullptr; // force call destructor immediately file_src_1 = nullptr; // force call destructor immediately // reload board using 1 SRC nodes src_nodes.pop_back(); board.reload(src_nodes); /* now the format of pipeline is: file_src_0 -> trt_vehicle_detector -> trt_color_cls -> track -> console_broker -> osd -> split -> screen_des_0 */ // 7. wait for 10 seconds then remove classifier node, track node and broker node from pipeline std::this_thread::sleep_for(std::chrono::seconds(10)); osd->detach(); console_broker->detach(); track->detach(); trt_color_cls->detach(); osd->attach_to({trt_vehicle_detector}); // relink osd and trt_vehicle_detector console_broker = nullptr; track = nullptr; trt_color_cls = nullptr; // reload board using previous SRC nodes board.reload(); /* now the format of pipeline is: file_src_0 -> trt_vehicle_detector -> osd -> split -> screen_des_0 */ } }; // start simulation thread std::thread simulator(simulate_run); // enter to exit std::string input; std::getline(std::cin, input); exit = true; simulator.join(); // split pipeline into single nodes before process exit for (auto& n: src_nodes) { n->detach_recursively(); } // pipeline destroyed and process exit normally }