test_camera.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "freertos/FreeRTOS.h"
  4. #include "freertos/task.h"
  5. #include "unity.h"
  6. #include <mbedtls/base64.h>
  7. #include "esp_log.h"
  8. #include "esp_camera.h"
  9. #ifdef CONFIG_IDF_TARGET_ESP32
  10. #define BOARD_WROVER_KIT 1
  11. #elif defined CONFIG_IDF_TARGET_ESP32S2
  12. #define BOARD_CAMERA_MODEL_ESP32S2 1
  13. #elif defined CONFIG_IDF_TARGET_ESP32S3
  14. #define BOARD_CAMERA_MODEL_ESP32_S3_EYE 1
  15. #endif
  16. // WROVER-KIT PIN Map
  17. #if BOARD_WROVER_KIT
  18. #define PWDN_GPIO_NUM -1 //power down is not used
  19. #define RESET_GPIO_NUM -1 //software reset will be performed
  20. #define XCLK_GPIO_NUM 21
  21. #define SIOD_GPIO_NUM 26
  22. #define SIOC_GPIO_NUM 27
  23. #define Y9_GPIO_NUM 35
  24. #define Y8_GPIO_NUM 34
  25. #define Y7_GPIO_NUM 39
  26. #define Y6_GPIO_NUM 36
  27. #define Y5_GPIO_NUM 19
  28. #define Y4_GPIO_NUM 18
  29. #define Y3_GPIO_NUM 5
  30. #define Y2_GPIO_NUM 4
  31. #define VSYNC_GPIO_NUM 25
  32. #define HREF_GPIO_NUM 23
  33. #define PCLK_GPIO_NUM 22
  34. // ESP32Cam (AiThinker) PIN Map
  35. #elif BOARD_ESP32CAM_AITHINKER
  36. #define PWDN_GPIO_NUM 32
  37. #define RESET_GPIO_NUM -1 //software reset will be performed
  38. #define XCLK_GPIO_NUM 0
  39. #define SIOD_GPIO_NUM 26
  40. #define SIOC_GPIO_NUM 27
  41. #define Y9_GPIO_NUM 35
  42. #define Y8_GPIO_NUM 34
  43. #define Y7_GPIO_NUM 39
  44. #define Y6_GPIO_NUM 36
  45. #define Y5_GPIO_NUM 21
  46. #define Y4_GPIO_NUM 19
  47. #define Y3_GPIO_NUM 18
  48. #define Y2_GPIO_NUM 5
  49. #define VSYNC_GPIO_NUM 25
  50. #define HREF_GPIO_NUM 23
  51. #define PCLK_GPIO_NUM 22
  52. #elif BOARD_CAMERA_MODEL_ESP32S2
  53. #define PWDN_GPIO_NUM -1
  54. #define RESET_GPIO_NUM -1
  55. #define VSYNC_GPIO_NUM 21
  56. #define HREF_GPIO_NUM 38
  57. #define PCLK_GPIO_NUM 11
  58. #define XCLK_GPIO_NUM 40
  59. #define SIOD_GPIO_NUM 17
  60. #define SIOC_GPIO_NUM 18
  61. #define Y9_GPIO_NUM 39
  62. #define Y8_GPIO_NUM 41
  63. #define Y7_GPIO_NUM 42
  64. #define Y6_GPIO_NUM 12
  65. #define Y5_GPIO_NUM 3
  66. #define Y4_GPIO_NUM 14
  67. #define Y3_GPIO_NUM 37
  68. #define Y2_GPIO_NUM 13
  69. #elif BOARD_CAMERA_MODEL_ESP32_S3_EYE
  70. #define PWDN_GPIO_NUM 43
  71. #define RESET_GPIO_NUM 44
  72. #define VSYNC_GPIO_NUM 6
  73. #define HREF_GPIO_NUM 7
  74. #define PCLK_GPIO_NUM 13
  75. #define XCLK_GPIO_NUM 15
  76. #define SIOD_GPIO_NUM 4
  77. #define SIOC_GPIO_NUM 5
  78. #define Y9_GPIO_NUM 16
  79. #define Y8_GPIO_NUM 17
  80. #define Y7_GPIO_NUM 18
  81. #define Y6_GPIO_NUM 12
  82. #define Y5_GPIO_NUM 11
  83. #define Y4_GPIO_NUM 10
  84. #define Y3_GPIO_NUM 9
  85. #define Y2_GPIO_NUM 8
  86. #endif
  87. static const char *TAG = "test camera";
  88. typedef void (*decode_func_t)(uint8_t *jpegbuffer, uint32_t size, uint8_t *outbuffer);
  89. static esp_err_t init_camera(uint32_t xclk_freq_hz, pixformat_t pixel_format, framesize_t frame_size, uint8_t fb_count)
  90. {
  91. framesize_t size_bak = frame_size;
  92. if (PIXFORMAT_JPEG == pixel_format && FRAMESIZE_SVGA > frame_size) {
  93. frame_size = FRAMESIZE_HD;
  94. }
  95. camera_config_t camera_config = {
  96. .pin_pwdn = PWDN_GPIO_NUM,
  97. .pin_reset = RESET_GPIO_NUM,
  98. .pin_xclk = XCLK_GPIO_NUM,
  99. .pin_sscb_sda = SIOD_GPIO_NUM,
  100. .pin_sscb_scl = SIOC_GPIO_NUM,
  101. .pin_d7 = Y9_GPIO_NUM,
  102. .pin_d6 = Y8_GPIO_NUM,
  103. .pin_d5 = Y7_GPIO_NUM,
  104. .pin_d4 = Y6_GPIO_NUM,
  105. .pin_d3 = Y5_GPIO_NUM,
  106. .pin_d2 = Y4_GPIO_NUM,
  107. .pin_d1 = Y3_GPIO_NUM,
  108. .pin_d0 = Y2_GPIO_NUM,
  109. .pin_vsync = VSYNC_GPIO_NUM,
  110. .pin_href = HREF_GPIO_NUM,
  111. .pin_pclk = PCLK_GPIO_NUM,
  112. //EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode
  113. .xclk_freq_hz = xclk_freq_hz,
  114. .ledc_timer = LEDC_TIMER_0,
  115. .ledc_channel = LEDC_CHANNEL_0,
  116. .pixel_format = pixel_format, //YUV422,GRAYSCALE,RGB565,JPEG
  117. .frame_size = frame_size, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
  118. .jpeg_quality = 12, //0-63 lower number means higher quality
  119. .fb_count = fb_count, //if more than one, i2s runs in continuous mode. Use only with JPEG
  120. .grab_mode = CAMERA_GRAB_WHEN_EMPTY
  121. };
  122. //initialize the camera
  123. esp_err_t ret = esp_camera_init(&camera_config);
  124. if (ESP_OK == ret && PIXFORMAT_JPEG == pixel_format && FRAMESIZE_SVGA > size_bak) {
  125. sensor_t *s = esp_camera_sensor_get();
  126. s->set_framesize(s, size_bak);
  127. }
  128. return ret;
  129. }
  130. static bool camera_test_fps(uint16_t times, float *fps, uint32_t *size)
  131. {
  132. *fps = 0.0f;
  133. *size = 0;
  134. uint32_t s = 0;
  135. uint32_t num = 0;
  136. uint64_t total_time = esp_timer_get_time();
  137. for (size_t i = 0; i < times; i++) {
  138. camera_fb_t *pic = esp_camera_fb_get();
  139. if (NULL == pic) {
  140. ESP_LOGW(TAG, "fb get failed");
  141. return 0;
  142. } else {
  143. s += pic->len;
  144. num++;
  145. }
  146. esp_camera_fb_return(pic);
  147. }
  148. total_time = esp_timer_get_time() - total_time;
  149. if (num) {
  150. *fps = num * 1000000.0f / total_time ;
  151. *size = s / num;
  152. }
  153. return 1;
  154. }
  155. static const char *get_cam_format_name(pixformat_t pixel_format)
  156. {
  157. switch (pixel_format) {
  158. case PIXFORMAT_JPEG: return "JPEG";
  159. case PIXFORMAT_RGB565: return "RGB565";
  160. case PIXFORMAT_RGB888: return "RGB888";
  161. case PIXFORMAT_YUV422: return "YUV422";
  162. default:
  163. break;
  164. }
  165. return "UNKNOW";
  166. }
  167. static void printf_img_base64(const camera_fb_t *pic)
  168. {
  169. uint8_t *outbuffer = NULL;
  170. size_t outsize = 0;
  171. if (PIXFORMAT_JPEG != pic->format) {
  172. fmt2jpg(pic->buf, pic->width * pic->height * 2, pic->width, pic->height, pic->format, 50, &outbuffer, &outsize);
  173. } else {
  174. outbuffer = pic->buf;
  175. outsize = pic->len;
  176. }
  177. uint8_t *base64_buf = calloc(1, outsize * 4);
  178. if (NULL != base64_buf) {
  179. size_t out_len = 0;
  180. mbedtls_base64_encode(base64_buf, outsize * 4, &out_len, outbuffer, outsize);
  181. printf("%s\n", base64_buf);
  182. free(base64_buf);
  183. if (PIXFORMAT_JPEG != pic->format) {
  184. free(outbuffer);
  185. }
  186. } else {
  187. ESP_LOGE(TAG, "malloc for base64 buffer failed");
  188. }
  189. }
  190. static void camera_performance_test(uint32_t xclk_freq, uint32_t pic_num)
  191. {
  192. esp_err_t ret = ESP_OK;
  193. //detect sensor information
  194. TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2));
  195. sensor_t *s = esp_camera_sensor_get();
  196. camera_sensor_info_t *info = esp_camera_sensor_get_info(&s->id);
  197. TEST_ASSERT_NOT_NULL(info);
  198. TEST_ESP_OK(esp_camera_deinit());
  199. vTaskDelay(500 / portTICK_RATE_MS);
  200. framesize_t max_size = info->max_size;
  201. pixformat_t all_format[] = {PIXFORMAT_JPEG, PIXFORMAT_RGB565, PIXFORMAT_YUV422, };
  202. pixformat_t *format_s = &all_format[0];
  203. pixformat_t *format_e = &all_format[2];
  204. if (false == info->support_jpeg) {
  205. format_s++; // skip jpeg
  206. }
  207. struct fps_result {
  208. float fps[FRAMESIZE_INVALID];
  209. uint32_t size[FRAMESIZE_INVALID];
  210. };
  211. struct fps_result results[3] = {0};
  212. for (; format_s <= format_e; format_s++) {
  213. for (size_t i = 0; i <= max_size; i++) {
  214. ESP_LOGI(TAG, "\n\n===> Testing format:%s resolution: %d x %d <===", get_cam_format_name(*format_s), resolution[i].width, resolution[i].height);
  215. ret = init_camera(xclk_freq, *format_s, i, 2);
  216. vTaskDelay(100 / portTICK_RATE_MS);
  217. if (ESP_OK != ret) {
  218. ESP_LOGW(TAG, "Testing init failed :-(, skip this item");
  219. vTaskDelay(500 / portTICK_RATE_MS);
  220. continue;
  221. }
  222. camera_test_fps(pic_num, &results[format_s - all_format].fps[i], &results[format_s - all_format].size[i]);
  223. TEST_ESP_OK(esp_camera_deinit());
  224. }
  225. }
  226. printf("FPS Result\n");
  227. printf("resolution , JPEG fps, JPEG size, RGB565 fps, RGB565 size, YUV422 fps, YUV422 size \n");
  228. for (size_t i = 0; i <= max_size; i++) {
  229. printf("%4d x %4d , %5.2f, %6d, %5.2f, %7d, %5.2f, %7d \n",
  230. resolution[i].width, resolution[i].height,
  231. results[0].fps[i], results[0].size[i],
  232. results[1].fps[i], results[1].size[i],
  233. results[2].fps[i], results[2].size[i]);
  234. }
  235. printf("----------------------------------------------------------------------------------------\n");
  236. }
  237. TEST_CASE("Camera driver init, deinit test", "[camera]")
  238. {
  239. uint64_t t1 = esp_timer_get_time();
  240. TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2));
  241. uint64_t t2 = esp_timer_get_time();
  242. ESP_LOGI(TAG, "Camera init time %llu ms", (t2 - t1) / 1000);
  243. TEST_ESP_OK(esp_camera_deinit());
  244. }
  245. TEST_CASE("Camera driver take RGB565 picture test", "[camera]")
  246. {
  247. TEST_ESP_OK(init_camera(10000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2));
  248. vTaskDelay(500 / portTICK_RATE_MS);
  249. ESP_LOGI(TAG, "Taking picture...");
  250. camera_fb_t *pic = esp_camera_fb_get();
  251. if (pic) {
  252. ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len);
  253. printf_img_base64(pic);
  254. esp_camera_fb_return(pic);
  255. }
  256. TEST_ESP_OK(esp_camera_deinit());
  257. TEST_ASSERT_NOT_NULL(pic);
  258. }
  259. TEST_CASE("Camera driver take YUV422 picture test", "[camera]")
  260. {
  261. TEST_ESP_OK(init_camera(10000000, PIXFORMAT_YUV422, FRAMESIZE_QVGA, 2));
  262. vTaskDelay(500 / portTICK_RATE_MS);
  263. ESP_LOGI(TAG, "Taking picture...");
  264. camera_fb_t *pic = esp_camera_fb_get();
  265. if (pic) {
  266. ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len);
  267. printf_img_base64(pic);
  268. esp_camera_fb_return(pic);
  269. }
  270. TEST_ESP_OK(esp_camera_deinit());
  271. TEST_ASSERT_NOT_NULL(pic);
  272. }
  273. TEST_CASE("Camera driver take JPEG picture test", "[camera]")
  274. {
  275. TEST_ESP_OK(init_camera(20000000, PIXFORMAT_JPEG, FRAMESIZE_QVGA, 2));
  276. vTaskDelay(500 / portTICK_RATE_MS);
  277. ESP_LOGI(TAG, "Taking picture...");
  278. camera_fb_t *pic = esp_camera_fb_get();
  279. if (pic) {
  280. ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len);
  281. printf_img_base64(pic);
  282. esp_camera_fb_return(pic);
  283. }
  284. TEST_ESP_OK(esp_camera_deinit());
  285. TEST_ASSERT_NOT_NULL(pic);
  286. }
  287. TEST_CASE("Camera driver performance test", "[camera]")
  288. {
  289. camera_performance_test(20 * 1000000, 16);
  290. }
  291. static void print_rgb565_img(uint8_t *img, int width, int height)
  292. {
  293. uint16_t *p = (uint16_t *)img;
  294. const char temp2char[17] = "@MNHQ&#UJ*x7^i;.";
  295. for (size_t j = 0; j < height; j++) {
  296. for (size_t i = 0; i < width; i++) {
  297. uint32_t c = p[j * width + i];
  298. uint8_t r = c >> 11;
  299. uint8_t g = (c >> 6) & 0x1f;
  300. uint8_t b = c & 0x1f;
  301. c = (r + g + b) / 3;
  302. c >>= 1;
  303. printf("%c", temp2char[15 - c]);
  304. }
  305. printf("\n");
  306. }
  307. }
  308. static void print_rgb888_img(uint8_t *img, int width, int height)
  309. {
  310. uint8_t *p = (uint8_t *)img;
  311. const char temp2char[17] = "@MNHQ&#UJ*x7^i;.";
  312. for (size_t j = 0; j < height; j++) {
  313. for (size_t i = 0; i < width; i++) {
  314. uint8_t *c = p + 3 * (j * width + i);
  315. uint8_t r = *c++;
  316. uint8_t g = *c++;
  317. uint8_t b = *c;
  318. uint32_t v = (r + g + b) / 3;
  319. v >>= 4;
  320. printf("%c", temp2char[15 - v]);
  321. }
  322. printf("\n");
  323. }
  324. }
  325. static void tjpgd_decode_rgb565(uint8_t *mjpegbuffer, uint32_t size, uint8_t *outbuffer)
  326. {
  327. jpg2rgb565(mjpegbuffer, size, outbuffer, JPG_SCALE_NONE);
  328. }
  329. static void tjpgd_decode_rgb888(uint8_t *mjpegbuffer, uint32_t size, uint8_t *outbuffer)
  330. {
  331. fmt2rgb888(mjpegbuffer, size, PIXFORMAT_JPEG, outbuffer);
  332. }
  333. typedef enum {
  334. DECODE_RGB565,
  335. DECODE_RGB888,
  336. } decode_type_t;
  337. static const decode_func_t g_decode_func[2][2] = {
  338. {tjpgd_decode_rgb565,},
  339. {tjpgd_decode_rgb888,},
  340. };
  341. static float jpg_decode_test(uint8_t decoder_index, decode_type_t type, const uint8_t *jpg, uint32_t length, uint32_t img_w, uint32_t img_h, uint32_t times)
  342. {
  343. uint8_t *jpg_buf = malloc(length);
  344. if (NULL == jpg_buf) {
  345. ESP_LOGE(TAG, "malloc for jpg buffer failed");
  346. return 0;
  347. }
  348. memcpy(jpg_buf, jpg, length);
  349. uint8_t *rgb_buf = heap_caps_malloc(img_w * img_h * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  350. if (NULL == rgb_buf) {
  351. free(jpg_buf);
  352. ESP_LOGE(TAG, "malloc for rgb buffer failed");
  353. return 0;
  354. }
  355. decode_func_t decode = g_decode_func[type][decoder_index];
  356. decode(jpg_buf, length, rgb_buf);
  357. if (DECODE_RGB565 == type) {
  358. ESP_LOGI(TAG, "jpeg decode to rgb565");
  359. print_rgb565_img(rgb_buf, img_w, img_h);
  360. } else {
  361. ESP_LOGI(TAG, "jpeg decode to rgb888");
  362. print_rgb888_img(rgb_buf, img_w, img_h);
  363. }
  364. uint64_t t_decode[times];
  365. for (size_t i = 0; i < times; i++) {
  366. uint64_t t1 = esp_timer_get_time();
  367. decode(jpg_buf, length, rgb_buf);
  368. t_decode[i] = esp_timer_get_time() - t1;
  369. }
  370. printf("resolution , t \n");
  371. uint64_t t_total = 0;
  372. for (size_t i = 0; i < times; i++) {
  373. t_total += t_decode[i];
  374. float t = t_decode[i] / 1000.0f;
  375. printf("%4d x %4d , %5.2f ms \n", img_w, img_h, t);
  376. }
  377. float fps = times / (t_total / 1000000.0f);
  378. printf("Decode FPS Result\n");
  379. printf("resolution , fps \n");
  380. printf("%4d x %4d , %5.2f \n", img_w, img_h, fps);
  381. free(jpg_buf);
  382. heap_caps_free(rgb_buf);
  383. return fps;
  384. }
  385. static void img_jpeg_decode_test(uint16_t pic_index, uint16_t lib_index)
  386. {
  387. extern const uint8_t img1_start[] asm("_binary_testimg_jpeg_start");
  388. extern const uint8_t img1_end[] asm("_binary_testimg_jpeg_end");
  389. extern const uint8_t img2_start[] asm("_binary_test_inside_jpeg_start");
  390. extern const uint8_t img2_end[] asm("_binary_test_inside_jpeg_end");
  391. extern const uint8_t img3_start[] asm("_binary_test_outside_jpeg_start");
  392. extern const uint8_t img3_end[] asm("_binary_test_outside_jpeg_end");
  393. struct img_t {
  394. const uint8_t *buf;
  395. uint32_t length;
  396. uint16_t w, h;
  397. };
  398. struct img_t imgs[3] = {
  399. {
  400. .buf = img1_start,
  401. .length = img1_end - img1_start,
  402. .w = 227,
  403. .h = 149,
  404. },
  405. {
  406. .buf = img2_start,
  407. .length = img2_end - img2_start,
  408. .w = 320,
  409. .h = 240,
  410. },
  411. {
  412. .buf = img3_start,
  413. .length = img3_end - img3_start,
  414. .w = 480,
  415. .h = 320,
  416. },
  417. };
  418. ESP_LOGI(TAG, "pic_index:%d", pic_index);
  419. ESP_LOGI(TAG, "lib_index:%d", lib_index);
  420. jpg_decode_test(lib_index, DECODE_RGB565, imgs[pic_index].buf, imgs[pic_index].length, imgs[pic_index].w, imgs[pic_index].h, 16);
  421. }
  422. TEST_CASE("Conversions image 227x149 jpeg decode test", "[camera]")
  423. {
  424. img_jpeg_decode_test(0, 0);
  425. }
  426. TEST_CASE("Conversions image 320x240 jpeg decode test", "[camera]")
  427. {
  428. img_jpeg_decode_test(1, 0);
  429. }
  430. TEST_CASE("Conversions image 480x320 jpeg decode test", "[camera]")
  431. {
  432. img_jpeg_decode_test(2, 0);
  433. }