#include <linux/videodev2.h>
#include <pthread.h>
#include "CaptureTypes.h"
Go to the source code of this file.
Data Structures | |
struct | _sBuffer |
struct | _sCapture |
Defines | |
#define | NUM_STREAMING_BUFFERS 4 |
Typedefs | |
typedef int | BOOL |
typedef _sBuffer | sBuffer |
typedef _sBuffer * | psBuffer |
typedef _sCapture | sCapture |
typedef _sCapture * | psCapture |
Functions | |
int | OpenCaptureDevice (char *device, psCapture pCapture, BOOL bBlock) |
int | OpenCaptureDeviceControl (psCapture pCapture) |
void | CloseCaptureDevice (int fd, psCapture pCapture) |
void | CloseCaptureDeviceControl (int fd) |
int | InitialiseReadCapture (psCapture pCapture, unsigned int buffer_size) |
int | UninitialiseReadCapture (psCapture pCapture) |
int | InitialiseMmapCapture (psCapture pCapture, unsigned int buffer_size) |
int | InitialiseUserPtrCapture (psCapture pCapture, unsigned int buffer_size) |
int | UninitialiseMmapCapture (psCapture pCapture) |
int | UninitialiseUserptrCapture (psCapture pCapture) |
int | InitialiseCapture (psCapture pCapture) |
int | StartCapture (psCapture pCapture) |
#define NUM_STREAMING_BUFFERS 4 |
typedef int BOOL |
Parent capture structure.
Parent capture structure.
void CloseCaptureDevice | ( | int | fd, | |
psCapture | pCapture | |||
) |
Implementation of CloseCaptureDevice.
00785 { 00786 CapDebug("Closing capture device fd: %d\n", fd); 00787 00788 /* Check for allocated memory */ 00789 if(pCapture->pInputs) 00790 { 00791 free(pCapture->pInputs); 00792 pCapture->pInputs = 0; 00793 } 00794 if(pCapture->pStandards) 00795 { 00796 free(pCapture->pStandards); 00797 pCapture->pStandards = 0; 00798 } 00799 if(pCapture->pFormats) 00800 { 00801 free(pCapture->pFormats); 00802 pCapture->pFormats = 0; 00803 } 00804 00805 /* close the handle */ 00806 close(fd); 00807 }
void CloseCaptureDeviceControl | ( | int | fd | ) |
Implementation of CloseCaptureDeviceControl.
00813 { 00814 CapDebug("Closing capture device control fd: %d\n", fd); 00815 00816 /* close the handle */ 00817 close(fd); 00818 }
int InitialiseCapture | ( | psCapture | pCapture | ) |
Implementation of InitialiseCapture.
00648 { 00649 unsigned int d1 = 0; 00650 unsigned int d2 = 0; 00651 00652 int rc = 0; 00653 00654 /* Initialise internals */ 00655 pCapture->inputs = 0; 00656 pCapture->standards = 0; 00657 00658 /* Setup the capture rate, if rate is 0.0 00659 * don't set, just use the default which is the input rate 00660 */ 00661 if(pCapture->fFrameRate > 0.0) 00662 { 00663 /* Convert the fp frame rate into a numerator and denominator for 00664 * use in the v4l struct 00665 * - Assume numerator is 1001 (??) 00666 * 00667 * - Calculate denominator 00668 * 00669 * n d 00670 * - = FrameTime and - = fps 00671 * d n 00672 * 00673 * d = (n * fps) 00674 */ 00675 pCapture->StrmParm.parm.capture.timeperframe.numerator = NUMERATOR; 00676 00677 /* Multiply by 10 to increase precision, then add half lowest value and 00678 * divide by 10 to obtain the 'real' denominator. 00679 */ 00680 pCapture->StrmParm.parm.capture.timeperframe.denominator = ((NUMERATOR * DIVISOR * pCapture->fFrameRate) + (DIVISOR / 2)) / DIVISOR; 00681 00682 pCapture->StrmParm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00683 if((rc = ioctl(pCapture->fd, VIDIOC_S_PARM, &pCapture->StrmParm)) < 0) 00684 { 00685 CapError("Failed to set capture rate to %.2f: %d\n", 00686 pCapture->fFrameRate, rc); 00687 return rc; 00688 } 00689 } 00690 00691 if(pCapture->CroppingActive) 00692 { 00693 struct v4l2_crop cropping; 00694 cropping.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00695 cropping.c.top = pCapture->CroppingTop; 00696 cropping.c.left = pCapture->CroppingLeft; 00697 cropping.c.width = pCapture->CroppingWidth; 00698 cropping.c.height = pCapture->CroppingHeight; 00699 00700 if((rc = ioctl(pCapture->fd, VIDIOC_S_CROP, &cropping)) < 0) 00701 { 00702 CapError("Failed to set cropping(%d,%d,%d,%d): %d\n", 00703 cropping.c.top, cropping.c.left, 00704 cropping.c.width, cropping.c.height, 00705 rc); 00706 return rc; 00707 } 00708 } 00709 00710 if(pCapture->livestream) 00711 { 00712 struct v4l2_queryctrl queryctrl; 00713 struct v4l2_control control; 00714 00715 memset(&queryctrl, 0, sizeof(queryctrl)); 00716 queryctrl.id = RGB133_V4L2_CID_LIVESTREAM; 00717 00718 if ((rc = ioctl(pCapture->fd, VIDIOC_QUERYCTRL, &queryctrl)) == -1) 00719 { 00720 if (errno != EINVAL) 00721 { 00722 CapError("VIDIOC_QUERYCTRL failed for RGB133_V4L2_CID_LIVESTREAM, error(0x%x)\n", rc); 00723 return rc; 00724 } 00725 else 00726 { 00727 CapError("RGB133_V4L2_CID_LIVESTREAM is not supported\n"); 00728 } 00729 } 00730 else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) 00731 { 00732 CapError("RGB133_V4L2_CID_LIVESTREAM is not supported\n"); 00733 } 00734 else 00735 { 00736 memset(&control, 0, sizeof (control)); 00737 control.id = RGB133_V4L2_CID_LIVESTREAM; 00738 control.value = pCapture->livestream; 00739 00740 if ((rc = ioctl(pCapture->fd, VIDIOC_S_CTRL, &control)) == -1) 00741 { 00742 perror("VIDIOC_S_CTRL failed for RGB133_V4L2_CID_LIVESTREAM: "); 00743 return rc; 00744 } 00745 } 00746 00747 memset(&control, 0, sizeof (control)); 00748 control.id = RGB133_V4L2_CID_LIVESTREAM; 00749 00750 if ((rc = ioctl(pCapture->fd, VIDIOC_G_CTRL, &control)) == -1) 00751 { 00752 perror("VIDIOC_G_CTRL failed for RGB133_V4L2_CID_LIVESTREAM: "); 00753 return rc; 00754 } 00755 00756 CapError("RGB133_V4L2_CID_LIVESTREAM current value: %d\n", control.value); 00757 } 00758 00759 return rc; 00760 }
int InitialiseMmapCapture | ( | psCapture | pCapture, | |
unsigned int | buffer_size | |||
) |
Implementation of InitialiseMmapCapture.
00484 { 00485 int ret = 0; 00486 00487 memset( &pCapture->req, 0, sizeof(pCapture->req) ); 00488 pCapture->req.count = NUM_STREAMING_BUFFERS; 00489 pCapture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00490 pCapture->req.memory = V4L2_MEMORY_MMAP; 00491 00492 if((ret = ioctl(pCapture->fd, VIDIOC_REQBUFS, &pCapture->req)) < 0) 00493 { 00494 CapError("Device does not support mmap IO: %d\n", ret); 00495 return -1; 00496 } 00497 00498 if( pCapture->req.count < NUM_STREAMING_BUFFERS ) 00499 { 00500 CapError("Insufficient buffers (%d, expected %d) for mmap IO\n", pCapture->req.count, NUM_STREAMING_BUFFERS); 00501 return -1; 00502 } 00503 00504 if(buffer_size == 0) 00505 { 00506 CapError("Invalid buffer initialisation size: %u bytes\n", buffer_size); 00507 return -1; 00508 } 00509 00510 for(pCapture->buffers = 0; pCapture->buffers < pCapture->req.count; ++pCapture->buffers ) 00511 { 00512 struct v4l2_buffer buf; 00513 memset(&buf, 0, sizeof(buf)); 00514 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00515 buf.memory = V4L2_MEMORY_MMAP; 00516 buf.index = pCapture->buffers; 00517 00518 if((ret = ioctl(pCapture->fd, VIDIOC_QUERYBUF, &buf)) < 0) 00519 { 00520 CapError("VIDIOC_QUERYBUF failed: %d\n", ret); 00521 return -1; 00522 } 00523 00524 pCapture->pBuffers[pCapture->buffers].DataLength = buf.length; 00525 pCapture->pBuffers[pCapture->buffers].pData = 00526 mmap( NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, pCapture->fd, buf.m.offset ); 00527 00528 CapMessage("Mmap buffer[%d](%p) of %u bytes mmap'd.\n", pCapture->buffers, 00529 pCapture->pBuffers[pCapture->buffers].pData, 00530 pCapture->pBuffers[pCapture->buffers].DataLength); 00531 00532 if( pCapture->pBuffers[pCapture->buffers].pData == MAP_FAILED ) 00533 { 00534 CapError("Failed to mmap buffer[%d]\n", pCapture->buffers); 00535 return -1; 00536 } 00537 } 00538 00539 return 0; 00540 }
int InitialiseReadCapture | ( | psCapture | pCapture, | |
unsigned int | buffer_size | |||
) |
Implementation of InitialiseReadCapture.
00449 { 00450 if(buffer_size == 0) 00451 { 00452 CapError("Invalid buffer initialisation size: %u bytes\n", buffer_size); 00453 return -1; 00454 } 00455 00456 pCapture->pBuffers[0].DataLength = buffer_size; 00457 pCapture->pBuffers[0].pData = malloc(buffer_size); 00458 if(pCapture->pBuffers[0].pData == 0) 00459 return -1; 00460 00461 CapMessage("Read buffer(%p) of %u bytes initialised.\n", 00462 pCapture->pBuffers[0].pData, pCapture->pBuffers[0].DataLength); 00463 return 0; 00464 }
int InitialiseUserPtrCapture | ( | psCapture | pCapture, | |
unsigned int | buffer_size | |||
) |
Implementation of InitialiseUserPtrCapture.
00546 { 00547 int ret = 0; 00548 00549 memset( &pCapture->req, 0, sizeof(pCapture->req) ); 00550 pCapture->req.count = NUM_STREAMING_BUFFERS; 00551 pCapture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00552 pCapture->req.memory = V4L2_MEMORY_USERPTR; 00553 00554 if(buffer_size == 0) 00555 { 00556 CapError("Invalid buffer initialisation size: %u bytes\n", buffer_size); 00557 return -1; 00558 } 00559 00560 if((ret = ioctl(pCapture->fd, VIDIOC_REQBUFS, &pCapture->req)) < 0) 00561 { 00562 CapError("Device does not support userptr IO: %d\n", ret); 00563 return -1; 00564 } 00565 00566 for(pCapture->buffers = 0; pCapture->buffers < pCapture->req.count; ++pCapture->buffers) 00567 { 00568 pCapture->pBuffers[pCapture->buffers].pData = malloc(buffer_size); 00569 if(!pCapture->pBuffers[pCapture->buffers].pData) 00570 { 00571 int i; 00572 // If allocation fails, free buffers we managed to allocate, then return 00573 for(i = (pCapture->buffers - 1); i >= 0; --i) 00574 { 00575 free(pCapture->pBuffers[i].pData); 00576 pCapture->pBuffers[i].pData = 0; 00577 pCapture->pBuffers[i].DataLength = 0; 00578 } 00579 CapError("Failed to allocate buffer %d for userptr io\n", pCapture->buffers); 00580 return -1; 00581 } 00582 00583 pCapture->pBuffers[pCapture->buffers].DataLength = buffer_size; 00584 00585 CapMessage("Userptr buffer[%d](%p) of %u bytes allocated.\n", 00586 pCapture->buffers, 00587 pCapture->pBuffers[pCapture->buffers].pData, 00588 pCapture->pBuffers[pCapture->buffers].DataLength); 00589 } 00590 00591 return 0; 00592 }
Implementation of OpenCaptureDevice.
00253 { 00254 char* realDevice = 0; 00255 unsigned long flags = O_RDWR; 00256 00257 if(device[0]) 00258 { 00259 CapLog("Opening capture device: %s\n", device); 00260 realDevice = device; 00261 } 00262 else 00263 { 00264 CapLog("Opening default capture device: %s\n", defaultDevice); 00265 realDevice = (char*)defaultDevice; 00266 } 00267 00268 if(blocking) 00269 { 00270 flags |= O_NONBLOCK; 00271 CapError("Opening device with non-blocking IO (0x%lx)\n", flags); 00272 } 00273 00274 /* Open the device */ 00275 if((pCapture->fd = open(realDevice, flags)) < 0) 00276 { 00277 CapError("Failed to open \"%s\"\n", realDevice); 00278 goto open_failed; 00279 } 00280 00281 /* Query the capture device capabilites */ 00282 CapMessage("Query device capabilities into %p\n", &pCapture->caps); 00283 if(ioctl(pCapture->fd, VIDIOC_QUERYCAP, &pCapture->caps) < 0) 00284 { 00285 CapError("Failed to query device capabilities.\n"); 00286 goto open_failed; 00287 } 00288 00289 /* Enumerate Capture Device Capabilities */ 00290 if( pCapture->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE ) 00291 { 00292 CapLog("Enumerate Capture Inputs\n"); 00293 if(EnumerateCaptureInputs(pCapture)) 00294 { 00295 CapError("Failed to enumerate capture inputs: %d\n", pCapture->inputs); 00296 goto open_failed; 00297 } 00298 CapLog("Enumerate Video Standards\n"); 00299 if(EnumerateVideoStandards(pCapture)) 00300 { 00301 CapError("Failed to enumerate video standards: %d\n", pCapture->standards); 00302 goto open_failed; 00303 } 00304 CapLog("Enumerate Capture Formats\n"); 00305 if(EnumerateCaptureFormats(pCapture)) 00306 { 00307 CapError("Failed to enumerate capture formats: %d\n", pCapture->formats); 00308 goto open_failed; 00309 } 00310 } 00311 else 00312 { 00313 CapError("Only Video Captures are supported by this application.\n"); 00314 goto open_failed; 00315 } 00316 00317 /* Check the io method */ 00318 if( !(pCapture->caps.capabilities & V4L2_CAP_READWRITE) ) 00319 { 00320 CapError("Capture device does not supoprt read io\n"); 00321 goto open_failed; 00322 } 00323 00324 /* Try and find default resolution if not specified */ 00325 memset( &pCapture->fmt, 0, sizeof(pCapture->fmt) ); 00326 pCapture->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 00327 00328 if( pCapture->output_width == 0 || pCapture->output_height == 0 ) 00329 { 00330 /* Use current width and height settings */ 00331 CapMessage("Get Current source width and height.\n"); 00332 if(ioctl(pCapture->fd, VIDIOC_G_FMT, &pCapture->fmt) < 0) 00333 { 00334 CapError("Failed to get current source width and height\n"); 00335 goto open_failed; 00336 } 00337 00338 pCapture->output_width = pCapture->fmt.fmt.pix.width; 00339 pCapture->output_height = pCapture->fmt.fmt.pix.height; 00340 00341 if( pCapture->fmt.fmt.pix.field == V4L2_FIELD_ALTERNATE ) 00342 { 00343 pCapture->output_height = pCapture->output_height * 2; 00344 } 00345 } 00346 else if( pCapture->output_width < 0 || pCapture->output_height < 0 ) 00347 { 00348 CapMessage("Using Optimal width and height.\n"); 00349 } 00350 else 00351 { 00352 /* The width and height have come from the command line (or defaults) */ 00353 CapMessage("Using Specified width and height -> %lux%lu\n", 00354 pCapture->output_width, pCapture->output_height); 00355 } 00356 00357 pCapture->fmt.fmt.pix.width = pCapture->output_width; 00358 pCapture->fmt.fmt.pix.height = pCapture->output_height; 00359 pCapture->fmt.fmt.pix.field = V4L2_FIELD_NONE; 00360 00361 /* Setup Capture Format */ 00362 pCapture->fmt.fmt.pix.pixelformat = pCapture->output_pixfmt; 00363 if(ioctl(pCapture->fd, VIDIOC_S_FMT, &pCapture->fmt) < 0) 00364 { 00365 CapError("Failed to set capture format: %lux%lu for 0x%x (%c%c%c%c)\n", 00366 pCapture->output_width, pCapture->output_height, 00367 pCapture->output_pixfmt, 00368 ((char*)&pCapture->output_pixfmt)[0], 00369 ((char*)&pCapture->output_pixfmt)[1], 00370 ((char*)&pCapture->output_pixfmt)[2], 00371 ((char*)&pCapture->output_pixfmt)[3]); 00372 goto open_failed; 00373 } 00374 CapDebug("Set capture format: %lux%lu for 0x%x (%c%c%c%c)\n", 00375 pCapture->output_width, pCapture->output_height, 00376 pCapture->output_pixfmt, 00377 ((char*)&pCapture->output_pixfmt)[0], 00378 ((char*)&pCapture->output_pixfmt)[1], 00379 ((char*)&pCapture->output_pixfmt)[2], 00380 ((char*)&pCapture->output_pixfmt)[3]); 00381 00382 /* Read back set width and height settings */ 00383 CapMessage("read back set output buffer width and height.\n"); 00384 if(ioctl(pCapture->fd, VIDIOC_G_FMT, &pCapture->fmt) < 0) 00385 { 00386 CapError("Failed to get current output buffer width and height\n"); 00387 goto open_failed; 00388 } 00389 00390 /* Get the source width and height settings */ 00391 memset( &pCapture->src_fmt, 0, sizeof(pCapture->src_fmt) ); 00392 pCapture->src_fmt.type = V4L2_BUF_TYPE_CAPTURE_SOURCE; 00393 CapMessage("read source width and height.\n"); 00394 if((ioctl(pCapture->fd, RGB133_VIDIOC_G_SRC_FMT, &pCapture->src_fmt)) < 0) 00395 { 00396 CapError("Failed to get source input format through proprietary ioctl\n"); 00397 if(ioctl(pCapture->fd, VIDIOC_G_FMT, &pCapture->src_fmt) < 0) 00398 { 00399 CapError("Failed to get source input format using ioctl\n"); 00400 goto open_failed; 00401 } 00402 else 00403 { 00404 CapLog("Source format (ioctl): "); 00405 } 00406 } 00407 else 00408 { 00409 CapLog("Source format (proprietary ioctl): "); 00410 } 00411 00412 CapLog("%ux%u @ %.2fHz for 0x%x (%c%c%c%c)\n", 00413 pCapture->src_fmt.fmt.pix.width, pCapture->src_fmt.fmt.pix.height, 00414 (float)((float)pCapture->src_fmt.fmt.pix.priv / 1000.0), 00415 pCapture->src_fmt.fmt.pix.pixelformat, 00416 ((char*)&pCapture->src_fmt.fmt.pix.pixelformat)[0], 00417 ((char*)&pCapture->src_fmt.fmt.pix.pixelformat)[1], 00418 ((char*)&pCapture->src_fmt.fmt.pix.pixelformat)[2], 00419 ((char*)&pCapture->src_fmt.fmt.pix.pixelformat)[3]); 00420 00421 return 0; 00422 00423 open_failed: 00424 if(pCapture->fd >= 0) 00425 CloseCaptureDevice(pCapture->fd, pCapture); 00426 return -1; 00427 }
int OpenCaptureDeviceControl | ( | psCapture | pCapture | ) |
Implementation of OpenCaptureDeviceControl.
00433 { 00434 CapDebug("Opening capture device control: %s\n", ctrlDevice); 00435 /* Open the device */ 00436 if((pCapture->ctrlFd = open(ctrlDevice, O_RDWR)) < 0) 00437 { 00438 CapError("Failed to open \"%s\"\n", ctrlDevice); 00439 return -1; 00440 } 00441 00442 return 0; 00443 }
int StartCapture | ( | psCapture | pCapture | ) |
Implementation of InitialiseCapture.
00766 { 00767 psCaptureThreadArgs pCaptureThreadArgs = 0; 00768 CapDebug("Start Capture Thread...\n"); 00769 if(CreateCaptureThread(pCapture, pCaptureThreadArgs)) 00770 return -1; 00771 00772 CapDebug("Wait Capture Thread...\n"); 00773 JoinCaptureThread(pCapture); 00774 00775 CapDebug("Joined Capture Thread...\n"); 00776 FreeCaptureThreadArgs(&pCaptureThreadArgs); 00777 00778 return 0; 00779 }
int UninitialiseMmapCapture | ( | psCapture | pCapture | ) |
Implementation of InitialiseMmapCapture.
00598 { 00599 unsigned int i = 0; 00600 for(i=0; i<pCapture->buffers; i++) 00601 { 00602 if(pCapture->pBuffers[i].pData != 0) 00603 { 00604 CapMessage("Uninitialise mmap buffer[%d](%p) of %u bytes.\n", i, 00605 pCapture->pBuffers[i].pData, 00606 pCapture->pBuffers[i].DataLength); 00607 if(munmap(pCapture->pBuffers[i].pData, pCapture->pBuffers[i].DataLength)) 00608 { 00609 CapError("Failed to munmap buffer[%d]", i); 00610 } 00611 pCapture->pBuffers[i].pData = 0; 00612 pCapture->pBuffers[i].DataLength = 0; 00613 } 00614 } 00615 return 0; 00616 }
int UninitialiseReadCapture | ( | psCapture | pCapture | ) |
int UninitialiseUserptrCapture | ( | psCapture | pCapture | ) |
Implementation of UninitialiseUserptrCapture.
00622 { 00623 unsigned int i = 0; 00624 for(i=0; i<pCapture->buffers; i++) 00625 { 00626 if(pCapture->pBuffers[i].pData != 0) 00627 { 00628 CapMessage("Uninitialise userptr buffer[%d](%p) of %u bytes.\n", i, 00629 pCapture->pBuffers[i].pData, 00630 pCapture->pBuffers[i].DataLength); 00631 00632 free(pCapture->pBuffers[i].pData); 00633 pCapture->pBuffers[i].pData = 0; 00634 pCapture->pBuffers[i].DataLength = 0; 00635 } 00636 } 00637 00638 return 0; 00639 }