123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935 |
- /*
- * Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of NVIDIA CORPORATION nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "NvV4l2ElementPlane.h"
- #include "NvLogging.h"
- #include <cstring>
- #include <errno.h>
- #include <libv4l2.h>
- #include <sys/mman.h>
- #include <sys/prctl.h>
- #include "nvbufsurface.h"
- #define CHECK_V4L2_RETURN(ret, str) \
- if (ret < 0) { \
- PLANE_SYS_ERROR_MSG(str << ": failed"); \
- return -1; \
- } else { \
- PLANE_DEBUG_MSG(str << ": success"); \
- return 0; \
- }
- using namespace std;
- NvV4l2ElementPlane::NvV4l2ElementPlane(enum v4l2_buf_type buf_type,
- const char *device_name, int &fd, bool blocking,
- NvElementProfiler &profiler)
- :fd(fd),
- v4l2elem_profiler(profiler),
- comp_name(device_name)
- {
- this->buf_type = buf_type;
- this->blocking = blocking;
- is_in_error = 0;
- switch (buf_type)
- {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- plane_name = "Output Plane";
- break;
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- plane_name = "Capture Plane";
- break;
- default:
- ERROR_MSG("Unsupported v4l2_buf_type " << buf_type);
- plane_name = "Unknown";
- is_in_error = 1;
- }
- num_buffers = 0;
- buffers = NULL;
- n_planes = 0;
- memset(&planefmts, 0, sizeof(planefmts));
- num_queued_buffers = 0;
- total_queued_buffers = 0;
- total_dequeued_buffers = 0;
- streamon = false;
- pthread_mutex_init(&plane_lock, NULL);
- pthread_cond_init(&plane_cond, NULL);
- dqthread_running = false;
- stop_dqthread = false;
- dq_thread = 0;
- callback = NULL;
- memory_type = V4L2_MEMORY_MMAP;
- dqThread_data = NULL;
- }
- NvV4l2ElementPlane::~NvV4l2ElementPlane()
- {
- pthread_mutex_destroy(&plane_lock);
- pthread_cond_destroy(&plane_cond);
- }
- NvBuffer *
- NvV4l2ElementPlane::getNthBuffer(uint32_t n)
- {
- if (n >= num_buffers)
- {
- PLANE_DEBUG_MSG("WARNING:Requested " << n << "th buffer out of " <<
- num_buffers << "buffers. Returning NULL");
- return NULL;
- }
- return buffers[n];
- }
- int
- NvV4l2ElementPlane::dqBuffer(struct v4l2_buffer &v4l2_buf, NvBuffer ** buffer,
- NvBuffer ** shared_buffer, uint32_t num_retries)
- {
- int ret;
- v4l2_buf.type = buf_type;
- v4l2_buf.memory = memory_type;
- do
- {
- ret = v4l2_ioctl(fd, VIDIOC_DQBUF, &v4l2_buf);
- if (ret == 0)
- {
- pthread_mutex_lock(&plane_lock);
- if (buffer)
- *buffer = buffers[v4l2_buf.index];
- if (shared_buffer && memory_type == V4L2_MEMORY_DMABUF)
- {
- *shared_buffer =
- (NvBuffer *) buffers[v4l2_buf.index]->shared_buffer;
- }
- for (uint32_t i = 0; i < buffers[v4l2_buf.index]->n_planes; i++)
- {
- buffers[v4l2_buf.index]->planes[i].bytesused =
- v4l2_buf.m.planes[i].bytesused;
- }
- if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- {
- v4l2elem_profiler.finishProcessing(0, false);
- }
- total_dequeued_buffers++;
- num_queued_buffers--;
- pthread_cond_broadcast(&plane_cond);
- PLANE_DEBUG_MSG("DQed buffer " << v4l2_buf.index);
- pthread_mutex_unlock(&plane_lock);
- }
- else if (errno == EAGAIN)
- {
- pthread_mutex_lock(&plane_lock);
- if (v4l2_buf.flags & V4L2_BUF_FLAG_LAST)
- {
- pthread_mutex_unlock(&plane_lock);
- break;
- }
- pthread_mutex_unlock(&plane_lock);
- if (num_retries-- == 0)
- {
- PLANE_WARN_MSG("Error while DQing buffer: Resource temporarily unavailable");
- break;
- }
- if (!blocking)
- {
- break;
- }
- }
- else
- {
- is_in_error = 1;
- PLANE_SYS_ERROR_MSG("Error while DQing buffer");
- break;
- }
- }
- while (ret && !is_in_error);
- return ret;
- }
- int
- NvV4l2ElementPlane::qBuffer(struct v4l2_buffer &v4l2_buf, NvBuffer * shared_buffer)
- {
- int ret;
- uint32_t i;
- NvBuffer *buffer;
- pthread_mutex_lock(&plane_lock);
- buffer = buffers[v4l2_buf.index];
- v4l2_buf.type = buf_type;
- v4l2_buf.memory = memory_type;
- v4l2_buf.length = n_planes;
- switch (memory_type)
- {
- case V4L2_MEMORY_USERPTR:
- buffer->shared_buffer = shared_buffer;
- for (i = 0; i < buffer->n_planes; i++)
- {
- if (shared_buffer)
- {
- v4l2_buf.m.planes[i].m.userptr =
- (unsigned long) shared_buffer->planes[i].data;
- v4l2_buf.m.planes[i].bytesused =
- shared_buffer->planes[i].bytesused;
- }
- else
- {
- v4l2_buf.m.planes[i].m.userptr =
- (unsigned long) buffer->planes[i].data;
- v4l2_buf.m.planes[i].bytesused =
- buffer->planes[i].bytesused;
- }
- }
- break;
- case V4L2_MEMORY_MMAP:
- for (i = 0; i < buffer->n_planes; i++)
- {
- v4l2_buf.m.planes[i].bytesused = buffer->planes[i].bytesused;
- }
- break;
- case V4L2_MEMORY_DMABUF:
- buffer->shared_buffer = shared_buffer;
- if (shared_buffer)
- {
- for (i = 0; i < buffer->n_planes; i++)
- {
- v4l2_buf.m.planes[i].m.fd = shared_buffer->planes[i].fd;
- v4l2_buf.m.planes[i].bytesused =
- shared_buffer->planes[i].bytesused;
- }
- }
- break;
- default:
- pthread_cond_broadcast(&plane_cond);
- pthread_mutex_unlock(&plane_lock);
- return -1;
- }
- if(buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
- {
- v4l2elem_profiler.startProcessing();
- }
- ret = v4l2_ioctl(fd, VIDIOC_QBUF, &v4l2_buf);
- if (ret)
- {
- is_in_error = 1;
- PLANE_SYS_ERROR_MSG("Error while Qing buffer");
- }
- else
- {
- PLANE_DEBUG_MSG("Qed buffer " << v4l2_buf.index);
- pthread_cond_broadcast(&plane_cond);
- total_queued_buffers++;
- num_queued_buffers++;
- }
- pthread_mutex_unlock(&plane_lock);
- return ret;
- }
- int
- NvV4l2ElementPlane::mapOutputBuffers(struct v4l2_buffer &v4l2_buf, int dmabuff_fd)
- {
- int ret;
- uint32_t i;
- pthread_mutex_lock(&plane_lock);
- unsigned char *data;
- NvBufSurface *nvbuf_surf = 0;
- switch (memory_type)
- {
- case V4L2_MEMORY_DMABUF:
- ret = NvBufSurfaceFromFd (dmabuff_fd, (void**)(&nvbuf_surf));
- if(ret < 0)
- {
- PLANE_SYS_ERROR_MSG("Error: NvBufSurfaceFromFd Failed\n");
- pthread_mutex_unlock(&plane_lock);
- return ret;
- }
- for (i = 0; i < n_planes; i++)
- {
- buffers[v4l2_buf.index]->planes[i].fd = dmabuff_fd;
- v4l2_buf.m.planes[i].m.fd = buffers[v4l2_buf.index]->planes[i].fd;
- buffers[v4l2_buf.index]->planes[i].mem_offset = nvbuf_surf->surfaceList[0].planeParams.offset[i];
- ret = NvBufSurfaceMap(nvbuf_surf, 0, i, NVBUF_MAP_READ_WRITE);
- if (ret < 0)
- {
- is_in_error = 1;
- PLANE_SYS_ERROR_MSG("Error while Mapping buffer");
- pthread_mutex_unlock(&plane_lock);
- return ret;
- }
- data = (unsigned char *)nvbuf_surf->surfaceList[0].mappedAddr.addr[i];
- buffers[v4l2_buf.index]->planes[i].data=data;
- }
- break;
- default:
- pthread_mutex_unlock(&plane_lock);
- return -1;
- }
- if(ret == 0)
- {
- PLANE_DEBUG_MSG("Mapped Nvbuffer to buffers " << v4l2_buf.index);
- }
- pthread_mutex_unlock(&plane_lock);
- return ret;
- }
- int
- NvV4l2ElementPlane::unmapOutputBuffers(int index, int dmabuff_fd)
- {
- int ret = 0;
- uint32_t i;
- NvBufSurface *nvbuf_surf = 0;
- pthread_mutex_lock(&plane_lock);
- switch (memory_type)
- {
- case V4L2_MEMORY_DMABUF:
- for (i = 0; i < n_planes; i++)
- {
- ret = NvBufSurfaceFromFd (dmabuff_fd, (void**)(&nvbuf_surf));
- if (ret < 0)
- {
- is_in_error = 1;
- PLANE_SYS_ERROR_MSG("Error while NvBufSurfaceFromFd");
- pthread_mutex_unlock(&plane_lock);
- return ret;
- }
- ret = NvBufSurfaceUnMap(nvbuf_surf, 0, i);
- if (ret < 0)
- {
- is_in_error = 1;
- PLANE_SYS_ERROR_MSG("Error while Unmapping buffer");
- pthread_mutex_unlock(&plane_lock);
- return ret;
- }
- }
- break;
- default:
- pthread_mutex_unlock(&plane_lock);
- return -1;
- }
- if(ret == 0)
- {
- PLANE_DEBUG_MSG("Unmapped Nvbuffer to buffers " << index);
- }
- pthread_mutex_unlock(&plane_lock);
- return ret;
- }
- int
- NvV4l2ElementPlane::getFormat(struct v4l2_format &format)
- {
- format.type = buf_type;
- CHECK_V4L2_RETURN(v4l2_ioctl(fd, VIDIOC_G_FMT, &format),
- "Getting format");
- }
- int
- NvV4l2ElementPlane::setFormat(struct v4l2_format &format)
- {
- int ret;
- int j;
- format.type = buf_type;
- ret = v4l2_ioctl(fd, VIDIOC_S_FMT, &format);
- if (ret)
- {
- PLANE_SYS_ERROR_MSG("Error in VIDIOC_S_FMT");
- is_in_error = 1;
- }
- else
- {
- PLANE_DEBUG_MSG("VIDIOC_S_FMT at capture plane successful");
- n_planes = format.fmt.pix_mp.num_planes;
- for (j = 0; j < n_planes; j++)
- {
- planefmts[j].stride = format.fmt.pix_mp.plane_fmt[j].bytesperline;
- planefmts[j].sizeimage = format.fmt.pix_mp.plane_fmt[j].sizeimage;
- }
- }
- return ret;
- }
- int
- NvV4l2ElementPlane::getCrop(struct v4l2_crop & crop)
- {
- crop.type = buf_type;
- CHECK_V4L2_RETURN(v4l2_ioctl(fd, VIDIOC_G_CROP, &crop),
- "Getting crop params");
- }
- int
- NvV4l2ElementPlane::setSelection(uint32_t target, uint32_t flags, struct v4l2_rect & rect)
- {
- struct v4l2_selection select;
- switch (buf_type)
- {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- select.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- break;
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- select.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- break;
- default:
- PLANE_ERROR_MSG("Unsupported v4l2_buf_type " << buf_type);
- return -1;
- }
- select.target = target;
- select.flags = flags;
- select.r = rect;
- CHECK_V4L2_RETURN(v4l2_ioctl(fd, VIDIOC_S_SELECTION, &select),
- "Setting selection");
- }
- void
- NvV4l2ElementPlane::setBufferPlaneFormat(int n_planes,
- NvBuffer::NvBufferPlaneFormat * planefmts)
- {
- int i;
- this->n_planes = n_planes;
- for (i = 0; i < n_planes; i++)
- {
- this->planefmts[i] = planefmts[i];
- }
- }
- void
- NvV4l2ElementPlane::deinitPlane()
- {
- setStreamStatus(false);
- waitForDQThread(-1);
- for (uint32_t i = 0; i < num_buffers; i++)
- {
- switch (memory_type)
- {
- case V4L2_MEMORY_USERPTR:
- buffers[i]->deallocateMemory();
- break;
- case V4L2_MEMORY_MMAP:
- buffers[i]->unmap();
- break;
- case V4L2_MEMORY_DMABUF:
- break;
- default:
- return;
- }
- }
- reqbufs(memory_type, 0);
- PLANE_DEBUG_MSG("deinit successful");
- }
- int
- NvV4l2ElementPlane::reqbufs(enum v4l2_memory mem_type, uint32_t num)
- {
- struct v4l2_requestbuffers reqbufs;
- int ret;
- memset(&reqbufs, 0, sizeof(struct v4l2_requestbuffers));
- reqbufs.count = num;
- reqbufs.type = buf_type;
- switch (mem_type)
- {
- case V4L2_MEMORY_USERPTR:
- for (uint32_t i = 0; i < n_planes; i++)
- {
- planefmts[i].stride =
- planefmts[i].width * planefmts[i].bytesperpixel;
- if(!planefmts[i].sizeimage)
- {
- planefmts[i].sizeimage =
- planefmts[i].width * planefmts[i].height;
- }
- }
- break;
- case V4L2_MEMORY_MMAP:
- case V4L2_MEMORY_DMABUF:
- break;
- default:
- PLANE_ERROR_MSG("Error in VIDIOC_REQBUFS:Unknown memory type " <<
- mem_type);
- return -1;
- }
- memory_type = mem_type;
- reqbufs.memory = mem_type;
- ret = v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
- if (ret)
- {
- PLANE_SYS_ERROR_MSG("Error in VIDIOC_REQBUFS at output plane");
- is_in_error = 1;
- }
- else
- {
- if (reqbufs.count)
- {
- buffers = new NvBuffer *[reqbufs.count];
- for (uint32_t i = 0; i < reqbufs.count; i++)
- {
- buffers[i] =
- new NvBuffer(buf_type, mem_type, n_planes, planefmts, i);
- }
- }
- else
- {
- for (uint32_t i = 0; i < num_buffers; i++)
- {
- delete buffers[i];
- }
- delete[] buffers;
- buffers = NULL;
- }
- num_buffers = reqbufs.count;
- PLANE_DEBUG_MSG("Reqbuf returned " << reqbufs.count << " buffers");
- }
- return ret;
- }
- int
- NvV4l2ElementPlane::setStreamStatus(bool status)
- {
- int ret;
- if (status == streamon)
- {
- PLANE_DEBUG_MSG("Already in " << ((status) ? "STREAMON" : "STREAMOFF"));
- return 0;
- }
- pthread_mutex_lock(&plane_lock);
- if (status)
- {
- ret = v4l2_ioctl(fd, VIDIOC_STREAMON, &buf_type);
- }
- else
- {
- ret = v4l2_ioctl(fd, VIDIOC_STREAMOFF, &buf_type);
- }
- if (ret)
- {
- PLANE_SYS_ERROR_MSG("Error in " <<
- ((status) ? "STREAMON" : "STREAMOFF"));
- is_in_error = 1;
- }
- else
- {
- PLANE_DEBUG_MSG(((status) ? "STREAMON" : "STREAMOFF") << " successful");
- streamon = status;
- if (!streamon)
- {
- num_queued_buffers = 0;
- pthread_cond_broadcast(&plane_cond);
- }
- if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- {
- if (status == false)
- {
- v4l2elem_profiler.disableProfiling();
- }
- }
- }
- pthread_mutex_unlock(&plane_lock);
- return ret;
- }
- bool
- NvV4l2ElementPlane::getStreamStatus()
- {
- return streamon;
- }
- int
- NvV4l2ElementPlane::setStreamParms(struct v4l2_streamparm &parm)
- {
- int ret;
- parm.type = buf_type;
- ret = v4l2_ioctl(fd, VIDIOC_S_PARM, &parm);
- if(ret == 0)
- {
- PLANE_DEBUG_MSG("Successfully set stream parameters");
- }
- else
- {
- PLANE_SYS_ERROR_MSG("Error while setting stream parameters");
- }
- return ret;
- }
- int
- NvV4l2ElementPlane::queryBuffer(uint32_t i)
- {
- struct v4l2_buffer v4l2_buf;
- struct v4l2_plane planes[MAX_PLANES];
- int ret;
- uint32_t j;
- memset(&v4l2_buf, 0, sizeof(struct v4l2_buffer));
- memset(planes, 0, sizeof(planes));
- v4l2_buf.index = i;
- v4l2_buf.type = buf_type;
- v4l2_buf.memory = memory_type;
- v4l2_buf.m.planes = planes;
- v4l2_buf.length = n_planes;
- ret = v4l2_ioctl(fd, VIDIOC_QUERYBUF, &v4l2_buf);
- if (ret)
- {
- PLANE_SYS_ERROR_MSG("Error in QueryBuf for " << i << "th buffer");
- is_in_error = 1;
- }
- else
- {
- PLANE_DEBUG_MSG("QueryBuf for " << i << "th buffer successful");
- for (j = 0; j < v4l2_buf.length; j++)
- {
- buffers[i]->planes[j].length = v4l2_buf.m.planes[j].length;
- buffers[i]->planes[j].mem_offset =
- v4l2_buf.m.planes[j].m.mem_offset;
- }
- }
- return ret;
- }
- int
- NvV4l2ElementPlane::exportBuffer(uint32_t i)
- {
- struct v4l2_exportbuffer expbuf;
- int ret;
- int j;
- memset(&expbuf, 0, sizeof(expbuf));
- expbuf.type = buf_type;
- expbuf.index = i;
- for (j = 0; j < n_planes; j++)
- {
- expbuf.plane = j;
- ret = v4l2_ioctl(fd, VIDIOC_EXPBUF, &expbuf);
- if (ret)
- {
- PLANE_SYS_ERROR_MSG("Error in ExportBuf for Buffer " << i <<
- ", Plane " << j);
- is_in_error = 1;
- return -1;
- }
- else
- {
- PLANE_DEBUG_MSG("ExportBuf successful for Buffer " << i <<
- ", Plane " << j << ", fd = " << expbuf.fd);
- buffers[i]->planes[j].fd = expbuf.fd;
- }
- }
- return 0;
- }
- int
- NvV4l2ElementPlane::setupPlane(enum v4l2_memory mem_type, uint32_t num_buffers,
- bool map, bool allocate)
- {
- uint32_t i;
- if (reqbufs(mem_type, num_buffers))
- {
- goto error;
- }
- for (i = 0; i < this->num_buffers; i++)
- {
- switch (mem_type)
- {
- case V4L2_MEMORY_USERPTR:
- if (allocate)
- {
- if (buffers[i]->allocateMemory())
- {
- goto error;
- }
- }
- break;
- case V4L2_MEMORY_MMAP:
- if (queryBuffer(i))
- {
- goto error;
- }
- if (exportBuffer(i))
- {
- goto error;
- }
- if (map)
- {
- if (buffers[i]->map())
- {
- goto error;
- }
- }
- break;
- default:
- continue;
- }
- }
- return 0;
- error:
- PLANE_ERROR_MSG("Error during setup");
- is_in_error = 1;
- deinitPlane();
- return -1;
- }
- int
- NvV4l2ElementPlane::waitAllBuffersQueued(uint32_t max_wait_ms)
- {
- struct timespec timeToWait;
- struct timeval now;
- int return_val = 0;
- int ret;
- gettimeofday(&now, NULL);
- timeToWait.tv_nsec = (now.tv_usec + (max_wait_ms % 1000) * 1000L) * 1000L;
- timeToWait.tv_sec = now.tv_sec + max_wait_ms / 1000 +
- timeToWait.tv_nsec / 1000000000L;
- timeToWait.tv_nsec = timeToWait.tv_nsec % 1000000000L;
- pthread_mutex_lock(&plane_lock);
- while (num_queued_buffers < num_buffers)
- {
- ret = pthread_cond_timedwait(&plane_cond, &plane_lock, &timeToWait);
- if (ret == ETIMEDOUT)
- {
- return_val = -1;
- break;
- }
- }
- pthread_mutex_unlock(&plane_lock);
- CHECK_V4L2_RETURN(return_val, "Waiting for all buffers to get queued");
- }
- int
- NvV4l2ElementPlane::waitAllBuffersDequeued(uint32_t max_wait_ms)
- {
- struct timespec timeToWait;
- struct timeval now;
- int return_val = 0;
- int ret;
- gettimeofday(&now, NULL);
- timeToWait.tv_nsec = (now.tv_usec + (max_wait_ms % 1000) * 1000L) * 1000L;
- timeToWait.tv_sec = now.tv_sec + max_wait_ms / 1000 +
- timeToWait.tv_nsec / 1000000000L;
- timeToWait.tv_nsec = timeToWait.tv_nsec % 1000000000L;
- pthread_mutex_lock(&plane_lock);
- while (num_queued_buffers)
- {
- ret = pthread_cond_timedwait(&plane_cond, &plane_lock, &timeToWait);
- if (ret == ETIMEDOUT)
- {
- return_val = -1;
- break;
- }
- }
- pthread_mutex_unlock(&plane_lock);
- CHECK_V4L2_RETURN(return_val, "Waiting for all buffers to get dequeued");
- }
- bool NvV4l2ElementPlane::setDQThreadCallback(dqThreadCallback callback)
- {
- if (dqthread_running)
- return false;
- this->callback = callback;
- return true;
- }
- void *
- NvV4l2ElementPlane::dqThread(void *data)
- {
- NvV4l2ElementPlane *plane = (NvV4l2ElementPlane *) data;
- const char *comp_name = plane->comp_name;
- const char *plane_name = plane->plane_name;
- PLANE_DEBUG_MSG("Starting DQthread");
- prctl (PR_SET_NAME, plane_name, 0, 0, 0);
- plane->stop_dqthread = false;
- while (!plane->stop_dqthread)
- {
- struct v4l2_buffer v4l2_buf;
- struct v4l2_plane planes[MAX_PLANES];
- NvBuffer *buffer;
- NvBuffer *shared_buffer;
- bool ret;
- memset(&v4l2_buf, 0, sizeof(v4l2_buf));
- memset(planes, 0, sizeof(planes));
- v4l2_buf.m.planes = planes;
- v4l2_buf.length = plane->n_planes;
- if (plane->dqBuffer(v4l2_buf, &buffer, &shared_buffer, -1) < 0)
- {
- if (errno != EAGAIN)
- {
- plane->is_in_error = 1;
- }
- if (errno != EAGAIN || plane->streamon)
- {
- ret = plane->callback(NULL, NULL, NULL, plane->dqThread_data);
- }
- if (!plane->streamon)
- {
- break;
- }
- }
- else
- {
- ret = plane->callback(&v4l2_buf, buffer, shared_buffer,
- plane->dqThread_data);
- }
- if (!ret)
- {
- break;
- }
- }
- plane->stop_dqthread = false;
- pthread_mutex_lock(&plane->plane_lock);
- plane->dqthread_running = false;
- pthread_cond_broadcast(&plane->plane_cond);
- pthread_mutex_unlock(&plane->plane_lock);
- PLANE_DEBUG_MSG("Exiting DQthread");
- return NULL;
- }
- int
- NvV4l2ElementPlane::startDQThread(void *data)
- {
- pthread_mutex_lock(&plane_lock);
- if (dqthread_running)
- {
- PLANE_DEBUG_MSG("DQ Thread already started");
- pthread_mutex_unlock(&plane_lock);
- return 0;
- }
- dqThread_data = data;
- pthread_create(&dq_thread, NULL, dqThread, this);
- dqthread_running = true;
- pthread_mutex_unlock(&plane_lock);
- PLANE_DEBUG_MSG("Started DQ Thread");
- return 0;
- }
- int
- NvV4l2ElementPlane::stopDQThread()
- {
- if (blocking)
- {
- PLANE_WARN_MSG("Should not be called in blocking mode");
- return 0;
- }
- stop_dqthread = true;
- pthread_join(dq_thread, NULL);
- dq_thread = 0;
- PLANE_DEBUG_MSG("Stopped DQ Thread");
- return 0;
- }
- int
- NvV4l2ElementPlane::waitForDQThread(uint32_t max_wait_ms)
- {
- struct timespec timeToWait;
- struct timeval now;
- int return_val = 0;
- int ret = 0;
- gettimeofday(&now, NULL);
- timeToWait.tv_nsec = (now.tv_usec + (max_wait_ms % 1000) * 1000L) * 1000L;
- timeToWait.tv_sec = now.tv_sec + max_wait_ms / 1000 +
- timeToWait.tv_nsec / 1000000000L;
- timeToWait.tv_nsec = timeToWait.tv_nsec % 1000000000L;
- pthread_mutex_lock(&plane_lock);
- while (dqthread_running)
- {
- ret = pthread_cond_timedwait(&plane_cond, &plane_lock, &timeToWait);
- if (ret == ETIMEDOUT)
- {
- return_val = -1;
- break;
- }
- }
- pthread_mutex_unlock(&plane_lock);
- if (ret == 0)
- {
- pthread_join(dq_thread, NULL);
- dq_thread = 0;
- PLANE_DEBUG_MSG("Stopped DQ Thread");
- }
- else
- {
- PLANE_ERROR_MSG("Timed out waiting for dqthread");
- }
- return return_val;
- }
|