takephoto.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "takephoto.h"
  2. // 模块名称
  3. static const char MODULE_NAME[] = "TakePhoto";
  4. // 保存照片
  5. static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const char *imgFile);
  6. // 单次执行相机拍照, 并保存到文件, 成功返回: 0值, 失败返回:非0值
  7. // "imgType" - 获取图像类型
  8. // "saveImgFilename" - 保存的文件名
  9. // "timeout" - 等待超时时间, 单位:秒: < 0 表示无超时;
  10. // 无论超时怎么设置, 首次尝试拍照一定会执行
  11. // , 但时间不确定; 拍照成功、超时或发生错误
  12. // 时会自动结束任务(相机持续无数据的时间).
  13. // "pImgMark" - 输出本次拍照图像的水印信息, 可以设置NULL
  14. int TakePhoto(EImgType imgType, const char *saveImgFilename, int timeout, SImgMark *pImgMark)
  15. {
  16. int fd; char runDir[MAX_PATH_CHARS] = { 0 }, lockFile[MAX_PATH_CHARS+32] = { 0 };
  17. int ret, waitTimeTick/* 计时单位: 秒 */; SImgMark imgMark = { 0 }; HANDLE hCam = NULL;
  18. MV_FRAME_OUT frame; MV_CC_DEVICE_INFO_LIST devList = { 0 }; MV_CC_DEVICE_INFO *pDevInfo;
  19. unsigned long startTime, now; // 计算"waitTimeTick"时使用
  20. // 1, 占用锁定, 避免同时间拍照
  21. xGetSelfRunningInfo(runDir, NULL);
  22. if(runDir[strlen(runDir)-1] == '/') sprintf(lockFile, "%s%s", runDir, "status/");
  23. else sprintf(lockFile, "%s/%s", runDir, "status/");
  24. if(!sw_dir_exists(lockFile)) sw_dir_create(lockFile);
  25. strcat(lockFile, "takephoto.lock");
  26. fd = open(lockFile, O_CREAT | O_RDWR | __O_CLOEXEC, 0666);
  27. if(-1 == fd) { return -1; }
  28. if(-1 == flock(fd, LOCK_EX | LOCK_NB)) { close(fd); return -2; }
  29. // 2, 查找相机, 获取其设备信息
  30. ret = MV_CC_Initialize();
  31. if(MV_OK != ret)
  32. {
  33. sw_log_error("[%s] 相机SDK初始化失败, errCode=0x%x!!", MODULE_NAME, ret);
  34. goto end_p;
  35. }
  36. ret = MV_CC_EnumDevices(MV_USB_DEVICE, &devList); // 目前只枚举USB连接的相机
  37. if(MV_OK != ret)
  38. {
  39. sw_log_error("[%s] USB口枚举相机失败, errCode=0x%x!!", MODULE_NAME, ret);
  40. goto end_p;
  41. }
  42. if(devList.nDeviceNum != 1)
  43. {
  44. ret = -3;
  45. sw_log_error("[%s] USB口相机数量错误, deviceNum=%u!!", MODULE_NAME, devList.nDeviceNum);
  46. goto end_p;
  47. }
  48. pDevInfo = devList.pDeviceInfo[0];
  49. if(!pDevInfo)
  50. {
  51. ret = -4;
  52. sw_log_error("[%s] unexpected internal error, unable to obtain detailed information about the industrial camera!!", MODULE_NAME);
  53. goto end_p;
  54. }
  55. strcpy(imgMark.camModelName, (const char *)pDevInfo->SpecialInfo.stUsb3VInfo.chModelName);
  56. strcpy(imgMark.camSerialNum, (const char *)pDevInfo->SpecialInfo.stUsb3VInfo.chSerialNumber);
  57. // 3, 打开相机, 设置其触发模式
  58. ret = MV_CC_CreateHandleWithoutLog(&hCam, pDevInfo);
  59. if(MV_OK == ret) ret = MV_CC_OpenDevice(hCam, MV_ACCESS_Exclusive, 0);
  60. if(MV_OK == ret) ret = MV_USB_SetTransferWays(hCam, 1); // 设置传输通道个数(RTU硬件资源有限, 需要降低通道数)
  61. if(MV_OK != ret)
  62. {
  63. sw_log_error("[%s] USB口相机打开失败, errCode=0x%x!!", MODULE_NAME, ret);
  64. goto end_p;
  65. }
  66. ret = MV_CC_SetEnumValue(hCam, "TriggerMode", 1); // 允许触发模式
  67. if(MV_OK == ret) ret = MV_CC_SetEnumValue(hCam, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE); // 设置软件触发
  68. if(MV_OK != ret)
  69. {
  70. sw_log_error("[%s] USB口相机设置失败, errCode=0x%x!!", MODULE_NAME, ret);
  71. goto end_p;
  72. }
  73. // 4, 开始拍照, 等待完成后输出
  74. ret = MV_CC_StartGrabbing(hCam);
  75. if(MV_OK != ret)
  76. {
  77. sw_log_error("[%s] USB口相机取流失败, errCode=0x%x!!", MODULE_NAME, ret);
  78. goto end_p;
  79. }
  80. waitTimeTick = 0; xgettickcount(&startTime);
  81. do
  82. {
  83. ret = MV_CC_SetCommandValue(hCam, "TriggerSoftware"); // 触发一次拍照
  84. if(MV_OK == ret)
  85. {
  86. memset(&frame, 0, sizeof(MV_FRAME_OUT));
  87. ret = MV_CC_GetImageBuffer(hCam, &frame, 1000);
  88. }
  89. else sw_thrd_delay(1000);
  90. if(MV_OK == ret)
  91. {
  92. ret = SavePhoto(hCam, &frame, imgType, saveImgFilename);
  93. MV_CC_FreeImageBuffer(hCam, &frame);
  94. }
  95. if(MV_OK == ret) break; // 拍照成功
  96. else if(MV_E_NODATA == ret)
  97. { // 无拍照数据时
  98. xgettickcount(&now); // 当前时间
  99. waitTimeTick = ((now-startTime)/1000);
  100. }
  101. else
  102. {
  103. sw_log_error("[%s] 相机SDK取图异常, errCode=0x%x!!", MODULE_NAME, ret);
  104. goto end_p;
  105. }
  106. } while(timeout < 0 ? true : (waitTimeTick < timeout));
  107. // 5, 成功拍照, 输出相机的信息
  108. if(MV_OK == ret)
  109. {
  110. MVCC_FLOATVALUE fv = { 0 };
  111. MV_CC_GetFloatValue(hCam, "ExposureTime", &fv);
  112. imgMark.imgExposureTime = fv.fCurValue;
  113. if(pImgMark) memcpy(pImgMark, &imgMark, sizeof(SImgMark));
  114. }
  115. else if(timeout >= 0 && waitTimeTick >= timeout) ret = -5; // 拍照超时
  116. // 6, 任务结束, 释放相关的资源
  117. end_p:
  118. if(hCam)
  119. {
  120. MV_CC_StopGrabbing(hCam);
  121. MV_CC_CloseDevice(hCam);
  122. MV_CC_DestroyHandle(hCam);
  123. }
  124. MV_CC_Finalize();
  125. flock(fd, LOCK_UN);
  126. close(fd);
  127. sw_file_delete(lockFile);
  128. return ret;
  129. }
  130. // 保存照片
  131. static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const char *imgFile)
  132. {
  133. MV_SAVE_IMAGE_PARAM_EX3 saveParams = { 0 }; MVCC_INTVALUE_EX iv;
  134. char *filename1 = (char *)imgFile, *filename2 = NULL; int ret; char ext[5];
  135. if(!hCam || !pFrame || !filename1 || strlen(filename1) <= 0) return -6;
  136. switch(imgType)
  137. {
  138. case IMG_TYPE_BMP: // 保存为.bmp格式
  139. imgType = MV_Image_Bmp;
  140. strcpy(ext, ".bmp");
  141. break;
  142. case IMG_TYPE_JPG: // 保存为.jpg格式
  143. imgType = MV_Image_Jpeg;
  144. strcpy(ext, ".jpg");
  145. break;
  146. default: return -7;
  147. }
  148. ret = MV_CC_GetIntValueEx(hCam, "PayloadSize", &iv);
  149. if(MV_OK != ret) return ret;
  150. saveParams.pData = pFrame->pBufAddr;
  151. saveParams.nDataLen = pFrame->stFrameInfo.nFrameLen;
  152. saveParams.enPixelType = pFrame->stFrameInfo.enPixelType;
  153. saveParams.nHeight = pFrame->stFrameInfo.nHeight;
  154. saveParams.nWidth = pFrame->stFrameInfo.nWidth;
  155. saveParams.enImageType = imgType;
  156. saveParams.nJpgQuality = 90; // JPG编码质量(50-99], 其它格式无效, 影响JPG图像文件大小
  157. saveParams.iMethodValue = 1;
  158. if(imgType == IMG_TYPE_JPG) saveParams.nBufferSize = (unsigned int)(iv.nCurValue * 1);
  159. else saveParams.nBufferSize = (unsigned int)(iv.nCurValue * 4);
  160. saveParams.pImageBuffer = (unsigned char *)sw_heap_malloc(saveParams.nBufferSize);
  161. if(!saveParams.pImageBuffer) return -8;
  162. ret = MV_CC_SaveImageEx3(hCam, &saveParams);
  163. if(MV_OK != ret) goto end_p;
  164. if(!xstrcasestr(filename1, "right", ext))
  165. {
  166. filename2 = (char *)sw_heap_malloc(strlen(filename1) +sizeof(ext));
  167. if(filename2) sprintf(filename2, "%s%s", filename1, ext);
  168. else { ret = -9; goto end_p; }
  169. ret = sw_file_update(filename2, "wb", (const char *)saveParams.pImageBuffer, saveParams.nImageLen);
  170. sw_heap_free(filename2);
  171. }
  172. else
  173. {
  174. ret = sw_file_update(filename1, "wb", (const char *)saveParams.pImageBuffer, saveParams.nImageLen);
  175. }
  176. if(ret == saveParams.nImageLen) ret = MV_OK;
  177. else ret = -10;
  178. end_p:
  179. sw_heap_free(saveParams.pImageBuffer);
  180. return ret;
  181. }
  182. // 获取系统当前USBFS内存大小(MB), 成功返回: >=0, 失败返回: -1值
  183. int GetSysUsbfsMemCurrentSize()
  184. {
  185. const char *usbfsFile = "/sys/module/usbcore/parameters/usbfs_memory_mb";
  186. char buf[MAX_LINE_CHARS]; int val = -1;
  187. FILE *fp = fopen(usbfsFile, "r");
  188. if(fp)
  189. {
  190. if(fgets(buf, sizeof(buf), fp)) sscanf(buf, "%d", &val);
  191. fclose(fp);
  192. }
  193. return val;
  194. }
  195. // 设置系统新的USBFS内存大小(MB), 成功返回: 0值, 失败返回: -1值
  196. int SetSysUsbfsMemSize(int val)
  197. {
  198. const char *usbfsFile = "/sys/module/usbcore/parameters/usbfs_memory_mb";
  199. char buf[MAX_LINE_CHARS]; sprintf(buf, "%d\n", val);
  200. if(val >= 0 && sw_file_update(usbfsFile, "w", buf, strlen(buf)) == strlen(buf)) return 0;
  201. else return -1;
  202. }