test_inference.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /*************************************************************************
  2. * Copyright (C) [2019] by Cambricon, Inc. All rights reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  13. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  15. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. * THE SOFTWARE.
  19. *************************************************************************/
  20. #include <gtest/gtest.h>
  21. #include <limits>
  22. #include <memory>
  23. #include <string>
  24. #include <utility>
  25. #include <vector>
  26. #include "opencv2/highgui/highgui.hpp"
  27. #include "opencv2/imgproc/imgproc.hpp"
  28. #if (CV_MAJOR_VERSION >= 3)
  29. #include "opencv2/imgcodecs/imgcodecs.hpp"
  30. #endif
  31. #include "device/mlu_context.h"
  32. #include "easyinfer/mlu_memory_op.h"
  33. #include "easyinfer/model_loader.h"
  34. #include "cnstream_frame_va.hpp"
  35. #include "inferencer.hpp"
  36. #include "obj_filter.hpp"
  37. #include "postproc.hpp"
  38. #include "preproc.hpp"
  39. #include "test_base.hpp"
  40. namespace cnstream {
  41. static bool gcalled_execute_v1 = false;
  42. static bool gcalled_execute_v2 = false;
  43. static std::atomic<bool> gpostproc_done {false};
  44. static void ResetGlobal() {
  45. gcalled_execute_v1 = false;
  46. gcalled_execute_v2 = false;
  47. gpostproc_done.store(false);
  48. }
  49. std::string gTestPerfDir = "./test_perf_tmp/"; // NOLINT
  50. class FakePostproc : public Postproc, virtual public ReflexObjectEx<Postproc> {
  51. public:
  52. int Execute(const std::vector<float *> &net_outputs, const std::shared_ptr<edk::ModelLoader> &model,
  53. const CNFrameInfoPtr &package) override {
  54. gcalled_execute_v1 = true;
  55. gpostproc_done.store(true);
  56. return 0;
  57. }
  58. int Execute(const std::vector<void*>& net_outputs, const std::shared_ptr<edk::ModelLoader>& model,
  59. const std::vector<CNFrameInfoPtr> &packages) override {
  60. gcalled_execute_v2 = true;
  61. gpostproc_done.store(true);
  62. return 0;
  63. }
  64. DECLARE_REFLEX_OBJECT_EX(FakePostproc, Postproc);
  65. }; // class FakePostproc
  66. IMPLEMENT_REFLEX_OBJECT_EX(FakePostproc, Postproc);
  67. class FakePreproc : public Preproc, virtual public ReflexObjectEx<Preproc> {
  68. public:
  69. int Execute(const std::vector<float *> &net_inputs, const std::shared_ptr<edk::ModelLoader> &model,
  70. const CNFrameInfoPtr &package) override {
  71. return 0;
  72. }
  73. DECLARE_REFLEX_OBJECT_EX(FakePreproc, Preproc);
  74. }; // class FakePreproc
  75. IMPLEMENT_REFLEX_OBJECT_EX(FakePreproc, Preproc);
  76. class FakeObjPostproc : public ObjPostproc {
  77. public:
  78. int Execute(const std::vector<float *> &net_outputs, const std::shared_ptr<edk::ModelLoader> &model,
  79. const CNFrameInfoPtr &package, const CNInferObjectPtr &obj) override {
  80. gcalled_execute_v1 = true;
  81. gpostproc_done.store(true);
  82. return 0;
  83. }
  84. int Execute(const std::vector<void*>& net_outputs, const std::shared_ptr<edk::ModelLoader>& model,
  85. const std::vector<std::pair<CNFrameInfoPtr, std::shared_ptr<CNInferObject>>> &obj_infos) override {
  86. gcalled_execute_v2 = true;
  87. gpostproc_done.store(true);
  88. return 0;
  89. }
  90. DECLARE_REFLEX_OBJECT_EX(FakeObjPostproc, ObjPostproc);
  91. }; // class FakeObjPostproc
  92. IMPLEMENT_REFLEX_OBJECT_EX(FakeObjPostproc, ObjPostproc);
  93. class FakeObjPreproc : public ObjPreproc {
  94. public:
  95. int Execute(const std::vector<float *> &net_inputs, const std::shared_ptr<edk::ModelLoader> &model,
  96. const CNFrameInfoPtr &package, const CNInferObjectPtr &obj) override {
  97. return 0;
  98. }
  99. DECLARE_REFLEX_OBJECT_EX(FakeObjPreproc, ObjPreproc);
  100. }; // class FakeObjPreproc
  101. IMPLEMENT_REFLEX_OBJECT_EX(FakeObjPreproc, ObjPreproc);
  102. class FakeObjFilter : public ObjFilter {
  103. public:
  104. bool Filter(const CNFrameInfoPtr &finfo, const CNInferObjectPtr &obj) override { return true; }
  105. DECLARE_REFLEX_OBJECT_EX(FakeObjFilter, ObjFilter);
  106. }; // class FakeObjFilter
  107. IMPLEMENT_REFLEX_OBJECT_EX(FakeObjFilter, ObjFilter);
  108. static const char *name = "test-infer";
  109. static const char *g_image_path = "../../data/images/3.jpg";
  110. static const char *g_func_name = "subnet0";
  111. static const char *g_postproc_name = "FakePostproc";
  112. static constexpr int g_dev_id = 0;
  113. static constexpr int g_channel_id = 0;
  114. static std::string GetModelPath() {
  115. edk::MluContext ctx;
  116. edk::CoreVersion core_ver = ctx.GetCoreVersion();
  117. std::string model_path = "";
  118. switch (core_ver) {
  119. case edk::CoreVersion::MLU220:
  120. model_path = "../../data/models/resnet18_b4c4_bgra_mlu220.cambricon";
  121. break;
  122. case edk::CoreVersion::MLU270:
  123. default:
  124. model_path = "../../data/models/resnet50_b16c16_bgra_mlu270.cambricon";
  125. break;
  126. }
  127. return model_path;
  128. }
  129. TEST(Inferencer, Construct) {
  130. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  131. EXPECT_STREQ(infer->GetName().c_str(), name);
  132. }
  133. TEST(Inferencer, CheckParamSet) {
  134. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  135. ModuleParamSet param;
  136. // the type of batching_timeout is uint32_t
  137. param["batching_timeout"] = std::to_string(std::numeric_limits<uint64_t>::max());
  138. EXPECT_FALSE(infer->CheckParamSet(param));
  139. param.clear();
  140. param["model_path"] = GetExePath() + GetModelPath();
  141. param["func_name"] = g_func_name;
  142. param["postproc_name"] = g_postproc_name;
  143. EXPECT_TRUE(infer->CheckParamSet(param));
  144. param["batching_timeout"] = "30";
  145. param["threshold"] = "0.3";
  146. param["device_id"] = "fake_value";
  147. EXPECT_FALSE(infer->CheckParamSet(param));
  148. param["device_id"] = "0";
  149. EXPECT_TRUE(infer->CheckParamSet(param));
  150. param["data_order"] = "NCHW";
  151. param["infer_interval"] = "1";
  152. param["threshold"] = "0.3";
  153. EXPECT_TRUE(infer->CheckParamSet(param));
  154. EXPECT_TRUE(infer->Open(param));
  155. }
  156. TEST(Inferencer, Open) {
  157. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  158. ModuleParamSet param;
  159. EXPECT_FALSE(infer->Open(param));
  160. param["model_path"] = "test-infer";
  161. param["func_name"] = g_func_name;
  162. EXPECT_FALSE(infer->Open(param));
  163. param["model_path"] = GetExePath() + GetModelPath();
  164. param["func_name"] = g_func_name;
  165. param["device_id"] = std::to_string(g_dev_id);
  166. param["postproc_name"] = "test-postproc-name";
  167. EXPECT_FALSE(infer->Open(param));
  168. param["postproc_name"] = g_postproc_name;
  169. EXPECT_TRUE(infer->Open(param));
  170. param["use_scaler"] = "true";
  171. EXPECT_TRUE(infer->Open(param));
  172. param["preproc_name"] = "test-preproc-name";
  173. EXPECT_FALSE(infer->Open(param));
  174. infer->Close();
  175. }
  176. TEST(Inferencer, ProcessFrame) {
  177. std::string model_path = GetExePath() + GetModelPath();
  178. std::string image_path = GetExePath() + g_image_path;
  179. // test with MLU preproc (resize & convert)
  180. {
  181. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  182. ModuleParamSet param;
  183. param["model_path"] = model_path;
  184. param["func_name"] = g_func_name;
  185. param["postproc_name"] = g_postproc_name;
  186. param["device_id"] = std::to_string(g_dev_id);
  187. param["batching_timeout"] = "30";
  188. ASSERT_TRUE(infer->Open(param));
  189. const int width = 1280, height = 720;
  190. size_t nbytes = width * height * sizeof(uint8_t) * 3;
  191. size_t boundary = 1 << 16;
  192. nbytes = (nbytes + boundary - 1) & ~(boundary - 1); // align to 64kb
  193. // fake data
  194. void *frame_data = nullptr;
  195. void *planes[CN_MAX_PLANES] = {nullptr, nullptr};
  196. edk::MluMemoryOp mem_op;
  197. frame_data = mem_op.AllocMlu(nbytes);
  198. planes[0] = frame_data; // y plane
  199. planes[1] = reinterpret_cast<void *>(reinterpret_cast<int64_t>(frame_data) + width * height); // uv plane
  200. // test nv12
  201. {
  202. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  203. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  204. frame->frame_id = 1;
  205. data->timestamp = 1000;
  206. frame->width = width;
  207. frame->height = height;
  208. void *ptr_mlu[2] = {planes[0], planes[1]};
  209. frame->stride[0] = frame->stride[1] = width;
  210. frame->ctx.ddr_channel = g_channel_id;
  211. frame->ctx.dev_id = g_dev_id;
  212. frame->ctx.dev_type = DevContext::DevType::MLU;
  213. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV12;
  214. frame->dst_device_id = g_dev_id;
  215. frame->CopyToSyncMem(ptr_mlu, true);
  216. data->collection.Add(kCNDataFrameTag, frame);
  217. int ret = infer->Process(data);
  218. EXPECT_EQ(ret, 1);
  219. // create eos frame for clearing stream idx
  220. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  221. }
  222. ASSERT_NO_THROW(infer->Close());
  223. ASSERT_TRUE(infer->Open(param));
  224. // test nv21
  225. {
  226. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  227. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  228. frame->frame_id = 1;
  229. data->timestamp = 1000;
  230. frame->width = width;
  231. frame->height = height;
  232. void *ptr_mlu[2] = {planes[0], planes[1]};
  233. frame->stride[0] = frame->stride[1] = width;
  234. frame->ctx.ddr_channel = g_channel_id;
  235. frame->ctx.dev_id = g_dev_id;
  236. frame->ctx.dev_type = DevContext::DevType::MLU;
  237. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21;
  238. frame->dst_device_id = g_dev_id;
  239. frame->CopyToSyncMem(ptr_mlu, true);
  240. data->collection.Add(kCNDataFrameTag, frame);
  241. int ret = infer->Process(data);
  242. EXPECT_EQ(ret, 1);
  243. // create eos frame for clearing stream idx
  244. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  245. }
  246. ASSERT_NO_THROW(infer->Close());
  247. param["keep_aspect_ratio"] = "true";
  248. ASSERT_TRUE(infer->Open(param));
  249. // test nv21 with keep_aspect_ratio
  250. {
  251. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  252. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  253. frame->frame_id = 1;
  254. data->timestamp = 1000;
  255. frame->width = width;
  256. frame->height = height;
  257. void *ptr_mlu[2] = {planes[0], planes[1]};
  258. frame->stride[0] = frame->stride[1] = width;
  259. frame->ctx.ddr_channel = g_channel_id;
  260. frame->ctx.dev_id = g_dev_id;
  261. frame->ctx.dev_type = DevContext::DevType::MLU;
  262. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21;
  263. frame->dst_device_id = g_dev_id;
  264. frame->CopyToSyncMem(ptr_mlu, true);
  265. data->collection.Add(kCNDataFrameTag, frame);
  266. int ret = infer->Process(data);
  267. EXPECT_EQ(ret, 1);
  268. // create eos frame for clearing stream idx
  269. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  270. }
  271. ASSERT_NO_THROW(infer->Close());
  272. mem_op.FreeMlu(frame_data);
  273. }
  274. // test with CPU preproc
  275. {
  276. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  277. ModuleParamSet param;
  278. param["model_path"] = model_path;
  279. param["func_name"] = g_func_name;
  280. param["preproc_name"] = "FakePreproc";
  281. param["postproc_name"] = g_postproc_name;
  282. param["device_id"] = std::to_string(g_dev_id);
  283. param["batching_timeout"] = "30";
  284. ASSERT_TRUE(infer->Open(param));
  285. const int width = 1920, height = 1080;
  286. size_t nbytes = width * height * sizeof(uint8_t) * 3 / 2;
  287. uint8_t *frame_data = new uint8_t[nbytes];
  288. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  289. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  290. frame->frame_id = 1;
  291. data->timestamp = 1000;
  292. frame->width = width;
  293. frame->height = height;
  294. void *ptr_cpu[2];
  295. ptr_cpu[0] = frame_data;
  296. ptr_cpu[1] = frame_data + nbytes * 2 / 3;
  297. frame->stride[0] = frame->stride[1] = width;
  298. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21;
  299. frame->ctx.dev_type = DevContext::DevType::CPU;
  300. frame->dst_device_id = g_dev_id;
  301. frame->CopyToSyncMem(ptr_cpu, true);
  302. data->collection.Add(kCNDataFrameTag, frame);
  303. int ret = infer->Process(data);
  304. EXPECT_EQ(ret, 1);
  305. delete[] frame_data;
  306. // create eos frame for clearing stream idx
  307. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  308. ASSERT_NO_THROW(infer->Close());
  309. }
  310. // test mem_on_mlu_for_postproc
  311. {
  312. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  313. ModuleParamSet param;
  314. param["model_path"] = model_path;
  315. param["func_name"] = g_func_name;
  316. param["preproc_name"] = "FakePreproc";
  317. param["postproc_name"] = g_postproc_name;
  318. param["mem_on_mlu_for_postproc"] = "true";
  319. param["device_id"] = std::to_string(g_dev_id);
  320. param["batching_timeout"] = "30";
  321. ASSERT_TRUE(infer->Open(param));
  322. const int width = 1920, height = 1080;
  323. size_t nbytes = width * height * sizeof(uint8_t) * 3 / 2;
  324. uint8_t *frame_data = new uint8_t[nbytes];
  325. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  326. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  327. frame->frame_id = 1;
  328. data->timestamp = 1000;
  329. frame->width = width;
  330. frame->height = height;
  331. void *ptr_cpu[2] = {frame_data, frame_data + nbytes * 2 / 3};
  332. frame->stride[0] = frame->stride[1] = width;
  333. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21;
  334. frame->ctx.dev_type = DevContext::DevType::CPU;
  335. frame->dst_device_id = g_dev_id;
  336. frame->CopyToSyncMem(ptr_cpu, true);
  337. data->collection.Add(kCNDataFrameTag, frame);
  338. ResetGlobal();
  339. int ret = infer->Process(data);
  340. EXPECT_EQ(ret, 1);
  341. while (!gpostproc_done.load()) usleep(20 * 1000);
  342. EXPECT_TRUE(gcalled_execute_v2);
  343. // create eos frame for clearing stream idx
  344. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  345. ASSERT_NO_THROW(infer->Close());
  346. param["mem_on_mlu_for_postproc"] = "false";
  347. ASSERT_TRUE(infer->Open(param));
  348. ResetGlobal();
  349. ret = infer->Process(data);
  350. EXPECT_EQ(ret, 1);
  351. while (!gpostproc_done.load()) usleep(20 * 1000);
  352. EXPECT_TRUE(gcalled_execute_v1);
  353. // create eos frame for clearing stream idx
  354. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  355. ASSERT_NO_THROW(infer->Close());
  356. delete[] frame_data;
  357. }
  358. }
  359. TEST(Inferencer, ProcessObject) {
  360. std::string model_path = GetExePath() + GetModelPath();
  361. std::string image_path = GetExePath() + g_image_path;
  362. auto obj = std::make_shared<CNInferObject>();
  363. obj->id = "1";
  364. obj->score = 0.8;
  365. obj->bbox.x = 0.1;
  366. obj->bbox.y = 0.1;
  367. obj->bbox.w = 0.3;
  368. obj->bbox.h = 0.3;
  369. // test with MLU preproc (resize & convert)
  370. {
  371. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  372. ModuleParamSet param;
  373. param["model_path"] = model_path;
  374. param["func_name"] = g_func_name;
  375. param["postproc_name"] = "FakeObjPostproc";
  376. param["device_id"] = std::to_string(g_dev_id);
  377. param["batching_timeout"] = "30";
  378. param["object_infer"] = "true";
  379. param["obj_filter_name"] = "FakeObjFilter";
  380. ASSERT_TRUE(infer->Open(param));
  381. const int width = 1280, height = 720;
  382. size_t nbytes = width * height * sizeof(uint8_t) * 3;
  383. size_t boundary = 1 << 16;
  384. nbytes = (nbytes + boundary - 1) & ~(boundary - 1); // align to 64kb
  385. // fake data
  386. void *frame_data = nullptr;
  387. void *planes[CN_MAX_PLANES] = {nullptr, nullptr};
  388. edk::MluMemoryOp mem_op;
  389. frame_data = mem_op.AllocMlu(nbytes);
  390. planes[0] = frame_data; // y plane
  391. planes[1] = reinterpret_cast<void *>(reinterpret_cast<int64_t>(frame_data) + width * height); // uv plane
  392. // test nv12
  393. {
  394. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  395. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  396. frame->frame_id = 1;
  397. data->timestamp = 1000;
  398. frame->width = width;
  399. frame->height = height;
  400. void *ptr_mlu[2] = {planes[0], planes[1]};
  401. frame->stride[0] = frame->stride[1] = width;
  402. frame->ctx.ddr_channel = g_channel_id;
  403. frame->ctx.dev_id = g_dev_id;
  404. frame->ctx.dev_type = DevContext::DevType::MLU;
  405. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV12;
  406. frame->dst_device_id = g_dev_id;
  407. frame->CopyToSyncMem(ptr_mlu, true);
  408. std::shared_ptr<CNInferObjs> objs_holder = std::make_shared<CNInferObjs>();
  409. objs_holder->objs_.push_back(obj);
  410. data->collection.Add(kCNDataFrameTag, frame);
  411. data->collection.Add(kCNInferObjsTag, objs_holder);
  412. int ret = infer->Process(data);
  413. EXPECT_EQ(ret, 1);
  414. // create eos frame for clearing stream idx
  415. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  416. }
  417. ASSERT_NO_THROW(infer->Close());
  418. ASSERT_TRUE(infer->Open(param));
  419. // test nv21
  420. {
  421. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  422. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  423. frame->frame_id = 1;
  424. data->timestamp = 1000;
  425. frame->width = width;
  426. frame->height = height;
  427. void *ptr_mlu[2] = {planes[0], planes[1]};
  428. frame->stride[0] = frame->stride[1] = width;
  429. frame->ctx.ddr_channel = g_channel_id;
  430. frame->ctx.dev_id = g_dev_id;
  431. frame->ctx.dev_type = DevContext::DevType::MLU;
  432. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21;
  433. frame->dst_device_id = g_dev_id;
  434. frame->CopyToSyncMem(ptr_mlu, true);
  435. std::shared_ptr<CNInferObjs> objs_holder = std::make_shared<CNInferObjs>();
  436. objs_holder->objs_.push_back(obj);
  437. data->collection.Add(kCNDataFrameTag, frame);
  438. data->collection.Add(kCNInferObjsTag, objs_holder);
  439. int ret = infer->Process(data);
  440. EXPECT_EQ(ret, 1);
  441. // create eos frame for clearing stream idx
  442. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  443. }
  444. ASSERT_NO_THROW(infer->Close());
  445. param["mem_on_mlu_for_postproc"] = "true";
  446. ASSERT_TRUE(infer->Open(param));
  447. ResetGlobal();
  448. // test mem_on_mlu_for_postproc (true)
  449. {
  450. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  451. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  452. frame->frame_id = 1;
  453. data->timestamp = 1000;
  454. frame->width = width;
  455. frame->height = height;
  456. void *ptr_mlu[2] = {planes[0], planes[1]};
  457. frame->stride[0] = frame->stride[1] = width;
  458. frame->ctx.ddr_channel = g_channel_id;
  459. frame->ctx.dev_id = g_dev_id;
  460. frame->ctx.dev_type = DevContext::DevType::MLU;
  461. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21;
  462. frame->dst_device_id = g_dev_id;
  463. frame->CopyToSyncMem(ptr_mlu, true);
  464. std::shared_ptr<CNInferObjs> objs_holder = std::make_shared<CNInferObjs>();
  465. objs_holder->objs_.push_back(obj);
  466. data->collection.Add(kCNDataFrameTag, frame);
  467. data->collection.Add(kCNInferObjsTag, objs_holder);
  468. int ret = infer->Process(data);
  469. EXPECT_EQ(ret, 1);
  470. while (!gpostproc_done.load()) usleep(20 * 1000);
  471. EXPECT_TRUE(gcalled_execute_v2);
  472. // create eos frame for clearing stream idx
  473. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  474. }
  475. ASSERT_NO_THROW(infer->Close());
  476. param["mem_on_mlu_for_postproc"] = "false";
  477. ASSERT_TRUE(infer->Open(param));
  478. ResetGlobal();
  479. // test mem_on_mlu_for_postproc (false)
  480. {
  481. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  482. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  483. frame->frame_id = 1;
  484. data->timestamp = 1000;
  485. frame->width = width;
  486. frame->height = height;
  487. void *ptr_mlu[2] = {planes[0], planes[1]};
  488. frame->stride[0] = frame->stride[1] = width;
  489. frame->ctx.ddr_channel = g_channel_id;
  490. frame->ctx.dev_id = g_dev_id;
  491. frame->ctx.dev_type = DevContext::DevType::MLU;
  492. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21;
  493. frame->dst_device_id = g_dev_id;
  494. frame->CopyToSyncMem(ptr_mlu, true);
  495. std::shared_ptr<CNInferObjs> objs_holder = std::make_shared<CNInferObjs>();
  496. objs_holder->objs_.push_back(obj);
  497. data->collection.Add(kCNDataFrameTag, frame);
  498. data->collection.Add(kCNInferObjsTag, objs_holder);
  499. int ret = infer->Process(data);
  500. EXPECT_EQ(ret, 1);
  501. while (!gpostproc_done.load()) usleep(20 * 1000);
  502. EXPECT_TRUE(gcalled_execute_v1);
  503. // create eos frame for clearing stream idx
  504. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  505. }
  506. ASSERT_NO_THROW(infer->Close());
  507. mem_op.FreeMlu(frame_data);
  508. }
  509. // test with CPU preproc
  510. {
  511. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  512. ModuleParamSet param;
  513. param["model_path"] = model_path;
  514. param["func_name"] = g_func_name;
  515. param["preproc_name"] = "FakeObjPreproc";
  516. param["postproc_name"] = "FakeObjPostproc";
  517. param["device_id"] = std::to_string(g_dev_id);
  518. param["batching_timeout"] = "30";
  519. param["object_infer"] = "true";
  520. param["obj_filter_name"] = "FakeObjFilter";
  521. ASSERT_TRUE(infer->Open(param));
  522. const int width = 1920, height = 1080;
  523. size_t nbytes = width * height * sizeof(uint8_t) * 3 / 2;
  524. uint8_t *frame_data = new uint8_t[nbytes];
  525. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  526. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  527. frame->frame_id = 1;
  528. data->timestamp = 1000;
  529. frame->width = width;
  530. frame->height = height;
  531. void *ptr_cpu[2] = {frame_data, frame_data + nbytes * 2 / 3};
  532. frame->stride[0] = frame->stride[1] = width;
  533. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21;
  534. frame->ctx.dev_type = DevContext::DevType::CPU;
  535. frame->dst_device_id = g_dev_id;
  536. frame->CopyToSyncMem(ptr_cpu, true);
  537. std::shared_ptr<CNInferObjs> objs_holder = std::make_shared<CNInferObjs>();
  538. objs_holder->objs_.push_back(obj);
  539. data->collection.Add(kCNDataFrameTag, frame);
  540. data->collection.Add(kCNInferObjsTag, objs_holder);
  541. int ret = infer->Process(data);
  542. EXPECT_EQ(ret, 1);
  543. delete[] frame_data;
  544. // create eos frame for clearing stream idx
  545. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  546. ASSERT_NO_THROW(infer->Close());
  547. }
  548. }
  549. TEST(Inferencer, ProcessPerf) {
  550. std::string model_path = GetExePath() + GetModelPath();
  551. std::string image_path = GetExePath() + g_image_path;
  552. std::shared_ptr<Module> infer = std::make_shared<Inferencer>(name);
  553. ModuleParamSet param;
  554. param["model_path"] = model_path;
  555. param["func_name"] = g_func_name;
  556. param["postproc_name"] = g_postproc_name;
  557. param["device_id"] = std::to_string(g_dev_id);
  558. param["batching_timeout"] = "30";
  559. ASSERT_TRUE(infer->Open(param));
  560. const int width = 1280, height = 720;
  561. size_t nbytes = width * height * sizeof(uint8_t) * 3;
  562. size_t boundary = 1 << 16;
  563. nbytes = (nbytes + boundary - 1) & ~(boundary - 1); // align to 64kb
  564. edk::MluMemoryOp mem_op;
  565. std::vector<void *> frame_data_vec;
  566. for (int i = 0; i < 32; i++) {
  567. // fake data
  568. void *frame_data = nullptr;
  569. void *planes[CN_MAX_PLANES] = {nullptr, nullptr};
  570. frame_data = mem_op.AllocMlu(nbytes);
  571. planes[0] = frame_data; // y plane
  572. planes[1] = reinterpret_cast<void *>(reinterpret_cast<int64_t>(frame_data) + width * height); // uv plane
  573. frame_data_vec.push_back(frame_data);
  574. auto data = cnstream::CNFrameInfo::Create(std::to_string(g_channel_id));
  575. std::shared_ptr<CNDataFrame> frame(new (std::nothrow) CNDataFrame());
  576. data->collection.Add(kCNDataFrameTag, frame);
  577. frame->frame_id = i;
  578. data->timestamp = 1000;
  579. frame->width = width;
  580. frame->height = height;
  581. void *ptr_mlu[2] = {planes[0], planes[1]};
  582. frame->stride[0] = frame->stride[1] = width;
  583. frame->ctx.ddr_channel = g_channel_id;
  584. frame->ctx.dev_id = g_dev_id;
  585. frame->ctx.dev_type = DevContext::DevType::MLU;
  586. frame->fmt = CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV12;
  587. frame->dst_device_id = g_dev_id;
  588. frame->CopyToSyncMem(ptr_mlu, true);
  589. int ret = infer->Process(data);
  590. std::this_thread::sleep_for(std::chrono::milliseconds(200));
  591. EXPECT_EQ(ret, 1);
  592. }
  593. // create eos frame for clearing stream idx
  594. cnstream::CNFrameInfo::Create(std::to_string(g_channel_id), true);
  595. ASSERT_NO_THROW(infer->Close());
  596. for (auto it : frame_data_vec) {
  597. mem_op.FreeMlu(it);
  598. }
  599. }
  600. TEST(Inferencer, Postproc_set_threshold) {
  601. auto postproc = Postproc::Create(std::string(g_postproc_name));
  602. ASSERT_NE(postproc, nullptr);
  603. postproc->SetThreshold(0.6);
  604. }
  605. } // namespace cnstream