home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
-
- #include <vl/vl.h>
-
- #define NBUFFERS 15
-
- VLServer svr = NULL;
- VLPath MEMtoVIDPath = NULL;
- VLNode src = 0, drn = 0;
- VLBuffer buf = NULL;
- int transferSize = 0;
-
- void cleanupAndExit(int exit_type);
-
- int
- createMemToVidPath(VLServer svr, VLPath *path, VLNode *src, VLNode *drn)
- {
- /*
- * Create the memory to video path (just grab the first device
- * that supports it)
- */
- *src = vlGetNode(svr, VL_SRC, VL_MEM, VL_ANY);
- *drn = vlGetNode(svr, VL_DRN, VL_VIDEO, VL_ANY);
-
- *path = vlCreatePath(svr, VL_ANY, *src, *drn);
-
- if (*path == -1) return -1;
-
- return 0;
- }
-
- int
- setMemToVidPathControls(VLServer svr, VLPath path, VLNode src, VLNode drn)
- {
- VLControlValue val;
-
- /*
- * Set to 8-bit YUV 4:2:2, SMPTE format
- */
- val.intVal = VL_PACKING_YVYU_422_8;
- if (vlSetControl(svr, path, src, VL_PACKING, &val) < 0) {
- vlPerror("Unable to set packing");
- return -1;
- }
-
- val.intVal = VL_FORMAT_SMPTE_YUV;
- if (vlSetControl(svr, path, src, VL_FORMAT, &val) < 0) {
- vlPerror("Unable to set format");
- return -1;
- }
-
- /*
- * Capture non-interleaved (field-based) images
- */
- val.intVal = VL_CAPTURE_NONINTERLEAVED;
- if (vlSetControl(svr, path, src, VL_CAP_TYPE, &val) < 0) {
- vlPerror("Unable to set noninterleaved capture type");
- return -1;
- }
-
- return 0;
- }
-
- int
- createBuffer(VLServer svr, VLPath path, VLNode memnode, VLBuffer *buffer)
- {
- /*
- * Create a VL ring buffer for the data transfers.
- */
- *buffer = vlCreateBuffer(svr, path, memnode, NBUFFERS);
- if (!*buffer) {
- vlPerror("Unable to create buffer");
- return -1;
- }
-
- /*
- * If the CPU will never touch the data in the buffer, then there is a
- * potential performance gain to marking the buffer "No Access." This is
- * the case, for example, if the buffer is read from disk using direct
- * I/O then sent immediately to VL. (Marking the buffer "No Access"
- * marks the buffer non-cacheable. There will be a substantial penalty
- * for accessing the buffer with the CPU.)
- */
- vlBufferAdvise(buf, VL_BUFFER_ADVISE_NOACCESS);
-
- transferSize = vlGetTransferSize(svr, path);
-
- return 0;
- }
-
- int
- process_event(VLEvent *ev)
- {
- switch (ev->reason)
- {
- case VLStreamPreempted:
- fprintf(stderr, "Stream Preempted by another Program\n");
- return -1;
- break;
-
- case VLTransferFailed:
- fprintf(stderr, "Transfer failed\n");
- return -1;
- break;
-
- case VLTransferComplete:
- fprintf(stderr, "Got Transfer Complete\n");
- break;
-
- default:
- break;
- }
-
- return 0;
- }
-
- int
- get_server_event(VLServer svr, VLPath path, VLNode memnode)
- {
- VLEvent ev;
-
- if (vlCheckEvent(svr, VLAllEventsMask, &ev) == -1) {
- return 0;
- }
-
- return process_event(&ev);
- }
-
- int
- buffer_ready(VLServer svr, VLPath path, VLNode memnode)
- {
- VLInfoPtr info;
- char *dataArea;
-
- info = vlGetNextFree(svr, buf, transferSize);
- dataArea = vlGetActiveRegion(svr, buf, info);
-
- /* Fill in image data here */
-
- vlPutValid(svr, buf);
-
- printf("Output Buffer\n");
- return 0;
- }
-
- void
- main(int argc, char **argv)
- {
- int ret;
- VLTransferDescriptor xferDesc;
- int bufferfd, vlfd;
- fd_set readfds, writefds, exceptfds;
- int nfds;
-
- /*
- * Connect to the video daemon
- */
- if (!(svr = vlOpenVideo(""))) {
- vlPerror("Couldn't open video");
- cleanupAndExit(1);
- }
-
- /*
- * Create a memory-to-video path
- */
- if (createMemToVidPath(svr, &MEMtoVIDPath, &src, &drn) == -1) {
- vlPerror("Couldn't create path");
- cleanupAndExit(1);
- }
-
- /*
- * Set up the hardware for and define the usage of the path
- */
- if (vlSetupPaths(svr, (VLPathList)&MEMtoVIDPath, 1, VL_SHARE, VL_SHARE)<0) {
- vlPerror("Unable to setup path");
- cleanupAndExit(1);
- }
-
- /*
- * Now set the controls on the path indicating how we would like to
- * output the video
- */
- if (setMemToVidPathControls(svr, MEMtoVIDPath, src, drn) < 0) {
- vlPerror("Couldn't set controls on path");
- cleanupAndExit(1);
- }
-
- /*
- * Create a VL buffer and associate it with the memory node
- */
- if (createBuffer(svr, MEMtoVIDPath, src, &buf) < 0) {
- vlPerror("Couldn't create buffer");
- cleanupAndExit(1);
- }
-
- if (vlRegisterBuffer(svr, MEMtoVIDPath, src, buf)) {
- vlPerror(argv[0]);
- vlDestroyBuffer(svr, buf);
- cleanupAndExit(1);
- }
-
- /*
- * Register for preempted and transfer failed masks
- */
- vlSelectEvents(svr, MEMtoVIDPath,
- ( VLStreamPreemptedMask | VLTransferFailedMask |
- VLTransferCompleteMask));
-
- /*
- * Create select desriptors so we know when the dmrb is ready for more
- * data, or when VL sends us an event.
- */
- bufferfd = vlBufferGetFd(buf);
- vlfd = vlGetFD(svr);
- if (vlfd > bufferfd) nfds = vlfd+1;
- else nfds = bufferfd+1;
-
- /*
- * Set up transfer descriptor for continuous capture mode with "immediate"
- * start (don't wait for a trigger event)
- */
- xferDesc.delay = 0;
- xferDesc.trigger = VLTriggerImmediate;
- xferDesc.count = 0;
- xferDesc.mode = VL_TRANSFER_MODE_CONTINUOUS;
-
- if (vlBeginTransfer(svr, MEMtoVIDPath, 1, &xferDesc) < 0) {
- vlPerror("vlBeginTransfer");
- cleanupAndExit(1);
- }
-
- /*
- * This is, for all practical purposes, an event loop that exits after
- * all the data has been read in.
- */
- while (1) {
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_ZERO(&exceptfds);
- FD_SET(vlfd, &readfds);
- FD_SET(bufferfd, &writefds);
- FD_SET(vlfd, &exceptfds);
- FD_SET(bufferfd, &exceptfds);
-
- if (select(nfds, &readfds, &writefds, &exceptfds, NULL) < 0) {
- perror("Select failed");
- cleanupAndExit(1);
- }
-
- /*
- * Check if a buffer is ready to be filled
- */
- if (FD_ISSET(bufferfd, &writefds)) {
- ret = buffer_ready(svr, MEMtoVIDPath, src);
- if (ret != 0) cleanupAndExit(1);
- }
-
- /*
- * Now see if we have a VL event
- */
- if (FD_ISSET(vlfd, &readfds)) {
- ret = get_server_event(svr, MEMtoVIDPath, src);
- if (ret != 0) cleanupAndExit(1);
- }
-
- /*
- * Also check for exception conditions, for example if the
- * connection to VL was broken, or the buffer was marked
- * "done" (i.e. will not accept more input).
- */
- if (FD_ISSET(vlfd, &exceptfds)) {
- fprintf(stderr, "Exceptional condition on VL connection\n");
- cleanupAndExit(1);
- }
-
- if (FD_ISSET(bufferfd, &exceptfds)) {
- fprintf(stderr, "Exception condition on ring buffer\n");
- cleanupAndExit(1);
- }
- }
-
- /*
- * Cleanup and exit with no error
- */
- cleanupAndExit(0);
- }
-
- void cleanupAndExit(int exit_type)
- {
- /*
- * If we opened a server connection, then destroy all the objects we
- * allocated before exiting.
- */
- if (svr) {
- /*
- * If we got as far as creating a path, then stop any transfer in
- * progress and destroy the path.
- */
- if (MEMtoVIDPath) {
- vlEndTransfer(svr, MEMtoVIDPath);
- /*
- * If we created a buffer, deregister it then destroy it too...
- */
- if (buf) {
- vlDeregisterBuffer(svr, MEMtoVIDPath, src, buf);
- vlDestroyBuffer(svr, buf);
- }
- vlDestroyPath(svr, MEMtoVIDPath);
- }
- vlCloseVideo(svr);
- }
-
- exit(exit_type);
- }
-