Path: blob/master/modules/videoio/src/cap_dc1394.cpp
16354 views
/* This is the contributed code:1Firewire and video4linux camera support for videoio232003-03-12 Magnus Lundin4[email protected]56THIS EXEPERIMENTAL CODE7Tested on 2.4.19 with 1394, video1394, v4l, dc1394 and raw1394 support89This set of files adds support for firevre and usb cameras.10First it tries to install a firewire camera,11if that fails it tries a v4l/USB camera1213It has been tested with the motempl sample program1415INSTALLATION16Install OpenCV17Install v4l18Install dc1394 raw1394 - coriander should work with your camera19Backup videoio folder20Copy new files21cd into videoio folder22make clean (cvcap.cpp must be rebuilt)23make24make install252627The build is controlled by the following entries in the videoio Makefile:2829libvideoio_la_LIBADD = -L/usr/X11R6/lib -lXm -lMrm -lUil -lpng -ljpeg -lz -ltiff -lavcodec -lraw1394 -ldc1394_control30DEFS = -DHAVE_CONFIG_H -DHAVE_DC1394 HAVE_CAMV4L313233Now it should be possible to use videoio camera functions, works for me.343536THINGS TO DO37Better ways to select 1394 or v4l camera38Better support for videosize39Format74041Comments and changes welcome42/Magnus43442005-10-19 Roman Stanchak45[email protected]4647Support added for setting MODE and other DC1394 properties. Also added CONVERT_RGB flag48which indicates whether or not color conversion is performed in cvRetrieveFrame. The default49for CONVERT_RGB=1 for backward compatibility.5051Tested with 2.6.12 with libdc1394-1.0.0, libraw1394-0.10.1 using a Point Grey Flea5253*/545556/*M///////////////////////////////////////////////////////////////////////////////////////57//58// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.59//60// By downloading, copying, installing or using the software you agree to this license.61// If you do not agree to this license, do not download, install,62// copy or use the software.63//64//65// Intel License Agreement66// For Open Source Computer Vision Library67//68// Copyright (C) 2000, Intel Corporation, all rights reserved.69// Third party copyrights are property of their respective owners.70//71// Redistribution and use in source and binary forms, with or without modification,72// are permitted provided that the following conditions are met:73//74// * Redistribution's of source code must retain the above copyright notice,75// this list of conditions and the following disclaimer.76//77// * Redistribution's in binary form must reproduce the above copyright notice,78// this list of conditions and the following disclaimer in the documentation79// and/or other materials provided with the distribution.80//81// * The name of Intel Corporation may not be used to endorse or promote products82// derived from this software without specific prior written permission.83//84// This software is provided by the copyright holders and contributors "as is" and85// any express or implied warranties, including, but not limited to, the implied86// warranties of merchantability and fitness for a particular purpose are disclaimed.87// In no event shall the Intel Corporation or contributors be liable for any direct,88// indirect, incidental, special, exemplary, or consequential damages89// (including, but not limited to, procurement of substitute goods or services;90// loss of use, data, or profits; or business interruption) however caused91// and on any theory of liability, whether in contract, strict liability,92// or tort (including negligence or otherwise) arising in any way out of93// the use of this software, even if advised of the possibility of such damage.94//95//M*/9697#include "precomp.hpp"9899#if !defined _WIN32 && defined HAVE_DC1394100101#include <unistd.h>102#include <stdint.h>103#include <libraw1394/raw1394.h>104#include <libdc1394/dc1394_control.h>105106#ifdef NDEBUG107#define CV_WARN(message)108#else109#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)110#endif111112#define CV_DC1394_CALL(expr) \113if((expr)<0){ \114OPENCV_ERROR(CV_StsInternal, "", "libdc1394 function call returned < 0"); \115}116117#define DELAY 50000118119// bpp for 16-bits cameras... this value works for PtGrey DragonFly...120#define MONO16_BPP 8121122/* should be in pixelformat */123static void uyv2bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels);124static void uyvy2bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels);125static void uyyvyy2bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels);126static void y2bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels);127static void y162bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels, int bits);128static void rgb482bgr(const unsigned char *src8, unsigned char *dest, unsigned long long int NumPixels, int bits);129130static const char * videodev[4]={131"/dev/video1394/0",132"/dev/video1394/1",133"/dev/video1394/2",134"/dev/video1394/3"135};136137typedef struct CvCaptureCAM_DC1394138{139raw1394handle_t handle;140nodeid_t camera_node;141dc1394_cameracapture* camera;142int format;143int mode;144int color_mode;145int frame_rate;146const char * device_name;147IplImage frame;148int convert;149int buffer_is_writeable; // indicates whether frame.imageData is allocated by OpenCV or DC1394150}151CvCaptureCAM_DC1394;152153static void icvCloseCAM_DC1394( CvCaptureCAM_DC1394* capture );154155static int icvGrabFrameCAM_DC1394( CvCaptureCAM_DC1394* capture );156static IplImage* icvRetrieveFrameCAM_DC1394( CvCaptureCAM_DC1394* capture, int );157158static double icvGetPropertyCAM_DC1394( CvCaptureCAM_DC1394* capture, int property_id );159static int icvSetPropertyCAM_DC1394( CvCaptureCAM_DC1394* capture, int property_id, double value );160161// utility functions162static int icvFormatSupportedCAM_DC1394(int format, quadlet_t formats);163static int icvModeSupportedCAM_DC1394(int format, int mode, quadlet_t modes);164static int icvColorMode( int mode );165static unsigned int icvGetBestFrameRate( CvCaptureCAM_DC1394 * capture, int format, int mode);166static int icvResizeFrame(CvCaptureCAM_DC1394 * capture);167168/*********************** Implementations ***************************************/169#define MAX_PORTS 3170#define MAX_CAMERAS 8171#define NUM_BUFFERS 8172struct raw1394_portinfo ports[MAX_PORTS];173static raw1394handle_t handles[MAX_PORTS];174static int camCount[MAX_PORTS];175static int numPorts = -1;176static int numCameras = 0;177static nodeid_t *camera_nodes;178struct camnode {dc1394_cameracapture cam;int portnum;} cameras[MAX_CAMERAS];179180static const int preferred_modes[]181= {182// uncomment the following line to test a particular mode:183//FORMAT_VGA_NONCOMPRESSED, MODE_640x480_MONO16, 0,184FORMAT_SVGA_NONCOMPRESSED_2,185MODE_1600x1200_RGB, MODE_1600x1200_YUV422, MODE_1280x960_RGB, MODE_1280x960_YUV422,186MODE_1600x1200_MONO, MODE_1280x960_MONO, MODE_1600x1200_MONO16, MODE_1280x960_MONO16,187FORMAT_SVGA_NONCOMPRESSED_1,188MODE_1024x768_RGB, MODE_1024x768_YUV422, MODE_800x600_RGB, MODE_800x600_YUV422,189MODE_1024x768_MONO, MODE_800x600_MONO, MODE_1024x768_MONO16, MODE_800x600_MONO16,190FORMAT_VGA_NONCOMPRESSED,191MODE_640x480_RGB, MODE_640x480_YUV422, MODE_640x480_YUV411, MODE_320x240_YUV422,192MODE_160x120_YUV444, MODE_640x480_MONO, MODE_640x480_MONO16,193FORMAT_SCALABLE_IMAGE_SIZE,194MODE_FORMAT7_0, MODE_FORMAT7_1, MODE_FORMAT7_2, MODE_FORMAT7_3,195MODE_FORMAT7_4, MODE_FORMAT7_5, MODE_FORMAT7_6, MODE_FORMAT7_7,1960197};198199void icvInitCapture_DC1394(){200int p;201202raw1394handle_t raw_handle = raw1394_new_handle();203if( raw_handle == 0 ) {204numPorts = 0;205return;206}207numPorts = raw1394_get_port_info(raw_handle, ports, MAX_PORTS);208raw1394_destroy_handle(raw_handle);209for (p = 0; p < numPorts; p++) {210handles[p] = dc1394_create_handle(p);211if (handles[p]==NULL) { numPorts=-1; return; /*ERROR_CLEANUP_EXIT*/ }212213/* get the camera nodes and describe them as we find them */214camera_nodes = dc1394_get_camera_nodes(handles[p], &camCount[p], 0);215for (int i=0;i<camCount[p];i++) {216cameras[numCameras].cam.node = camera_nodes[i];217cameras[numCameras].portnum = p;218dc1394_stop_iso_transmission(handles[p], camera_nodes[i]);219numCameras++;220}221}222};223224static CvCaptureCAM_DC1394 * icvCaptureFromCAM_DC1394 (int index)225{226quadlet_t modes[8], formats;227int i;228229if (numPorts<0) icvInitCapture_DC1394();230if (numPorts==0)231return 0; /* No i1394 ports found */232if (numCameras<1)233return 0;234if (index>=numCameras)235return 0;236if (index<0)237return 0;238239CvCaptureCAM_DC1394 * pcap = (CvCaptureCAM_DC1394*)cvAlloc(sizeof(*pcap));240241/* Select a port and camera */242pcap->device_name = videodev[cameras[index].portnum];243pcap->handle = handles[cameras[index].portnum];244pcap->camera = &cameras[index].cam;245246// get supported formats247if (dc1394_query_supported_formats(pcap->handle, pcap->camera->node, &formats)<0) {248fprintf(stderr,"%s:%d: Could not query supported formats\n",__FILE__,__LINE__);249formats=0x0;250}251for (i=0; i < NUM_FORMATS; i++) {252modes[i]=0;253if (icvFormatSupportedCAM_DC1394(i+FORMAT_MIN, formats)){254if (dc1394_query_supported_modes(pcap->handle, pcap->camera->node, i+FORMAT_MIN, &modes[i])<0) {255fprintf(stderr,"%s:%d: Could not query Format%d modes\n",__FILE__,__LINE__,i);256}257}258}259260pcap->format = 0;261pcap->mode = 0;262pcap->color_mode = 0;263pcap->frame_rate = 0;264265int format_idx = -1;266267// scan the list of preferred modes, and find a supported one268for(i=0; (pcap->mode == 0) && (preferred_modes[i] != 0); i++) {269if((preferred_modes[i] >= FORMAT_MIN) && (preferred_modes[i] <= FORMAT_MAX)) {270pcap->format = preferred_modes[i];271format_idx = preferred_modes[i] - FORMAT_MIN;272continue;273}274assert(format_idx != -1);275if ( ! icvFormatSupportedCAM_DC1394(pcap->format, formats) )276continue;277if ( icvModeSupportedCAM_DC1394(pcap->format, preferred_modes[i], modes[format_idx]) ){278pcap->mode = preferred_modes[i];279}280}281if (pcap->mode == 0) {282fprintf(stderr,"%s:%d: Could not find a supported mode for this camera\n",__FILE__,__LINE__);283goto ERROR;284}285286pcap->color_mode = icvColorMode( pcap->mode );287if( pcap->color_mode == -1){288fprintf(stderr,"%s:%d: ERROR: BPP is Unsupported!!\n",__FILE__,__LINE__);289goto ERROR;290}291292// set frame rate to optimal value given format and mode293pcap->frame_rate = icvGetBestFrameRate(pcap, pcap->format, pcap->mode);294295if (pcap->format!=FORMAT_SCALABLE_IMAGE_SIZE) { // everything except Format 7296if (dc1394_dma_setup_capture(pcap->handle, pcap->camera->node, index+1 /*channel*/,297pcap->format, pcap->mode, SPEED_400,298pcap->frame_rate, NUM_BUFFERS, 1 /*drop_frames*/,299pcap->device_name, pcap->camera) != DC1394_SUCCESS) {300fprintf(stderr,"%s:%d: Failed to setup DMA capture with VIDEO1394\n",__FILE__,__LINE__);301goto ERROR;302}303}304else {305if(dc1394_dma_setup_format7_capture(pcap->handle,pcap->camera->node,index+1 /*channel*/,306pcap->mode, SPEED_400, QUERY_FROM_CAMERA,307(unsigned int)QUERY_FROM_CAMERA, (unsigned int)QUERY_FROM_CAMERA,308(unsigned int)QUERY_FROM_CAMERA, (unsigned int)QUERY_FROM_CAMERA,309NUM_BUFFERS, 1 /*drop_frames*/,310pcap->device_name, pcap->camera) != DC1394_SUCCESS) {311fprintf(stderr,"%s:%d: Failed to setup DMA capture with VIDEO1394\n",__FILE__,__LINE__);312goto ERROR;313}314}315316if (dc1394_start_iso_transmission(pcap->handle, pcap->camera->node)!=DC1394_SUCCESS) {317fprintf(stderr,"%s:%d: Could not start ISO transmission\n",__FILE__,__LINE__);318goto ERROR;319}320321usleep(DELAY);322323dc1394bool_t status;324if (dc1394_get_iso_status(pcap->handle, pcap->camera->node, &status)!=DC1394_SUCCESS) {325fprintf(stderr,"%s:%d: Could get ISO status",__FILE__,__LINE__);326goto ERROR;327}328if (status==DC1394_FALSE) {329fprintf(stderr,"%s:%d: ISO transmission refuses to start",__FILE__,__LINE__);330goto ERROR;331}332333// convert camera image to RGB by default334pcap->convert=1;335336// no image data allocated yet337pcap->buffer_is_writeable = 0;338339memset(&(pcap->frame), 0, sizeof(IplImage));340icvResizeFrame( pcap );341return pcap;342343ERROR:344return 0;345};346347static void icvCloseCAM_DC1394( CvCaptureCAM_DC1394* capture ){348dc1394_stop_iso_transmission(capture->handle, capture->camera->node);349dc1394_dma_unlisten (capture->handle, capture->camera);350/* Deallocate space for RGBA data */351if(capture->convert){352cvFree(&capture->frame.imageData);353}354}355356static int icvGrabFrameCAM_DC1394( CvCaptureCAM_DC1394* capture ){357// TODO: should this function wait until the next frame is available or return358// immediately ?359float waiting = 0;360do{361int result = dc1394_dma_single_capture_poll(capture->camera);362if(result==DC1394_SUCCESS){363return 1;364}365else if(result==DC1394_NO_FRAME){366usleep(1000000/120); //sleep for at least a 1/2 of the frame rate367waiting += 1.0/120.0;368}369else{370printf("dc1394_dma_single_capture_poll failed\n");371return 0;372}373} while(waiting<2);374printf("dc1394_dma_single_capture_poll timed out\n");375return 0;376}377378static IplImage* icvRetrieveFrameCAM_DC1394( CvCaptureCAM_DC1394* capture, int ){379if(capture->camera->capture_buffer )380{381if(capture->convert){382/* Convert to RGBA */383unsigned char * src = (unsigned char *)capture->camera->capture_buffer;384unsigned char * dst = (unsigned char *)capture->frame.imageData;385switch (capture->color_mode) {386case COLOR_FORMAT7_RGB8:387//printf("icvRetrieveFrame convert RGB to BGR\n");388/* Convert RGB to BGR */389for (int i=0;i<capture->frame.imageSize;i+=6) {390dst[i] = src[i+2];391dst[i+1] = src[i+1];392dst[i+2] = src[i];393dst[i+3] = src[i+5];394dst[i+4] = src[i+4];395dst[i+5] = src[i+3];396}397break;398case COLOR_FORMAT7_YUV422:399//printf("icvRetrieveFrame convert YUV422 to BGR %d\n");400uyvy2bgr(src,401dst,402capture->camera->frame_width * capture->camera->frame_height);403break;404case COLOR_FORMAT7_MONO8:405//printf("icvRetrieveFrame convert MONO8 to BGR %d\n");406y2bgr(src,407dst,408capture->camera->frame_width * capture->camera->frame_height);409break;410case COLOR_FORMAT7_YUV411:411//printf("icvRetrieveFrame convert YUV411 to BGR %d\n");412uyyvyy2bgr(src,413dst,414capture->camera->frame_width * capture->camera->frame_height);415break;416case COLOR_FORMAT7_YUV444:417//printf("icvRetrieveFrame convert YUV444 to BGR %d\n");418uyv2bgr(src,419dst,420capture->camera->frame_width * capture->camera->frame_height);421break;422case COLOR_FORMAT7_MONO16:423//printf("icvRetrieveFrame convert MONO16 to BGR %d\n");424y162bgr(src,425dst,426capture->camera->frame_width * capture->camera->frame_height, MONO16_BPP);427break;428case COLOR_FORMAT7_RGB16:429//printf("icvRetrieveFrame convert RGB16 to BGR %d\n");430rgb482bgr(src,431dst,432capture->camera->frame_width * capture->camera->frame_height, MONO16_BPP);433break;434default:435fprintf(stderr,"%s:%d: Unsupported color mode %d\n",__FILE__,__LINE__,capture->color_mode);436return 0;437} /* switch (capture->mode) */438}439else{440// return raw data441capture->frame.imageData = (char *) capture->camera->capture_buffer;442capture->frame.imageDataOrigin = (char *) capture->camera->capture_buffer;443}444445// TODO: if convert=0, we are not actually done with the buffer446// but this seems to work anyway.447dc1394_dma_done_with_buffer(capture->camera);448449return &capture->frame;450}451return 0;452};453454static double icvGetPropertyCAM_DC1394( CvCaptureCAM_DC1394* capture, int property_id ){455int index=-1;456switch ( property_id ) {457case CV_CAP_PROP_CONVERT_RGB:458return capture->convert;459case CV_CAP_PROP_MODE:460return capture->mode;461case CV_CAP_PROP_FORMAT:462return capture->format;463case CV_CAP_PROP_FPS:464CV_DC1394_CALL(dc1394_get_video_framerate(capture->handle, capture->camera->node,465(unsigned int *) &capture->camera->frame_rate));466switch(capture->camera->frame_rate) {467case FRAMERATE_1_875:468return 1.875;469case FRAMERATE_3_75:470return 3.75;471case FRAMERATE_7_5:472return 7.5;473case FRAMERATE_15:474return 15.;475case FRAMERATE_30:476return 30.;477case FRAMERATE_60:478return 60;479#if NUM_FRAMERATES > 6480case FRAMERATE_120:481return 120;482#endif483#if NUM_FRAMERATES > 7484case FRAMERATE_240:485return 240;486#endif487}488default:489index = property_id; // did they pass in a LIBDC1394 feature flag?490break;491}492if(index>=FEATURE_MIN && index<=FEATURE_MAX){493dc1394bool_t has_feature;494CV_DC1394_CALL( dc1394_is_feature_present(capture->handle, capture->camera->node,495index, &has_feature));496if(!has_feature){497CV_WARN("Feature is not supported by this camera");498}499else{500unsigned int value;501dc1394_get_feature_value(capture->handle, capture->camera->node, index, &value);502return (double) value;503}504}505506return 0;507};508509// resize capture->frame appropriately depending on camera and capture settings510static int icvResizeFrame(CvCaptureCAM_DC1394 * capture){511if(capture->convert){512// resize if sizes are different, formats are different513// or conversion option has changed514if(capture->camera->frame_width != capture->frame.width ||515capture->camera->frame_height != capture->frame.height ||516capture->frame.depth != 8 ||517capture->frame.nChannels != 3 ||518capture->frame.imageData == NULL ||519capture->buffer_is_writeable == 0)520{521if(capture->frame.imageData && capture->buffer_is_writeable){522cvReleaseData( &(capture->frame));523}524cvInitImageHeader( &capture->frame, cvSize( capture->camera->frame_width,525capture->camera->frame_height ),526IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );527cvCreateData( &(capture->frame) );528capture->buffer_is_writeable = 1;529}530531}532else {533// free image data if allocated by opencv534if(capture->buffer_is_writeable){535cvReleaseData(&(capture->frame));536}537538// figure out number of channels and bpp539int bpp = 8;540int nch = 3;541int width = capture->camera->frame_width;542int height = capture->camera->frame_height;543double code = CV_FOURCC('B','G','R',0);544switch(capture->color_mode){545case COLOR_FORMAT7_YUV422:546nch = 2;547code = CV_FOURCC('Y','4','2','2');548break;549case COLOR_FORMAT7_MONO8:550code = CV_FOURCC('Y',0,0,0);551nch = 1;552break;553case COLOR_FORMAT7_YUV411:554code = CV_FOURCC('Y','4','1','1');555width *= 2;556nch = 3; //yy[u/v]557break;558case COLOR_FORMAT7_YUV444:559code = CV_FOURCC('Y','U','V',0);560nch = 3;561break;562case COLOR_FORMAT7_MONO16:563code = CV_FOURCC('Y',0,0,0);564bpp = IPL_DEPTH_16S;565nch = 1;566break;567case COLOR_FORMAT7_RGB16:568bpp = IPL_DEPTH_16S;569nch = 3;570break;571default:572break;573}574// reset image header575cvInitImageHeader( &capture->frame,cvSize( width, height ), bpp, nch, IPL_ORIGIN_TL, 4 );576//assert(capture->frame.imageSize == capture->camera->quadlets_per_frame*4);577capture->buffer_is_writeable = 0;578}579return 1;580}581582// Toggle setting about whether or not RGB color conversion is to be performed583// Allocates/Initializes capture->frame appropriately584int icvSetConvertRGB(CvCaptureCAM_DC1394 * capture, int convert){585if(convert==capture->convert){586// no action necessary587return 1;588}589capture->convert = convert;590return icvResizeFrame( capture );591}592593// given desired format, mode, and modes bitmask from camera, determine if format and mode are supported594static int595icvFormatSupportedCAM_DC1394(int format, quadlet_t formats){596// formats is a bitmask whose higher order bits indicate whether format is supported597int shift = 31 - (format - FORMAT_MIN);598int mask = 1 << shift;599return (formats & mask) != 0;600}601602// analyze modes bitmask from camera to determine if desired format and mode are supported603static int604icvModeSupportedCAM_DC1394(int format, int mode, quadlet_t modes){605// modes is a bitmask whose higher order bits indicate whether mode is supported606int format_idx = format - FORMAT_MIN;607int mode_format_min = MODE_FORMAT0_MIN + 32*format_idx;608int shift = 31 - (mode - mode_format_min);609int mask = 0x1 << shift;610return (modes & mask) != 0;611}612613// Setup camera to use given dc1394 mode614static int615icvSetModeCAM_DC1394( CvCaptureCAM_DC1394 * capture, int mode ){616quadlet_t modes, formats;617//printf("<icvSetModeCAM_DC1394>\n");618619// figure out corrent format for this mode620int format = (mode - MODE_FORMAT0_MIN) / 32 + FORMAT_MIN;621622// get supported formats623if (dc1394_query_supported_formats(capture->handle, capture->camera->node, &formats)<0) {624fprintf(stderr,"%s:%d: Could not query supported formats\n",__FILE__,__LINE__);625return 0;626}627628// is format for requested mode supported ?629if(icvFormatSupportedCAM_DC1394(format, formats)==0){630return 0;631}632633// get supported modes for requested format634if (dc1394_query_supported_modes(capture->handle, capture->camera->node, format, &modes)<0){635fprintf(stderr,"%s:%d: Could not query supported modes for format %d\n",__FILE__,__LINE__, capture->format);636return 0;637}638639// is requested mode supported ?640if(! icvModeSupportedCAM_DC1394(format, mode, modes) ){641return 0;642}643644int color_mode = icvColorMode( mode );645646if(color_mode == -1){647return 0;648}649650int frame_rate = icvGetBestFrameRate(capture, format, mode);651652dc1394_dma_unlisten(capture->handle, capture->camera);653if (dc1394_dma_setup_capture(capture->handle, capture->camera->node, capture->camera->channel /*channel*/,654format, mode, SPEED_400,655frame_rate, NUM_BUFFERS, 1 /*drop_frames*/,656capture->device_name, capture->camera) != DC1394_SUCCESS) {657fprintf(stderr,"%s:%d: Failed to setup DMA capture with VIDEO1394\n",__FILE__,__LINE__);658return 0;659}660dc1394_start_iso_transmission(capture->handle, capture->camera->node);661662capture->frame_rate = frame_rate;663capture->format = format;664capture->mode = mode;665capture->color_mode = color_mode;666667// now fix image size to match new mode668icvResizeFrame( capture );669return 1;670}671672// query camera for supported frame rates and select fastest for given format and mode673static unsigned int icvGetBestFrameRate( CvCaptureCAM_DC1394 * capture, int format, int mode ){674quadlet_t framerates;675if (dc1394_query_supported_framerates(capture->handle, capture->camera->node,676format, mode, &framerates)!=DC1394_SUCCESS)677{678fprintf(stderr,"%s:%d: Could not query supported framerates\n",__FILE__,__LINE__);679framerates = 0;680}681682for (int f=FRAMERATE_MAX; f>=FRAMERATE_MIN; f--) {683if (framerates & (0x1<< (31-(f-FRAMERATE_MIN)))) {684return f;685}686}687return 0;688}689690static int691icvSetFrameRateCAM_DC1394( CvCaptureCAM_DC1394 * capture, double value ){692unsigned int fps=15;693if(capture->format == FORMAT_SCALABLE_IMAGE_SIZE)694return 0; /* format 7 has no fixed framerates */695if (value==-1){696fps=icvGetBestFrameRate( capture, capture->format, capture->mode );697}698else if (value==1.875)699fps=FRAMERATE_1_875;700else if (value==3.75)701fps=FRAMERATE_3_75;702else if (value==7.5)703fps=FRAMERATE_7_5;704else if (value==15)705fps=FRAMERATE_15;706else if (value==30)707fps=FRAMERATE_30;708else if (value==60)709fps=FRAMERATE_60;710#if NUM_FRAMERATES > 6711else if (value==120)712fps=FRAMERATE_120;713#endif714#if NUM_FRAMERATES > 7715else if (value==240)716fps=FRAMERATE_240;717#endif718dc1394_set_video_framerate(capture->handle, capture->camera->node,fps);719dc1394_get_video_framerate(capture->handle, capture->camera->node,720(unsigned int *) &capture->camera->frame_rate);721722return fps==(unsigned int) capture->camera->frame_rate;723}724725// for given mode return color format726static int727icvColorMode( int mode ){728switch(mode) {729case MODE_160x120_YUV444:730return COLOR_FORMAT7_YUV444;731case MODE_320x240_YUV422:732case MODE_640x480_YUV422:733case MODE_800x600_YUV422:734case MODE_1024x768_YUV422:735case MODE_1280x960_YUV422:736case MODE_1600x1200_YUV422:737return COLOR_FORMAT7_YUV422;738case MODE_640x480_YUV411:739return COLOR_FORMAT7_YUV411;740case MODE_640x480_RGB:741case MODE_800x600_RGB:742case MODE_1024x768_RGB:743case MODE_1280x960_RGB:744case MODE_1600x1200_RGB:745return COLOR_FORMAT7_RGB8;746case MODE_640x480_MONO:747case MODE_800x600_MONO:748case MODE_1024x768_MONO:749case MODE_1280x960_MONO:750case MODE_1600x1200_MONO:751return COLOR_FORMAT7_MONO8;752case MODE_640x480_MONO16:753case MODE_800x600_MONO16:754case MODE_1024x768_MONO16:755case MODE_1280x960_MONO16:756case MODE_1600x1200_MONO16:757return COLOR_FORMAT7_MONO16;758case MODE_FORMAT7_0:759case MODE_FORMAT7_1:760case MODE_FORMAT7_2:761case MODE_FORMAT7_3:762case MODE_FORMAT7_4:763case MODE_FORMAT7_5:764case MODE_FORMAT7_6:765case MODE_FORMAT7_7:766fprintf(stderr,"%s:%d: Format7 not yet supported\n",__FILE__,__LINE__);767default:768break;769}770return -1;771}772773// function to set camera properties using dc1394 feature enum774// val == -1 indicates to set this property to 'auto'775static int776icvSetFeatureCAM_DC1394( CvCaptureCAM_DC1394* capture, int feature_id, int val){777dc1394bool_t isOn = DC1394_FALSE;778dc1394bool_t hasAutoCapability = DC1394_FALSE;779dc1394bool_t isAutoOn = DC1394_FALSE;780unsigned int nval;781unsigned int minval,maxval;782783// Turn the feature on if it is OFF784if( dc1394_is_feature_on(capture->handle, capture->camera->node, feature_id, &isOn)785== DC1394_FAILURE ) {786return 0;787}788if( isOn == DC1394_FALSE ) {789// try to turn it on.790if( dc1394_feature_on_off(capture->handle, capture->camera->node, feature_id, 1) == DC1394_FAILURE ) {791fprintf(stderr, "error turning feature %d on!\n", feature_id);792return 0;793}794}795796// Check if the feature supports auto mode797dc1394_has_auto_mode(capture->handle, capture->camera->node, feature_id, &hasAutoCapability);798if( hasAutoCapability ) {799800// now check if the auto is on.801if( dc1394_is_feature_auto(capture->handle, capture->camera->node, feature_id, &isAutoOn ) == DC1394_FAILURE ) {802fprintf(stderr, "error determining if feature %d has auto on!\n", feature_id);803return 0;804}805}806// Caller requested auto mode, but cannot support it807else if(val==-1){808fprintf(stderr, "feature %d does not support auto mode\n", feature_id);809return 0;810}811812if(val==-1){813// if the auto mode isn't enabled, enable it814if( isAutoOn == DC1394_FALSE ) {815if(dc1394_auto_on_off(capture->handle, capture->camera->node, feature_id, 1) == DC1394_FAILURE ) {816fprintf(stderr, "error turning feature %d auto ON!\n", feature_id);817return 0;818}819}820return 1;821}822823// ELSE turn OFF auto and adjust feature manually824if( isAutoOn == DC1394_TRUE ) {825if(dc1394_auto_on_off(capture->handle, capture->camera->node, feature_id, 0) == DC1394_FAILURE ) {826fprintf(stderr, "error turning feature %d auto OFF!\n", feature_id);827return 0;828}829}830831// Clamp val to within feature range832CV_DC1394_CALL( dc1394_get_min_value(capture->handle, capture->camera->node, feature_id, &minval));833CV_DC1394_CALL( dc1394_get_max_value(capture->handle, capture->camera->node, feature_id, &maxval));834val = (int)MIN(maxval, MAX((unsigned)val, minval));835836837if (dc1394_set_feature_value(capture->handle, capture->camera->node, feature_id, val) ==838DC1394_FAILURE){839fprintf(stderr, "error setting feature value\n");840return 0;841}842if (dc1394_get_feature_value(capture->handle, capture->camera->node, feature_id, &nval) ==843DC1394_FAILURE){844fprintf(stderr, "error setting feature value\n");845return 0;846}847return nval==(unsigned int)val;848849}850851// cvSetCaptureProperty callback function implementation852static int853icvSetPropertyCAM_DC1394( CvCaptureCAM_DC1394* capture, int property_id, double value ){854int index=-1;855switch ( property_id ) {856case CV_CAP_PROP_CONVERT_RGB:857return icvSetConvertRGB( capture, value != 0 );858case CV_CAP_PROP_MODE:859return icvSetModeCAM_DC1394( capture, (int) value );860case CV_CAP_PROP_FPS:861return icvSetFrameRateCAM_DC1394( capture, value );862case CV_CAP_PROP_BRIGHTNESS:863index = FEATURE_BRIGHTNESS;864break;865case CV_CAP_PROP_CONTRAST:866index = FEATURE_GAMMA;867break;868case CV_CAP_PROP_SATURATION:869index = FEATURE_SATURATION;870break;871case CV_CAP_PROP_HUE:872index = FEATURE_HUE;873break;874case CV_CAP_PROP_GAIN:875index = FEATURE_GAIN;876break;877default:878index = property_id; // did they pass in a LIBDC1394 feature flag?879break;880}881if(index>=FEATURE_MIN && index<=FEATURE_MAX){882return icvSetFeatureCAM_DC1394(capture, index, (int) value);883}884return 0;885};886887/**********************************************************************888*889* CONVERSION FUNCTIONS TO RGB 24bpp890*891**********************************************************************/892893/* color conversion functions from Bart Nabbe. *//* corrected by Damien: bad coeficients in YUV2RGB */894#define YUV2RGB(y, u, v, r, g, b)\895r = y + ((v*1436) >> 10);\896g = y - ((u*352 + v*731) >> 10);\897b = y + ((u*1814) >> 10);\898r = r < 0 ? 0 : r;\899g = g < 0 ? 0 : g;\900b = b < 0 ? 0 : b;\901r = r > 255 ? 255 : r;\902g = g > 255 ? 255 : g;\903b = b > 255 ? 255 : b904905static void906uyv2bgr(const unsigned char *src, unsigned char *dest,907unsigned long long int NumPixels)908{909int i = NumPixels + (NumPixels << 1) - 1;910int j = NumPixels + (NumPixels << 1) - 1;911int y, u, v;912int r, g, b;913914while (i > 0) {915v = src[i--] - 128;916y = src[i--];917u = src[i--] - 128;918YUV2RGB(y, u, v, r, g, b);919dest[j--] = r;920dest[j--] = g;921dest[j--] = b;922}923}924925static void926uyvy2bgr(const unsigned char *src, unsigned char *dest,927unsigned long long int NumPixels)928{929int i = (NumPixels << 1) - 1;930int j = NumPixels + (NumPixels << 1) - 1;931int y0, y1, u, v;932int r, g, b;933934while (i > 0) {935y1 = src[i--];936v = src[i--] - 128;937y0 = src[i--];938u = src[i--] - 128;939YUV2RGB(y1, u, v, r, g, b);940dest[j--] = r;941dest[j--] = g;942dest[j--] = b;943YUV2RGB(y0, u, v, r, g, b);944dest[j--] = r;945dest[j--] = g;946dest[j--] = b;947}948}949950951static void952uyyvyy2bgr(const unsigned char *src, unsigned char *dest,953unsigned long long int NumPixels)954{955int i = NumPixels + (NumPixels >> 1) - 1;956int j = NumPixels + (NumPixels << 1) - 1;957int y0, y1, y2, y3, u, v;958int r, g, b;959960while (i > 0) {961y3 = src[i--];962y2 = src[i--];963v = src[i--] - 128;964y1 = src[i--];965y0 = src[i--];966u = src[i--] - 128;967YUV2RGB(y3, u, v, r, g, b);968dest[j--] = r;969dest[j--] = g;970dest[j--] = b;971YUV2RGB(y2, u, v, r, g, b);972dest[j--] = r;973dest[j--] = g;974dest[j--] = b;975YUV2RGB(y1, u, v, r, g, b);976dest[j--] = r;977dest[j--] = g;978dest[j--] = b;979YUV2RGB(y0, u, v, r, g, b);980dest[j--] = r;981dest[j--] = g;982dest[j--] = b;983}984}985986static void987y2bgr(const unsigned char *src, unsigned char *dest,988unsigned long long int NumPixels)989{990int i = NumPixels - 1;991int j = NumPixels + (NumPixels << 1) - 1;992int y;993994while (i > 0) {995y = src[i--];996dest[j--] = y;997dest[j--] = y;998dest[j--] = y;999}1000}10011002static void1003y162bgr(const unsigned char *src, unsigned char *dest,1004unsigned long long int NumPixels, int bits)1005{1006int i = (NumPixels << 1) - 1;1007int j = NumPixels + (NumPixels << 1) - 1;1008int y;10091010while (i > 0) {1011y = src[i--];1012y = (y + (src[i--] << 8)) >> (bits - 8);1013dest[j--] = y;1014dest[j--] = y;1015dest[j--] = y;1016}1017}10181019// this one was in coriander but didn't take bits into account1020static void1021rgb482bgr(const unsigned char *src, unsigned char *dest,1022unsigned long long int NumPixels, int bits)1023{1024int i = (NumPixels << 1) - 1;1025int j = NumPixels + (NumPixels << 1) - 1;1026int y;10271028while (i > 0) {1029y = src[i--];1030dest[j-2] = (y + (src[i--] << 8)) >> (bits - 8);1031j--;1032y = src[i--];1033dest[j] = (y + (src[i--] << 8)) >> (bits - 8);1034j--;1035y = src[i--];1036dest[j+2] = (y + (src[i--] << 8)) >> (bits - 8);1037j--;1038}1039}104010411042class CvCaptureCAM_DC1394_CPP : public CvCapture1043{1044public:1045CvCaptureCAM_DC1394_CPP() { captureDC1394 = 0; }1046virtual ~CvCaptureCAM_DC1394_CPP() { close(); }10471048virtual bool open( int index );1049virtual void close();10501051virtual double getProperty(int) const CV_OVERRIDE;1052virtual bool setProperty(int, double) CV_OVERRIDE;1053virtual bool grabFrame() CV_OVERRIDE;1054virtual IplImage* retrieveFrame(int) CV_OVERRIDE;1055virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_DC1394; }1056protected:10571058CvCaptureCAM_DC1394* captureDC1394;1059};10601061bool CvCaptureCAM_DC1394_CPP::open( int index )1062{1063close();1064captureDC1394 = icvCaptureFromCAM_DC1394(index);1065return captureDC1394 != 0;1066}10671068void CvCaptureCAM_DC1394_CPP::close()1069{1070if( captureDC1394 )1071{1072icvCloseCAM_DC1394( captureDC1394 );1073cvFree( &captureDC1394 );1074}1075}10761077bool CvCaptureCAM_DC1394_CPP::grabFrame()1078{1079return captureDC1394 ? icvGrabFrameCAM_DC1394( captureDC1394 ) != 0 : false;1080}10811082IplImage* CvCaptureCAM_DC1394_CPP::retrieveFrame(int)1083{1084return captureDC1394 ? (IplImage*)icvRetrieveFrameCAM_DC1394( captureDC1394, 0 ) : 0;1085}10861087double CvCaptureCAM_DC1394_CPP::getProperty( int propId ) const1088{1089// Simulate mutable (C++11-like) member variable1090// (some members are used to cache property settings).1091CvCaptureCAM_DC1394* cap = const_cast<CvCaptureCAM_DC1394*>(captureDC1394);10921093return cap ? icvGetPropertyCAM_DC1394( cap, propId ) : 0;1094}10951096bool CvCaptureCAM_DC1394_CPP::setProperty( int propId, double value )1097{1098return captureDC1394 ? icvSetPropertyCAM_DC1394( captureDC1394, propId, value ) != 0 : false;1099}11001101CvCapture* cvCreateCameraCapture_DC1394( int index )1102{1103CvCaptureCAM_DC1394_CPP* capture = new CvCaptureCAM_DC1394_CPP;11041105if( capture->open( index ))1106return capture;11071108delete capture;1109return 0;1110}11111112#endif111311141115