NvBuffer.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /*
  2. * Copyright (c) 2016-2021, NVIDIA CORPORATION. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of NVIDIA CORPORATION nor the names of its
  13. * contributors may be used to endorse or promote products derived
  14. * from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  20. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  21. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  22. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  23. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  24. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "NvBuffer.h"
  29. #include "NvLogging.h"
  30. #include <cstring>
  31. #include <errno.h>
  32. #include <sys/mman.h>
  33. #include <libv4l2.h>
  34. #define CAT_NAME "Buffer"
  35. #define MAX(a,b) (a > b ? a : b)
  36. NvBuffer::NvBuffer(enum v4l2_buf_type buf_type, enum v4l2_memory memory_type,
  37. uint32_t n_planes, NvBufferPlaneFormat * fmt, uint32_t index)
  38. :buf_type(buf_type),
  39. memory_type(memory_type),
  40. index(index),
  41. n_planes(n_planes)
  42. {
  43. uint32_t i;
  44. mapped = false;
  45. allocated = false;
  46. memset(planes, 0, sizeof(planes));
  47. for (i = 0; i < n_planes; i++)
  48. {
  49. this->planes[i].fd = -1;
  50. this->planes[i].fmt = fmt[i];
  51. }
  52. ref_count = 0;
  53. pthread_mutex_init(&ref_lock, NULL);
  54. shared_buffer = NULL;
  55. }
  56. NvBuffer::NvBuffer(uint32_t pixfmt, uint32_t width, uint32_t height,
  57. uint32_t index)
  58. :buf_type(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE),
  59. memory_type(V4L2_MEMORY_USERPTR),
  60. index(index)
  61. {
  62. uint32_t i;
  63. NvBuffer::NvBufferPlaneFormat fmt[MAX_PLANES];
  64. mapped = false;
  65. allocated = false;
  66. fill_buffer_plane_format(&n_planes, fmt, width, height, pixfmt);
  67. for (i = 0; i < MAX_PLANES; i++)
  68. {
  69. this->planes[i].fd = -1;
  70. this->planes[i].data = NULL;
  71. this->planes[i].bytesused = 0;
  72. this->planes[i].mem_offset = 0;
  73. this->planes[i].length = 0;
  74. this->planes[i].fmt = fmt[i];
  75. this->planes[i].fmt.sizeimage = fmt[i].width * fmt[i].height *
  76. fmt[i].bytesperpixel;
  77. this->planes[i].fmt.stride = fmt[i].width * fmt[i].bytesperpixel;
  78. }
  79. ref_count = 0;
  80. pthread_mutex_init(&ref_lock, NULL);
  81. shared_buffer = NULL;
  82. }
  83. NvBuffer::NvBuffer(uint32_t size, uint32_t index)
  84. :buf_type(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE),
  85. memory_type(V4L2_MEMORY_USERPTR),
  86. index(index)
  87. {
  88. uint32_t i;
  89. mapped = false;
  90. allocated = false;
  91. n_planes = 1;
  92. for (i = 0; i < n_planes; i++)
  93. {
  94. this->planes[i].fd = -1;
  95. this->planes[i].data = NULL;
  96. this->planes[i].bytesused = 0;
  97. this->planes[i].mem_offset = 0;
  98. this->planes[i].length = 0;
  99. this->planes[i].fmt.sizeimage = size;
  100. }
  101. ref_count = 0;
  102. pthread_mutex_init(&ref_lock, NULL);
  103. shared_buffer = NULL;
  104. }
  105. NvBuffer::~NvBuffer()
  106. {
  107. if (mapped)
  108. {
  109. unmap();
  110. }
  111. if (allocated)
  112. {
  113. deallocateMemory();
  114. }
  115. pthread_mutex_destroy(&ref_lock);
  116. }
  117. int
  118. NvBuffer::map()
  119. {
  120. uint32_t j;
  121. if (memory_type != V4L2_MEMORY_MMAP)
  122. {
  123. CAT_WARN_MSG("Buffer " << index << "already mapped");
  124. return -1;
  125. }
  126. if (mapped)
  127. {
  128. CAT_WARN_MSG("Buffer " << index << "already mapped");
  129. return 0;
  130. }
  131. for (j = 0; j < n_planes; j++)
  132. {
  133. if (planes[j].fd == -1)
  134. {
  135. return -1;
  136. }
  137. planes[j].data = (unsigned char *) mmap(NULL,
  138. planes[j].length,
  139. PROT_READ | PROT_WRITE,
  140. MAP_SHARED,
  141. planes[j].fd,
  142. planes[j].mem_offset);
  143. if (planes[j].data == MAP_FAILED)
  144. {
  145. CAT_ERROR_MSG("Could not map buffer " << index << ", plane " << j);
  146. return -1;
  147. }
  148. else
  149. {
  150. CAT_DEBUG_MSG("Mapped buffer " << index << ", plane " << j << " to "
  151. << planes[j].data);
  152. }
  153. }
  154. mapped = true;
  155. return 0;
  156. }
  157. void
  158. NvBuffer::unmap()
  159. {
  160. if (memory_type != V4L2_MEMORY_MMAP || !mapped)
  161. {
  162. CAT_WARN_MSG("Cannot Unmap Buffer " << index <<
  163. ". Only mapped MMAP buffer can be unmapped");
  164. return;
  165. }
  166. for (uint32_t j = 0; j < n_planes; j++)
  167. {
  168. if (planes[j].data)
  169. {
  170. munmap(planes[j].data, planes[j].length);
  171. }
  172. planes[j].data = NULL;
  173. }
  174. mapped = false;
  175. CAT_DEBUG_MSG("Buffer " << index << " unmapped ");
  176. }
  177. int
  178. NvBuffer::allocateMemory()
  179. {
  180. uint32_t j;
  181. if (memory_type != V4L2_MEMORY_USERPTR)
  182. {
  183. CAT_ERROR_MSG("Only USERPTR buffers can be allocated");
  184. return -1;
  185. }
  186. if (allocated)
  187. {
  188. CAT_WARN_MSG("Buffer " << index << "already allocated memory");
  189. return 0;
  190. }
  191. for (j = 0; j < n_planes; j++)
  192. {
  193. if (planes[j].data)
  194. {
  195. ERROR_MSG("Buffer " << index << ", Plane " << j <<
  196. " already allocated");
  197. return -1;
  198. }
  199. planes[j].length = MAX(planes[j].fmt.sizeimage,
  200. planes[j].fmt.width *
  201. planes[j].fmt.bytesperpixel *
  202. planes[j].fmt.height);
  203. planes[j].data = new unsigned char [planes[j].length];
  204. if (planes[j].data == MAP_FAILED)
  205. {
  206. SYS_ERROR_MSG("Error while allocating buffer " << index <<
  207. " plane " << j);
  208. return -1;
  209. }
  210. else
  211. {
  212. DEBUG_MSG("Buffer " << index << ", Plane " << j <<
  213. " allocated to " << (void *) planes[j].data);
  214. }
  215. }
  216. allocated = true;
  217. return 0;
  218. }
  219. void
  220. NvBuffer::deallocateMemory()
  221. {
  222. uint32_t j;
  223. if (memory_type != V4L2_MEMORY_USERPTR || !allocated)
  224. {
  225. ERROR_MSG("Only allocated USERPTR buffers can be deallocated");
  226. return;
  227. }
  228. for (j = 0; j < n_planes; j++)
  229. {
  230. if (!planes[j].data)
  231. {
  232. DEBUG_MSG("Buffer " << index << ", Plane " << j <<
  233. " not allocated");
  234. continue;
  235. }
  236. delete[] planes[j].data;
  237. planes[j].data = NULL;
  238. }
  239. allocated = false;
  240. DEBUG_MSG("Buffer " << index << " deallocated");
  241. }
  242. int
  243. NvBuffer::ref()
  244. {
  245. int ref_count;
  246. pthread_mutex_lock(&ref_lock);
  247. ref_count = ++this->ref_count;
  248. pthread_mutex_unlock(&ref_lock);
  249. return ref_count;
  250. }
  251. int
  252. NvBuffer::unref()
  253. {
  254. int ref_count;
  255. pthread_mutex_lock(&ref_lock);
  256. if (this->ref_count > 0)
  257. {
  258. --this->ref_count;
  259. }
  260. ref_count = this->ref_count;
  261. pthread_mutex_unlock(&ref_lock);
  262. return ref_count;
  263. }
  264. int
  265. NvBuffer::fill_buffer_plane_format(uint32_t *num_planes,
  266. NvBuffer::NvBufferPlaneFormat *planefmts,
  267. uint32_t width, uint32_t height, uint32_t raw_pixfmt)
  268. {
  269. switch (raw_pixfmt)
  270. {
  271. case V4L2_PIX_FMT_YUV444M:
  272. *num_planes = 3;
  273. planefmts[0].width = width;
  274. planefmts[1].width = width;
  275. planefmts[2].width = width;
  276. planefmts[0].height = height;
  277. planefmts[1].height = height;
  278. planefmts[2].height = height;
  279. planefmts[0].bytesperpixel = 1;
  280. planefmts[1].bytesperpixel = 1;
  281. planefmts[2].bytesperpixel = 1;
  282. break;
  283. case V4L2_PIX_FMT_YUV422M:
  284. *num_planes = 3;
  285. planefmts[0].width = width;
  286. planefmts[1].width = width / 2;
  287. planefmts[2].width = width / 2;
  288. planefmts[0].height = height;
  289. planefmts[1].height = height;
  290. planefmts[2].height = height;
  291. planefmts[0].bytesperpixel = 1;
  292. planefmts[1].bytesperpixel = 1;
  293. planefmts[2].bytesperpixel = 1;
  294. break;
  295. case V4L2_PIX_FMT_YUV422RM:
  296. *num_planes = 3;
  297. planefmts[0].width = width;
  298. planefmts[1].width = width;
  299. planefmts[2].width = width;
  300. planefmts[0].height = height;
  301. planefmts[1].height = height / 2;
  302. planefmts[2].height = height / 2;
  303. planefmts[0].bytesperpixel = 1;
  304. planefmts[1].bytesperpixel = 1;
  305. planefmts[2].bytesperpixel = 1;
  306. break;
  307. case V4L2_PIX_FMT_YUV420M:
  308. case V4L2_PIX_FMT_YVU420M:
  309. *num_planes = 3;
  310. planefmts[0].width = width;
  311. planefmts[1].width = width / 2;
  312. planefmts[2].width = width / 2;
  313. planefmts[0].height = height;
  314. planefmts[1].height = height / 2;
  315. planefmts[2].height = height / 2;
  316. planefmts[0].bytesperpixel = 1;
  317. planefmts[1].bytesperpixel = 1;
  318. planefmts[2].bytesperpixel = 1;
  319. break;
  320. case V4L2_PIX_FMT_NV12M:
  321. *num_planes = 2;
  322. planefmts[0].width = width;
  323. planefmts[1].width = width / 2;
  324. planefmts[0].height = height;
  325. planefmts[1].height = height / 2;
  326. planefmts[0].bytesperpixel = 1;
  327. planefmts[1].bytesperpixel = 2;
  328. break;
  329. case V4L2_PIX_FMT_GREY:
  330. *num_planes = 1;
  331. planefmts[0].width = width;
  332. planefmts[0].height = height;
  333. planefmts[0].bytesperpixel = 1;
  334. break;
  335. case V4L2_PIX_FMT_YUYV:
  336. case V4L2_PIX_FMT_YVYU:
  337. case V4L2_PIX_FMT_UYVY:
  338. case V4L2_PIX_FMT_VYUY:
  339. *num_planes = 1;
  340. planefmts[0].width = width;
  341. planefmts[0].height = height;
  342. planefmts[0].bytesperpixel = 2;
  343. break;
  344. case V4L2_PIX_FMT_ABGR32:
  345. case V4L2_PIX_FMT_XRGB32:
  346. *num_planes = 1;
  347. planefmts[0].width = width;
  348. planefmts[0].height = height;
  349. planefmts[0].bytesperpixel = 4;
  350. break;
  351. case V4L2_PIX_FMT_P010M:
  352. *num_planes = 2;
  353. planefmts[0].width = width;
  354. planefmts[1].width = width / 2;
  355. planefmts[0].height = height;
  356. planefmts[1].height = height / 2;
  357. planefmts[0].bytesperpixel = 2;
  358. planefmts[1].bytesperpixel = 4;
  359. break;
  360. case V4L2_PIX_FMT_NV24M:
  361. *num_planes = 2;
  362. planefmts[0].width = width;
  363. planefmts[1].width = width;
  364. planefmts[0].height = height;
  365. planefmts[1].height = height;
  366. planefmts[0].bytesperpixel = 1;
  367. planefmts[1].bytesperpixel = 2;
  368. break;
  369. case V4L2_PIX_FMT_NV24_10LE:
  370. *num_planes = 2;
  371. planefmts[0].width = width;
  372. planefmts[1].width = width;
  373. planefmts[0].height = height;
  374. planefmts[1].height = height;
  375. planefmts[0].bytesperpixel = 2;
  376. planefmts[1].bytesperpixel = 4;
  377. break;
  378. default:
  379. ERROR_MSG("Unsupported pixel format " << raw_pixfmt);
  380. return -1;
  381. }
  382. return 0;
  383. }