00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "NvBuffer.h"
00030 #include "NvLogging.h"
00031
00032 #include <cstring>
00033 #include <errno.h>
00034 #include <sys/mman.h>
00035 #include <libv4l2.h>
00036
00037 #define CAT_NAME "Buffer"
00038
00039 #define MAX(a,b) (a > b ? a : b)
00040
00041 NvBuffer::NvBuffer(enum v4l2_buf_type buf_type, enum v4l2_memory memory_type,
00042 uint32_t n_planes, NvBufferPlaneFormat * fmt, uint32_t index)
00043 :buf_type(buf_type),
00044 memory_type(memory_type),
00045 index(index),
00046 n_planes(n_planes)
00047 {
00048 uint32_t i;
00049
00050 mapped = false;
00051 allocated = false;
00052
00053 memset(planes, 0, sizeof(planes));
00054 for (i = 0; i < n_planes; i++)
00055 {
00056 this->planes[i].fd = -1;
00057 this->planes[i].fmt = fmt[i];
00058 }
00059
00060 ref_count = 0;
00061 pthread_mutex_init(&ref_lock, NULL);
00062 shared_buffer = NULL;
00063 }
00064
00065 NvBuffer::NvBuffer(uint32_t pixfmt, uint32_t width, uint32_t height,
00066 uint32_t index)
00067 :buf_type(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE),
00068 memory_type(V4L2_MEMORY_USERPTR),
00069 index(index)
00070 {
00071 uint32_t i;
00072 NvBuffer::NvBufferPlaneFormat fmt[MAX_PLANES];
00073
00074 mapped = false;
00075 allocated = false;
00076
00077 fill_buffer_plane_format(&n_planes, fmt, width, height, pixfmt);
00078
00079 for (i = 0; i < n_planes; i++)
00080 {
00081 this->planes[i].fd = -1;
00082 this->planes[i].data = NULL;
00083 this->planes[i].bytesused = 0;
00084 this->planes[i].mem_offset = 0;
00085 this->planes[i].length = 0;
00086 this->planes[i].fmt = fmt[i];
00087 this->planes[i].fmt.sizeimage = fmt[i].width * fmt[i].height *
00088 fmt[i].bytesperpixel;
00089 this->planes[i].fmt.stride = fmt[i].width * fmt[i].bytesperpixel;
00090 }
00091
00092 ref_count = 0;
00093 pthread_mutex_init(&ref_lock, NULL);
00094 shared_buffer = NULL;
00095 }
00096
00097 NvBuffer::NvBuffer(uint32_t size, uint32_t index)
00098 :buf_type(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE),
00099 memory_type(V4L2_MEMORY_USERPTR),
00100 index(index)
00101 {
00102 uint32_t i;
00103
00104 mapped = false;
00105 allocated = false;
00106
00107 n_planes = 1;
00108 for (i = 0; i < n_planes; i++)
00109 {
00110 this->planes[i].fd = -1;
00111 this->planes[i].data = NULL;
00112 this->planes[i].bytesused = 0;
00113 this->planes[i].mem_offset = 0;
00114 this->planes[i].length = 0;
00115 this->planes[i].fmt.sizeimage = size;
00116 }
00117
00118 ref_count = 0;
00119 pthread_mutex_init(&ref_lock, NULL);
00120 shared_buffer = NULL;
00121 }
00122
00123 NvBuffer::~NvBuffer()
00124 {
00125 if (mapped)
00126 {
00127 unmap();
00128 }
00129 if (allocated)
00130 {
00131 deallocateMemory();
00132 }
00133
00134 pthread_mutex_destroy(&ref_lock);
00135 }
00136
00137 int
00138 NvBuffer::map()
00139 {
00140 uint32_t j;
00141
00142 if (memory_type != V4L2_MEMORY_MMAP)
00143 {
00144 CAT_WARN_MSG("Buffer " << index << "already mapped");
00145 return -1;
00146 }
00147
00148 if (mapped)
00149 {
00150 CAT_WARN_MSG("Buffer " << index << "already mapped");
00151 return 0;
00152 }
00153
00154 for (j = 0; j < n_planes; j++)
00155 {
00156 if (planes[j].fd == -1)
00157 {
00158 return -1;
00159 }
00160
00161 planes[j].data = (unsigned char *) mmap(NULL,
00162 planes[j].length,
00163 PROT_READ | PROT_WRITE,
00164 MAP_SHARED,
00165 planes[j].fd,
00166 planes[j].mem_offset);
00167 if (planes[j].data == MAP_FAILED)
00168 {
00169 CAT_ERROR_MSG("Could not map buffer " << index << ", plane " << j);
00170 return -1;
00171 }
00172 else
00173 {
00174 CAT_DEBUG_MSG("Mapped buffer " << index << ", plane " << j << " to "
00175 << planes[j].data);
00176 }
00177 }
00178 mapped = true;
00179 return 0;
00180 }
00181
00182 void
00183 NvBuffer::unmap()
00184 {
00185 if (memory_type != V4L2_MEMORY_MMAP || !mapped)
00186 {
00187 CAT_WARN_MSG("Cannot Unmap Buffer " << index <<
00188 ". Only mapped MMAP buffer can be unmapped");
00189 return;
00190 }
00191
00192 for (uint32_t j = 0; j < n_planes; j++)
00193 {
00194 if (planes[j].data)
00195 {
00196 munmap(planes[j].data, planes[j].length);
00197 }
00198 planes[j].data = NULL;
00199 }
00200 mapped = false;
00201 CAT_DEBUG_MSG("Buffer " << index << " unmapped ");
00202 }
00203
00204 int
00205 NvBuffer::allocateMemory()
00206 {
00207 uint32_t j;
00208
00209 if (memory_type != V4L2_MEMORY_USERPTR)
00210 {
00211 CAT_ERROR_MSG("Only USERPTR buffers can be allocated");
00212 return -1;
00213 }
00214
00215 if (allocated)
00216 {
00217 CAT_WARN_MSG("Buffer " << index << "already allocated memory");
00218 return 0;
00219 }
00220
00221 for (j = 0; j < n_planes; j++)
00222 {
00223 if (planes[j].data)
00224 {
00225 ERROR_MSG("Buffer " << index << ", Plane " << j <<
00226 " already allocated");
00227 return -1;
00228 }
00229
00230 planes[j].length = MAX(planes[j].fmt.sizeimage,
00231 planes[j].fmt.width *
00232 planes[j].fmt.bytesperpixel *
00233 planes[j].fmt.height);
00234 planes[j].data = new unsigned char [planes[j].length];
00235
00236 if (planes[j].data == MAP_FAILED)
00237 {
00238 SYS_ERROR_MSG("Error while allocating buffer " << index <<
00239 " plane " << j);
00240 return -1;
00241 }
00242 else
00243 {
00244 DEBUG_MSG("Buffer " << index << ", Plane " << j <<
00245 " allocated to " << (void *) planes[j].data);
00246 }
00247 }
00248 allocated = true;
00249 return 0;
00250 }
00251
00252 void
00253 NvBuffer::deallocateMemory()
00254 {
00255 uint32_t j;
00256
00257 if (memory_type != V4L2_MEMORY_USERPTR || !allocated)
00258 {
00259 ERROR_MSG("Only allocated USERPTR buffers can be deallocated");
00260 return;
00261 }
00262
00263 for (j = 0; j < n_planes; j++)
00264 {
00265 if (!planes[j].data)
00266 {
00267 DEBUG_MSG("Buffer " << index << ", Plane " << j <<
00268 " not allocated");
00269 continue;
00270 }
00271 delete[] planes[j].data;
00272 planes[j].data = NULL;
00273 }
00274 allocated = false;
00275 DEBUG_MSG("Buffer " << index << " deallocated");
00276 }
00277
00278 int
00279 NvBuffer::ref()
00280 {
00281 int ref_count;
00282
00283 pthread_mutex_lock(&ref_lock);
00284 ref_count = ++this->ref_count;
00285 pthread_mutex_unlock(&ref_lock);
00286 return ref_count;
00287 }
00288
00289 int
00290 NvBuffer::unref()
00291 {
00292 int ref_count;
00293
00294 pthread_mutex_lock(&ref_lock);
00295 if (this->ref_count > 0)
00296 {
00297 --this->ref_count;
00298 }
00299 ref_count = this->ref_count;
00300 pthread_mutex_unlock(&ref_lock);
00301 return ref_count;
00302 }
00303
00304 int
00305 NvBuffer::fill_buffer_plane_format(uint32_t *num_planes,
00306 NvBuffer::NvBufferPlaneFormat *planefmts,
00307 uint32_t width, uint32_t height, uint32_t raw_pixfmt)
00308 {
00309 switch (raw_pixfmt)
00310 {
00311 case V4L2_PIX_FMT_YUV444M:
00312 *num_planes = 3;
00313
00314 planefmts[0].width = width;
00315 planefmts[1].width = width;
00316 planefmts[2].width = width;
00317
00318 planefmts[0].height = height;
00319 planefmts[1].height = height;
00320 planefmts[2].height = height;
00321
00322 planefmts[0].bytesperpixel = 1;
00323 planefmts[1].bytesperpixel = 1;
00324 planefmts[2].bytesperpixel = 1;
00325 break;
00326 case V4L2_PIX_FMT_YUV422M:
00327 *num_planes = 3;
00328
00329 planefmts[0].width = width;
00330 planefmts[1].width = width / 2;
00331 planefmts[2].width = width / 2;
00332
00333 planefmts[0].height = height;
00334 planefmts[1].height = height;
00335 planefmts[2].height = height;
00336
00337 planefmts[0].bytesperpixel = 1;
00338 planefmts[1].bytesperpixel = 1;
00339 planefmts[2].bytesperpixel = 1;
00340 break;
00341 case V4L2_PIX_FMT_YUV422RM:
00342 *num_planes = 3;
00343
00344 planefmts[0].width = width;
00345 planefmts[1].width = width;
00346 planefmts[2].width = width;
00347
00348 planefmts[0].height = height;
00349 planefmts[1].height = height / 2;
00350 planefmts[2].height = height / 2;
00351
00352 planefmts[0].bytesperpixel = 1;
00353 planefmts[1].bytesperpixel = 1;
00354 planefmts[2].bytesperpixel = 1;
00355 break;
00356 case V4L2_PIX_FMT_YUV420M:
00357 case V4L2_PIX_FMT_YVU420M:
00358 *num_planes = 3;
00359
00360 planefmts[0].width = width;
00361 planefmts[1].width = width / 2;
00362 planefmts[2].width = width / 2;
00363
00364 planefmts[0].height = height;
00365 planefmts[1].height = height / 2;
00366 planefmts[2].height = height / 2;
00367
00368 planefmts[0].bytesperpixel = 1;
00369 planefmts[1].bytesperpixel = 1;
00370 planefmts[2].bytesperpixel = 1;
00371 break;
00372 case V4L2_PIX_FMT_NV12M:
00373 *num_planes = 2;
00374
00375 planefmts[0].width = width;
00376 planefmts[1].width = width / 2;
00377
00378 planefmts[0].height = height;
00379 planefmts[1].height = height / 2;
00380
00381 planefmts[0].bytesperpixel = 1;
00382 planefmts[1].bytesperpixel = 2;
00383 break;
00384 case V4L2_PIX_FMT_GREY:
00385 *num_planes = 1;
00386
00387 planefmts[0].width = width;
00388
00389 planefmts[0].height = height;
00390
00391 planefmts[0].bytesperpixel = 1;
00392 break;
00393 case V4L2_PIX_FMT_YUYV:
00394 case V4L2_PIX_FMT_YVYU:
00395 case V4L2_PIX_FMT_UYVY:
00396 case V4L2_PIX_FMT_VYUY:
00397 *num_planes = 1;
00398
00399 planefmts[0].width = width;
00400
00401 planefmts[0].height = height;
00402
00403 planefmts[0].bytesperpixel = 2;
00404 break;
00405 case V4L2_PIX_FMT_ABGR32:
00406 case V4L2_PIX_FMT_XRGB32:
00407 *num_planes = 1;
00408
00409 planefmts[0].width = width;
00410
00411 planefmts[0].height = height;
00412
00413 planefmts[0].bytesperpixel = 4;
00414 break;
00415 default:
00416 ERROR_MSG("Unsupported pixel format " << raw_pixfmt);
00417 return -1;
00418 }
00419 return 0;
00420 }