/* * This program captures images from a IEEE 1394 (FireWire) digital * camera conforming "IIDC 1394-based Digital Camera Specification" * and outputs images to stdout in the ffmpeg "rawvideo" format. * This program allows you to use a FireWire digital camera with * ffmpeg. * * FireWire camcorders do not conform to that specification, and they * are already supported by "-dv1394" ffmpeg option. * * Installation: * You have to install libdc1394 (http://sf.net/projects/libdc1394) * and libraw1394 (http://www.linux1394.org). * To compile, run * gcc -O3 thisfile.c -ldc1394_control -lraw1394 * * Usage: Run this program without options. */ /* * This program is based on grab_gray_image.c in libdc1394 0.9.0-2, * whose copyright notice is as follows. * This program requires libdc1394 0.9.1. */ /************************************************************************** ** Title: grab one gray image using libdc1394 ** $RCSfile: grab_gray_image.c,v $ ** $Revision: 1.3 $$Name: $ ** $Date: 2001/10/16 09:14:14 $ ** Copyright: LGPL $Author: ronneber $ ** Description: ** ** Get one gray image using libdc1394 and store it as portable gray map ** (pgm). Based on 'samplegrab' from Chris Urmson ** **------------------------------------------------------------------------- ** ** $Log: grab_gray_image.c,v $ ** Revision 1.3 2001/10/16 09:14:14 ronneber ** - added more meaningful error message, when no raw1394 handle could be get ** - does not exit anymore, when camera has no trigger ** ** Revision 1.2 2001/09/14 08:10:41 ronneber ** - some cosmetic changes ** ** Revision 1.1 2001/07/24 13:50:59 ronneber ** - simple test programs to demonstrate the use of libdc1394 (based ** on 'samplegrab' of Chris Urmson ** ** **************************************************************************/ #include #include #include #include #include #include #include #define PMIN(x,y) ((x) > (y) ? (y) : (x)) #define BLACK_Y 0 #define BLACK_U 128 #define BLACK_V 128 #define FALSE 0 #define TRUE 1 inline int uyvy422_yuv420p(const unsigned char *srcFrameBuffer, unsigned char *dstFrameBuffer) { const int srcFrameWidth = 320, srcFrameHeight = 240, dstFrameWidth = 320, dstFrameHeight = 240; unsigned int row,column; unsigned char *y = dstFrameBuffer; /*Initialise y,u,v here, to stop compiler warnings.*/ unsigned char *u = dstFrameBuffer + dstFrameWidth*dstFrameHeight; unsigned char *v = dstFrameBuffer + dstFrameWidth*(dstFrameHeight + dstFrameHeight/4); const unsigned char *src = srcFrameBuffer; if (srcFrameBuffer == dstFrameBuffer) return FALSE; for(row=0; row < PMIN(srcFrameHeight, dstFrameHeight); row+=2) { y = dstFrameBuffer + dstFrameWidth*row; u = dstFrameBuffer + dstFrameWidth*dstFrameHeight + dstFrameWidth*row/4; v = dstFrameBuffer + dstFrameWidth*(dstFrameHeight + dstFrameHeight/4) + dstFrameWidth*row/4; src = srcFrameBuffer + row*srcFrameWidth*2; for(column=0; column < PMIN(srcFrameWidth, dstFrameWidth); column+=2) { *(u++) = (unsigned char)(((int)src[0] + src[srcFrameWidth*2])/2); *(y++) = src[1]; *(v++) = (unsigned char)(((int)src[2] + src[2+srcFrameWidth*2])/2); *(y++) = src[3]; src += 4; } for(column = PMIN(srcFrameWidth, dstFrameWidth); column < dstFrameWidth; column+=2) { *(u++) = BLACK_U; *(y++) = BLACK_Y; *(v++) = BLACK_V; *(y++) = BLACK_Y; } y = dstFrameBuffer + dstFrameWidth*(row+1); src = srcFrameBuffer + (row+1)*srcFrameWidth*2; for(column=0; column < PMIN(srcFrameWidth,dstFrameWidth); column+=2) { src++; *(y++) = *(src++); src++; *(y++) = *(src++); } for(column = PMIN(srcFrameWidth, dstFrameWidth); column < dstFrameWidth; column+=2) { *(y++) = BLACK_Y; *(y++) = BLACK_Y; } } for(row = PMIN(srcFrameHeight, dstFrameHeight); row < dstFrameHeight; row+=2) { for(column = 0; column < dstFrameWidth; column+=2) { *(u++) = BLACK_U; *(y++) = BLACK_Y; *(v++) = BLACK_V; *(y++) = BLACK_Y; } for(column = 0; column < dstFrameWidth; column+=2) { *(y++) = BLACK_Y; *(y++) = BLACK_Y; } } return TRUE; } inline int uyv444_yuv420p(const unsigned char *srcFrameBuffer, unsigned char *dstFrameBuffer) { const int srcFrameWidth = 160, srcFrameHeight = 120, dstFrameWidth = 160, dstFrameHeight = 120; unsigned int row,column; unsigned char *y = dstFrameBuffer; /*Initialise y,u,v here, to stop compiler warnings.*/ unsigned char *u = dstFrameBuffer + dstFrameWidth*dstFrameHeight; unsigned char *v = dstFrameBuffer + dstFrameWidth*(dstFrameHeight + dstFrameHeight/4); const unsigned char *src = srcFrameBuffer; if (srcFrameBuffer == dstFrameBuffer) return FALSE; for(row=0; row < PMIN(srcFrameHeight, dstFrameHeight); row+=2) { y = dstFrameBuffer + dstFrameWidth*row; u = dstFrameBuffer + dstFrameWidth*dstFrameHeight + dstFrameWidth*row/4; v = dstFrameBuffer + dstFrameWidth*(dstFrameHeight + dstFrameHeight/4) + dstFrameWidth*row/4; src = srcFrameBuffer + row*srcFrameWidth*3; for(column=0; column < PMIN(srcFrameWidth, dstFrameWidth); column+=2) { *(u++) = (unsigned char)(((unsigned int)src[0] + src[3] + src[srcFrameWidth*3] + src[3+srcFrameWidth*3])/4); *(y++) = src[1]; *(v++) = (unsigned char)(((unsigned int)src[2] + src[5] + src[srcFrameWidth*3] +src[3+srcFrameWidth*3])/4); *(y++) = src[4]; src += 6; } for(column = PMIN(srcFrameWidth, dstFrameWidth); column < dstFrameWidth; column+=2) { *(u++) = BLACK_U; *(y++) = BLACK_Y; *(v++) = BLACK_V; *(y++) = BLACK_Y; } y = dstFrameBuffer + dstFrameWidth*(row+1); src = srcFrameBuffer + (row+1)*srcFrameWidth*3; for(column=0; column < PMIN(srcFrameWidth, dstFrameWidth); column++) { src++; *(y++) = *(src++); src++; } for(column = PMIN(srcFrameWidth, dstFrameWidth); column < dstFrameWidth; column++) *(y++) = BLACK_Y; } for(row = PMIN(srcFrameHeight, dstFrameHeight); row: frames will be captured. -1 means infinity.\n" "-d : Device name is usually /dev/raw1394 or /dev/video1394/0.\n" "-s : Frame size is one of 160x120, 320x240, or 640x480.\n" "-r : Frame rate is one of 1.875, 3.75, 7.5, 15, 30, or 60.\n"); } static void check_unset_opt(void) { if (device_name == NULL) { fprintf(stderr, "The device name is not set. Please specify it with -d option.\n"); usage(); exit(1); } if (frame_size == UNSET) { fprintf(stderr, "The frame size is not set. Please specify it with -s option.\n"); usage(); exit(1); } if (frame_rate == UNSET) { fprintf(stderr, "The frame rate is not set. Please specify it with -r option.\n"); usage(); exit(1); } } static void process_options(int argc, char **argv) { int optchar; while ((optchar = getopt(argc, argv, "s:r:d:c:")) != -1) { if (optchar == 'd') device_name = optarg; else if (optchar == 's') process_size_opt(optarg); else if (optchar == 'r') process_rate_opt(optarg); else if (optchar == 'c') sscanf(optarg, "%d", &capture_count); else { usage(); exit(1); } } check_unset_opt(); } int main(int argc, char *argv[]) { dc1394_cameracapture camera; int numNodes; int numCameras; raw1394handle_t handle; nodeid_t * camera_nodes; quadlet_t supported_framerates; unsigned char *buf; int i; int buf_size; process_options(argc, argv); /*----------------------------------------------------------------------- * Open ohci and asign handle to it *-----------------------------------------------------------------------*/ handle = dc1394_create_handle(0); if (handle==NULL) { fprintf( stderr, "Unable to aquire a raw1394 handle\n\n" "Please check \n" " - if the kernel modules `ieee1394',`raw1394' and `ohci1394' are loaded \n" " - if you have read/write access to /dev/raw1394\n\n"); exit(1); } /*----------------------------------------------------------------------- * get the camera nodes and describe them as we find them *-----------------------------------------------------------------------*/ numNodes = raw1394_get_nodecount(handle); camera_nodes = dc1394_get_camera_nodes(handle,&numCameras,0); fflush(stdout); if (numCameras<1) { fprintf( stderr, "no cameras found :(\n"); dc1394_destroy_handle(handle); exit(1); } fprintf(stderr, "working with the first camera on the bus\n"); /*----------------------------------------------------------------------- * to prevent the iso-transfer bug from raw1394 system, check if * camera is highest node. For details see * http://linux1394.sourceforge.net/faq.html#DCbusmgmt * and * http://sourceforge.net/tracker/index.php?func=detail&aid=435107&group_id=8157&atid=108157 *-----------------------------------------------------------------------*/ for (i=0; i 0) { current_written = write(1, buf, buf_size-num_written); num_written += current_written; } dc1394_dma_done_with_buffer(&camera); if (current_written == -1) break; } close(1); /*----------------------------------------------------------------------- * Stop data transmission *-----------------------------------------------------------------------*/ if (dc1394_stop_iso_transmission(handle,camera.node)!=DC1394_SUCCESS) { fprintf(stderr, "couldn't stop the camera?\n"); } /*----------------------------------------------------------------------- * Close camera *-----------------------------------------------------------------------*/ dc1394_dma_unlisten(handle, &camera); dc1394_dma_release_camera(handle,&camera); dc1394_destroy_handle(handle); return 0; }