• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2 * Copyright 2022-2023 Huawei Technologies Co., Ltd
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 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "minddata/dataset/kernels/image/dvpp/utils/AclLiteUtils.h"
17 
18 #include <dirent.h>
19 #include <sys/stat.h>
20 
21 #include <fstream>
22 #include <iostream>
23 #include <map>
24 #include <regex>
25 #include <vector>
26 
27 #include "acl/ops/acl_dvpp.h"
28 #include "transform/symbol/acl_rt_symbol.h"
29 #include "transform/symbol/symbol_utils.h"
30 
31 namespace {
32 const char COMMENT_CHAR = '#';
33 const char EQUALS_CHAR = '=';
34 const char BLANK_SPACE_CHAR = ' ';
35 const char TABLE_CHAR = '\t';
36 
37 const std::string kImagePathSeparator = ",";
38 const int kStatSuccess = 0;
39 const std::string kFileSperator = "/";
40 const std::string kPathSeparator = "/";
41 // output image prefix
42 const std::string kOutputFilePrefix = "out_";
43 
44 const std::string kRegexIpAddr =
45   "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[0-9])\\."
46   "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
47   "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
48   "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)"
49   ":([1-9]|[1-9]\\d|[1-9]\\d{2}|[1-9]\\d{3}|[1-5]\\d{4}|"
50   "6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$";
51 
52 // regex for verify video file name
53 const std::string kRegexVideoFile = "^.+\\.(mp4|h264|h265)$";
54 
55 // regex for verify RTSP rtsp://ip:port/channelname
56 const std::string kRegexRtsp = "^rtsp://.*";
57 }  // namespace
58 
IsDigitStr(const std::string & str)59 bool IsDigitStr(const std::string &str) { return std::all_of(str.begin(), str.end(), isdigit); }
60 
IsPathExist(const std::string & path)61 bool IsPathExist(const std::string &path) {
62   std::ifstream file(path, std::ios::in);
63   if (!file) {
64     return false;
65   }
66   file.close();
67   return true;
68 }
69 
IsVideoFile(const std::string & path)70 bool IsVideoFile(const std::string &path) {
71   std::regex regexVideoFile(kRegexVideoFile.c_str());
72   return regex_match(path, regexVideoFile);
73 }
74 
IsRtspAddr(const std::string & str)75 bool IsRtspAddr(const std::string &str) {
76   std::regex regexRtspAddress(kRegexRtsp.c_str());
77 
78   return regex_match(str, regexRtspAddress);
79 }
80 
IsIpAddrWithPort(const std::string & addrStr)81 bool IsIpAddrWithPort(const std::string &addrStr) {
82   std::regex regexIpAddr(kRegexIpAddr.c_str());
83 
84   return regex_match(addrStr, regexIpAddr);
85 }
86 
ParseIpAddr(std::string & ip,std::string & port,const std::string & addr)87 void ParseIpAddr(std::string &ip, std::string &port, const std::string &addr) {
88   std::string::size_type pos = addr.find(':');
89 
90   (void)ip.assign(addr.substr(0, pos));
91   (void)port.assign(addr.substr(pos + 1));
92 }
93 
IsDirectory(const std::string & path)94 bool IsDirectory(const std::string &path) {
95   // get path stat
96   struct stat buf {};
97   if (stat(path.c_str(), &buf) != kStatSuccess) {
98     return false;
99   }
100 
101   // check
102   return S_ISDIR(buf.st_mode);
103 }
104 
SplitPath(const std::string & path,std::vector<std::string> & pathVec)105 void SplitPath(const std::string &path, std::vector<std::string> &pathVec) {
106   char *imageFile = strtok(const_cast<char *>(path.c_str()), kImagePathSeparator.c_str());
107   while (imageFile) {
108     (void)pathVec.emplace_back(imageFile);
109     imageFile = strtok(nullptr, kImagePathSeparator.c_str());
110   }
111 }
112 
GetPathFiles(const std::string & path,std::vector<std::string> & fileVec)113 void GetPathFiles(const std::string &path, std::vector<std::string> &fileVec) {
114   if (IsDirectory(path)) {
115     DIR *dir = opendir(path.c_str());
116     struct dirent *direntPtr;
117     while ((direntPtr = readdir(dir)) != nullptr) {
118       // skip . and ..
119       if (direntPtr->d_name[0] == '.') {
120         continue;
121       }
122 
123       // file path
124       std::string fullPath = path + kPathSeparator + direntPtr->d_name;
125       // directory need recursion
126       if (IsDirectory(fullPath)) {
127         GetPathFiles(fullPath, fileVec);
128       } else {
129         // put file
130         (void)fileVec.emplace_back(fullPath);
131       }
132     }
133     closedir(dir);
134   } else {
135     (void)fileVec.emplace_back(path);
136   }
137 }
138 
GetAllFiles(const std::string & pathList,std::vector<std::string> & fileVec)139 void GetAllFiles(const std::string &pathList, std::vector<std::string> &fileVec) {
140   // split file path
141   std::vector<std::string> pathVec;
142   SplitPath(pathList, pathVec);
143 
144   for (const std::string &everyPath : pathVec) {
145     // check path exist or not
146     if (!IsPathExist(pathList)) {
147       ACLLITE_LOG_ERROR("Failed to deal path=%s. Reason: not exist or can not access.", everyPath.c_str());
148       continue;
149     }
150     // get files in path and sub-path
151     GetPathFiles(everyPath, fileVec);
152   }
153 }
154 
MallocMemory(uint32_t dataSize,MemoryType memType)155 void *MallocMemory(uint32_t dataSize, MemoryType memType) {
156   void *buffer = nullptr;
157   aclError aclRet = ACL_SUCCESS;
158 
159   switch (memType) {
160     case MemoryType::MEMORY_NORMAL:
161       buffer = new uint8_t[dataSize];
162       break;
163     case MemoryType::MEMORY_HOST:
164       aclRet = CALL_ASCEND_API(aclrtMallocHost, &buffer, dataSize);
165       break;
166     case MemoryType::MEMORY_DEVICE:
167       aclRet = CALL_ASCEND_API(aclrtMalloc, &buffer, dataSize, ACL_MEM_MALLOC_HUGE_FIRST);
168       break;
169     case MemoryType::MEMORY_DVPP:
170       aclRet = acldvppMalloc(&buffer, dataSize);
171       break;
172     default:
173       ACLLITE_LOG_ERROR("Invalid memory type %d", memType);
174       aclRet = ACL_ERROR_INVALID_PARAM;
175       break;
176   }
177 
178   if ((aclRet != ACL_SUCCESS) || (buffer == nullptr)) {
179     ACLLITE_LOG_ERROR("Malloc memory failed, type: %d, errorno:%d", memType, aclRet);
180     return nullptr;
181   }
182 
183   return buffer;
184 }
185 
FreeMemory(void * mem,MemoryType memType)186 void FreeMemory(void *mem, MemoryType memType) {
187   if (mem == nullptr) {
188     ACLLITE_LOG_ERROR("Invalid mem");
189     return;
190   }
191   aclError ret = ACL_SUCCESS;
192   switch (memType) {
193     case MemoryType::MEMORY_NORMAL:
194       delete[](reinterpret_cast<uint8_t *>(mem));
195       break;
196     case MemoryType::MEMORY_HOST:
197       ret = CALL_ASCEND_API(aclrtFreeHost, mem);
198       if (ret != ACL_SUCCESS) {
199         ACLLITE_LOG_ERROR("aclrtFreeHost failed, errorno: %d", ret);
200       }
201       break;
202     case MemoryType::MEMORY_DEVICE:
203       ret = CALL_ASCEND_API(aclrtFree, mem);
204       if (ret != ACL_SUCCESS) {
205         ACLLITE_LOG_ERROR("aclrtFree failed, errorno: %d", ret);
206       }
207       break;
208     case MemoryType::MEMORY_DVPP:
209       ret = acldvppFree(mem);
210       if (ret != ACL_SUCCESS) {
211         ACLLITE_LOG_ERROR("acldvppFree failed, errorno: %d", ret);
212       }
213       break;
214     default:
215       ACLLITE_LOG_ERROR("Invalid memory type %d", memType);
216       break;
217   }
218 }
219 
GetCopyPolicy(aclrtRunMode srcDev,CopyDirection direct,MemoryType memType)220 aclrtMemcpyKind GetCopyPolicy(aclrtRunMode srcDev, CopyDirection direct, MemoryType memType) {
221   aclrtMemcpyKind policy = ACL_MEMCPY_HOST_TO_HOST;
222 
223   if (direct == CopyDirection::TO_DEVICE) {
224     if (srcDev == ACL_HOST) {
225       policy = ACL_MEMCPY_HOST_TO_DEVICE;
226     } else {
227       policy = ACL_MEMCPY_DEVICE_TO_DEVICE;
228     }
229   } else {  // TO_HOST
230     if (srcDev == ACL_DEVICE) {
231       policy = ACL_MEMCPY_DEVICE_TO_HOST;
232     }
233   }
234 
235   return policy;
236 }
237 
CopyDataToDevice(const void * data,uint32_t size,aclrtRunMode curRunMode,MemoryType memType)238 void *CopyDataToDevice(const void *data, uint32_t size, aclrtRunMode curRunMode, MemoryType memType) {
239   if ((data == nullptr) || (size == 0) || ((curRunMode != ACL_HOST) && (curRunMode != ACL_DEVICE)) ||
240       (memType >= MemoryType::MEMORY_INVALID_TYPE) || (memType == MemoryType::MEMORY_HOST)) {
241     ACLLITE_LOG_ERROR(
242       "Copy data args invalid, data %p, "
243       "size %d, src dev %d, memory type %d",
244       data, size, curRunMode, memType);
245     return nullptr;
246   }
247 
248   aclrtMemcpyKind policy = GetCopyPolicy(curRunMode, CopyDirection::TO_DEVICE, memType);
249 
250   return CopyData(data, size, policy, memType);
251 }
252 
CopyDataToDeviceEx(void * dest,uint32_t destSize,const void * src,uint32_t srcSize,aclrtRunMode runMode)253 AclLiteError CopyDataToDeviceEx(void *dest, uint32_t destSize, const void *src, uint32_t srcSize,
254                                 aclrtRunMode runMode) {
255   aclrtMemcpyKind policy = ACL_MEMCPY_HOST_TO_DEVICE;
256   if (runMode == ACL_DEVICE) {
257     policy = ACL_MEMCPY_DEVICE_TO_DEVICE;
258   }
259 
260   aclError aclRet = CALL_ASCEND_API(aclrtMemcpy, dest, destSize, src, srcSize, policy);
261   if (aclRet != ACL_SUCCESS) {
262     ACLLITE_LOG_ERROR("Copy data to device failed, aclRet is %d", aclRet);
263     return ACLLITE_ERROR;
264   }
265 
266   return ACLLITE_OK;
267 }
268 
CopyDataToHost(const void * data,uint32_t size,aclrtRunMode curRunMode,MemoryType memType)269 void *CopyDataToHost(const void *data, uint32_t size, aclrtRunMode curRunMode, MemoryType memType) {
270   if ((data == nullptr) || (size == 0) || ((curRunMode != ACL_HOST) && (curRunMode != ACL_DEVICE)) ||
271       ((memType != MemoryType::MEMORY_HOST) && (memType != MemoryType::MEMORY_NORMAL))) {
272     ACLLITE_LOG_ERROR(
273       "Copy data args invalid, data %p, "
274       "size %d, src dev %d, memory type %d",
275       data, size, curRunMode, memType);
276     return nullptr;
277   }
278 
279   aclrtMemcpyKind policy = GetCopyPolicy(curRunMode, CopyDirection::TO_HOST, memType);
280 
281   return CopyData(data, size, policy, memType);
282 }
283 
CopyDataToHostEx(void * dest,uint32_t destSize,const void * src,uint32_t srcSize,aclrtRunMode runMode)284 AclLiteError CopyDataToHostEx(void *dest, uint32_t destSize, const void *src, uint32_t srcSize, aclrtRunMode runMode) {
285   aclrtMemcpyKind policy = ACL_MEMCPY_DEVICE_TO_HOST;
286   if (runMode == ACL_DEVICE) {
287     policy = ACL_MEMCPY_DEVICE_TO_DEVICE;
288   }
289 
290   aclError aclRet = CALL_ASCEND_API(aclrtMemcpy, dest, destSize, src, srcSize, policy);
291   if (aclRet != ACL_SUCCESS) {
292     ACLLITE_LOG_ERROR("Copy data to device failed, aclRet is %d", aclRet);
293     return ACLLITE_ERROR;
294   }
295 
296   return ACLLITE_OK;
297 }
298 
CopyData(const void * data,uint32_t size,aclrtMemcpyKind policy,MemoryType memType)299 void *CopyData(const void *data, uint32_t size, aclrtMemcpyKind policy, MemoryType memType) {
300   void *buffer = MallocMemory(size, memType);
301   if (buffer == nullptr) {
302     return nullptr;
303   }
304 
305   aclError aclRet = CALL_ASCEND_API(aclrtMemcpy, buffer, size, data, size, policy);
306   if (aclRet != ACL_SUCCESS) {
307     ACLLITE_LOG_ERROR("Copy data to device failed, aclRet is %d", aclRet);
308     FreeMemory(buffer, memType);
309     return nullptr;
310   }
311 
312   return buffer;
313 }
314 
CopyImageToLocal(ImageData & destImage,ImageData & srcImage,aclrtRunMode curRunMode)315 AclLiteError CopyImageToLocal(ImageData &destImage, ImageData &srcImage, aclrtRunMode curRunMode) {
316   void *data = CopyDataToHost(srcImage.data.get(), srcImage.size, curRunMode, MemoryType::MEMORY_NORMAL);
317   if (data == nullptr) {
318     return ACLLITE_ERROR_COPY_DATA;
319   }
320 
321   destImage.format = srcImage.format;
322   destImage.width = srcImage.width;
323   destImage.height = srcImage.height;
324   destImage.size = srcImage.size;
325   destImage.alignWidth = srcImage.alignWidth;
326   destImage.alignHeight = srcImage.alignHeight;
327   destImage.data = SHARED_PTR_U8_BUF(data);
328 
329   return ACLLITE_OK;
330 }
331 
CopyImageToDevice(ImageData & destImage,ImageData & srcImage,aclrtRunMode curRunMode,MemoryType memType)332 AclLiteError CopyImageToDevice(ImageData &destImage, ImageData &srcImage, aclrtRunMode curRunMode, MemoryType memType) {
333   void *data = CopyDataToDevice(srcImage.data.get(), srcImage.size, curRunMode, memType);
334   if (data == nullptr) {
335     return ACLLITE_ERROR_COPY_DATA;
336   }
337 
338   destImage.format = srcImage.format;
339   destImage.width = srcImage.width;
340   destImage.height = srcImage.height;
341   destImage.size = srcImage.size;
342   destImage.alignWidth = srcImage.alignWidth;
343   destImage.alignHeight = srcImage.alignHeight;
344 
345   if (memType == MemoryType::MEMORY_DEVICE) {
346     destImage.data = SHARED_PTR_DEV_BUF(data);
347   } else {
348     destImage.data = SHARED_PTR_DVPP_BUF(data);
349   }
350 
351   return ACLLITE_OK;
352 }
353 
ReadBinFile(const std::string & fileName,void * & data,uint32_t & size)354 AclLiteError ReadBinFile(const std::string &fileName, void *&data, uint32_t &size) {
355   struct stat sBuf {};
356   int fileStatus = stat(fileName.data(), &sBuf);
357   if (fileStatus == -1) {
358     ACLLITE_LOG_ERROR("failed to get file");
359     return ACLLITE_ERROR_ACCESS_FILE;
360   }
361   if (S_ISREG(sBuf.st_mode) == 0) {
362     ACLLITE_LOG_ERROR("%s is not a file, please enter a file", fileName.c_str());
363     return ACLLITE_ERROR_INVALID_FILE;
364   }
365   std::ifstream binFile(fileName, std::ifstream::in | std::ifstream::binary);
366   if (!binFile.is_open()) {
367     ACLLITE_LOG_ERROR("open file %s failed", fileName.c_str());
368     return ACLLITE_ERROR_OPEN_FILE;
369   }
370 
371   (void)binFile.seekg(0, std::ifstream::end);
372   uint32_t binFileBufferLen = binFile.tellg();
373   if (binFileBufferLen == 0) {
374     ACLLITE_LOG_ERROR("binfile is empty, filename is %s", fileName.c_str());
375     binFile.close();
376     return ACLLITE_ERROR_INVALID_FILE;
377   }
378 
379   (void)binFile.seekg(0, std::ifstream::beg);
380 
381   auto *binFileBufferData = new (std::nothrow) uint8_t[binFileBufferLen];
382   if (binFileBufferData == nullptr) {
383     ACLLITE_LOG_ERROR("malloc binFileBufferData failed");
384     binFile.close();
385     return ACLLITE_ERROR_MALLOC;
386   }
387   (void)binFile.read(reinterpret_cast<char *>(binFileBufferData), binFileBufferLen);
388   binFile.close();
389 
390   data = binFileBufferData;
391   size = binFileBufferLen;
392 
393   return ACLLITE_OK;
394 }
395 
ReadJpeg(ImageData & image,const std::string & fileName)396 AclLiteError ReadJpeg(ImageData &image, const std::string &fileName) {
397   uint32_t size = 0;
398   void *buf = nullptr;
399 
400   auto lite_ret = ReadBinFile(fileName, buf, size);
401   if (lite_ret != ACLLITE_OK) {
402     delete[](reinterpret_cast<uint8_t *>(buf));
403     return lite_ret;
404   }
405 
406   int32_t ch = 0;
407   auto ret = acldvppJpegGetImageInfo(buf, size, &(image.width), &(image.height), &ch);
408   if (ret != ACL_SUCCESS) {
409     ACLLITE_LOG_ERROR("acldvppJpegGetImageInfo failed, errorno: %d", ret);
410     delete[](reinterpret_cast<uint8_t *>(buf));
411     return ACLLITE_ERROR;
412   }
413   if (image.width == 0 || image.height == 0) {
414     ACLLITE_LOG_ERROR("unsupported format, only Baseline JPEG");
415     delete[](reinterpret_cast<uint8_t *>(buf));
416     return ACLLITE_ERROR;
417   }
418   image.data.reset(reinterpret_cast<uint8_t *>(buf), [](const uint8_t *p) { delete[](p); });
419   image.size = size;
420 
421   return ACLLITE_OK;
422 }
423 
SaveBinFile(const std::string & filename,const void * data,uint32_t size)424 void SaveBinFile(const std::string &filename, const void *data, uint32_t size) {
425   FILE *outFileFp = fopen(filename.c_str(), "wb+");
426   if (outFileFp == nullptr) {
427     ACLLITE_LOG_ERROR("Save file %s failed for open error", filename.c_str());
428     return;
429   }
430   (void)fwrite(data, 1, size, outFileFp);
431 
432   (void)fflush(outFileFp);
433   (void)fclose(outFileFp);
434 }
435 
IsSpace(char c)436 bool IsSpace(char c) { return (c == BLANK_SPACE_CHAR || c == TABLE_CHAR); }
437 
Trim(std::string & str)438 void Trim(std::string &str) {
439   if (str.empty()) {
440     return;
441   }
442   int32_t i;
443   int32_t start_pos;
444   int32_t end_pos;
445   for (i = 0; i < str.size(); ++i) {
446     if (!IsSpace(str[i])) {
447       break;
448     }
449   }
450   if (i == str.size()) {  // is all blank space
451     str = "";
452     return;
453   }
454 
455   start_pos = i;
456 
457   for (i = str.size() - 1; i >= 0; --i) {
458     if (!IsSpace(str[i])) {
459       break;
460     }
461   }
462   end_pos = i;
463 
464   str = str.substr(start_pos, end_pos - start_pos + 1);
465 }
466 
AnalyseLine(const std::string & line,std::string & key,std::string & value)467 bool AnalyseLine(const std::string &line, std::string &key, std::string &value) {
468   if (line.empty()) {
469     return false;
470   }
471 
472   int start_pos = 0;
473   auto end_pos = line.size() - 1;
474   std::string::size_type pos = line.find(COMMENT_CHAR);
475   if (pos != std::string::npos) {
476     if (pos == 0) {  // the first charactor is #
477       return false;
478     }
479     end_pos = pos - 1;
480   }
481   std::string new_line = line.substr(start_pos, start_pos + 1 - end_pos);  // delete comment
482   pos = new_line.find(EQUALS_CHAR);
483   if (pos == std::string::npos) {  // has no =
484     return false;
485   }
486 
487   key = new_line.substr(0, pos);
488   value = new_line.substr(pos + 1, end_pos + 1 - (pos + 1));
489 
490   Trim(key);
491   if (key.empty()) {
492     return false;
493   }
494   Trim(value);
495   return true;
496 }
497 
ReadConfig(std::map<std::string,std::string> & config,const char * configFile)498 bool ReadConfig(std::map<std::string, std::string> &config, const char *configFile) {
499   config.clear();
500   std::ifstream infile(configFile, std::ifstream::in);
501   if (!infile) {
502     return false;
503   }
504   std::string line;
505   std::string key;
506   std::string value;
507   while (getline(infile, line)) {
508     if (AnalyseLine(line, key, value)) {
509       config[key] = value;
510     }
511   }
512 
513   infile.close();
514   return true;
515 }
516 
PrintConfig(const std::map<std::string,std::string> & config)517 void PrintConfig(const std::map<std::string, std::string> &config) {
518   auto mIter = config.begin();
519   for (; mIter != config.end(); ++mIter) {
520     std::cout << mIter->first << "=" << mIter->second << std::endl;
521   }
522 }
523