demo.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #include "libuvc/libuvc.h"
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <sys/time.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <gpiod.h>
  8. #include <string>
  9. #include <thread>
  10. #include <iostream>
  11. #include <stack>
  12. #include "gpio_explorer.hpp"
  13. #define GPIO_PIN "XX" // 替换为实际的 GPIO 引脚编号
  14. struct timeval pre_frame_time;
  15. char *save_path;
  16. GPIOExplorer *pExplor;
  17. /* This callback function runs once per frame. Use it to perform any
  18. * quick processing you need, or have it put the frame into your application's
  19. * input queue. If this function takes too long, you'll start losing frames. */
  20. void cb(uvc_frame_t *frame, void *ptr)
  21. {
  22. uvc_frame_t *bgr;
  23. uvc_error_t ret;
  24. enum uvc_frame_format *frame_format = (enum uvc_frame_format *)ptr;
  25. FILE *fp;
  26. static int jpeg_count = 0;
  27. static int jpeg_group = 0;
  28. static const char *H264_FILE = "iOSDevLog.h264";
  29. static const char *MJPEG_FILE = ".jpeg";
  30. char filename[64];
  31. char filepath[264];
  32. /* We'll convert the image from YUV/JPEG to BGR, so allocate space */
  33. bgr = uvc_allocate_frame(frame->width * frame->height * 3);
  34. if (!bgr)
  35. {
  36. printf("unable to allocate bgr frame!\n");
  37. return;
  38. }
  39. // printf("callback! frame_format = %d, width = %d, height = %d, length = %lu, ptr = %p\n",
  40. // frame->frame_format, frame->width, frame->height, frame->data_bytes, ptr);
  41. switch (frame->frame_format)
  42. {
  43. case UVC_FRAME_FORMAT_H264:
  44. /* use `ffplay H264_FILE` to play */
  45. fp = fopen(H264_FILE, "a");
  46. fwrite(frame->data, 1, frame->data_bytes, fp);
  47. fclose(fp);
  48. break;
  49. case UVC_COLOR_FORMAT_MJPEG:
  50. if (!pExplor->getFailingStatus())
  51. break;
  52. pExplor->resetFailingStatus();
  53. struct timeval current_frame_time;
  54. gettimeofday(&current_frame_time, NULL);
  55. if (pre_frame_time.tv_sec != 0 || pre_frame_time.tv_usec != 0)
  56. {
  57. long seconds = current_frame_time.tv_sec; //- pre_frame_time.tv_sec;
  58. long microseconds = current_frame_time.tv_usec; // - pre_frame_time.tv_usec;
  59. double elapsed = seconds + microseconds * 1e-6;
  60. printf("Time between frames: %f seconds \n", elapsed);
  61. }
  62. // update the prev timeval
  63. pre_frame_time = current_frame_time;
  64. if(jpeg_count/12>=1)
  65. jpeg_group++;
  66. jpeg_count = jpeg_count % 12 ;
  67. std::cout << "Current File Index : " << jpeg_count << std::endl;
  68. if (save_path == NULL)
  69. sprintf(filename, "%d-%d%s",jpeg_group, jpeg_count, MJPEG_FILE);
  70. else
  71. sprintf(filename, "%d-%d%s",jpeg_group, jpeg_count++, MJPEG_FILE);
  72. sprintf(filepath, "%s%s", save_path, filename);
  73. fp = fopen(filepath, "w");
  74. fwrite(frame->data, 1, frame->data_bytes, fp);
  75. fclose(fp);
  76. break;
  77. case UVC_COLOR_FORMAT_YUYV:
  78. /* Do the BGR conversion */
  79. ret = uvc_any2bgr(frame, bgr);
  80. if (ret)
  81. {
  82. uvc_perror(ret, "uvc_any2bgr");
  83. uvc_free_frame(bgr);
  84. return;
  85. }
  86. break;
  87. default:
  88. break;
  89. }
  90. if (frame->sequence % 30 == 0)
  91. {
  92. printf(" * got image %u\n", frame->sequence);
  93. }
  94. /* Call a user function:
  95. *
  96. * my_type *my_obj = (*my_type) ptr;
  97. * my_user_function(ptr, bgr);
  98. * my_other_function(ptr, bgr->data, bgr->width, bgr->height);
  99. */
  100. /* Call a C++ method:
  101. * my_type *my_obj = (*my_type) ptr;
  102. * my_obj->my_func(bgr);
  103. */
  104. /* Use opencv.highgui to display the image:
  105. *
  106. * cvImg = cvCreateImageHeader(
  107. * cvSize(bgr->width, bgr->height),
  108. * IPL_DEPTH_8U,
  109. * 3);
  110. *
  111. * cvSetData(cvImg, bgr->data, bgr->width * 3);
  112. *
  113. * cvNamedWindow("Test", CV_WINDOW_AUTOSIZE);
  114. * cvShowImage("Test", cvImg);
  115. * cvWaitKey(10);
  116. *
  117. * cvReleaseImageHeader(&cvImg);
  118. */
  119. uvc_free_frame(bgr);
  120. }
  121. int main(int argc, char **argv)
  122. {
  123. // ...existing code...
  124. if (argv[1] == NULL)
  125. printf("图像将保存到相对路径,与可执行文件同文件");
  126. else
  127. {
  128. save_path = argv[1];
  129. printf("图像将保存到: %s\n", save_path);
  130. }
  131. uvc_context_t *ctx;
  132. uvc_device_t *dev;
  133. uvc_device_handle_t *devh;
  134. uvc_stream_ctrl_t ctrl;
  135. uvc_error_t res;
  136. GPIOExplorer explorer("gpiochip0", 16);
  137. pExplor = &explorer;
  138. // struct timeval current_frame_time;
  139. // gettimeofday(&current_frame_time,NULL);
  140. // while(true)
  141. // {
  142. // if(!explorer.monitorRisingEdge())
  143. // {
  144. // struct timeval current_frame_time;
  145. // gettimeofday(&current_frame_time,NULL);
  146. // if(pre_frame_time.tv_sec != 0 || pre_frame_time.tv_usec != 0){
  147. // long seconds = current_frame_time.tv_sec - pre_frame_time.tv_sec;
  148. // long microseconds = current_frame_time.tv_usec - pre_frame_time.tv_usec;
  149. // double elapsed = seconds + microseconds * 1e-6;
  150. // printf("Time between frames: %f seconds \n",elapsed);
  151. // }
  152. // // update the prev timeval
  153. // pre_frame_time = current_frame_time;
  154. // }
  155. // }
  156. /* Initialize a UVC service context. Libuvc will set up its own libusb
  157. * context. Replace NULL with a libusb_context pointer to run libuvc
  158. * from an existing libusb context. */
  159. res = uvc_init(&ctx, NULL);
  160. if (res < 0)
  161. {
  162. uvc_perror(res, "uvc_init");
  163. return res;
  164. }
  165. puts("UVC initialized");
  166. /* Locates the first attached UVC device, stores in dev */
  167. res = uvc_find_device(
  168. ctx, &dev,
  169. 0, 0, NULL); /* filter devices: vendor_id, product_id, "serial_num" */
  170. if (res < 0)
  171. {
  172. uvc_perror(res, "uvc_find_device"); /* no devices found */
  173. }
  174. else
  175. {
  176. puts("Device found");
  177. /* Try to open the device: requires exclusive access */
  178. res = uvc_open(dev, &devh);
  179. if (res < 0)
  180. {
  181. uvc_perror(res, "uvc_open"); /* unable to open device */
  182. }
  183. else
  184. {
  185. puts("Device opened");
  186. /* Print out a message containing all the information that libuvc
  187. * knows about the device */
  188. uvc_print_diag(devh, stderr);
  189. const uvc_format_desc_t *format_desc = uvc_get_format_descs(devh);
  190. const uvc_frame_desc_t *frame_desc = format_desc->frame_descs;
  191. enum uvc_frame_format frame_format;
  192. int width = 640;
  193. int height = 480;
  194. int fps = 30;
  195. switch (format_desc->bDescriptorSubtype)
  196. {
  197. case UVC_VS_FORMAT_MJPEG:
  198. frame_format = UVC_COLOR_FORMAT_MJPEG;
  199. break;
  200. case UVC_VS_FORMAT_FRAME_BASED:
  201. frame_format = UVC_FRAME_FORMAT_H264;
  202. break;
  203. default:
  204. frame_format = UVC_FRAME_FORMAT_YUYV;
  205. break;
  206. }
  207. if (frame_desc)
  208. {
  209. width = frame_desc->wWidth;
  210. height = frame_desc->wHeight;
  211. fps = 10000000 / frame_desc->dwDefaultFrameInterval;
  212. }
  213. printf("\nFirst format: (%4s) %dx%d %dfps\n", format_desc->fourccFormat, width, height, fps);
  214. /* Try to negotiate first stream profile */
  215. res = uvc_get_stream_ctrl_format_size(
  216. devh, &ctrl, /* result stored in ctrl */
  217. frame_format,
  218. width, height, fps /* width, height, fps */
  219. );
  220. /* Print out the result */
  221. uvc_print_stream_ctrl(&ctrl, stderr);
  222. if (res < 0)
  223. {
  224. uvc_perror(res, "get_mode"); /* device doesn't provide a matching stream */
  225. }
  226. else
  227. {
  228. /* Start the video stream. The library will call user function cb:
  229. * cb(frame, (void *) 12345)*/
  230. res = uvc_start_streaming(devh, &ctrl, cb, (void *)12345, 0);
  231. if (res < 0)
  232. {
  233. uvc_perror(res, "start_streaming"); /* unable to start stream */
  234. }
  235. else
  236. {
  237. puts("Streaming...");
  238. /* enable auto exposure - see uvc_set_ae_mode documentation */
  239. puts("Enabling auto exposure ...");
  240. const uint8_t UVC_AUTO_EXPOSURE_MODE_AUTO = 2;
  241. res = uvc_set_ae_mode(devh, UVC_AUTO_EXPOSURE_MODE_AUTO);
  242. if (res == UVC_SUCCESS)
  243. {
  244. puts(" ... enabled auto exposure");
  245. }
  246. else if (res == UVC_ERROR_PIPE)
  247. {
  248. /* this error indicates that the camera does not support the full AE mode;
  249. * try again, using aperture priority mode (fixed aperture, variable exposure time) */
  250. puts(" ... full AE not supported, trying aperture priority mode");
  251. const uint8_t UVC_AUTO_EXPOSURE_MODE_APERTURE_PRIORITY = 8;
  252. res = uvc_set_ae_mode(devh, UVC_AUTO_EXPOSURE_MODE_APERTURE_PRIORITY);
  253. if (res < 0)
  254. {
  255. uvc_perror(res, " ... uvc_set_ae_mode failed to enable aperture priority mode");
  256. }
  257. else
  258. {
  259. puts(" ... enabled aperture priority auto exposure mode");
  260. }
  261. }
  262. else
  263. {
  264. uvc_perror(res, " ... uvc_set_ae_mode failed to enable auto exposure mode");
  265. }
  266. sleep(48); /* stream for 10 seconds */
  267. /* End the stream. Blocks until last callback is serviced */
  268. uvc_stop_streaming(devh);
  269. puts("Done streaming.");
  270. }
  271. }
  272. /* Release our handle on the device */
  273. uvc_close(devh);
  274. puts("Device closed");
  275. }
  276. /* Release the device descriptor */
  277. uvc_unref_device(dev);
  278. }
  279. /* Close the UVC context. This closes and cleans up any existing device handles,
  280. * and it closes the libusb context if one was not provided. */
  281. uvc_exit(ctx);
  282. puts("UVC exited");
  283. return 0;
  284. }