camera.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  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. static void errno_printerr(const char *s)
  159. {
  160. g_printerr("MPCamera: %s error %d, %s\n", s, errno, strerror(errno));
  161. }
  162. static int xioctl(int fd, int request, void *arg)
  163. {
  164. int r;
  165. do {
  166. r = ioctl(fd, request, arg);
  167. } while (r == -1 && errno == EINTR);
  168. return r;
  169. }
  170. struct video_buffer {
  171. uint32_t length;
  172. uint8_t *data;
  173. };
  174. struct _MPCamera {
  175. int video_fd;
  176. int subdev_fd;
  177. bool has_set_mode;
  178. MPCameraMode current_mode;
  179. struct video_buffer buffers[MAX_VIDEO_BUFFERS];
  180. uint32_t num_buffers;
  181. bool use_mplane;
  182. };
  183. MPCamera *mp_camera_new(int video_fd, int subdev_fd)
  184. {
  185. g_return_val_if_fail(video_fd != -1, NULL);
  186. // Query capabilities
  187. struct v4l2_capability cap;
  188. if (xioctl(video_fd, VIDIOC_QUERYCAP, &cap) == -1) {
  189. return NULL;
  190. }
  191. // Check whether this is a video capture device
  192. bool use_mplane;
  193. if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) {
  194. use_mplane = true;
  195. printf("!!\n");
  196. } else if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
  197. use_mplane = false;
  198. } else {
  199. return NULL;
  200. }
  201. MPCamera *camera = malloc(sizeof(MPCamera));
  202. camera->video_fd = video_fd;
  203. camera->subdev_fd = subdev_fd;
  204. camera->has_set_mode = false;
  205. camera->num_buffers = 0;
  206. camera->use_mplane = use_mplane;
  207. return camera;
  208. }
  209. void mp_camera_free(MPCamera *camera)
  210. {
  211. g_warn_if_fail(camera->num_buffers == 0);
  212. if (camera->num_buffers != 0) {
  213. mp_camera_stop_capture(camera);
  214. }
  215. free(camera);
  216. }
  217. bool mp_camera_is_subdev(MPCamera *camera)
  218. {
  219. return camera->subdev_fd != -1;
  220. }
  221. int mp_camera_get_video_fd(MPCamera *camera)
  222. {
  223. return camera->video_fd;
  224. }
  225. int mp_camera_get_subdev_fd(MPCamera *camera)
  226. {
  227. return camera->subdev_fd;
  228. }
  229. static bool camera_mode_impl(MPCamera *camera, int request, MPCameraMode *mode)
  230. {
  231. uint32_t pixfmt = mp_pixel_format_from_v4l_pixel_format(mode->pixel_format);
  232. struct v4l2_format fmt = {};
  233. if (camera->use_mplane) {
  234. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
  235. fmt.fmt.pix_mp.width = mode->width;
  236. fmt.fmt.pix_mp.height = mode->height;
  237. fmt.fmt.pix_mp.pixelformat = pixfmt;
  238. fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
  239. } else {
  240. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  241. fmt.fmt.pix.width = mode->width;
  242. fmt.fmt.pix.height = mode->height;
  243. fmt.fmt.pix.pixelformat = pixfmt;
  244. fmt.fmt.pix.field = V4L2_FIELD_ANY;
  245. }
  246. if (xioctl(camera->video_fd, request, &fmt) == -1) {
  247. return false;
  248. }
  249. if (camera->use_mplane) {
  250. mode->width = fmt.fmt.pix_mp.width;
  251. mode->height = fmt.fmt.pix_mp.height;
  252. mode->pixel_format = mp_pixel_format_from_v4l_pixel_format(
  253. fmt.fmt.pix_mp.pixelformat);
  254. } else {
  255. mode->width = fmt.fmt.pix.width;
  256. mode->height = fmt.fmt.pix.height;
  257. mode->pixel_format = mp_pixel_format_from_v4l_pixel_format(
  258. fmt.fmt.pix.pixelformat);
  259. }
  260. return true;
  261. }
  262. bool mp_camera_try_mode(MPCamera *camera, MPCameraMode *mode)
  263. {
  264. if (!camera_mode_impl(camera, VIDIOC_TRY_FMT, mode)) {
  265. errno_printerr("VIDIOC_S_FMT");
  266. return false;
  267. }
  268. return true;
  269. }
  270. const MPCameraMode *mp_camera_get_mode(const MPCamera *camera)
  271. {
  272. return &camera->current_mode;
  273. }
  274. bool mp_camera_set_mode(MPCamera *camera, MPCameraMode *mode)
  275. {
  276. // Set the mode in the subdev the camera is one
  277. if (mp_camera_is_subdev(camera))
  278. {
  279. struct v4l2_subdev_frame_interval interval = {};
  280. interval.pad = 0;
  281. interval.interval = mode->frame_interval;
  282. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &interval) == -1) {
  283. errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL");
  284. return false;
  285. }
  286. bool did_set_frame_rate =
  287. interval.interval.numerator == mode->frame_interval.numerator
  288. && interval.interval.denominator == mode->frame_interval.denominator;
  289. struct v4l2_subdev_format fmt = {};
  290. fmt.pad = 0;
  291. fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
  292. fmt.format.width = mode->width;
  293. fmt.format.height = mode->height;
  294. fmt.format.code = mp_pixel_format_to_v4l_bus_code(mode->pixel_format);
  295. fmt.format.field = V4L2_FIELD_ANY;
  296. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FMT, &fmt) == -1) {
  297. errno_printerr("VIDIOC_SUBDEV_S_FMT");
  298. return false;
  299. }
  300. // Some drivers like ov5640 don't allow you to set the frame format with
  301. // too high a frame-rate, but that means the frame-rate won't be set
  302. // after the format change. So we need to try again here if we didn't
  303. // succeed before. Ideally we'd be able to set both at once.
  304. if (!did_set_frame_rate)
  305. {
  306. interval.interval = mode->frame_interval;
  307. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &interval) == -1) {
  308. errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL");
  309. return false;
  310. }
  311. }
  312. // Update the mode
  313. mode->pixel_format = mp_pixel_format_from_v4l_bus_code(fmt.format.code);
  314. mode->frame_interval = interval.interval;
  315. mode->width = fmt.format.width;
  316. mode->height = fmt.format.height;
  317. }
  318. // Set the mode for the video device
  319. {
  320. if (!camera_mode_impl(camera, VIDIOC_S_FMT, mode)) {
  321. errno_printerr("VIDIOC_S_FMT");
  322. return false;
  323. }
  324. }
  325. camera->has_set_mode = true;
  326. camera->current_mode = *mode;
  327. return true;
  328. }
  329. bool mp_camera_start_capture(MPCamera *camera)
  330. {
  331. g_return_val_if_fail(camera->has_set_mode, false);
  332. g_return_val_if_fail(camera->num_buffers == 0, false);
  333. // Start by requesting buffers
  334. struct v4l2_requestbuffers req = {};
  335. req.count = MAX_VIDEO_BUFFERS;
  336. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  337. req.memory = V4L2_MEMORY_MMAP;
  338. if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) {
  339. errno_printerr("VIDIOC_REQBUFS");
  340. return false;
  341. }
  342. if (req.count < 2) {
  343. g_printerr("Insufficient buffer memory. Only %d buffers available.\n",
  344. req.count);
  345. goto error;
  346. }
  347. for (uint32_t i = 0; i < req.count; ++i) {
  348. // Query each buffer and mmap it
  349. struct v4l2_buffer buf = {
  350. .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
  351. .memory = V4L2_MEMORY_MMAP,
  352. .index = i,
  353. };
  354. struct v4l2_plane planes[1];
  355. if (camera->use_mplane) {
  356. buf.m.planes = planes;
  357. buf.length = 1;
  358. }
  359. if (xioctl(camera->video_fd, VIDIOC_QUERYBUF, &buf) == -1) {
  360. errno_printerr("VIDIOC_QUERYBUF");
  361. break;
  362. }
  363. if (camera->use_mplane) {
  364. camera->buffers[i].length = planes[0].length;
  365. camera->buffers[i].data = mmap(
  366. NULL,
  367. planes[0].length,
  368. PROT_READ,
  369. MAP_SHARED,
  370. camera->video_fd,
  371. planes[0].m.mem_offset);
  372. } else {
  373. camera->buffers[i].length = buf.length;
  374. camera->buffers[i].data = mmap(
  375. NULL,
  376. buf.length,
  377. PROT_READ,
  378. MAP_SHARED,
  379. camera->video_fd,
  380. buf.m.offset);
  381. }
  382. if (camera->buffers[i].data == MAP_FAILED) {
  383. errno_printerr("mmap");
  384. break;
  385. }
  386. ++camera->num_buffers;
  387. }
  388. if (camera->num_buffers != req.count) {
  389. g_printerr("Unable to map all buffers\n");
  390. goto error;
  391. }
  392. for (uint32_t i = 0; i < camera->num_buffers; ++i) {
  393. struct v4l2_buffer buf = {
  394. .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
  395. .memory = V4L2_MEMORY_MMAP,
  396. .index = i,
  397. };
  398. struct v4l2_plane planes[1];
  399. if (camera->use_mplane) {
  400. buf.m.planes = planes;
  401. buf.length = 1;
  402. }
  403. // Queue the buffer for capture
  404. if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) {
  405. errno_printerr("VIDIOC_QBUF");
  406. goto error;
  407. }
  408. }
  409. // Start capture
  410. enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  411. if (xioctl(camera->video_fd, VIDIOC_STREAMON, &type) == -1) {
  412. errno_printerr("VIDIOC_STREAMON");
  413. goto error;
  414. }
  415. return true;
  416. error:
  417. // Unmap any mapped buffers
  418. assert(camera->num_buffers <= MAX_VIDEO_BUFFERS);
  419. for (uint32_t i = 0; i < camera->num_buffers; ++i) {
  420. if (munmap(camera->buffers[i].data, camera->buffers[i].length) == -1) {
  421. errno_printerr("munmap");
  422. }
  423. }
  424. // Reset allocated buffers
  425. {
  426. struct v4l2_requestbuffers req = {};
  427. req.count = 0;
  428. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  429. req.memory = V4L2_MEMORY_MMAP;
  430. if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) {
  431. errno_printerr("VIDIOC_REQBUFS");
  432. }
  433. }
  434. return false;
  435. }
  436. bool mp_camera_stop_capture(MPCamera *camera)
  437. {
  438. g_return_val_if_fail(camera->num_buffers > 0, false);
  439. enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  440. if (xioctl(camera->video_fd, VIDIOC_STREAMOFF, &type) == -1) {
  441. errno_printerr("VIDIOC_STREAMOFF");
  442. }
  443. assert(camera->num_buffers <= MAX_VIDEO_BUFFERS);
  444. for (int i = 0; i < camera->num_buffers; ++i) {
  445. if (munmap(camera->buffers[i].data, camera->buffers[i].length) == -1) {
  446. errno_printerr("munmap");
  447. }
  448. }
  449. camera->num_buffers = 0;
  450. struct v4l2_requestbuffers req = {};
  451. req.count = 0;
  452. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  453. req.memory = V4L2_MEMORY_MMAP;
  454. if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) {
  455. errno_printerr("VIDIOC_REQBUFS");
  456. }
  457. return true;
  458. }
  459. bool mp_camera_is_capturing(MPCamera *camera)
  460. {
  461. return camera->num_buffers > 0;
  462. }
  463. bool mp_camera_capture_image(MPCamera *camera, void (*callback)(MPImage, void *), void *user_data)
  464. {
  465. struct v4l2_buffer buf = {};
  466. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  467. buf.memory = V4L2_MEMORY_MMAP;
  468. struct v4l2_plane planes[1];
  469. if (camera->use_mplane) {
  470. buf.m.planes = planes;
  471. buf.length = 1;
  472. }
  473. if (xioctl(camera->video_fd, VIDIOC_DQBUF, &buf) == -1) {
  474. switch (errno) {
  475. case EAGAIN:
  476. return true;
  477. case EIO:
  478. /* Could ignore EIO, see spec. */
  479. /* fallthrough */
  480. default:
  481. errno_printerr("VIDIOC_DQBUF");
  482. return false;
  483. }
  484. }
  485. uint32_t pixel_format = camera->current_mode.pixel_format;
  486. uint32_t width = camera->current_mode.width;
  487. uint32_t height = camera->current_mode.height;
  488. uint32_t bytesused;
  489. if (camera->use_mplane) {
  490. bytesused = planes[0].bytesused;
  491. } else {
  492. bytesused = buf.bytesused;
  493. }
  494. assert(bytesused == mp_pixel_format_width_to_bytes(pixel_format, width) * height);
  495. assert(bytesused == camera->buffers[buf.index].length);
  496. MPImage image = {
  497. .pixel_format = pixel_format,
  498. .width = width,
  499. .height = height,
  500. .data = camera->buffers[buf.index].data,
  501. };
  502. callback(image, user_data);
  503. // The callback may have stopped the capture, only queue the buffer if we're
  504. // still capturing.
  505. if (mp_camera_is_capturing(camera)) {
  506. if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) {
  507. errno_printerr("VIDIOC_QBUF");
  508. return false;
  509. }
  510. }
  511. return true;
  512. }
  513. struct _MPCameraModeList {
  514. MPCameraMode mode;
  515. MPCameraModeList *next;
  516. };
  517. static MPCameraModeList *
  518. get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
  519. {
  520. MPCameraModeList *item = NULL;
  521. for (uint32_t fmt_index = 0;; ++fmt_index) {
  522. struct v4l2_subdev_mbus_code_enum fmt = {};
  523. fmt.index = fmt_index;
  524. fmt.pad = 0;
  525. fmt.which = V4L2_SUBDEV_FORMAT_TRY;
  526. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &fmt) == -1) {
  527. if (errno != EINVAL) {
  528. errno_printerr("VIDIOC_SUBDEV_ENUM_MBUS_CODE");
  529. }
  530. break;
  531. }
  532. // Skip unsupported formats
  533. uint32_t format = mp_pixel_format_from_v4l_bus_code(fmt.code);
  534. if (format == MP_PIXEL_FMT_UNSUPPORTED) {
  535. continue;
  536. }
  537. for (uint32_t frame_index = 0;; ++frame_index) {
  538. struct v4l2_subdev_frame_size_enum frame = {};
  539. frame.index = frame_index;
  540. frame.pad = 0;
  541. frame.code = fmt.code;
  542. frame.which = V4L2_SUBDEV_FORMAT_TRY;
  543. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &frame) == -1) {
  544. if (errno != EINVAL) {
  545. errno_printerr("VIDIOC_SUBDEV_ENUM_FRAME_SIZE");
  546. }
  547. break;
  548. }
  549. // TODO: Handle other types
  550. if (frame.min_width != frame.max_width
  551. || frame.min_height != frame.max_height) {
  552. break;
  553. }
  554. for (uint32_t interval_index = 0;; ++interval_index) {
  555. struct v4l2_subdev_frame_interval_enum interval = {};
  556. interval.index = interval_index;
  557. interval.pad = 0;
  558. interval.code = fmt.code;
  559. interval.width = frame.max_width;
  560. interval.height = frame.max_height;
  561. interval.which = V4L2_SUBDEV_FORMAT_TRY;
  562. if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, &interval) == -1) {
  563. if (errno != EINVAL) {
  564. errno_printerr("VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL");
  565. }
  566. break;
  567. }
  568. MPCameraMode mode = {
  569. .pixel_format = format,
  570. .frame_interval = interval.interval,
  571. .width = frame.max_width,
  572. .height = frame.max_height,
  573. };
  574. if (!check(camera, &mode)) {
  575. continue;
  576. }
  577. MPCameraModeList *new_item = malloc(sizeof(MPCameraModeList));
  578. new_item->mode = mode;
  579. new_item->next = item;
  580. item = new_item;
  581. }
  582. }
  583. }
  584. return item;
  585. }
  586. static MPCameraModeList *
  587. get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
  588. {
  589. MPCameraModeList *item = NULL;
  590. for (uint32_t fmt_index = 0;; ++fmt_index) {
  591. struct v4l2_fmtdesc fmt = {};
  592. fmt.index = fmt_index;
  593. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  594. if (xioctl(camera->video_fd, VIDIOC_ENUM_FMT, &fmt) == -1) {
  595. if (errno != EINVAL) {
  596. errno_printerr("VIDIOC_ENUM_FMT");
  597. }
  598. break;
  599. }
  600. // Skip unsupported formats
  601. uint32_t format = mp_pixel_format_from_v4l_pixel_format(fmt.pixelformat);
  602. if (format == MP_PIXEL_FMT_UNSUPPORTED) {
  603. continue;
  604. }
  605. for (uint32_t frame_index = 0;; ++frame_index) {
  606. struct v4l2_frmsizeenum frame = {};
  607. frame.index = frame_index;
  608. frame.pixel_format = fmt.pixelformat;
  609. if (xioctl(camera->video_fd, VIDIOC_ENUM_FRAMESIZES, &frame) == -1) {
  610. if (errno != EINVAL) {
  611. errno_printerr("VIDIOC_ENUM_FRAMESIZES");
  612. }
  613. break;
  614. }
  615. // TODO: Handle other types
  616. if (frame.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
  617. break;
  618. }
  619. for (uint32_t interval_index = 0;; ++interval_index) {
  620. struct v4l2_frmivalenum interval = {};
  621. interval.index = interval_index;
  622. interval.pixel_format = fmt.pixelformat;
  623. interval.width = frame.discrete.width;
  624. interval.height = frame.discrete.height;
  625. if (xioctl(camera->video_fd, VIDIOC_ENUM_FRAMEINTERVALS, &interval) == -1) {
  626. if (errno != EINVAL) {
  627. errno_printerr("VIDIOC_ENUM_FRAMESIZES");
  628. }
  629. break;
  630. }
  631. // TODO: Handle other types
  632. if (interval.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
  633. break;
  634. }
  635. MPCameraMode mode = {
  636. .pixel_format = format,
  637. .frame_interval = interval.discrete,
  638. .width = frame.discrete.width,
  639. .height = frame.discrete.height,
  640. };
  641. if (!check(camera, &mode)) {
  642. continue;
  643. }
  644. MPCameraModeList *new_item = malloc(sizeof(MPCameraModeList));
  645. new_item->mode = mode;
  646. new_item->next = item;
  647. item = new_item;
  648. }
  649. }
  650. }
  651. return item;
  652. }
  653. static bool all_modes(MPCamera *camera, MPCameraMode *mode)
  654. {
  655. return true;
  656. }
  657. static bool available_modes(MPCamera *camera, MPCameraMode *mode)
  658. {
  659. MPCameraMode attempt = *mode;
  660. return mp_camera_try_mode(camera, &attempt)
  661. && mp_camera_mode_is_equivalent(mode, &attempt);
  662. }
  663. MPCameraModeList *mp_camera_list_supported_modes(MPCamera *camera)
  664. {
  665. if (mp_camera_is_subdev(camera)) {
  666. return get_subdev_modes(camera, all_modes);
  667. } else {
  668. return get_video_modes(camera, all_modes);
  669. }
  670. }
  671. MPCameraModeList *mp_camera_list_available_modes(MPCamera *camera)
  672. {
  673. if (mp_camera_is_subdev(camera)) {
  674. return get_subdev_modes(camera, available_modes);
  675. } else {
  676. return get_video_modes(camera, available_modes);
  677. }
  678. }
  679. MPCameraMode *mp_camera_mode_list_get(MPCameraModeList *list)
  680. {
  681. g_return_val_if_fail(list, NULL);
  682. return &list->mode;
  683. }
  684. MPCameraModeList *mp_camera_mode_list_next(MPCameraModeList *list)
  685. {
  686. g_return_val_if_fail(list, NULL);
  687. return list->next;
  688. }
  689. void mp_camera_mode_list_free(MPCameraModeList *list)
  690. {
  691. while (list) {
  692. MPCameraModeList *tmp = list;
  693. list = tmp->next;
  694. free(tmp);
  695. }
  696. }