camera.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. #include "camera.h"
  2. #include <assert.h>
  3. #include <errno.h>
  4. #include <glib.h>
  5. #include <stdio.h>
  6. #include <sys/ioctl.h>
  7. #include <sys/mman.h>
  8. #define MAX_VIDEO_BUFFERS 20
  9. static const char *pixel_format_names[MP_PIXEL_FMT_MAX] = {
  10. "unsupported",
  11. "BGGR8",
  12. "GBRG8",
  13. "GRBG8",
  14. "RGGB8",
  15. "BGGR10P",
  16. "GBRG10P",
  17. "GRBG10P",
  18. "RGGB10P",
  19. "UYVY",
  20. "YUYV",
  21. };
  22. const char *mp_pixel_format_to_str(uint32_t pixel_format)
  23. {
  24. g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, "INVALID");
  25. return pixel_format_names[pixel_format];
  26. }
  27. MPPixelFormat mp_pixel_format_from_str(const char *name)
  28. {
  29. for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
  30. if (strcasecmp(pixel_format_names[i], name) == 0) {
  31. return i;
  32. }
  33. }
  34. g_return_val_if_reached(MP_PIXEL_FMT_UNSUPPORTED);
  35. }
  36. static const uint32_t pixel_format_v4l_pixel_formats[MP_PIXEL_FMT_MAX] = {
  37. 0,
  38. V4L2_PIX_FMT_SBGGR8,
  39. V4L2_PIX_FMT_SGBRG8,
  40. V4L2_PIX_FMT_SGRBG8,
  41. V4L2_PIX_FMT_SRGGB8,
  42. V4L2_PIX_FMT_SBGGR10P,
  43. V4L2_PIX_FMT_SGBRG10P,
  44. V4L2_PIX_FMT_SGRBG10P,
  45. V4L2_PIX_FMT_SRGGB10P,
  46. V4L2_PIX_FMT_UYVY,
  47. V4L2_PIX_FMT_YUYV,
  48. };
  49. uint32_t mp_pixel_format_to_v4l_pixel_format(MPPixelFormat pixel_format)
  50. {
  51. g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
  52. return pixel_format_v4l_pixel_formats[pixel_format];
  53. }
  54. MPPixelFormat mp_pixel_format_from_v4l_pixel_format(uint32_t v4l_pixel_format)
  55. {
  56. for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
  57. if (pixel_format_v4l_pixel_formats[i] == v4l_pixel_format) {
  58. return i;
  59. }
  60. }
  61. return MP_PIXEL_FMT_UNSUPPORTED;
  62. }
  63. static const uint32_t pixel_format_v4l_bus_codes[MP_PIXEL_FMT_MAX] = {
  64. 0,
  65. MEDIA_BUS_FMT_SBGGR8_1X8,
  66. MEDIA_BUS_FMT_SGBRG8_1X8,
  67. MEDIA_BUS_FMT_SGRBG8_1X8,
  68. MEDIA_BUS_FMT_SRGGB8_1X8,
  69. MEDIA_BUS_FMT_SBGGR10_1X10,
  70. MEDIA_BUS_FMT_SGBRG10_1X10,
  71. MEDIA_BUS_FMT_SGRBG10_1X10,
  72. MEDIA_BUS_FMT_SRGGB10_1X10,
  73. MEDIA_BUS_FMT_UYVY8_2X8,
  74. MEDIA_BUS_FMT_YUYV8_2X8,
  75. };
  76. uint32_t mp_pixel_format_to_v4l_bus_code(MPPixelFormat pixel_format)
  77. {
  78. g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
  79. return pixel_format_v4l_bus_codes[pixel_format];
  80. }
  81. MPPixelFormat mp_pixel_format_from_v4l_bus_code(uint32_t v4l_bus_code)
  82. {
  83. for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
  84. if (pixel_format_v4l_bus_codes[i] == v4l_bus_code) {
  85. return i;
  86. }
  87. }
  88. return MP_PIXEL_FMT_UNSUPPORTED;
  89. }
  90. uint32_t mp_pixel_format_bits_per_pixel(MPPixelFormat pixel_format)
  91. {
  92. g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
  93. switch (pixel_format) {
  94. case MP_PIXEL_FMT_BGGR8:
  95. case MP_PIXEL_FMT_GBRG8:
  96. case MP_PIXEL_FMT_GRBG8:
  97. case MP_PIXEL_FMT_RGGB8: return 8;
  98. case MP_PIXEL_FMT_BGGR10P:
  99. case MP_PIXEL_FMT_GBRG10P:
  100. case MP_PIXEL_FMT_GRBG10P:
  101. case MP_PIXEL_FMT_RGGB10P: return 10;
  102. case MP_PIXEL_FMT_UYVY:
  103. case MP_PIXEL_FMT_YUYV: return 16;
  104. default: return 0;
  105. }
  106. }
  107. uint32_t mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width)
  108. {
  109. uint32_t bits_per_pixel = mp_pixel_format_bits_per_pixel(pixel_format);
  110. uint64_t bits_per_width = width * (uint64_t) bits_per_pixel;
  111. uint64_t remainder = bits_per_width % 8;
  112. if (remainder == 0)
  113. return bits_per_width / 8;
  114. return (bits_per_width + 8 - remainder) / 8;
  115. }
  116. uint32_t mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width)
  117. {
  118. g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
  119. switch (pixel_format) {
  120. case MP_PIXEL_FMT_BGGR8:
  121. case MP_PIXEL_FMT_GBRG8:
  122. case MP_PIXEL_FMT_GRBG8:
  123. case MP_PIXEL_FMT_RGGB8: return width / 2;
  124. case MP_PIXEL_FMT_BGGR10P:
  125. case MP_PIXEL_FMT_GBRG10P:
  126. case MP_PIXEL_FMT_GRBG10P:
  127. case MP_PIXEL_FMT_RGGB10P: return width / 2 * 5;
  128. case MP_PIXEL_FMT_UYVY:
  129. case MP_PIXEL_FMT_YUYV: return width;
  130. default: return 0;
  131. }
  132. }
  133. uint32_t mp_pixel_format_height_to_colors(MPPixelFormat pixel_format, uint32_t height)
  134. {
  135. g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
  136. switch (pixel_format) {
  137. case MP_PIXEL_FMT_BGGR8:
  138. case MP_PIXEL_FMT_GBRG8:
  139. case MP_PIXEL_FMT_GRBG8:
  140. case MP_PIXEL_FMT_RGGB8:
  141. case MP_PIXEL_FMT_BGGR10P:
  142. case MP_PIXEL_FMT_GBRG10P:
  143. case MP_PIXEL_FMT_GRBG10P:
  144. case MP_PIXEL_FMT_RGGB10P: return height / 2;
  145. case MP_PIXEL_FMT_UYVY:
  146. case MP_PIXEL_FMT_YUYV: return height;
  147. default: return 0;
  148. }
  149. }
  150. bool mp_camera_mode_is_equivalent(const MPCameraMode *m1, const MPCameraMode *m2)
  151. {
  152. return m1->pixel_format == m2->pixel_format
  153. && m1->frame_interval.numerator == m2->frame_interval.numerator
  154. && m1->frame_interval.denominator == m2->frame_interval.denominator
  155. && m1->width == m2->width
  156. && m1->height == m2->height;
  157. }
  158. struct video_buffer {
  159. uint32_t length;
  160. uint8_t *data;
  161. };
  162. struct _MPCamera {
  163. int video_fd;
  164. int subdev_fd;
  165. bool has_set_mode;
  166. MPCameraMode current_mode;
  167. struct video_buffer buffers[MAX_VIDEO_BUFFERS];
  168. uint32_t num_buffers;
  169. };
  170. MPCamera *mp_camera_new(int video_fd, int subdev_fd)
  171. {
  172. g_return_val_if_fail(video_fd != -1, NULL);
  173. MPCamera *camera = malloc(sizeof(MPCamera));
  174. camera->video_fd = video_fd;
  175. camera->subdev_fd = subdev_fd;
  176. camera->has_set_mode = false;
  177. camera->num_buffers = 0;
  178. return camera;
  179. }
  180. void mp_camera_free(MPCamera *camera)
  181. {
  182. g_warn_if_fail(camera->num_buffers == 0);
  183. if (camera->num_buffers != 0) {
  184. mp_camera_stop_capture(camera);
  185. }
  186. free(camera);
  187. }
  188. bool mp_camera_is_subdev(MPCamera *camera)
  189. {
  190. return camera->subdev_fd != -1;
  191. }
  192. int mp_camera_get_video_fd(MPCamera *camera)
  193. {
  194. return camera->video_fd;
  195. }
  196. int mp_camera_get_subdev_fd(MPCamera *camera)
  197. {
  198. return camera->subdev_fd;
  199. }
  200. static void errno_printerr(const char *s)
  201. {
  202. g_printerr("MPCamera: %s error %d, %s\n", s, errno, strerror(errno));
  203. }
  204. static int xioctl(int fd, int request, void *arg)
  205. {
  206. int r;
  207. do {
  208. r = ioctl(fd, request, arg);
  209. } while (r == -1 && errno == EINTR);
  210. return r;
  211. }
  212. bool mp_camera_try_mode(MPCamera *camera, MPCameraMode *mode)
  213. {
  214. struct v4l2_format fmt = {};
  215. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  216. fmt.fmt.pix.width = mode->width;
  217. fmt.fmt.pix.height = mode->height;
  218. fmt.fmt.pix.pixelformat = mp_pixel_format_from_v4l_pixel_format(mode->pixel_format);
  219. fmt.fmt.pix.field = V4L2_FIELD_ANY;
  220. if (xioctl(camera->video_fd, VIDIOC_TRY_FMT, &fmt) == -1) {
  221. errno_printerr("VIDIOC_S_FMT");
  222. return false;
  223. }
  224. mode->width = fmt.fmt.pix.width;
  225. mode->height = fmt.fmt.pix.height;
  226. mode->pixel_format = mp_pixel_format_from_v4l_pixel_format(fmt.fmt.pix.pixelformat);
  227. return true;
  228. }
  229. const MPCameraMode *mp_camera_get_mode(const MPCamera *camera)
  230. {
  231. return &camera->current_mode;
  232. }
  233. bool mp_camera_set_mode(MPCamera *camera, MPCameraMode *mode)
  234. {
  235. // Set the mode in the subdev the camera is one
  236. if (mp_camera_is_subdev(camera))
  237. {
  238. struct v4l2_subdev_frame_interval interval = {};
  239. interval.pad = 0;
  240. interval.interval = mode->frame_interval;
  241. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &interval) == -1) {
  242. errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL");
  243. return false;
  244. }
  245. bool did_set_frame_rate =
  246. interval.interval.numerator == mode->frame_interval.numerator
  247. && interval.interval.denominator == mode->frame_interval.denominator;
  248. struct v4l2_subdev_format fmt = {};
  249. fmt.pad = 0;
  250. fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
  251. fmt.format.width = mode->width;
  252. fmt.format.height = mode->height;
  253. fmt.format.code = mp_pixel_format_to_v4l_bus_code(mode->pixel_format);
  254. fmt.format.field = V4L2_FIELD_ANY;
  255. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FMT, &fmt) == -1) {
  256. errno_printerr("VIDIOC_SUBDEV_S_FMT");
  257. return false;
  258. }
  259. // Some drivers like ov5640 don't allow you to set the frame format with
  260. // too high a frame-rate, but that means the frame-rate won't be set
  261. // after the format change. So we need to try again here if we didn't
  262. // succeed before. Ideally we'd be able to set both at once.
  263. if (!did_set_frame_rate)
  264. {
  265. interval.interval = mode->frame_interval;
  266. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &interval) == -1) {
  267. errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL");
  268. return false;
  269. }
  270. }
  271. // Update the mode
  272. mode->pixel_format = mp_pixel_format_from_v4l_bus_code(fmt.format.code);
  273. mode->frame_interval = interval.interval;
  274. mode->width = fmt.format.width;
  275. mode->height = fmt.format.height;
  276. }
  277. // Set the mode for the video device
  278. {
  279. struct v4l2_format fmt = {};
  280. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  281. fmt.fmt.pix.width = mode->width;
  282. fmt.fmt.pix.height = mode->height;
  283. fmt.fmt.pix.pixelformat = mp_pixel_format_to_v4l_pixel_format(mode->pixel_format);
  284. fmt.fmt.pix.field = V4L2_FIELD_ANY;
  285. if (xioctl(camera->video_fd, VIDIOC_S_FMT, &fmt) == -1) {
  286. errno_printerr("VIDIOC_S_FMT");
  287. return false;
  288. }
  289. // Update the mode
  290. mode->pixel_format = mp_pixel_format_from_v4l_pixel_format(fmt.fmt.pix.pixelformat);
  291. mode->width = fmt.fmt.pix.width;
  292. mode->height = fmt.fmt.pix.height;
  293. }
  294. camera->has_set_mode = true;
  295. camera->current_mode = *mode;
  296. return true;
  297. }
  298. bool mp_camera_start_capture(MPCamera *camera)
  299. {
  300. g_return_val_if_fail(camera->has_set_mode, false);
  301. g_return_val_if_fail(camera->num_buffers == 0, false);
  302. // Start by requesting buffers
  303. struct v4l2_requestbuffers req = {};
  304. req.count = MAX_VIDEO_BUFFERS;
  305. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  306. req.memory = V4L2_MEMORY_MMAP;
  307. if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) {
  308. errno_printerr("VIDIOC_REQBUFS");
  309. return false;
  310. }
  311. if (req.count < 2) {
  312. g_printerr("Insufficient buffer memory. Only %d buffers available.\n",
  313. req.count);
  314. goto error;
  315. }
  316. for (uint32_t i = 0; i < req.count; ++i) {
  317. // Query each buffer and mmap it
  318. struct v4l2_buffer buf = {
  319. .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
  320. .memory = V4L2_MEMORY_MMAP,
  321. .index = i,
  322. };
  323. if (xioctl(camera->video_fd, VIDIOC_QUERYBUF, &buf) == -1) {
  324. errno_printerr("VIDIOC_QUERYBUF");
  325. break;
  326. }
  327. camera->buffers[i].length = buf.length;
  328. camera->buffers[i].data = mmap(
  329. NULL,
  330. buf.length,
  331. PROT_READ,
  332. MAP_SHARED,
  333. camera->video_fd,
  334. buf.m.offset);
  335. if (camera->buffers[i].data == MAP_FAILED) {
  336. errno_printerr("mmap");
  337. break;
  338. }
  339. ++camera->num_buffers;
  340. }
  341. if (camera->num_buffers != req.count) {
  342. g_printerr("Unable to map all buffers\n");
  343. goto error;
  344. }
  345. for (uint32_t i = 0; i < camera->num_buffers; ++i) {
  346. struct v4l2_buffer buf = {
  347. .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
  348. .memory = V4L2_MEMORY_MMAP,
  349. .index = i,
  350. };
  351. // Queue the buffer for capture
  352. if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) {
  353. errno_printerr("VIDIOC_QBUF");
  354. goto error;
  355. }
  356. }
  357. // Start capture
  358. enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  359. if (xioctl(camera->video_fd, VIDIOC_STREAMON, &type) == -1) {
  360. errno_printerr("VIDIOC_STREAMON");
  361. goto error;
  362. }
  363. return true;
  364. error:
  365. // Unmap any mapped buffers
  366. assert(camera->num_buffers <= MAX_VIDEO_BUFFERS);
  367. for (uint32_t i = 0; i < camera->num_buffers; ++i) {
  368. if (munmap(camera->buffers[i].data, camera->buffers[i].length) == -1) {
  369. errno_printerr("munmap");
  370. }
  371. }
  372. // Reset allocated buffers
  373. {
  374. struct v4l2_requestbuffers req = {};
  375. req.count = 0;
  376. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  377. req.memory = V4L2_MEMORY_MMAP;
  378. if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) {
  379. errno_printerr("VIDIOC_REQBUFS");
  380. }
  381. }
  382. return false;
  383. }
  384. bool mp_camera_stop_capture(MPCamera *camera)
  385. {
  386. g_return_val_if_fail(camera->num_buffers > 0, false);
  387. enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  388. if (xioctl(camera->video_fd, VIDIOC_STREAMOFF, &type) == -1) {
  389. errno_printerr("VIDIOC_STREAMOFF");
  390. }
  391. assert(camera->num_buffers <= MAX_VIDEO_BUFFERS);
  392. for (int i = 0; i < camera->num_buffers; ++i) {
  393. if (munmap(camera->buffers[i].data, camera->buffers[i].length) == -1) {
  394. errno_printerr("munmap");
  395. }
  396. }
  397. camera->num_buffers = 0;
  398. struct v4l2_requestbuffers req = {};
  399. req.count = 0;
  400. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  401. req.memory = V4L2_MEMORY_MMAP;
  402. if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) {
  403. errno_printerr("VIDIOC_REQBUFS");
  404. }
  405. return true;
  406. }
  407. bool mp_camera_is_capturing(MPCamera *camera)
  408. {
  409. return camera->num_buffers > 0;
  410. }
  411. bool mp_camera_capture_image(MPCamera *camera, void (*callback)(MPImage, void *), void *user_data)
  412. {
  413. struct v4l2_buffer buf = {};
  414. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  415. buf.memory = V4L2_MEMORY_MMAP;
  416. if (xioctl(camera->video_fd, VIDIOC_DQBUF, &buf) == -1) {
  417. switch (errno) {
  418. case EAGAIN:
  419. return true;
  420. case EIO:
  421. /* Could ignore EIO, see spec. */
  422. /* fallthrough */
  423. default:
  424. errno_printerr("VIDIOC_DQBUF");
  425. return false;
  426. }
  427. }
  428. uint32_t pixel_format = camera->current_mode.pixel_format;
  429. uint32_t width = camera->current_mode.width;
  430. uint32_t height = camera->current_mode.height;
  431. assert(buf.bytesused == mp_pixel_format_width_to_bytes(pixel_format, width) * height);
  432. assert(buf.bytesused == camera->buffers[buf.index].length);
  433. MPImage image = {
  434. .pixel_format = pixel_format,
  435. .width = width,
  436. .height = height,
  437. .data = camera->buffers[buf.index].data,
  438. };
  439. callback(image, user_data);
  440. // The callback may have stopped the capture, only queue the buffer if we're
  441. // still capturing.
  442. if (mp_camera_is_capturing(camera)) {
  443. if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) {
  444. errno_printerr("VIDIOC_QBUF");
  445. return false;
  446. }
  447. }
  448. return true;
  449. }
  450. struct _MPCameraModeList {
  451. MPCameraMode mode;
  452. MPCameraModeList *next;
  453. };
  454. static MPCameraModeList *
  455. get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
  456. {
  457. MPCameraModeList *item = NULL;
  458. for (uint32_t fmt_index = 0;; ++fmt_index) {
  459. struct v4l2_subdev_mbus_code_enum fmt = {};
  460. fmt.index = fmt_index;
  461. fmt.pad = 0;
  462. fmt.which = V4L2_SUBDEV_FORMAT_TRY;
  463. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &fmt) == -1) {
  464. if (errno != EINVAL) {
  465. errno_printerr("VIDIOC_SUBDEV_ENUM_MBUS_CODE");
  466. }
  467. break;
  468. }
  469. // Skip unsupported formats
  470. uint32_t format = mp_pixel_format_from_v4l_bus_code(fmt.code);
  471. if (format == MP_PIXEL_FMT_UNSUPPORTED) {
  472. continue;
  473. }
  474. for (uint32_t frame_index = 0;; ++frame_index) {
  475. struct v4l2_subdev_frame_size_enum frame = {};
  476. frame.index = frame_index;
  477. frame.pad = 0;
  478. frame.code = fmt.code;
  479. frame.which = V4L2_SUBDEV_FORMAT_TRY;
  480. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &frame) == -1) {
  481. if (errno != EINVAL) {
  482. errno_printerr("VIDIOC_SUBDEV_ENUM_FRAME_SIZE");
  483. }
  484. break;
  485. }
  486. // TODO: Handle other types
  487. if (frame.min_width != frame.max_width
  488. || frame.min_height != frame.max_height) {
  489. break;
  490. }
  491. for (uint32_t interval_index = 0;; ++interval_index) {
  492. struct v4l2_subdev_frame_interval_enum interval = {};
  493. interval.index = interval_index;
  494. interval.pad = 0;
  495. interval.code = fmt.code;
  496. interval.width = frame.max_width;
  497. interval.height = frame.max_height;
  498. interval.which = V4L2_SUBDEV_FORMAT_TRY;
  499. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, &interval) == -1) {
  500. if (errno != EINVAL) {
  501. errno_printerr("VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL");
  502. }
  503. break;
  504. }
  505. MPCameraMode mode = {
  506. .pixel_format = format,
  507. .frame_interval = interval.interval,
  508. .width = frame.max_width,
  509. .height = frame.max_height,
  510. };
  511. if (!check(camera, &mode)) {
  512. continue;
  513. }
  514. MPCameraModeList *new_item = malloc(sizeof(MPCameraModeList));
  515. new_item->mode = mode;
  516. new_item->next = item;
  517. item = new_item;
  518. }
  519. }
  520. }
  521. return item;
  522. }
  523. static MPCameraModeList *
  524. get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
  525. {
  526. MPCameraModeList *item = NULL;
  527. for (uint32_t fmt_index = 0;; ++fmt_index) {
  528. struct v4l2_fmtdesc fmt = {};
  529. fmt.index = fmt_index;
  530. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  531. if (xioctl(camera->video_fd, VIDIOC_ENUM_FMT, &fmt) == -1) {
  532. if (errno != EINVAL) {
  533. errno_printerr("VIDIOC_ENUM_FMT");
  534. }
  535. break;
  536. }
  537. // Skip unsupported formats
  538. uint32_t format = mp_pixel_format_from_v4l_pixel_format(fmt.pixelformat);
  539. if (format == MP_PIXEL_FMT_UNSUPPORTED) {
  540. continue;
  541. }
  542. for (uint32_t frame_index = 0;; ++frame_index) {
  543. struct v4l2_frmsizeenum frame = {};
  544. frame.index = frame_index;
  545. frame.pixel_format = fmt.pixelformat;
  546. if (xioctl(camera->video_fd, VIDIOC_ENUM_FRAMESIZES, &frame) == -1) {
  547. if (errno != EINVAL) {
  548. errno_printerr("VIDIOC_ENUM_FRAMESIZES");
  549. }
  550. break;
  551. }
  552. // TODO: Handle other types
  553. if (frame.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
  554. break;
  555. }
  556. for (uint32_t interval_index = 0;; ++interval_index) {
  557. struct v4l2_frmivalenum interval = {};
  558. interval.index = interval_index;
  559. interval.pixel_format = fmt.pixelformat;
  560. interval.width = frame.discrete.width;
  561. interval.height = frame.discrete.height;
  562. if (xioctl(camera->video_fd, VIDIOC_ENUM_FRAMEINTERVALS, &interval) == -1) {
  563. if (errno != EINVAL) {
  564. errno_printerr("VIDIOC_ENUM_FRAMESIZES");
  565. }
  566. break;
  567. }
  568. // TODO: Handle other types
  569. if (interval.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
  570. break;
  571. }
  572. MPCameraMode mode = {
  573. .pixel_format = format,
  574. .frame_interval = interval.discrete,
  575. .width = frame.discrete.width,
  576. .height = frame.discrete.height,
  577. };
  578. if (!check(camera, &mode)) {
  579. continue;
  580. }
  581. MPCameraModeList *new_item = malloc(sizeof(MPCameraModeList));
  582. new_item->mode = mode;
  583. new_item->next = item;
  584. item = new_item;
  585. }
  586. }
  587. }
  588. return item;
  589. }
  590. static bool all_modes(MPCamera *camera, MPCameraMode *mode)
  591. {
  592. return true;
  593. }
  594. static bool available_modes(MPCamera *camera, MPCameraMode *mode)
  595. {
  596. MPCameraMode attempt = *mode;
  597. return mp_camera_try_mode(camera, &attempt)
  598. && mp_camera_mode_is_equivalent(mode, &attempt);
  599. }
  600. MPCameraModeList *mp_camera_list_supported_modes(MPCamera *camera)
  601. {
  602. if (mp_camera_is_subdev(camera)) {
  603. return get_subdev_modes(camera, all_modes);
  604. } else {
  605. return get_video_modes(camera, all_modes);
  606. }
  607. }
  608. MPCameraModeList *mp_camera_list_available_modes(MPCamera *camera)
  609. {
  610. if (mp_camera_is_subdev(camera)) {
  611. return get_subdev_modes(camera, available_modes);
  612. } else {
  613. return get_video_modes(camera, available_modes);
  614. }
  615. }
  616. MPCameraMode *mp_camera_mode_list_get(MPCameraModeList *list)
  617. {
  618. g_return_val_if_fail(list, NULL);
  619. return &list->mode;
  620. }
  621. MPCameraModeList *mp_camera_mode_list_next(MPCameraModeList *list)
  622. {
  623. g_return_val_if_fail(list, NULL);
  624. return list->next;
  625. }
  626. void mp_camera_mode_list_free(MPCameraModeList *list)
  627. {
  628. while (list) {
  629. MPCameraModeList *tmp = list;
  630. list = tmp->next;
  631. free(tmp);
  632. }
  633. }