v4l2cam.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. #include <getopt.h>
  2. #include <fcntl.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <time.h>
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include <sys/time.h>
  9. #include <sys/mman.h>
  10. #include <sys/ioctl.h>
  11. #include <dlfcn.h>
  12. #include <poll.h>
  13. #include "v4l2cam.hpp"
  14. #ifdef TZTEK_V4L2_DMA
  15. #include "nvbuf_utils.h"
  16. #endif
  17. //buf个数
  18. #define V4L2_BUFFER_LENGHT 4
  19. //图像格式
  20. #define V4L2_VIDEO_FORMAT V4L2_PIX_FMT_YUYV
  21. #ifdef TZTEK_V4L2_DMA
  22. static nv_color_fmt nvcolor_fmt[] =
  23. {
  24. /* TODO: add more pixel format mapping */
  25. {V4L2_PIX_FMT_UYVY, NvBufferColorFormat_UYVY},
  26. {V4L2_PIX_FMT_VYUY, NvBufferColorFormat_VYUY},
  27. {V4L2_PIX_FMT_YUYV, NvBufferColorFormat_YUYV},
  28. {V4L2_PIX_FMT_YVYU, NvBufferColorFormat_YVYU},
  29. {V4L2_PIX_FMT_GREY, NvBufferColorFormat_GRAY8},
  30. {V4L2_PIX_FMT_YUV420M, NvBufferColorFormat_YUV420},
  31. };
  32. static NvBufferColorFormat get_nvbuff_color_fmt(unsigned int v4l2_pixfmt)
  33. {
  34. unsigned i;
  35. for (i = 0; i < sizeof(nvcolor_fmt) / sizeof(nvcolor_fmt[0]); i++)
  36. {
  37. if (v4l2_pixfmt == nvcolor_fmt[i].v4l2_pixfmt)
  38. return nvcolor_fmt[i].nvbuff_color;
  39. }
  40. return NvBufferColorFormat_Invalid;
  41. }
  42. #endif
  43. CV4l2Cam::CV4l2Cam(string strDevName,int nWidth,int nHeight)
  44. {
  45. m_strDevName = strDevName;
  46. m_videoFd = -1;
  47. m_dwWidth = nWidth;
  48. m_dwHeight = nHeight;
  49. m_pBuffers = NULL;
  50. #ifdef TZTEK_V4L2_DMA
  51. m_dwIoType = IO_METHOD_DMA;
  52. m_pNvbuff = NULL;
  53. #else
  54. m_dwIoType = IO_METHOD_MMAP;
  55. #endif
  56. }
  57. CV4l2Cam::~CV4l2Cam()
  58. {
  59. }
  60. int CV4l2Cam::Init()
  61. {
  62. do
  63. {
  64. m_pData = new unsigned char [2*m_dwWidth*m_dwHeight];
  65. //阻塞形式打开设备
  66. m_videoFd = open(m_strDevName.c_str(), O_RDWR /* required */ /*| O_NONBLOCK*/, 0);
  67. if (-1 == m_videoFd)
  68. {
  69. printf("cannot open %s:,errno:%d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  70. break;
  71. }
  72. //校验能力级
  73. if(checkCapabilities() == false)
  74. {
  75. printf("checkCapabilities failed,devname=%s\n", m_strDevName.c_str());
  76. break;
  77. }
  78. //设备输出格式
  79. if(setVideoFmt() == false)
  80. {
  81. printf("setVideoFmt failed,devname=%s\n", m_strDevName.c_str());
  82. break;
  83. }
  84. usleep(10000);
  85. //初始化内存
  86. if(initDevice() == false)
  87. {
  88. printf("initDevice failed,devname=%s\n", m_strDevName.c_str());
  89. break;
  90. }
  91. return 0;
  92. } while (0);
  93. if(m_videoFd != -1)
  94. {
  95. close(m_videoFd);
  96. m_videoFd = -1;
  97. }
  98. if(m_pData)
  99. {
  100. delete []m_pData;
  101. m_pData = NULL;
  102. }
  103. m_dwFault = 1; //掉线
  104. return -1;
  105. }
  106. int CV4l2Cam::Release()
  107. {
  108. releaseDevice();
  109. if(m_pData)
  110. {
  111. delete []m_pData;
  112. m_pData = NULL;
  113. }
  114. return 0;
  115. }
  116. int CV4l2Cam::startAcquire()
  117. {
  118. if(m_videoFd < 0)
  119. {
  120. printf("video fd is invlaid,devname=%s\n", m_strDevName.c_str());
  121. return -1;
  122. }
  123. enum v4l2_buf_type type;
  124. switch(m_dwIoType)
  125. {
  126. case IO_METHOD_MMAP:
  127. for (int i = 0; i < V4L2_BUFFER_LENGHT; ++i) {
  128. struct v4l2_buffer buf;
  129. memset(&buf,0,sizeof(struct v4l2_buffer));
  130. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  131. buf.memory = V4L2_MEMORY_MMAP;
  132. buf.index = i;
  133. if (-1 == xioctl(m_videoFd, VIDIOC_QBUF, &buf))
  134. {
  135. printf("xioctl VIDIOC_QBUF,devname=%s\n", m_strDevName.c_str());
  136. return -1;
  137. }
  138. }
  139. break;
  140. case IO_METHOD_USERPTR:
  141. for (int i = 0; i < V4L2_BUFFER_LENGHT; ++i) {
  142. struct v4l2_buffer buf;
  143. memset(&buf,0,sizeof(struct v4l2_buffer));
  144. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  145. buf.memory = V4L2_MEMORY_USERPTR;
  146. buf.index = i;
  147. buf.m.userptr = m_pBuffers[i].length;
  148. if (-1 == xioctl(m_videoFd, VIDIOC_QBUF, &buf))
  149. {
  150. printf("xioctl VIDIOC_QBUF,devname=%s\n", m_strDevName.c_str());
  151. return -1;
  152. }
  153. }
  154. break;
  155. #ifdef TZTEK_V4L2_DMA
  156. case IO_METHOD_DMA:
  157. for (unsigned int index = 0; index < V4L2_BUFFER_LENGHT; index++)
  158. {
  159. struct v4l2_buffer buf;
  160. memset(&buf, 0, sizeof buf);
  161. buf.index = index;
  162. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  163. buf.memory = V4L2_MEMORY_DMABUF;
  164. buf.m.fd = (unsigned long)m_pNvbuff[index].dmabuff_fd;
  165. if (ioctl(m_videoFd, VIDIOC_QBUF, &buf) < 0)
  166. {
  167. //TZTEK_CLASSLOG(TZTEK_WARNING_LEV,"xioctl VIDIOC_REQBUFS failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  168. return -1;
  169. }
  170. }
  171. break;
  172. #endif
  173. default:
  174. break;
  175. }
  176. //set streaming on
  177. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  178. if (-1 == xioctl(m_videoFd, VIDIOC_STREAMON, &type))
  179. {
  180. printf("xioctl VIDIOC_STREAMON,devname=%s\n", m_strDevName.c_str());
  181. return -1;
  182. }
  183. #ifndef TZTEK_TRIG_CONTROL
  184. //实际测试,底层有数据缓存
  185. clearBuffer();
  186. #endif
  187. return 0;
  188. }
  189. int CV4l2Cam::stopAcquire()
  190. {
  191. enum v4l2_buf_type type;
  192. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  193. if (-1 == xioctl(m_videoFd, VIDIOC_STREAMOFF, &type))
  194. {
  195. printf("xioctl VIDIOC_STREAMOFF,devname=%s\n", m_strDevName.c_str());
  196. }
  197. return 0;
  198. }
  199. int CV4l2Cam::GrabImg(unsigned char *&pData,int &nDatalen)
  200. {
  201. pData = NULL;
  202. nDatalen = 0;
  203. unsigned char *srcData = NULL;
  204. int srcDatalen;
  205. /* 将已经捕获好视频的内存拉出已捕获视频的队列 */
  206. fd_set rset;
  207. FD_ZERO(&rset);
  208. FD_SET(m_videoFd,&rset);
  209. struct timeval tv;
  210. tv.tv_sec = 1;
  211. tv.tv_usec = 0;
  212. int retsel = select(m_videoFd+1,&rset,NULL,NULL,&tv);
  213. if(retsel <= 0)
  214. {
  215. printf( "%s:select failed,retsel=%d,dev=%s,errno=%d,errstr=%s\n",__func__,retsel,m_strDevName.c_str(),errno,strerror(errno));
  216. return -1;
  217. }
  218. struct v4l2_buffer buf;
  219. memset(&buf,0,sizeof(struct v4l2_buffer));
  220. switch (m_dwIoType)
  221. {
  222. case IO_METHOD_MMAP:
  223. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  224. buf.memory = V4L2_MEMORY_MMAP;
  225. if (-1 == xioctl(m_videoFd, VIDIOC_DQBUF, &buf))
  226. {
  227. printf( "xioctl VIDIOC_DQBUF failed,dev=%s,error:%d:%s\n",m_strDevName.c_str(),errno,strerror(errno));
  228. return -1;
  229. }
  230. srcData = (unsigned char*)m_pBuffers[buf.index].start;
  231. srcDatalen = buf.bytesused;
  232. break;
  233. case IO_METHOD_USERPTR:
  234. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  235. buf.memory = V4L2_MEMORY_USERPTR;
  236. if (-1 == xioctl(m_videoFd, VIDIOC_DQBUF, &buf))
  237. {
  238. printf( "xioctl VIDIOC_DQBUF failed,dev=%s,error:%d:%s\n",m_strDevName.c_str(),errno,strerror(errno));
  239. return -1;
  240. }
  241. srcData = (unsigned char*)buf.m.userptr;
  242. srcDatalen = buf.bytesused;
  243. break;
  244. #ifdef TZTEK_V4L2_DMA
  245. case IO_METHOD_DMA:
  246. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  247. buf.memory = V4L2_MEMORY_DMABUF;
  248. if (-1 == xioctl(m_videoFd, VIDIOC_DQBUF, &buf))
  249. {
  250. printf( "xioctl VIDIOC_DQBUF failed,dev=%s,error:%d:%s\n",m_strDevName.c_str(),errno,strerror(errno));
  251. return -1;
  252. }
  253. NvBufferMemSyncForDevice(m_pNvbuff[buf.index].dmabuff_fd, 0, (void**)&m_pNvbuff[buf.index].start);
  254. srcData = m_pNvbuff[buf.index].start;
  255. srcDatalen = m_pNvbuff[buf.index].size;
  256. break;
  257. #endif
  258. default:
  259. break;
  260. }
  261. //数据拷贝
  262. memcpy(m_pData,srcData,srcDatalen);
  263. //将buf重新入队
  264. if (-1 == xioctl(m_videoFd, VIDIOC_QBUF, &buf))
  265. {
  266. printf( "xioctl VIDIOC_QBUF failed,dev=%s,error:%d:%s\n",m_strDevName.c_str(),errno,strerror(errno));
  267. }
  268. struct timeval t;
  269. gettimeofday(&t, NULL);
  270. // printf("=========================selecttime: %ld.%06ld\n" ,t.tv_sec, t.tv_usec);
  271. pData = m_pData;
  272. nDatalen = srcDatalen;
  273. return 0;
  274. }
  275. bool CV4l2Cam::clearBuffer()
  276. {
  277. struct v4l2_buffer buf;
  278. /* 将已经捕获好视频的内存拉出已捕获视频的队列 */
  279. for(int i = 0; i < V4L2_BUFFER_LENGHT;i++)
  280. {
  281. memset(&buf,0,sizeof(struct v4l2_buffer));
  282. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  283. buf.memory = V4L2_MEMORY_MMAP;
  284. fd_set rset;
  285. FD_ZERO(&rset);
  286. FD_SET(m_videoFd,&rset);
  287. struct timeval tv;
  288. tv.tv_sec = 0;
  289. tv.tv_usec = 100*1000;
  290. int retsel = select(m_videoFd+1,&rset,NULL,NULL,&tv);
  291. if(retsel <= 0)
  292. {
  293. break;
  294. }
  295. if (-1 == xioctl(m_videoFd, VIDIOC_DQBUF, &buf))
  296. {
  297. printf( "xioctl VIDIOC_DQBUF failed,dev=%s,error:%d:%s\n",m_strDevName.c_str(),errno,strerror(errno));
  298. break;
  299. }
  300. if (-1 == xioctl(m_videoFd, VIDIOC_QBUF, &buf))
  301. {
  302. printf( "xioctl VIDIOC_QBUF failed,dev=%s,error:%d:%s\n",m_strDevName.c_str(),errno,strerror(errno));
  303. break;
  304. }
  305. }
  306. return true;
  307. }
  308. bool CV4l2Cam::initUserp()
  309. {
  310. struct v4l2_requestbuffers req;
  311. memset(&req,0,sizeof( struct v4l2_requestbuffers));
  312. req.count = V4L2_BUFFER_LENGHT; //缓存数量,根据图像占用空间大小申请的缓存区个数
  313. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,视频捕获模式.
  314. req.memory = V4L2_MEMORY_USERPTR;
  315. //请求buf
  316. if (-1 == xioctl(m_videoFd, VIDIOC_REQBUFS, &req))
  317. {
  318. printf("xioctl VIDIOC_REQBUFS failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  319. return false;
  320. }
  321. //分别struct buffer结构
  322. m_pBuffers = new V4l2Buffer[V4L2_BUFFER_LENGHT];
  323. if (!m_pBuffers)
  324. {
  325. printf("calloc buffer failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  326. return false;
  327. }
  328. memset(m_pBuffers,0,sizeof(V4l2Buffer)*V4L2_BUFFER_LENGHT);
  329. //获取请求的buf
  330. bool bRet = true;
  331. for (uint32_t i = 0; i < req.count; ++i)
  332. {
  333. m_pBuffers[i].length = 2*m_dwWidth*m_dwHeight;
  334. m_pBuffers[i].start = new char[m_pBuffers[i].length];
  335. if (NULL == m_pBuffers[i].start)
  336. {
  337. bRet = false;
  338. printf("new failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  339. break;
  340. }
  341. }
  342. //失败,释放已映射的内存
  343. if(bRet == false)
  344. {
  345. if(m_pBuffers)
  346. {
  347. for(uint32_t i = 0; i < req.count;i++)
  348. {
  349. if(m_pBuffers[i].start != NULL)
  350. {
  351. free(m_pBuffers[i].start);
  352. m_pBuffers[i].start = NULL;
  353. }
  354. }
  355. delete [] m_pBuffers;
  356. m_pBuffers = NULL;
  357. }
  358. }
  359. return bRet;
  360. }
  361. bool CV4l2Cam::initDevice()
  362. {
  363. int bRet = false;
  364. switch (m_dwIoType)
  365. {
  366. case IO_METHOD_MMAP:
  367. bRet = initMmap();
  368. break;
  369. case IO_METHOD_USERPTR:
  370. bRet = initUserp();
  371. break;
  372. #ifdef TZTEK_V4L2_DMA
  373. case IO_METHOD_DMA:
  374. bRet = initDma();
  375. break;
  376. #endif
  377. default:
  378. break;
  379. }
  380. return bRet;
  381. }
  382. bool CV4l2Cam::releaseDevice()
  383. {
  384. if(m_videoFd != -1)
  385. {
  386. close(m_videoFd);
  387. m_videoFd = -1;
  388. }
  389. switch (m_dwIoType)
  390. {
  391. case IO_METHOD_MMAP:
  392. for (int i = 0; i < V4L2_BUFFER_LENGHT; ++i)
  393. munmap(m_pBuffers[i].start, m_pBuffers[i].length);
  394. break;
  395. case IO_METHOD_USERPTR:
  396. for (int i = 0; i < V4L2_BUFFER_LENGHT; ++i)
  397. free(m_pBuffers[i].start);
  398. break;
  399. #ifdef TZTEK_V4L2_DMA
  400. case IO_METHOD_DMA:
  401. if (m_pNvbuff != NULL)
  402. {
  403. for (unsigned i = 0; i < V4L2_BUFFER_LENGHT; i++)
  404. {
  405. if (m_pNvbuff[i].dmabuff_fd)
  406. {
  407. NvBufferDestroy(m_pNvbuff[i].dmabuff_fd);
  408. }
  409. }
  410. delete []m_pNvbuff;
  411. m_pNvbuff = NULL;
  412. }
  413. break;
  414. #endif
  415. default:
  416. break;
  417. }
  418. if(m_pBuffers)
  419. {
  420. delete [] m_pBuffers;
  421. m_pBuffers = NULL;
  422. }
  423. return true;
  424. }
  425. #ifdef TZTEK_V4L2_DMA
  426. bool CV4l2Cam::initDma()
  427. {
  428. m_pNvbuff = new nv_buffer[V4L2_BUFFER_LENGHT];
  429. NvBufferCreateParams input_params = {0};
  430. input_params.payloadType = NvBufferPayload_SurfArray;
  431. input_params.width = m_dwWidth;
  432. input_params.height = m_dwHeight;
  433. input_params.layout = NvBufferLayout_Pitch;
  434. /* Create buffer and provide it with camera */
  435. for (unsigned int index = 0; index < V4L2_BUFFER_LENGHT; index++)
  436. {
  437. int fd;
  438. //NvBufferParams params = {0};
  439. input_params.colorFormat = get_nvbuff_color_fmt(V4L2_VIDEO_FORMAT);
  440. input_params.nvbuf_tag = NvBufferTag_CAMERA;
  441. if (-1 == NvBufferCreateEx(&fd, &input_params))
  442. {
  443. printf("NvBufferCreateEx failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  444. return false;
  445. }
  446. m_pNvbuff[index].dmabuff_fd = fd;
  447. if (-1 == NvBufferMemMap(m_pNvbuff[index].dmabuff_fd, 0, NvBufferMem_Read_Write,
  448. (void**)&m_pNvbuff[index].start))
  449. {
  450. printf("NvBufferMemMap failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  451. return false;
  452. }
  453. }
  454. bool bRet = true;
  455. struct v4l2_requestbuffers req;
  456. memset(&req,0,sizeof( struct v4l2_requestbuffers));
  457. req.count = V4L2_BUFFER_LENGHT; //缓存数量,根据图像占用空间大小申请的缓存区个数
  458. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,视频捕获模式.
  459. req.memory = V4L2_MEMORY_DMABUF; //DMA使用方式
  460. //请求buf
  461. if (-1 == xioctl(m_videoFd, VIDIOC_REQBUFS, &req))
  462. {
  463. printf("xioctl VIDIOC_REQBUFS failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  464. return false;
  465. }
  466. for (unsigned int index = 0; index < V4L2_BUFFER_LENGHT; index++)
  467. {
  468. struct v4l2_buffer buf;
  469. /* Query camera v4l2 buf length */
  470. memset(&buf, 0, sizeof buf);
  471. buf.index = index;
  472. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  473. buf.memory = V4L2_MEMORY_DMABUF;
  474. if (ioctl(m_videoFd, VIDIOC_QUERYBUF, &buf) < 0)
  475. {
  476. bRet = false;
  477. printf("xioctl VIDIOC_QUERYBUF failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  478. break;
  479. }
  480. buf.m.fd = (unsigned long)m_pNvbuff[index].dmabuff_fd;
  481. if (buf.length != m_pNvbuff[index].size)
  482. {
  483. // TZTEK_CLASSLOG(TZTEK_WARNING_LEV,"Camera v4l2 buf length is not expected,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  484. m_pNvbuff[index].size = buf.length;
  485. }
  486. }
  487. if(bRet == false)
  488. {
  489. if (m_pNvbuff != NULL)
  490. {
  491. for (unsigned i = 0; i < V4L2_BUFFER_LENGHT; i++)
  492. {
  493. if (m_pNvbuff[i].dmabuff_fd)
  494. {
  495. NvBufferDestroy(m_pNvbuff[i].dmabuff_fd);
  496. }
  497. }
  498. delete []m_pNvbuff;
  499. m_pNvbuff = NULL;
  500. }
  501. }
  502. return bRet;
  503. }
  504. #endif
  505. bool CV4l2Cam::initMmap()
  506. {
  507. struct v4l2_requestbuffers req;
  508. memset(&req,0,sizeof( struct v4l2_requestbuffers));
  509. req.count = V4L2_BUFFER_LENGHT; //缓存数量,根据图像占用空间大小申请的缓存区个数
  510. req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,视频捕获模式.
  511. req.memory = V4L2_MEMORY_MMAP; //内存区的使用方式
  512. //请求buf
  513. if (-1 == xioctl(m_videoFd, VIDIOC_REQBUFS, &req))
  514. {
  515. printf("xioctl VIDIOC_REQBUFS failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  516. return false;
  517. }
  518. //分别struct buffer结构
  519. m_pBuffers = new V4l2Buffer[V4L2_BUFFER_LENGHT];
  520. if (!m_pBuffers)
  521. {
  522. printf("calloc buffer failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  523. return false;
  524. }
  525. memset(m_pBuffers,0,sizeof(V4l2Buffer)*V4L2_BUFFER_LENGHT);
  526. //获取请求的buf
  527. bool bRet = true;
  528. for (uint32_t i = 0; i < req.count; ++i)
  529. {
  530. struct v4l2_buffer buf;
  531. memset(&buf,0,sizeof(struct v4l2_buffer ));
  532. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  533. buf.memory = V4L2_MEMORY_MMAP;
  534. buf.index = i;
  535. if (-1 == xioctl(m_videoFd, VIDIOC_QUERYBUF, &buf))
  536. {
  537. bRet = false;
  538. printf("xioctl VIDIOC_QUERYBUF failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  539. break;
  540. }
  541. m_pBuffers[i].length = buf.length;
  542. m_pBuffers[i].start = mmap(NULL , buf.length, PROT_READ | PROT_WRITE , MAP_SHARED, m_videoFd, buf.m.offset);
  543. if (MAP_FAILED == m_pBuffers[i].start)
  544. {
  545. bRet = false;
  546. printf("mmap failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  547. break;
  548. }
  549. }
  550. //失败,释放已映射的内存
  551. if(bRet == false)
  552. {
  553. if(m_pBuffers)
  554. {
  555. for(uint32_t i = 0; i < req.count;i++)
  556. {
  557. if(m_pBuffers[i].start != MAP_FAILED && m_pBuffers[i].start != NULL)
  558. {
  559. munmap( m_pBuffers[i].start, m_pBuffers[i].length);
  560. m_pBuffers[i].start = NULL;
  561. }
  562. }
  563. delete [] m_pBuffers;
  564. m_pBuffers = NULL;
  565. }
  566. }
  567. return bRet;
  568. }
  569. bool CV4l2Cam::setVideoFmt()
  570. {
  571. struct v4l2_format fmt;
  572. memset(&fmt,0,sizeof(fmt));
  573. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  574. fmt.fmt.pix.width = m_dwWidth;
  575. fmt.fmt.pix.height = m_dwHeight;
  576. fmt.fmt.pix.pixelformat = V4L2_VIDEO_FORMAT;
  577. fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
  578. //设置当前驱动的频捕获格式
  579. if (-1 == xioctl(m_videoFd, VIDIOC_S_FMT, &fmt))
  580. {
  581. printf("xioctl VIDIOC_S_FMT failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  582. return false;
  583. }
  584. return true;
  585. }
  586. bool CV4l2Cam::checkCapabilities()
  587. {
  588. //得到视频设备信息
  589. struct v4l2_capability cap;
  590. if (-1 == xioctl(m_videoFd, VIDIOC_QUERYCAP, &cap))
  591. {
  592. printf("xioctl VIDIOC_QUERYCAP failed,devname=%s,errno: %d, %s\n", m_strDevName.c_str(), errno, strerror(errno));
  593. return false;
  594. }
  595. if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
  596. {
  597. printf( "capabilities not support V4L2_CAP_VIDEO_CAPTURE \n");
  598. return false;
  599. }
  600. if (!(cap.capabilities & V4L2_CAP_STREAMING))
  601. {
  602. printf( "capabilities not support V4L2_CAP_STREAMING \n");
  603. return false;
  604. }
  605. return true;
  606. }
  607. int CV4l2Cam::xioctl(int fh, int request, void *arg)
  608. {
  609. int r;
  610. do {
  611. r = ioctl(fh, request, arg);
  612. } while (-1 == r && EINTR == errno);
  613. return r;
  614. }