videodevice_info_linux.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. #include "../imediadeviceinfo.h"
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <sys/ioctl.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. #include <md5.h>
  9. //v4l includes
  10. #include <linux/videodev2.h>
  11. #ifndef MAX_PATH
  12. #define MAX_PATH 260
  13. #endif // !MAX_PATH
  14. int rvc_videocap_get_device_count()
  15. {
  16. int icount = 0;
  17. int fd = -1;
  18. for (int index = 0; index < 64; index++)
  19. {
  20. char device[MAX_PATH] = { 0 };
  21. snprintf(device, MAX_PATH, "/dev/video%d", index);
  22. if (-1 != (fd = open(device, O_RDONLY)) )
  23. {
  24. // query device capabilities
  25. struct v4l2_capability cap = {0};
  26. if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0){
  27. close(fd);
  28. continue;
  29. }
  30. if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){
  31. close(fd);
  32. continue;
  33. }
  34. if (cap.capabilities & V4L2_CAP_STREAMING) {
  35. }
  36. if (cap.capabilities & V4L2_CAP_READWRITE) {
  37. }
  38. /* 查询支持的格式 */
  39. struct v4l2_fmtdesc tFmtDesc = {0};
  40. int iPixelFormat = 0;
  41. tFmtDesc.index = 0;
  42. tFmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  43. while ((ioctl(fd, VIDIOC_ENUM_FMT, &tFmtDesc)) == 0) {
  44. if (V4L2_PIX_FMT_YUYV == tFmtDesc.pixelformat || V4L2_PIX_FMT_MJPEG == tFmtDesc.pixelformat)
  45. {
  46. iPixelFormat = tFmtDesc.pixelformat;
  47. icount++;
  48. break;
  49. }
  50. tFmtDesc.index++;
  51. }
  52. close(fd);
  53. }
  54. }
  55. return icount;
  56. }
  57. int rvc_videocap_get_device_name(int device_id, char* buf, int len)
  58. {
  59. int iret = -1;
  60. char device[MAX_PATH] = { 0 };
  61. int fd = -1;
  62. snprintf(device, MAX_PATH, "/dev/video%d", device_id);
  63. if (-1 != (fd = open(device, O_RDONLY)))
  64. {
  65. // query device capabilities
  66. struct v4l2_capability cap = { 0 };
  67. if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0){
  68. close(fd);
  69. return iret;
  70. }
  71. if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){
  72. close(fd);
  73. return iret;
  74. }
  75. if (cap.capabilities & V4L2_CAP_STREAMING) {
  76. }
  77. if (cap.capabilities & V4L2_CAP_READWRITE) {
  78. }
  79. /* 查询支持的格式 */
  80. struct v4l2_fmtdesc tFmtDesc = { 0 };
  81. int iPixelFormat = 0;
  82. tFmtDesc.index = 0;
  83. tFmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  84. while ((ioctl(fd, VIDIOC_ENUM_FMT, &tFmtDesc)) == 0) {
  85. if (V4L2_PIX_FMT_YUYV == tFmtDesc.pixelformat || V4L2_PIX_FMT_MJPEG == tFmtDesc.pixelformat){
  86. iPixelFormat = tFmtDesc.pixelformat;
  87. break;
  88. }
  89. tFmtDesc.index++;
  90. }
  91. if (0 != iPixelFormat)
  92. {
  93. snprintf(buf, len, "%s%s%s", cap.card, ";", cap.bus_info);
  94. iret = 0;
  95. }
  96. close(fd);
  97. }
  98. return iret;
  99. }
  100. int rvc_videocap_get_device_path(int device_id, char* buf, int len)
  101. {
  102. return 0;
  103. }
  104. int rvc_videocap_get_device_info(int device_id, char* namebuf, int namelen, char* pathbuf, int pathlen)
  105. {
  106. int iret = -1;
  107. char device[MAX_PATH] = { 0 };
  108. int fd = -1;
  109. snprintf(device, MAX_PATH, "/dev/video%d", device_id);
  110. if (-1 != (fd = open(device, O_RDONLY)))
  111. {
  112. // query device capabilities
  113. struct v4l2_capability cap = { 0 };
  114. if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0)
  115. {
  116. close(fd);
  117. return iret;
  118. }
  119. if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
  120. {
  121. close(fd);
  122. return iret;
  123. }
  124. if (cap.capabilities & V4L2_CAP_STREAMING) {
  125. }
  126. if (cap.capabilities & V4L2_CAP_READWRITE) {
  127. }
  128. /* 查询支持的格式 */
  129. struct v4l2_fmtdesc tFmtDesc = { 0 };
  130. int iPixelFormat = 0;
  131. tFmtDesc.index = 0;
  132. tFmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  133. while ((ioctl(fd, VIDIOC_ENUM_FMT, &tFmtDesc)) == 0) {
  134. if (V4L2_PIX_FMT_YUYV == tFmtDesc.pixelformat || V4L2_PIX_FMT_MJPEG == tFmtDesc.pixelformat)
  135. {
  136. iPixelFormat = tFmtDesc.pixelformat;
  137. break;
  138. }
  139. tFmtDesc.index++;
  140. }
  141. if (0 != iPixelFormat)
  142. {
  143. snprintf(namebuf, namelen, "%s", cap.card);
  144. snprintf(pathbuf, pathlen, "%s", cap.bus_info);
  145. iret = 0;
  146. }
  147. close(fd);
  148. }
  149. return iret;
  150. }
  151. static int bin2str(unsigned char* x, int xlen, char* str, int str_size)
  152. {
  153. static const char* hex2char = "0123456789ABCDEF";
  154. int i, k = 0;
  155. if (str_size <= xlen * 2)
  156. return -1;
  157. for (i = 0; i < xlen; ++i) {
  158. int h = x[i] >> 4;
  159. int l = x[i] & 0xf;
  160. str[k++] = hex2char[h];
  161. str[k++] = hex2char[l];
  162. }
  163. str[k] = 0;
  164. return k;
  165. }
  166. int rvc_videocap_get_device_fullpathname(int device_id, char* fullnamebuf, int fulllen)
  167. {
  168. int iret = -1;
  169. char device[MAX_PATH] = { 0 };
  170. int fd = -1;
  171. snprintf(device, MAX_PATH, "/dev/video%d", device_id);
  172. if (-1 != (fd = open(device, O_RDONLY))){
  173. // query device capabilities
  174. struct v4l2_capability cap = { 0 };
  175. if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0){
  176. close(fd);
  177. return iret;
  178. }
  179. if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){
  180. close(fd);
  181. return iret;
  182. }
  183. if (cap.capabilities & V4L2_CAP_STREAMING) {
  184. }
  185. if (cap.capabilities & V4L2_CAP_READWRITE) {
  186. }
  187. /* 查询支持的格式 */
  188. struct v4l2_fmtdesc tFmtDesc = { 0 };
  189. int iPixelFormat = 0;
  190. tFmtDesc.index = 0;
  191. tFmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  192. while ((ioctl(fd, VIDIOC_ENUM_FMT, &tFmtDesc)) == 0) {
  193. if (V4L2_PIX_FMT_YUYV == tFmtDesc.pixelformat || V4L2_PIX_FMT_MJPEG == tFmtDesc.pixelformat){
  194. iPixelFormat = tFmtDesc.pixelformat;
  195. break;
  196. }
  197. tFmtDesc.index++;
  198. }
  199. if (0 != iPixelFormat){
  200. if (NULL != cap.bus_info && NULL != cap.card){
  201. char strmd5[MAX_PATH] = { 0 };
  202. snprintf(strmd5, MAX_PATH, "%s", cap.bus_info);
  203. unsigned char x[MD5_DIGESTSIZE] = {0};
  204. md5_ctx_t ctx;
  205. md5_init(&ctx);
  206. md5(x, strmd5, strlen(strmd5));
  207. bin2str(x, sizeof(x), strmd5, sizeof(strmd5));
  208. snprintf(fullnamebuf, fulllen, "%s:%s", cap.card, strmd5);
  209. iret = 0;
  210. }
  211. }
  212. close(fd);
  213. }
  214. return iret;
  215. }
  216. int rvc_videocap_get_video_device_id(const char* dev_name)
  217. {
  218. int iret = -1;
  219. if (NULL == dev_name){
  220. return iret;
  221. }
  222. int icount = rvc_videocap_get_device_count();
  223. int ifound = 0;
  224. for (int i = 0; i < 64 && ifound < icount; ++i) {
  225. char strfullname[2*MAX_PATH] = { 0 };
  226. if (0 == rvc_videocap_get_device_fullpathname(i, strfullname, 2 * MAX_PATH)){
  227. ifound++;
  228. if (0 == strcasecmp(strfullname, dev_name)){
  229. iret = i;
  230. break;
  231. }
  232. }
  233. }
  234. return iret;
  235. }
  236. int rvc_videocap_get_camera_infos(int device_id, rvc_camera_info_t* tinfo)
  237. {
  238. int iret = -1;
  239. if (NULL == tinfo) {
  240. return iret;
  241. }
  242. char device[MAX_PATH] = { 0 };
  243. int fd = -1;
  244. snprintf(device, MAX_PATH, "/dev/video%d", device_id);
  245. if (-1 != (fd = open(device, O_RDONLY))) {
  246. // query device capabilities
  247. struct v4l2_capability cap = { 0 };
  248. if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
  249. close(fd);
  250. return iret;
  251. }
  252. if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
  253. close(fd);
  254. return iret;
  255. }
  256. if (cap.capabilities & V4L2_CAP_STREAMING) {
  257. }
  258. if (cap.capabilities & V4L2_CAP_READWRITE) {
  259. }
  260. /* 查询支持的格式 */
  261. struct v4l2_fmtdesc tFmtDesc = { 0 };
  262. int iPixelFormat = 0;
  263. tFmtDesc.index = 0;
  264. tFmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  265. while ((ioctl(fd, VIDIOC_ENUM_FMT, &tFmtDesc)) == 0) {
  266. if (V4L2_PIX_FMT_YUYV == tFmtDesc.pixelformat || V4L2_PIX_FMT_MJPEG == tFmtDesc.pixelformat) {
  267. iPixelFormat = tFmtDesc.pixelformat;
  268. break;
  269. }
  270. tFmtDesc.index++;
  271. }
  272. if (0 != iPixelFormat) {
  273. if (NULL != cap.bus_info && NULL != cap.card) {
  274. memcpy(tinfo->strdriver, cap.driver, 16);
  275. memcpy(tinfo->strcard, cap.card, 32);
  276. memcpy(tinfo->strbus_info, cap.bus_info, 32);
  277. iret = 0;
  278. }
  279. }
  280. close(fd);
  281. }
  282. return iret;
  283. }