- Main Page
- Modules
- Namespaces
- Classes
- Files

- Search for |

- File List
- File Members

# samples/common/classes/NvBuffer.cpp

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
    00003  *
    00004  * Redistribution and use in source and binary forms, with or without
    00005  * modification, are permitted provided that the following conditions
    00006  * are met:
    00007  *  * Redistributions of source code must retain the above copyright
    00008  *    notice, this list of conditions and the following disclaimer.
    00009  *  * Redistributions in binary form must reproduce the above copyright
    00010  *    notice, this list of conditions and the following disclaimer in the
    00011  *    documentation and/or other materials provided with the distribution.
    00012  *  * Neither the name of NVIDIA CORPORATION nor the names of its
    00013  *    contributors may be used to endorse or promote products derived
    00014  *    from this software without specific prior written permission.
    00015  *
    00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
    00017  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    00019  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    00020  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    00021  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    00022  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    00023  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    00024  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    00026  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    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 }