1 /* This is the contributed code:
2 Firewire and video4linux camera support for videoio
3
4 2003-03-12 Magnus Lundin
5 lundin@mlu.mine.nu
6
7 THIS EXEPERIMENTAL CODE
8 Tested on 2.4.19 with 1394, video1394, v4l, dc1394 and raw1394 support
9
10 This set of files adds support for firevre and usb cameras.
11 First it tries to install a firewire camera,
12 if that fails it tries a v4l/USB camera
13
14 It has been tested with the motempl sample program
15
16 INSTALLATION
17 Install OpenCV
18 Install v4l
19 Install dc1394 raw1394 - coriander should work with your camera
20 Backup videoio folder
21 Copy new files
22 cd into videoio folder
23 make clean (cvcap.cpp must be rebuilt)
24 make
25 make install
26
27
28 The build is controlled by the following entries in the videoio Makefile:
29
30 libvideoio_la_LIBADD = -L/usr/X11R6/lib -lXm -lMrm -lUil -lpng -ljpeg -lz -ltiff -lavcodec -lraw1394 -ldc1394_control
31 DEFS = -DHAVE_CONFIG_H -DHAVE_DC1394 HAVE_CAMV4L
32
33
34 Now it should be possible to use videoio camera functions, works for me.
35
36
37 THINGS TO DO
38 Better ways to select 1394 or v4l camera
39 Better support for videosize
40 Format7
41
42 Comments and changes welcome
43 /Magnus
44
45 2005-10-19 Roman Stanchak
46 rstanchak@yahoo.com
47
48 Support added for setting MODE and other DC1394 properties. Also added CONVERT_RGB flag
49 which indicates whether or not color conversion is performed in cvRetrieveFrame. The default
50 for CONVERT_RGB=1 for backward compatibility.
51
52 Tested with 2.6.12 with libdc1394-1.0.0, libraw1394-0.10.1 using a Point Grey Flea
53
54 */
55
56
57 /*M///////////////////////////////////////////////////////////////////////////////////////
58 //
59 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
60 //
61 // By downloading, copying, installing or using the software you agree to this license.
62 // If you do not agree to this license, do not download, install,
63 // copy or use the software.
64 //
65 //
66 // Intel License Agreement
67 // For Open Source Computer Vision Library
68 //
69 // Copyright (C) 2000, Intel Corporation, all rights reserved.
70 // Third party copyrights are property of their respective owners.
71 //
72 // Redistribution and use in source and binary forms, with or without modification,
73 // are permitted provided that the following conditions are met:
74 //
75 // * Redistribution's of source code must retain the above copyright notice,
76 // this list of conditions and the following disclaimer.
77 //
78 // * Redistribution's in binary form must reproduce the above copyright notice,
79 // this list of conditions and the following disclaimer in the documentation
80 // and/or other materials provided with the distribution.
81 //
82 // * The name of Intel Corporation may not be used to endorse or promote products
83 // derived from this software without specific prior written permission.
84 //
85 // This software is provided by the copyright holders and contributors "as is" and
86 // any express or implied warranties, including, but not limited to, the implied
87 // warranties of merchantability and fitness for a particular purpose are disclaimed.
88 // In no event shall the Intel Corporation or contributors be liable for any direct,
89 // indirect, incidental, special, exemplary, or consequential damages
90 // (including, but not limited to, procurement of substitute goods or services;
91 // loss of use, data, or profits; or business interruption) however caused
92 // and on any theory of liability, whether in contract, strict liability,
93 // or tort (including negligence or otherwise) arising in any way out of
94 // the use of this software, even if advised of the possibility of such damage.
95 //
96 //M*/
97
98 #include "precomp.hpp"
99
100 #if !defined WIN32 && defined HAVE_DC1394
101
102 #include <unistd.h>
103 #include <stdint.h>
104 #include <libraw1394/raw1394.h>
105 #include <libdc1394/dc1394_control.h>
106
107 #ifdef NDEBUG
108 #define CV_WARN(message)
109 #else
110 #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
111 #endif
112
113 #define CV_DC1394_CALL(expr) \
114 if((expr)<0){ \
115 OPENCV_ERROR(CV_StsInternal, "", "libdc1394 function call returned < 0"); \
116 }
117
118 #define DELAY 50000
119
120 // bpp for 16-bits cameras... this value works for PtGrey DragonFly...
121 #define MONO16_BPP 8
122
123 /* should be in pixelformat */
124 static void uyv2bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels);
125 static void uyvy2bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels);
126 static void uyyvyy2bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels);
127 static void y2bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels);
128 static void y162bgr(const unsigned char *src, unsigned char *dest, unsigned long long int NumPixels, int bits);
129 static void rgb482bgr(const unsigned char *src8, unsigned char *dest, unsigned long long int NumPixels, int bits);
130
131 static const char * videodev[4]={
132 "/dev/video1394/0",
133 "/dev/video1394/1",
134 "/dev/video1394/2",
135 "/dev/video1394/3"
136 };
137
138 typedef struct CvCaptureCAM_DC1394
139 {
140 raw1394handle_t handle;
141 nodeid_t camera_node;
142 dc1394_cameracapture* camera;
143 int format;
144 int mode;
145 int color_mode;
146 int frame_rate;
147 const char * device_name;
148 IplImage frame;
149 int convert;
150 int buffer_is_writeable; // indicates whether frame.imageData is allocated by OpenCV or DC1394
151 }
152 CvCaptureCAM_DC1394;
153
154 static void icvCloseCAM_DC1394( CvCaptureCAM_DC1394* capture );
155
156 static int icvGrabFrameCAM_DC1394( CvCaptureCAM_DC1394* capture );
157 static IplImage* icvRetrieveFrameCAM_DC1394( CvCaptureCAM_DC1394* capture, int );
158
159 static double icvGetPropertyCAM_DC1394( CvCaptureCAM_DC1394* capture, int property_id );
160 static int icvSetPropertyCAM_DC1394( CvCaptureCAM_DC1394* capture, int property_id, double value );
161
162 // utility functions
163 static int icvFormatSupportedCAM_DC1394(int format, quadlet_t formats);
164 static int icvModeSupportedCAM_DC1394(int format, int mode, quadlet_t modes);
165 static int icvColorMode( int mode );
166 static unsigned int icvGetBestFrameRate( CvCaptureCAM_DC1394 * capture, int format, int mode);
167 static int icvResizeFrame(CvCaptureCAM_DC1394 * capture);
168
169 /*********************** Implementations ***************************************/
170 #define MAX_PORTS 3
171 #define MAX_CAMERAS 8
172 #define NUM_BUFFERS 8
173 struct raw1394_portinfo ports[MAX_PORTS];
174 static raw1394handle_t handles[MAX_PORTS];
175 static int camCount[MAX_PORTS];
176 static int numPorts = -1;
177 static int numCameras = 0;
178 static nodeid_t *camera_nodes;
179 struct camnode {dc1394_cameracapture cam;int portnum;} cameras[MAX_CAMERAS];
180
181 static const int preferred_modes[]
182 = {
183 // uncomment the following line to test a particular mode:
184 //FORMAT_VGA_NONCOMPRESSED, MODE_640x480_MONO16, 0,
185 FORMAT_SVGA_NONCOMPRESSED_2,
186 MODE_1600x1200_RGB, MODE_1600x1200_YUV422, MODE_1280x960_RGB, MODE_1280x960_YUV422,
187 MODE_1600x1200_MONO, MODE_1280x960_MONO, MODE_1600x1200_MONO16, MODE_1280x960_MONO16,
188 FORMAT_SVGA_NONCOMPRESSED_1,
189 MODE_1024x768_RGB, MODE_1024x768_YUV422, MODE_800x600_RGB, MODE_800x600_YUV422,
190 MODE_1024x768_MONO, MODE_800x600_MONO, MODE_1024x768_MONO16, MODE_800x600_MONO16,
191 FORMAT_VGA_NONCOMPRESSED,
192 MODE_640x480_RGB, MODE_640x480_YUV422, MODE_640x480_YUV411, MODE_320x240_YUV422,
193 MODE_160x120_YUV444, MODE_640x480_MONO, MODE_640x480_MONO16,
194 FORMAT_SCALABLE_IMAGE_SIZE,
195 MODE_FORMAT7_0, MODE_FORMAT7_1, MODE_FORMAT7_2, MODE_FORMAT7_3,
196 MODE_FORMAT7_4, MODE_FORMAT7_5, MODE_FORMAT7_6, MODE_FORMAT7_7,
197 0
198 };
199
icvInitCapture_DC1394()200 void icvInitCapture_DC1394(){
201 int p;
202
203 raw1394handle_t raw_handle = raw1394_new_handle();
204 if( raw_handle == 0 ) {
205 numPorts = 0;
206 return;
207 }
208 numPorts = raw1394_get_port_info(raw_handle, ports, MAX_PORTS);
209 raw1394_destroy_handle(raw_handle);
210 for (p = 0; p < numPorts; p++) {
211 handles[p] = dc1394_create_handle(p);
212 if (handles[p]==NULL) { numPorts=-1; return; /*ERROR_CLEANUP_EXIT*/ }
213
214 /* get the camera nodes and describe them as we find them */
215 camera_nodes = dc1394_get_camera_nodes(handles[p], &camCount[p], 0);
216 for (int i=0;i<camCount[p];i++) {
217 cameras[numCameras].cam.node = camera_nodes[i];
218 cameras[numCameras].portnum = p;
219 dc1394_stop_iso_transmission(handles[p], camera_nodes[i]);
220 numCameras++;
221 }
222 }
223 };
224
icvCaptureFromCAM_DC1394(int index)225 static CvCaptureCAM_DC1394 * icvCaptureFromCAM_DC1394 (int index)
226 {
227 quadlet_t modes[8], formats;
228 int i;
229
230 if (numPorts<0) icvInitCapture_DC1394();
231 if (numPorts==0)
232 return 0; /* No i1394 ports found */
233 if (numCameras<1)
234 return 0;
235 if (index>=numCameras)
236 return 0;
237 if (index<0)
238 return 0;
239
240 CvCaptureCAM_DC1394 * pcap = (CvCaptureCAM_DC1394*)cvAlloc(sizeof(*pcap));
241
242 /* Select a port and camera */
243 pcap->device_name = videodev[cameras[index].portnum];
244 pcap->handle = handles[cameras[index].portnum];
245 pcap->camera = &cameras[index].cam;
246
247 // get supported formats
248 if (dc1394_query_supported_formats(pcap->handle, pcap->camera->node, &formats)<0) {
249 fprintf(stderr,"%s:%d: Could not query supported formats\n",__FILE__,__LINE__);
250 formats=0x0;
251 }
252 for (i=0; i < NUM_FORMATS; i++) {
253 modes[i]=0;
254 if (icvFormatSupportedCAM_DC1394(i+FORMAT_MIN, formats)){
255 if (dc1394_query_supported_modes(pcap->handle, pcap->camera->node, i+FORMAT_MIN, &modes[i])<0) {
256 fprintf(stderr,"%s:%d: Could not query Format%d modes\n",__FILE__,__LINE__,i);
257 }
258 }
259 }
260
261 pcap->format = 0;
262 pcap->mode = 0;
263 pcap->color_mode = 0;
264 pcap->frame_rate = 0;
265
266 int format_idx = -1;
267
268 // scan the list of preferred modes, and find a supported one
269 for(i=0; (pcap->mode == 0) && (preferred_modes[i] != 0); i++) {
270 if((preferred_modes[i] >= FORMAT_MIN) && (preferred_modes[i] <= FORMAT_MAX)) {
271 pcap->format = preferred_modes[i];
272 format_idx = preferred_modes[i] - FORMAT_MIN;
273 continue;
274 }
275 assert(format_idx != -1);
276 if ( ! icvFormatSupportedCAM_DC1394(pcap->format, formats) )
277 continue;
278 if ( icvModeSupportedCAM_DC1394(pcap->format, preferred_modes[i], modes[format_idx]) ){
279 pcap->mode = preferred_modes[i];
280 }
281 }
282 if (pcap->mode == 0) {
283 fprintf(stderr,"%s:%d: Could not find a supported mode for this camera\n",__FILE__,__LINE__);
284 goto ERROR;
285 }
286
287 pcap->color_mode = icvColorMode( pcap->mode );
288 if( pcap->color_mode == -1){
289 fprintf(stderr,"%s:%d: ERROR: BPP is Unsupported!!\n",__FILE__,__LINE__);
290 goto ERROR;
291 }
292
293 // set frame rate to optimal value given format and mode
294 pcap->frame_rate = icvGetBestFrameRate(pcap, pcap->format, pcap->mode);
295
296 if (pcap->format!=FORMAT_SCALABLE_IMAGE_SIZE) { // everything except Format 7
297 if (dc1394_dma_setup_capture(pcap->handle, pcap->camera->node, index+1 /*channel*/,
298 pcap->format, pcap->mode, SPEED_400,
299 pcap->frame_rate, NUM_BUFFERS, 1 /*drop_frames*/,
300 pcap->device_name, pcap->camera) != DC1394_SUCCESS) {
301 fprintf(stderr,"%s:%d: Failed to setup DMA capture with VIDEO1394\n",__FILE__,__LINE__);
302 goto ERROR;
303 }
304 }
305 else {
306 if(dc1394_dma_setup_format7_capture(pcap->handle,pcap->camera->node,index+1 /*channel*/,
307 pcap->mode, SPEED_400, QUERY_FROM_CAMERA,
308 (unsigned int)QUERY_FROM_CAMERA, (unsigned int)QUERY_FROM_CAMERA,
309 (unsigned int)QUERY_FROM_CAMERA, (unsigned int)QUERY_FROM_CAMERA,
310 NUM_BUFFERS, 1 /*drop_frames*/,
311 pcap->device_name, pcap->camera) != DC1394_SUCCESS) {
312 fprintf(stderr,"%s:%d: Failed to setup DMA capture with VIDEO1394\n",__FILE__,__LINE__);
313 goto ERROR;
314 }
315 }
316
317 if (dc1394_start_iso_transmission(pcap->handle, pcap->camera->node)!=DC1394_SUCCESS) {
318 fprintf(stderr,"%s:%d: Could not start ISO transmission\n",__FILE__,__LINE__);
319 goto ERROR;
320 }
321
322 usleep(DELAY);
323
324 dc1394bool_t status;
325 if (dc1394_get_iso_status(pcap->handle, pcap->camera->node, &status)!=DC1394_SUCCESS) {
326 fprintf(stderr,"%s:%d: Could get ISO status",__FILE__,__LINE__);
327 goto ERROR;
328 }
329 if (status==DC1394_FALSE) {
330 fprintf(stderr,"%s:%d: ISO transmission refuses to start",__FILE__,__LINE__);
331 goto ERROR;
332 }
333
334 // convert camera image to RGB by default
335 pcap->convert=1;
336
337 // no image data allocated yet
338 pcap->buffer_is_writeable = 0;
339
340 memset(&(pcap->frame), 0, sizeof(IplImage));
341 icvResizeFrame( pcap );
342 return pcap;
343
344 ERROR:
345 return 0;
346 };
347
icvCloseCAM_DC1394(CvCaptureCAM_DC1394 * capture)348 static void icvCloseCAM_DC1394( CvCaptureCAM_DC1394* capture ){
349 dc1394_stop_iso_transmission(capture->handle, capture->camera->node);
350 dc1394_dma_unlisten (capture->handle, capture->camera);
351 /* Deallocate space for RGBA data */
352 if(capture->convert){
353 cvFree(&capture->frame.imageData);
354 }
355 }
356
icvGrabFrameCAM_DC1394(CvCaptureCAM_DC1394 * capture)357 static int icvGrabFrameCAM_DC1394( CvCaptureCAM_DC1394* capture ){
358 // TODO: should this function wait until the next frame is available or return
359 // immediately ?
360 float waiting = 0;
361 do{
362 int result = dc1394_dma_single_capture_poll(capture->camera);
363 if(result==DC1394_SUCCESS){
364 return 1;
365 }
366 else if(result==DC1394_NO_FRAME){
367 usleep(1000000/120); //sleep for at least a 1/2 of the frame rate
368 waiting += 1.0/120.0;
369 }
370 else{
371 printf("dc1394_dma_single_capture_poll failed\n");
372 return 0;
373 }
374 } while(waiting<2);
375 printf("dc1394_dma_single_capture_poll timed out\n");
376 return 0;
377 }
378
icvRetrieveFrameCAM_DC1394(CvCaptureCAM_DC1394 * capture,int)379 static IplImage* icvRetrieveFrameCAM_DC1394( CvCaptureCAM_DC1394* capture, int ){
380 if(capture->camera->capture_buffer )
381 {
382 if(capture->convert){
383 /* Convert to RGBA */
384 unsigned char * src = (unsigned char *)capture->camera->capture_buffer;
385 unsigned char * dst = (unsigned char *)capture->frame.imageData;
386 switch (capture->color_mode) {
387 case COLOR_FORMAT7_RGB8:
388 //printf("icvRetrieveFrame convert RGB to BGR\n");
389 /* Convert RGB to BGR */
390 for (int i=0;i<capture->frame.imageSize;i+=6) {
391 dst[i] = src[i+2];
392 dst[i+1] = src[i+1];
393 dst[i+2] = src[i];
394 dst[i+3] = src[i+5];
395 dst[i+4] = src[i+4];
396 dst[i+5] = src[i+3];
397 }
398 break;
399 case COLOR_FORMAT7_YUV422:
400 //printf("icvRetrieveFrame convert YUV422 to BGR %d\n");
401 uyvy2bgr(src,
402 dst,
403 capture->camera->frame_width * capture->camera->frame_height);
404 break;
405 case COLOR_FORMAT7_MONO8:
406 //printf("icvRetrieveFrame convert MONO8 to BGR %d\n");
407 y2bgr(src,
408 dst,
409 capture->camera->frame_width * capture->camera->frame_height);
410 break;
411 case COLOR_FORMAT7_YUV411:
412 //printf("icvRetrieveFrame convert YUV411 to BGR %d\n");
413 uyyvyy2bgr(src,
414 dst,
415 capture->camera->frame_width * capture->camera->frame_height);
416 break;
417 case COLOR_FORMAT7_YUV444:
418 //printf("icvRetrieveFrame convert YUV444 to BGR %d\n");
419 uyv2bgr(src,
420 dst,
421 capture->camera->frame_width * capture->camera->frame_height);
422 break;
423 case COLOR_FORMAT7_MONO16:
424 //printf("icvRetrieveFrame convert MONO16 to BGR %d\n");
425 y162bgr(src,
426 dst,
427 capture->camera->frame_width * capture->camera->frame_height, MONO16_BPP);
428 break;
429 case COLOR_FORMAT7_RGB16:
430 //printf("icvRetrieveFrame convert RGB16 to BGR %d\n");
431 rgb482bgr(src,
432 dst,
433 capture->camera->frame_width * capture->camera->frame_height, MONO16_BPP);
434 break;
435 default:
436 fprintf(stderr,"%s:%d: Unsupported color mode %d\n",__FILE__,__LINE__,capture->color_mode);
437 return 0;
438 } /* switch (capture->mode) */
439 }
440 else{
441 // return raw data
442 capture->frame.imageData = (char *) capture->camera->capture_buffer;
443 capture->frame.imageDataOrigin = (char *) capture->camera->capture_buffer;
444 }
445
446 // TODO: if convert=0, we are not actually done with the buffer
447 // but this seems to work anyway.
448 dc1394_dma_done_with_buffer(capture->camera);
449
450 return &capture->frame;
451 }
452 return 0;
453 };
454
icvGetPropertyCAM_DC1394(CvCaptureCAM_DC1394 * capture,int property_id)455 static double icvGetPropertyCAM_DC1394( CvCaptureCAM_DC1394* capture, int property_id ){
456 int index=-1;
457 switch ( property_id ) {
458 case CV_CAP_PROP_CONVERT_RGB:
459 return capture->convert;
460 case CV_CAP_PROP_MODE:
461 return capture->mode;
462 case CV_CAP_PROP_FORMAT:
463 return capture->format;
464 case CV_CAP_PROP_FPS:
465 CV_DC1394_CALL(dc1394_get_video_framerate(capture->handle, capture->camera->node,
466 (unsigned int *) &capture->camera->frame_rate));
467 switch(capture->camera->frame_rate) {
468 case FRAMERATE_1_875:
469 return 1.875;
470 case FRAMERATE_3_75:
471 return 3.75;
472 case FRAMERATE_7_5:
473 return 7.5;
474 case FRAMERATE_15:
475 return 15.;
476 case FRAMERATE_30:
477 return 30.;
478 case FRAMERATE_60:
479 return 60;
480 #if NUM_FRAMERATES > 6
481 case FRAMERATE_120:
482 return 120;
483 #endif
484 #if NUM_FRAMERATES > 7
485 case FRAMERATE_240:
486 return 240;
487 #endif
488 }
489 default:
490 index = property_id; // did they pass in a LIBDC1394 feature flag?
491 break;
492 }
493 if(index>=FEATURE_MIN && index<=FEATURE_MAX){
494 dc1394bool_t has_feature;
495 CV_DC1394_CALL( dc1394_is_feature_present(capture->handle, capture->camera->node,
496 index, &has_feature));
497 if(!has_feature){
498 CV_WARN("Feature is not supported by this camera");
499 }
500 else{
501 unsigned int value;
502 dc1394_get_feature_value(capture->handle, capture->camera->node, index, &value);
503 return (double) value;
504 }
505 }
506
507 return 0;
508 };
509
510 // resize capture->frame appropriately depending on camera and capture settings
icvResizeFrame(CvCaptureCAM_DC1394 * capture)511 static int icvResizeFrame(CvCaptureCAM_DC1394 * capture){
512 if(capture->convert){
513 // resize if sizes are different, formats are different
514 // or conversion option has changed
515 if(capture->camera->frame_width != capture->frame.width ||
516 capture->camera->frame_height != capture->frame.height ||
517 capture->frame.depth != 8 ||
518 capture->frame.nChannels != 3 ||
519 capture->frame.imageData == NULL ||
520 capture->buffer_is_writeable == 0)
521 {
522 if(capture->frame.imageData && capture->buffer_is_writeable){
523 cvReleaseData( &(capture->frame));
524 }
525 cvInitImageHeader( &capture->frame, cvSize( capture->camera->frame_width,
526 capture->camera->frame_height ),
527 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
528 cvCreateData( &(capture->frame) );
529 capture->buffer_is_writeable = 1;
530 }
531
532 }
533 else {
534 // free image data if allocated by opencv
535 if(capture->buffer_is_writeable){
536 cvReleaseData(&(capture->frame));
537 }
538
539 // figure out number of channels and bpp
540 int bpp = 8;
541 int nch = 3;
542 int width = capture->camera->frame_width;
543 int height = capture->camera->frame_height;
544 double code = CV_FOURCC('B','G','R',0);
545 switch(capture->color_mode){
546 case COLOR_FORMAT7_YUV422:
547 nch = 2;
548 code = CV_FOURCC('Y','4','2','2');
549 break;
550 case COLOR_FORMAT7_MONO8:
551 code = CV_FOURCC('Y',0,0,0);
552 nch = 1;
553 break;
554 case COLOR_FORMAT7_YUV411:
555 code = CV_FOURCC('Y','4','1','1');
556 width *= 2;
557 nch = 3; //yy[u/v]
558 break;
559 case COLOR_FORMAT7_YUV444:
560 code = CV_FOURCC('Y','U','V',0);
561 nch = 3;
562 break;
563 case COLOR_FORMAT7_MONO16:
564 code = CV_FOURCC('Y',0,0,0);
565 bpp = IPL_DEPTH_16S;
566 nch = 1;
567 break;
568 case COLOR_FORMAT7_RGB16:
569 bpp = IPL_DEPTH_16S;
570 nch = 3;
571 break;
572 default:
573 break;
574 }
575 // reset image header
576 cvInitImageHeader( &capture->frame,cvSize( width, height ), bpp, nch, IPL_ORIGIN_TL, 4 );
577 //assert(capture->frame.imageSize == capture->camera->quadlets_per_frame*4);
578 capture->buffer_is_writeable = 0;
579 }
580 return 1;
581 }
582
583 // Toggle setting about whether or not RGB color conversion is to be performed
584 // Allocates/Initializes capture->frame appropriately
icvSetConvertRGB(CvCaptureCAM_DC1394 * capture,int convert)585 int icvSetConvertRGB(CvCaptureCAM_DC1394 * capture, int convert){
586 if(convert==capture->convert){
587 // no action necessary
588 return 1;
589 }
590 capture->convert = convert;
591 return icvResizeFrame( capture );
592 }
593
594 // given desired format, mode, and modes bitmask from camera, determine if format and mode are supported
595 static int
icvFormatSupportedCAM_DC1394(int format,quadlet_t formats)596 icvFormatSupportedCAM_DC1394(int format, quadlet_t formats){
597 // formats is a bitmask whose higher order bits indicate whether format is supported
598 int shift = 31 - (format - FORMAT_MIN);
599 int mask = 1 << shift;
600 return (formats & mask) != 0;
601 }
602
603 // analyze modes bitmask from camera to determine if desired format and mode are supported
604 static int
icvModeSupportedCAM_DC1394(int format,int mode,quadlet_t modes)605 icvModeSupportedCAM_DC1394(int format, int mode, quadlet_t modes){
606 // modes is a bitmask whose higher order bits indicate whether mode is supported
607 int format_idx = format - FORMAT_MIN;
608 int mode_format_min = MODE_FORMAT0_MIN + 32*format_idx;
609 int shift = 31 - (mode - mode_format_min);
610 int mask = 0x1 << shift;
611 return (modes & mask) != 0;
612 }
613
614 // Setup camera to use given dc1394 mode
615 static int
icvSetModeCAM_DC1394(CvCaptureCAM_DC1394 * capture,int mode)616 icvSetModeCAM_DC1394( CvCaptureCAM_DC1394 * capture, int mode ){
617 quadlet_t modes, formats;
618 //printf("<icvSetModeCAM_DC1394>\n");
619
620 // figure out corrent format for this mode
621 int format = (mode - MODE_FORMAT0_MIN) / 32 + FORMAT_MIN;
622
623 // get supported formats
624 if (dc1394_query_supported_formats(capture->handle, capture->camera->node, &formats)<0) {
625 fprintf(stderr,"%s:%d: Could not query supported formats\n",__FILE__,__LINE__);
626 return 0;
627 }
628
629 // is format for requested mode supported ?
630 if(icvFormatSupportedCAM_DC1394(format, formats)==0){
631 return 0;
632 }
633
634 // get supported modes for requested format
635 if (dc1394_query_supported_modes(capture->handle, capture->camera->node, format, &modes)<0){
636 fprintf(stderr,"%s:%d: Could not query supported modes for format %d\n",__FILE__,__LINE__, capture->format);
637 return 0;
638 }
639
640 // is requested mode supported ?
641 if(! icvModeSupportedCAM_DC1394(format, mode, modes) ){
642 return 0;
643 }
644
645 int color_mode = icvColorMode( mode );
646
647 if(color_mode == -1){
648 return 0;
649 }
650
651 int frame_rate = icvGetBestFrameRate(capture, format, mode);
652
653 dc1394_dma_unlisten(capture->handle, capture->camera);
654 if (dc1394_dma_setup_capture(capture->handle, capture->camera->node, capture->camera->channel /*channel*/,
655 format, mode, SPEED_400,
656 frame_rate, NUM_BUFFERS, 1 /*drop_frames*/,
657 capture->device_name, capture->camera) != DC1394_SUCCESS) {
658 fprintf(stderr,"%s:%d: Failed to setup DMA capture with VIDEO1394\n",__FILE__,__LINE__);
659 return 0;
660 }
661 dc1394_start_iso_transmission(capture->handle, capture->camera->node);
662
663 capture->frame_rate = frame_rate;
664 capture->format = format;
665 capture->mode = mode;
666 capture->color_mode = color_mode;
667
668 // now fix image size to match new mode
669 icvResizeFrame( capture );
670 return 1;
671 }
672
673 // query camera for supported frame rates and select fastest for given format and mode
icvGetBestFrameRate(CvCaptureCAM_DC1394 * capture,int format,int mode)674 static unsigned int icvGetBestFrameRate( CvCaptureCAM_DC1394 * capture, int format, int mode ){
675 quadlet_t framerates;
676 if (dc1394_query_supported_framerates(capture->handle, capture->camera->node,
677 format, mode, &framerates)!=DC1394_SUCCESS)
678 {
679 fprintf(stderr,"%s:%d: Could not query supported framerates\n",__FILE__,__LINE__);
680 framerates = 0;
681 }
682
683 for (int f=FRAMERATE_MAX; f>=FRAMERATE_MIN; f--) {
684 if (framerates & (0x1<< (31-(f-FRAMERATE_MIN)))) {
685 return f;
686 }
687 }
688 return 0;
689 }
690
691 static int
icvSetFrameRateCAM_DC1394(CvCaptureCAM_DC1394 * capture,double value)692 icvSetFrameRateCAM_DC1394( CvCaptureCAM_DC1394 * capture, double value ){
693 unsigned int fps=15;
694 if(capture->format == FORMAT_SCALABLE_IMAGE_SIZE)
695 return 0; /* format 7 has no fixed framerates */
696 if (value==-1){
697 fps=icvGetBestFrameRate( capture, capture->format, capture->mode );
698 }
699 else if (value==1.875)
700 fps=FRAMERATE_1_875;
701 else if (value==3.75)
702 fps=FRAMERATE_3_75;
703 else if (value==7.5)
704 fps=FRAMERATE_7_5;
705 else if (value==15)
706 fps=FRAMERATE_15;
707 else if (value==30)
708 fps=FRAMERATE_30;
709 else if (value==60)
710 fps=FRAMERATE_60;
711 #if NUM_FRAMERATES > 6
712 else if (value==120)
713 fps=FRAMERATE_120;
714 #endif
715 #if NUM_FRAMERATES > 7
716 else if (value==240)
717 fps=FRAMERATE_240;
718 #endif
719 dc1394_set_video_framerate(capture->handle, capture->camera->node,fps);
720 dc1394_get_video_framerate(capture->handle, capture->camera->node,
721 (unsigned int *) &capture->camera->frame_rate);
722
723 return fps==(unsigned int) capture->camera->frame_rate;
724 }
725
726 // for given mode return color format
727 static int
icvColorMode(int mode)728 icvColorMode( int mode ){
729 switch(mode) {
730 case MODE_160x120_YUV444:
731 return COLOR_FORMAT7_YUV444;
732 case MODE_320x240_YUV422:
733 case MODE_640x480_YUV422:
734 case MODE_800x600_YUV422:
735 case MODE_1024x768_YUV422:
736 case MODE_1280x960_YUV422:
737 case MODE_1600x1200_YUV422:
738 return COLOR_FORMAT7_YUV422;
739 case MODE_640x480_YUV411:
740 return COLOR_FORMAT7_YUV411;
741 case MODE_640x480_RGB:
742 case MODE_800x600_RGB:
743 case MODE_1024x768_RGB:
744 case MODE_1280x960_RGB:
745 case MODE_1600x1200_RGB:
746 return COLOR_FORMAT7_RGB8;
747 case MODE_640x480_MONO:
748 case MODE_800x600_MONO:
749 case MODE_1024x768_MONO:
750 case MODE_1280x960_MONO:
751 case MODE_1600x1200_MONO:
752 return COLOR_FORMAT7_MONO8;
753 case MODE_640x480_MONO16:
754 case MODE_800x600_MONO16:
755 case MODE_1024x768_MONO16:
756 case MODE_1280x960_MONO16:
757 case MODE_1600x1200_MONO16:
758 return COLOR_FORMAT7_MONO16;
759 case MODE_FORMAT7_0:
760 case MODE_FORMAT7_1:
761 case MODE_FORMAT7_2:
762 case MODE_FORMAT7_3:
763 case MODE_FORMAT7_4:
764 case MODE_FORMAT7_5:
765 case MODE_FORMAT7_6:
766 case MODE_FORMAT7_7:
767 fprintf(stderr,"%s:%d: Format7 not yet supported\n",__FILE__,__LINE__);
768 default:
769 break;
770 }
771 return -1;
772 }
773
774 // function to set camera properties using dc1394 feature enum
775 // val == -1 indicates to set this property to 'auto'
776 static int
icvSetFeatureCAM_DC1394(CvCaptureCAM_DC1394 * capture,int feature_id,int val)777 icvSetFeatureCAM_DC1394( CvCaptureCAM_DC1394* capture, int feature_id, int val){
778 dc1394bool_t isOn = DC1394_FALSE;
779 dc1394bool_t hasAutoCapability = DC1394_FALSE;
780 dc1394bool_t isAutoOn = DC1394_FALSE;
781 unsigned int nval;
782 unsigned int minval,maxval;
783
784 // Turn the feature on if it is OFF
785 if( dc1394_is_feature_on(capture->handle, capture->camera->node, feature_id, &isOn)
786 == DC1394_FAILURE ) {
787 return 0;
788 }
789 if( isOn == DC1394_FALSE ) {
790 // try to turn it on.
791 if( dc1394_feature_on_off(capture->handle, capture->camera->node, feature_id, 1) == DC1394_FAILURE ) {
792 fprintf(stderr, "error turning feature %d on!\n", feature_id);
793 return 0;
794 }
795 }
796
797 // Check if the feature supports auto mode
798 dc1394_has_auto_mode(capture->handle, capture->camera->node, feature_id, &hasAutoCapability);
799 if( hasAutoCapability ) {
800
801 // now check if the auto is on.
802 if( dc1394_is_feature_auto(capture->handle, capture->camera->node, feature_id, &isAutoOn ) == DC1394_FAILURE ) {
803 fprintf(stderr, "error determining if feature %d has auto on!\n", feature_id);
804 return 0;
805 }
806 }
807 // Caller requested auto mode, but cannot support it
808 else if(val==-1){
809 fprintf(stderr, "feature %d does not support auto mode\n", feature_id);
810 return 0;
811 }
812
813 if(val==-1){
814 // if the auto mode isn't enabled, enable it
815 if( isAutoOn == DC1394_FALSE ) {
816 if(dc1394_auto_on_off(capture->handle, capture->camera->node, feature_id, 1) == DC1394_FAILURE ) {
817 fprintf(stderr, "error turning feature %d auto ON!\n", feature_id);
818 return 0;
819 }
820 }
821 return 1;
822 }
823
824 // ELSE turn OFF auto and adjust feature manually
825 if( isAutoOn == DC1394_TRUE ) {
826 if(dc1394_auto_on_off(capture->handle, capture->camera->node, feature_id, 0) == DC1394_FAILURE ) {
827 fprintf(stderr, "error turning feature %d auto OFF!\n", feature_id);
828 return 0;
829 }
830 }
831
832 // Clamp val to within feature range
833 CV_DC1394_CALL( dc1394_get_min_value(capture->handle, capture->camera->node, feature_id, &minval));
834 CV_DC1394_CALL( dc1394_get_max_value(capture->handle, capture->camera->node, feature_id, &maxval));
835 val = (int)MIN(maxval, MAX((unsigned)val, minval));
836
837
838 if (dc1394_set_feature_value(capture->handle, capture->camera->node, feature_id, val) ==
839 DC1394_FAILURE){
840 fprintf(stderr, "error setting feature value\n");
841 return 0;
842 }
843 if (dc1394_get_feature_value(capture->handle, capture->camera->node, feature_id, &nval) ==
844 DC1394_FAILURE){
845 fprintf(stderr, "error setting feature value\n");
846 return 0;
847 }
848 return nval==(unsigned int)val;
849
850 }
851
852 // cvSetCaptureProperty callback function implementation
853 static int
icvSetPropertyCAM_DC1394(CvCaptureCAM_DC1394 * capture,int property_id,double value)854 icvSetPropertyCAM_DC1394( CvCaptureCAM_DC1394* capture, int property_id, double value ){
855 int index=-1;
856 switch ( property_id ) {
857 case CV_CAP_PROP_CONVERT_RGB:
858 return icvSetConvertRGB( capture, value != 0 );
859 case CV_CAP_PROP_MODE:
860 return icvSetModeCAM_DC1394( capture, (int) value );
861 case CV_CAP_PROP_FPS:
862 return icvSetFrameRateCAM_DC1394( capture, value );
863 case CV_CAP_PROP_BRIGHTNESS:
864 index = FEATURE_BRIGHTNESS;
865 break;
866 case CV_CAP_PROP_CONTRAST:
867 index = FEATURE_GAMMA;
868 break;
869 case CV_CAP_PROP_SATURATION:
870 index = FEATURE_SATURATION;
871 break;
872 case CV_CAP_PROP_HUE:
873 index = FEATURE_HUE;
874 break;
875 case CV_CAP_PROP_GAIN:
876 index = FEATURE_GAIN;
877 break;
878 default:
879 index = property_id; // did they pass in a LIBDC1394 feature flag?
880 break;
881 }
882 if(index>=FEATURE_MIN && index<=FEATURE_MAX){
883 return icvSetFeatureCAM_DC1394(capture, index, (int) value);
884 }
885 return 0;
886 };
887
888 /**********************************************************************
889 *
890 * CONVERSION FUNCTIONS TO RGB 24bpp
891 *
892 **********************************************************************/
893
894 /* color conversion functions from Bart Nabbe. *//* corrected by Damien: bad coeficients in YUV2RGB */
895 #define YUV2RGB(y, u, v, r, g, b)\
896 r = y + ((v*1436) >> 10);\
897 g = y - ((u*352 + v*731) >> 10);\
898 b = y + ((u*1814) >> 10);\
899 r = r < 0 ? 0 : r;\
900 g = g < 0 ? 0 : g;\
901 b = b < 0 ? 0 : b;\
902 r = r > 255 ? 255 : r;\
903 g = g > 255 ? 255 : g;\
904 b = b > 255 ? 255 : b
905
906 static void
uyv2bgr(const unsigned char * src,unsigned char * dest,unsigned long long int NumPixels)907 uyv2bgr(const unsigned char *src, unsigned char *dest,
908 unsigned long long int NumPixels)
909 {
910 register int i = NumPixels + (NumPixels << 1) - 1;
911 register int j = NumPixels + (NumPixels << 1) - 1;
912 register int y, u, v;
913 register int r, g, b;
914
915 while (i > 0) {
916 v = src[i--] - 128;
917 y = src[i--];
918 u = src[i--] - 128;
919 YUV2RGB(y, u, v, r, g, b);
920 dest[j--] = r;
921 dest[j--] = g;
922 dest[j--] = b;
923 }
924 }
925
926 static void
uyvy2bgr(const unsigned char * src,unsigned char * dest,unsigned long long int NumPixels)927 uyvy2bgr(const unsigned char *src, unsigned char *dest,
928 unsigned long long int NumPixels)
929 {
930 register int i = (NumPixels << 1) - 1;
931 register int j = NumPixels + (NumPixels << 1) - 1;
932 register int y0, y1, u, v;
933 register int r, g, b;
934
935 while (i > 0) {
936 y1 = src[i--];
937 v = src[i--] - 128;
938 y0 = src[i--];
939 u = src[i--] - 128;
940 YUV2RGB(y1, u, v, r, g, b);
941 dest[j--] = r;
942 dest[j--] = g;
943 dest[j--] = b;
944 YUV2RGB(y0, u, v, r, g, b);
945 dest[j--] = r;
946 dest[j--] = g;
947 dest[j--] = b;
948 }
949 }
950
951
952 static void
uyyvyy2bgr(const unsigned char * src,unsigned char * dest,unsigned long long int NumPixels)953 uyyvyy2bgr(const unsigned char *src, unsigned char *dest,
954 unsigned long long int NumPixels)
955 {
956 register int i = NumPixels + (NumPixels >> 1) - 1;
957 register int j = NumPixels + (NumPixels << 1) - 1;
958 register int y0, y1, y2, y3, u, v;
959 register int r, g, b;
960
961 while (i > 0) {
962 y3 = src[i--];
963 y2 = src[i--];
964 v = src[i--] - 128;
965 y1 = src[i--];
966 y0 = src[i--];
967 u = src[i--] - 128;
968 YUV2RGB(y3, u, v, r, g, b);
969 dest[j--] = r;
970 dest[j--] = g;
971 dest[j--] = b;
972 YUV2RGB(y2, u, v, r, g, b);
973 dest[j--] = r;
974 dest[j--] = g;
975 dest[j--] = b;
976 YUV2RGB(y1, u, v, r, g, b);
977 dest[j--] = r;
978 dest[j--] = g;
979 dest[j--] = b;
980 YUV2RGB(y0, u, v, r, g, b);
981 dest[j--] = r;
982 dest[j--] = g;
983 dest[j--] = b;
984 }
985 }
986
987 static void
y2bgr(const unsigned char * src,unsigned char * dest,unsigned long long int NumPixels)988 y2bgr(const unsigned char *src, unsigned char *dest,
989 unsigned long long int NumPixels)
990 {
991 register int i = NumPixels - 1;
992 register int j = NumPixels + (NumPixels << 1) - 1;
993 register int y;
994
995 while (i > 0) {
996 y = src[i--];
997 dest[j--] = y;
998 dest[j--] = y;
999 dest[j--] = y;
1000 }
1001 }
1002
1003 static void
y162bgr(const unsigned char * src,unsigned char * dest,unsigned long long int NumPixels,int bits)1004 y162bgr(const unsigned char *src, unsigned char *dest,
1005 unsigned long long int NumPixels, int bits)
1006 {
1007 register int i = (NumPixels << 1) - 1;
1008 register int j = NumPixels + (NumPixels << 1) - 1;
1009 register int y;
1010
1011 while (i > 0) {
1012 y = src[i--];
1013 y = (y + (src[i--] << 8)) >> (bits - 8);
1014 dest[j--] = y;
1015 dest[j--] = y;
1016 dest[j--] = y;
1017 }
1018 }
1019
1020 // this one was in coriander but didn't take bits into account
1021 static void
rgb482bgr(const unsigned char * src,unsigned char * dest,unsigned long long int NumPixels,int bits)1022 rgb482bgr(const unsigned char *src, unsigned char *dest,
1023 unsigned long long int NumPixels, int bits)
1024 {
1025 register int i = (NumPixels << 1) - 1;
1026 register int j = NumPixels + (NumPixels << 1) - 1;
1027 register int y;
1028
1029 while (i > 0) {
1030 y = src[i--];
1031 dest[j-2] = (y + (src[i--] << 8)) >> (bits - 8);
1032 j--;
1033 y = src[i--];
1034 dest[j] = (y + (src[i--] << 8)) >> (bits - 8);
1035 j--;
1036 y = src[i--];
1037 dest[j+2] = (y + (src[i--] << 8)) >> (bits - 8);
1038 j--;
1039 }
1040 }
1041
1042
1043 class CvCaptureCAM_DC1394_CPP : public CvCapture
1044 {
1045 public:
CvCaptureCAM_DC1394_CPP()1046 CvCaptureCAM_DC1394_CPP() { captureDC1394 = 0; }
~CvCaptureCAM_DC1394_CPP()1047 virtual ~CvCaptureCAM_DC1394_CPP() { close(); }
1048
1049 virtual bool open( int index );
1050 virtual void close();
1051
1052 virtual double getProperty(int) const;
1053 virtual bool setProperty(int, double);
1054 virtual bool grabFrame();
1055 virtual IplImage* retrieveFrame(int);
getCaptureDomain()1056 virtual int getCaptureDomain() { return CV_CAP_DC1394; } // Return the type of the capture object: CV_CAP_VFW, etc...
1057 protected:
1058
1059 CvCaptureCAM_DC1394* captureDC1394;
1060 };
1061
open(int index)1062 bool CvCaptureCAM_DC1394_CPP::open( int index )
1063 {
1064 close();
1065 captureDC1394 = icvCaptureFromCAM_DC1394(index);
1066 return captureDC1394 != 0;
1067 }
1068
close()1069 void CvCaptureCAM_DC1394_CPP::close()
1070 {
1071 if( captureDC1394 )
1072 {
1073 icvCloseCAM_DC1394( captureDC1394 );
1074 cvFree( &captureDC1394 );
1075 }
1076 }
1077
grabFrame()1078 bool CvCaptureCAM_DC1394_CPP::grabFrame()
1079 {
1080 return captureDC1394 ? icvGrabFrameCAM_DC1394( captureDC1394 ) != 0 : false;
1081 }
1082
retrieveFrame(int)1083 IplImage* CvCaptureCAM_DC1394_CPP::retrieveFrame(int)
1084 {
1085 return captureDC1394 ? (IplImage*)icvRetrieveFrameCAM_DC1394( captureDC1394, 0 ) : 0;
1086 }
1087
getProperty(int propId) const1088 double CvCaptureCAM_DC1394_CPP::getProperty( int propId ) const
1089 {
1090 // Simulate mutable (C++11-like) member variable
1091 // (some members are used to cache property settings).
1092 CvCaptureCAM_DC1394* cap = const_cast<CvCaptureCAM_DC1394*>(captureDC1394);
1093
1094 return cap ? icvGetPropertyCAM_DC1394( cap, propId ) : 0;
1095 }
1096
setProperty(int propId,double value)1097 bool CvCaptureCAM_DC1394_CPP::setProperty( int propId, double value )
1098 {
1099 return captureDC1394 ? icvSetPropertyCAM_DC1394( captureDC1394, propId, value ) != 0 : false;
1100 }
1101
cvCreateCameraCapture_DC1394(int index)1102 CvCapture* cvCreateCameraCapture_DC1394( int index )
1103 {
1104 CvCaptureCAM_DC1394_CPP* capture = new CvCaptureCAM_DC1394_CPP;
1105
1106 if( capture->open( index ))
1107 return capture;
1108
1109 delete capture;
1110 return 0;
1111 }
1112
1113 #endif
1114