- Main Page
- Modules
- Namespaces
- Classes
- Files

- Search for |

- File List
- File Members

# samples/common/classes/NvV4l2ElementPlane.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 "NvV4l2ElementPlane.h"
    00030 #include "NvLogging.h"
    00031
    00032 #include <cstring>
    00033 #include <errno.h>
    00034 #include <libv4l2.h>
    00035 #include <sys/mman.h>
    00036 #include <sys/prctl.h>
    00037
    00038 #define CHECK_V4L2_RETURN(ret, str)              \
    00039     if (ret < 0) {                               \
    00040         PLANE_SYS_ERROR_MSG(str << ": failed");   \
    00041         return -1;                               \
    00042     } else {                                     \
    00043         PLANE_DEBUG_MSG(str << ": success");      \
    00044         return 0;                                \
    00045     }
    00046
    00047 using namespace std;
    00048
    00049 NvV4l2ElementPlane::NvV4l2ElementPlane(enum v4l2_buf_type buf_type,
    00050         const char *device_name, int &fd, bool blocking,
    00051         NvElementProfiler &profiler)
    00052     :fd(fd),
    00053      v4l2elem_profiler(profiler),
    00054      comp_name(device_name)
    00055 {
    00056     this->buf_type = buf_type;
    00057     this->blocking = blocking;
    00058     is_in_error = 0;
    00059     switch (buf_type)
    00060     {
    00061         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    00062             plane_name = "Output Plane";
    00063             break;
    00064         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    00065             plane_name = "Capture Plane";
    00066             break;
    00067         default:
    00068             ERROR_MSG("Unsupported v4l2_buf_type " << buf_type);
    00069             plane_name = "Unknown";
    00070             is_in_error = 1;
    00071     }
    00072
    00073     num_buffers = 0;
    00074     buffers = NULL;
    00075
    00076     n_planes = 0;
    00077     memset(&planefmts, 0, sizeof(planefmts));
    00078
    00079     num_queued_buffers = 0;
    00080     total_queued_buffers = 0;
    00081     total_dequeued_buffers = 0;
    00082
    00083     streamon = false;
    00084     pthread_mutex_init(&plane_lock, NULL);
    00085     pthread_cond_init(&plane_cond, NULL);
    00086
    00087     dqthread_running = false;
    00088     stop_dqthread = false;
    00089     dq_thread = 0;
    00090     callback = NULL;
    00091
    00092     memory_type = V4L2_MEMORY_MMAP;
    00093
    00094     dqThread_data = NULL;
    00095 }
    00096
    00097 NvV4l2ElementPlane::~NvV4l2ElementPlane()
    00098 {
    00099     pthread_mutex_destroy(&plane_lock);
    00100     pthread_cond_destroy(&plane_cond);
    00101 }
    00102
    00103 NvBuffer *
    00104 NvV4l2ElementPlane::getNthBuffer(uint32_t n)
    00105 {
    00106     if (n >= num_buffers)
    00107     {
    00108         PLANE_DEBUG_MSG("WARNING:Requested " << n << "th buffer out of " <<
    00109                 num_buffers << "buffers. Returning NULL");
    00110         return NULL;
    00111     }
    00112     return buffers[n];
    00113 }
    00114
    00115 int
    00116 NvV4l2ElementPlane::dqBuffer(struct v4l2_buffer &v4l2_buf, NvBuffer ** buffer,
    00117         NvBuffer ** shared_buffer, uint32_t num_retries)
    00118 {
    00119     int ret;
    00120
    00121     v4l2_buf.type = buf_type;
    00122     v4l2_buf.memory = memory_type;
    00123     do
    00124     {
    00125         ret = v4l2_ioctl(fd, VIDIOC_DQBUF, &v4l2_buf);
    00126
    00127         if (ret == 0)
    00128         {
    00129             pthread_mutex_lock(&plane_lock);
    00130             if (buffer)
    00131                 *buffer = buffers[v4l2_buf.index];
    00132             if (shared_buffer && memory_type == V4L2_MEMORY_DMABUF)
    00133             {
    00134                 *shared_buffer =
    00135                     (NvBuffer *) buffers[v4l2_buf.index]->shared_buffer;
    00136             }
    00137             for (uint32_t i = 0; i < buffers[v4l2_buf.index]->n_planes; i++)
    00138             {
    00139                 buffers[v4l2_buf.index]->planes[i].bytesused =
    00140                     v4l2_buf.m.planes[i].bytesused;
    00141             }
    00142
    00143             if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
    00144             {
    00145                 v4l2elem_profiler.finishProcessing(0, false);
    00146             }
    00147
    00148             total_dequeued_buffers++;
    00149             num_queued_buffers--;
    00150             pthread_cond_broadcast(&plane_cond);
    00151             PLANE_DEBUG_MSG("DQed buffer " << v4l2_buf.index);
    00152             pthread_mutex_unlock(&plane_lock);
    00153         }
    00154         else if (errno == EAGAIN)
    00155         {
    00156             pthread_mutex_lock(&plane_lock);
    00157             if (!streamon)
    00158             {
    00159                 pthread_mutex_unlock(&plane_lock);
    00160                 break;
    00161             }
    00162             pthread_mutex_unlock(&plane_lock);
    00163
    00164             if (num_retries-- == 0)
    00165             {
    00166                 PLANE_SYS_ERROR_MSG("Error while DQing buffer");
    00167                 break;
    00168             }
    00169             if (!blocking)
    00170             {
    00171                 usleep(1000);
    00172             }
    00173         }
    00174         else
    00175         {
    00176             is_in_error = 1;
    00177             PLANE_SYS_ERROR_MSG("Error while DQing buffer");
    00178             break;
    00179         }
    00180     }
    00181     while (ret && !is_in_error);
    00182
    00183     return ret;
    00184 }
    00185
    00186 int
    00187 NvV4l2ElementPlane::qBuffer(struct v4l2_buffer &v4l2_buf, NvBuffer * shared_buffer)
    00188 {
    00189     int ret;
    00190     uint32_t i;
    00191     NvBuffer *buffer;
    00192
    00193     pthread_mutex_lock(&plane_lock);
    00194     buffer = buffers[v4l2_buf.index];
    00195
    00196     v4l2_buf.type = buf_type;
    00197     v4l2_buf.memory = memory_type;
    00198     v4l2_buf.length = n_planes;
    00199
    00200     switch (memory_type)
    00201     {
    00202         case V4L2_MEMORY_USERPTR:
    00203             buffer->shared_buffer = shared_buffer;
    00204             for (i = 0; i < buffer->n_planes; i++)
    00205             {
    00206                 if (shared_buffer)
    00207                 {
    00208                     v4l2_buf.m.planes[i].m.userptr =
    00209                         (unsigned long) shared_buffer->planes[i].data;
    00210                     v4l2_buf.m.planes[i].bytesused =
    00211                         shared_buffer->planes[i].bytesused;
    00212                 }
    00213                 else
    00214                 {
    00215                     v4l2_buf.m.planes[i].m.userptr =
    00216                         (unsigned long) buffer->planes[i].data;
    00217                     v4l2_buf.m.planes[i].bytesused =
    00218                         buffer->planes[i].bytesused;
    00219                 }
    00220             }
    00221             break;
    00222         case V4L2_MEMORY_MMAP:
    00223             for (i = 0; i < buffer->n_planes; i++)
    00224             {
    00225                 v4l2_buf.m.planes[i].bytesused = buffer->planes[i].bytesused;
    00226             }
    00227             break;
    00228         case V4L2_MEMORY_DMABUF:
    00229             buffer->shared_buffer = shared_buffer;
    00230             if (shared_buffer)
    00231             {
    00232                 for (i = 0; i < buffer->n_planes; i++)
    00233                 {
    00234                     v4l2_buf.m.planes[i].m.fd = shared_buffer->planes[i].fd;
    00235                     v4l2_buf.m.planes[i].bytesused =
    00236                         shared_buffer->planes[i].bytesused;
    00237                 }
    00238             }
    00239             break;
    00240         default:
    00241             return -1;
    00242     }
    00243
    00244     if(buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
    00245     {
    00246         v4l2elem_profiler.startProcessing();
    00247     }
    00248
    00249     ret = v4l2_ioctl(fd, VIDIOC_QBUF, &v4l2_buf);
    00250     if (ret)
    00251     {
    00252         is_in_error = 1;
    00253         PLANE_SYS_ERROR_MSG("Error while Qing buffer");
    00254     }
    00255     else
    00256     {
    00257         PLANE_DEBUG_MSG("Qed buffer " << v4l2_buf.index);
    00258         pthread_cond_broadcast(&plane_cond);
    00259         total_queued_buffers++;
    00260         num_queued_buffers++;
    00261     }
    00262     pthread_mutex_unlock(&plane_lock);
    00263
    00264     return ret;
    00265 }
    00266
    00267 int
    00268 NvV4l2ElementPlane::getFormat(struct v4l2_format &format)
    00269 {
    00270     format.type = buf_type;
    00271     CHECK_V4L2_RETURN(v4l2_ioctl(fd, VIDIOC_G_FMT, &format),
    00272             "Getting format");
    00273 }
    00274
    00275 int
    00276 NvV4l2ElementPlane::setFormat(struct v4l2_format &format)
    00277 {
    00278     int ret;
    00279     int j;
    00280
    00281     format.type = buf_type;
    00282     ret = v4l2_ioctl(fd, VIDIOC_S_FMT, &format);
    00283     if (ret)
    00284     {
    00285         PLANE_SYS_ERROR_MSG("Error in VIDIOC_S_FMT");
    00286         is_in_error = 1;
    00287     }
    00288     else
    00289     {
    00290         PLANE_DEBUG_MSG("VIDIOC_S_FMT at capture plane successful");
    00291         n_planes = format.fmt.pix_mp.num_planes;
    00292         for (j = 0; j < n_planes; j++)
    00293         {
    00294             planefmts[j].stride = format.fmt.pix_mp.plane_fmt[j].bytesperline;
    00295             planefmts[j].sizeimage = format.fmt.pix_mp.plane_fmt[j].sizeimage;
    00296         }
    00297     }
    00298
    00299     return ret;
    00300 }
    00301
    00302 int
    00303 NvV4l2ElementPlane::getCrop(struct v4l2_crop & crop)
    00304 {
    00305     crop.type = buf_type;
    00306
    00307     CHECK_V4L2_RETURN(v4l2_ioctl(fd, VIDIOC_G_CROP, &crop),
    00308             "Getting crop params");
    00309 }
    00310
    00311 int
    00312 NvV4l2ElementPlane::setSelection(uint32_t target, uint32_t flags, struct v4l2_rect & rect)
    00313 {
    00314     struct v4l2_selection select;
    00315
    00316     switch (buf_type)
    00317     {
    00318         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    00319             select.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
    00320             break;
    00321         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    00322             select.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    00323             break;
    00324         default:
    00325             PLANE_ERROR_MSG("Unsupported v4l2_buf_type " << buf_type);
    00326             return -1;
    00327     }
    00328
    00329     select.target = target;
    00330     select.flags = flags;
    00331     select.r = rect;
    00332
    00333     CHECK_V4L2_RETURN(v4l2_ioctl(fd, VIDIOC_S_SELECTION, &select),
    00334             "Setting selection");
    00335 }
    00336
    00337 void
    00338 NvV4l2ElementPlane::setBufferPlaneFormat(int n_planes,
    00339         NvBuffer::NvBufferPlaneFormat * planefmts)
    00340 {
    00341     int i;
    00342
    00343     this->n_planes = n_planes;
    00344     for (i = 0; i < n_planes; i++)
    00345     {
    00346         this->planefmts[i] = planefmts[i];
    00347     }
    00348 }
    00349
    00350 void
    00351 NvV4l2ElementPlane::deinitPlane()
    00352 {
    00353     setStreamStatus(false);
    00354     waitForDQThread(-1);
    00355     for (uint32_t i = 0; i < num_buffers; i++)
    00356     {
    00357         switch (memory_type)
    00358         {
    00359             case V4L2_MEMORY_USERPTR:
    00360                 buffers[i]->deallocateMemory();
    00361                 break;
    00362             case V4L2_MEMORY_MMAP:
    00363                 buffers[i]->unmap();
    00364                 break;
    00365             case V4L2_MEMORY_DMABUF:
    00366                 break;
    00367             default:
    00368                 return;
    00369         }
    00370     }
    00371     reqbufs(memory_type, 0);
    00372     PLANE_DEBUG_MSG("deinit successful");
    00373 }
    00374
    00375 int
    00376 NvV4l2ElementPlane::reqbufs(enum v4l2_memory mem_type, uint32_t num)
    00377 {
    00378     struct v4l2_requestbuffers reqbufs;
    00379     int ret;
    00380
    00381     memset(&reqbufs, 0, sizeof(struct v4l2_requestbuffers));
    00382     reqbufs.count = num;
    00383     reqbufs.type = buf_type;
    00384     switch (mem_type)
    00385     {
    00386         case V4L2_MEMORY_USERPTR:
    00387             for (uint32_t i = 0; i < n_planes; i++)
    00388             {
    00389                 planefmts[i].stride =
    00390                     planefmts[i].width * planefmts[i].bytesperpixel;
    00391                 planefmts[i].sizeimage =
    00392                     planefmts[i].width * planefmts[i].height;
    00393             }
    00394             break;
    00395         case V4L2_MEMORY_MMAP:
    00396         case V4L2_MEMORY_DMABUF:
    00397             break;
    00398         default:
    00399             PLANE_ERROR_MSG("Error in VIDIOC_REQBUFS:Unknown memory type " <<
    00400                     mem_type);
    00401             return -1;
    00402     }
    00403     memory_type = mem_type;
    00404
    00405     reqbufs.memory = mem_type;
    00406     ret = v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
    00407     if (ret)
    00408     {
    00409         PLANE_SYS_ERROR_MSG("Error in VIDIOC_REQBUFS at output plane");
    00410         is_in_error = 1;
    00411     }
    00412     else
    00413     {
    00414         if (reqbufs.count)
    00415         {
    00416             buffers = new NvBuffer *[reqbufs.count];
    00417             for (uint32_t i = 0; i < reqbufs.count; i++)
    00418             {
    00419                 buffers[i] =
    00420                     new NvBuffer(buf_type, mem_type, n_planes, planefmts, i);
    00421             }
    00422         }
    00423         else
    00424         {
    00425             for (uint32_t i = 0; i < num_buffers; i++)
    00426             {
    00427                 delete buffers[i];
    00428             }
    00429             delete[] buffers;
    00430             buffers = NULL;
    00431         }
    00432         num_buffers = reqbufs.count;
    00433         PLANE_DEBUG_MSG("Reqbuf returned " << reqbufs.count << " buffers");
    00434     }
    00435
    00436     return ret;
    00437 }
    00438
    00439 int
    00440 NvV4l2ElementPlane::setStreamStatus(bool status)
    00441 {
    00442     int ret;
    00443
    00444     if (status == streamon)
    00445     {
    00446         PLANE_DEBUG_MSG("Already in " << ((status) ? "STREAMON" : "STREAMOFF"));
    00447         return 0;
    00448     }
    00449
    00450     pthread_mutex_lock(&plane_lock);
    00451     if (status)
    00452     {
    00453         ret = v4l2_ioctl(fd, VIDIOC_STREAMON, &buf_type);
    00454     }
    00455     else
    00456     {
    00457         ret = v4l2_ioctl(fd, VIDIOC_STREAMOFF, &buf_type);
    00458     }
    00459     if (ret)
    00460     {
    00461         PLANE_SYS_ERROR_MSG("Error in " <<
    00462                 ((status) ? "STREAMON" : "STREAMOFF"));
    00463         is_in_error = 1;
    00464     }
    00465     else
    00466     {
    00467         PLANE_DEBUG_MSG(((status) ? "STREAMON" : "STREAMOFF") << " successful");
    00468         streamon = status;
    00469         if (!streamon)
    00470         {
    00471             num_queued_buffers = 0;
    00472             pthread_cond_broadcast(&plane_cond);
    00473         }
    00474
    00475         if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
    00476         {
    00477             if (status)
    00478             {
    00479                 v4l2elem_profiler.enableProfiling(false);
    00480             }
    00481             else
    00482             {
    00483                 v4l2elem_profiler.disableProfiling();
    00484             }
    00485         }
    00486
    00487     }
    00488
    00489     pthread_mutex_unlock(&plane_lock);
    00490     return ret;
    00491 }
    00492
    00493 bool
    00494 NvV4l2ElementPlane::getStreamStatus()
    00495 {
    00496     return streamon;
    00497 }
    00498
    00499 int
    00500 NvV4l2ElementPlane::setStreamParms(struct v4l2_streamparm &parm)
    00501 {
    00502     int ret;
    00503
    00504     parm.type = buf_type;
    00505     ret = v4l2_ioctl(fd, VIDIOC_S_PARM, &parm);
    00506
    00507     if(ret == 0)
    00508     {
    00509         PLANE_DEBUG_MSG("Successfully set stream parameters");
    00510     }
    00511     else
    00512     {
    00513         PLANE_SYS_ERROR_MSG("Error while setting stream parameters");
    00514     }
    00515     return ret;
    00516 }
    00517
    00518 int
    00519 NvV4l2ElementPlane::queryBuffer(uint32_t i)
    00520 {
    00521     struct v4l2_buffer v4l2_buf;
    00522     struct v4l2_plane planes[MAX_PLANES];
    00523     int ret;
    00524     uint32_t j;
    00525
    00526     memset(&v4l2_buf, 0, sizeof(struct v4l2_buffer));
    00527     memset(planes, 0, sizeof(planes));
    00528     v4l2_buf.index = i;
    00529     v4l2_buf.type = buf_type;
    00530     v4l2_buf.memory = memory_type;
    00531     v4l2_buf.m.planes = planes;
    00532     v4l2_buf.length = n_planes;
    00533
    00534     ret = v4l2_ioctl(fd, VIDIOC_QUERYBUF, &v4l2_buf);
    00535     if (ret)
    00536     {
    00537         PLANE_SYS_ERROR_MSG("Error in QueryBuf for " << i << "th buffer");
    00538         is_in_error = 1;
    00539     }
    00540     else
    00541     {
    00542         PLANE_DEBUG_MSG("QueryBuf for " << i << "th buffer successful");
    00543
    00544         for (j = 0; j < v4l2_buf.length; j++)
    00545         {
    00546             buffers[i]->planes[j].length = v4l2_buf.m.planes[j].length;
    00547             buffers[i]->planes[j].mem_offset =
    00548                 v4l2_buf.m.planes[j].m.mem_offset;
    00549         }
    00550     }
    00551
    00552     return ret;
    00553 }
    00554
    00555 int
    00556 NvV4l2ElementPlane::exportBuffer(uint32_t i)
    00557 {
    00558     struct v4l2_exportbuffer expbuf;
    00559     int ret;
    00560     int j;
    00561
    00562     memset(&expbuf, 0, sizeof(expbuf));
    00563     expbuf.type = buf_type;
    00564     expbuf.index = i;
    00565
    00566     for (j = 0; j < n_planes; j++)
    00567     {
    00568         expbuf.plane = j;
    00569         ret = v4l2_ioctl(fd, VIDIOC_EXPBUF, &expbuf);
    00570         if (ret)
    00571         {
    00572             PLANE_SYS_ERROR_MSG("Error in ExportBuf for Buffer " << i <<
    00573                     ", Plane " << j);
    00574             is_in_error = 1;
    00575             return -1;
    00576         }
    00577         else
    00578         {
    00579             PLANE_DEBUG_MSG("ExportBuf successful for Buffer " << i <<
    00580                     ", Plane " << j << ", fd = " << expbuf.fd);
    00581             buffers[i]->planes[j].fd = expbuf.fd;
    00582         }
    00583     }
    00584     return 0;
    00585 }
    00586
    00587 int
    00588 NvV4l2ElementPlane::setupPlane(enum v4l2_memory mem_type, uint32_t num_buffers,
    00589         bool map, bool allocate)
    00590 {
    00591     uint32_t i;
    00592
    00593     if (reqbufs(mem_type, num_buffers))
    00594     {
    00595         goto error;
    00596     }
    00597
    00598     for (i = 0; i < this->num_buffers; i++)
    00599     {
    00600         switch (mem_type)
    00601         {
    00602             case V4L2_MEMORY_USERPTR:
    00603                 if (allocate)
    00604                 {
    00605                     if (buffers[i]->allocateMemory())
    00606                     {
    00607                         goto error;
    00608                     }
    00609                 }
    00610                 break;
    00611             case V4L2_MEMORY_MMAP:
    00612                 if (queryBuffer(i))
    00613                 {
    00614                     goto error;
    00615                 }
    00616                 if (exportBuffer(i))
    00617                 {
    00618                     goto error;
    00619                 }
    00620                 if (map)
    00621                 {
    00622                     if (buffers[i]->map())
    00623                     {
    00624                         goto error;
    00625                     }
    00626                 }
    00627                 break;
    00628             default:
    00629                 continue;
    00630         }
    00631     }
    00632     return 0;
    00633
    00634 error:
    00635     PLANE_ERROR_MSG("Error during setup");
    00636     is_in_error = 1;
    00637     deinitPlane();
    00638     return -1;
    00639 }
    00640
    00641 int
    00642 NvV4l2ElementPlane::waitAllBuffersQueued(uint32_t max_wait_ms)
    00643 {
    00644     struct timespec timeToWait;
    00645     struct timeval now;
    00646     int return_val = 0;
    00647     int ret;
    00648
    00649     gettimeofday(&now, NULL);
    00650
    00651     timeToWait.tv_nsec = (now.tv_usec + (max_wait_ms % 1000) * 1000L) * 1000L;
    00652     timeToWait.tv_sec = now.tv_sec + max_wait_ms / 1000 +
    00653         timeToWait.tv_nsec / 1000000000L;
    00654     timeToWait.tv_nsec = timeToWait.tv_nsec % 1000000000L;
    00655
    00656     pthread_mutex_lock(&plane_lock);
    00657     while (num_queued_buffers < num_buffers)
    00658     {
    00659         ret = pthread_cond_timedwait(&plane_cond, &plane_lock, &timeToWait);
    00660         if (ret == ETIMEDOUT)
    00661         {
    00662             return_val = -1;
    00663             break;
    00664         }
    00665     }
    00666     pthread_mutex_unlock(&plane_lock);
    00667
    00668     CHECK_V4L2_RETURN(return_val, "Waiting for all buffers to get queued");
    00669 }
    00670
    00671 int
    00672 NvV4l2ElementPlane::waitAllBuffersDequeued(uint32_t max_wait_ms)
    00673 {
    00674     struct timespec timeToWait;
    00675     struct timeval now;
    00676     int return_val = 0;
    00677     int ret;
    00678
    00679     gettimeofday(&now, NULL);
    00680
    00681     timeToWait.tv_nsec = (now.tv_usec + (max_wait_ms % 1000) * 1000L) * 1000L;
    00682     timeToWait.tv_sec = now.tv_sec + max_wait_ms / 1000 +
    00683         timeToWait.tv_nsec / 1000000000L;
    00684     timeToWait.tv_nsec = timeToWait.tv_nsec % 1000000000L;
    00685
    00686     pthread_mutex_lock(&plane_lock);
    00687     while (num_queued_buffers)
    00688     {
    00689         ret = pthread_cond_timedwait(&plane_cond, &plane_lock, &timeToWait);
    00690         if (ret == ETIMEDOUT)
    00691         {
    00692             return_val = -1;
    00693             break;
    00694         }
    00695     }
    00696     pthread_mutex_unlock(&plane_lock);
    00697
    00698     CHECK_V4L2_RETURN(return_val, "Waiting for all buffers to get dequeued");
    00699 }
    00700
    00701 bool NvV4l2ElementPlane::setDQThreadCallback(dqThreadCallback callback)
    00702 {
    00703     if (dqthread_running)
    00704         return false;
    00705     this->callback = callback;
    00706     return true;
    00707 }
    00708
    00709 void *
    00710 NvV4l2ElementPlane::dqThread(void *data)
    00711 {
    00712     NvV4l2ElementPlane *plane = (NvV4l2ElementPlane *) data;
    00713     const char *comp_name = plane->comp_name;
    00714     const char *plane_name = plane->plane_name;
    00715
    00716     PLANE_DEBUG_MSG("Starting DQthread");
    00717     prctl (PR_SET_NAME, plane_name, 0, 0, 0);
    00718     plane->stop_dqthread = false;
    00719     while (!plane->stop_dqthread)
    00720     {
    00721         struct v4l2_buffer v4l2_buf;
    00722         struct v4l2_plane planes[MAX_PLANES];
    00723         NvBuffer *buffer;
    00724         NvBuffer *shared_buffer;
    00725         bool ret;
    00726
    00727         memset(&v4l2_buf, 0, sizeof(v4l2_buf));
    00728         memset(planes, 0, sizeof(planes));
    00729         v4l2_buf.m.planes = planes;
    00730         v4l2_buf.length = plane->n_planes;
    00731
    00732         if (plane->dqBuffer(v4l2_buf, &buffer, &shared_buffer, -1) < 0)
    00733         {
    00734             if (errno != EAGAIN)
    00735             {
    00736                 plane->is_in_error = 1;
    00737             }
    00738             if (errno != EAGAIN || plane->streamon)
    00739             {
    00740                 ret = plane->callback(NULL, NULL, NULL, plane->dqThread_data);
    00741             }
    00742             if (!plane->streamon)
    00743             {
    00744                 break;
    00745             }
    00746         }
    00747         else
    00748         {
    00749             ret = plane->callback(&v4l2_buf, buffer, shared_buffer,
    00750                     plane->dqThread_data);
    00751         }
    00752         if (!ret)
    00753         {
    00754             break;
    00755         }
    00756     }
    00757     plane->stop_dqthread = false;
    00758
    00759     pthread_mutex_lock(&plane->plane_lock);
    00760     plane->dqthread_running = false;
    00761     pthread_cond_broadcast(&plane->plane_cond);
    00762     pthread_mutex_unlock(&plane->plane_lock);
    00763     PLANE_DEBUG_MSG("Exiting DQthread");
    00764     return NULL;
    00765 }
    00766
    00767 int
    00768 NvV4l2ElementPlane::startDQThread(void *data)
    00769 {
    00770     pthread_mutex_lock(&plane_lock);
    00771     if (dqthread_running)
    00772     {
    00773         PLANE_DEBUG_MSG("DQ Thread already started");
    00774         pthread_mutex_unlock(&plane_lock);
    00775         return 0;
    00776     }
    00777     dqThread_data = data;
    00778     pthread_create(&dq_thread, NULL, dqThread, this);
    00779     dqthread_running = true;
    00780     pthread_mutex_unlock(&plane_lock);
    00781     PLANE_DEBUG_MSG("Started DQ Thread");
    00782     return 0;
    00783 }
    00784
    00785 int
    00786 NvV4l2ElementPlane::stopDQThread()
    00787 {
    00788     if (blocking)
    00789     {
    00790         PLANE_WARN_MSG("Should not be called in blocking mode");
    00791         return 0;
    00792     }
    00793     stop_dqthread = true;
    00794     pthread_join(dq_thread, NULL);
    00795     dq_thread = 0;
    00796     PLANE_DEBUG_MSG("Stopped DQ Thread");
    00797     return 0;
    00798 }
    00799
    00800 int
    00801 NvV4l2ElementPlane::waitForDQThread(uint32_t max_wait_ms)
    00802 {
    00803     struct timespec timeToWait;
    00804     struct timeval now;
    00805     int return_val = 0;
    00806     int ret = 0;
    00807
    00808     gettimeofday(&now, NULL);
    00809
    00810     timeToWait.tv_nsec = (now.tv_usec + (max_wait_ms % 1000) * 1000L) * 1000L;
    00811     timeToWait.tv_sec = now.tv_sec + max_wait_ms / 1000 +
    00812         timeToWait.tv_nsec / 1000000000L;
    00813     timeToWait.tv_nsec = timeToWait.tv_nsec % 1000000000L;
    00814
    00815     pthread_mutex_lock(&plane_lock);
    00816     while (dqthread_running)
    00817     {
    00818         ret = pthread_cond_timedwait(&plane_cond, &plane_lock, &timeToWait);
    00819         if (ret == ETIMEDOUT)
    00820         {
    00821             return_val = -1;
    00822             break;
    00823         }
    00824     }
    00825     pthread_mutex_unlock(&plane_lock);
    00826
    00827     if (ret == 0)
    00828     {
    00829         pthread_join(dq_thread, NULL);
    00830         dq_thread = 0;
    00831         PLANE_DEBUG_MSG("Stopped DQ Thread");
    00832     }
    00833     else
    00834     {
    00835         PLANE_ERROR_MSG("Timed out waiting for dqthread");
    00836     }
    00837     return return_val;
    00838 }