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 "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 }