Update the trunk to the OpenCV's CVS (2008-07-14)
[opencv] / otherlibs / highgui / cvcap_cmu.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "_highgui.h"
43
44 #ifdef WIN32
45
46 /****************** Capturing video from camera via CMU lib *******************/
47
48 #if HAVE_CMU1394
49
50 // This firewire capability added by Philip Gruebele (pgruebele@cox.net).
51 // For this to work you need to install the CMU firewire DCAM drivers,
52 // located at http://www-2.cs.cmu.edu/~iwan/1394/.
53 #include "1394camera.h"
54
55 class CvCaptureCAM_CMU : public CvCapture
56 {
57 public:
58     CvCaptureCAM_CMU()
59     {
60         index = -1;
61         image = 0;
62     }
63
64     virtual ~CvCaptureCAM_CMU()
65     {
66         close();
67     }
68
69     virtual bool open(int cameraId);
70     virtual void close();
71     virtual double getProperty(int);
72     virtual bool setProperty(int, double);
73     virtual bool grabFrame();
74     virtual IplImage* retrieveFrame();
75
76 protected:
77     C1394Camera* camera();
78     CvSize getSize();
79     int getDepth();
80     int getNChannels();
81
82     bool setVideoSize(int, int);
83     bool setMode(int mode);
84     bool setFrameRate(int rate);
85     bool setFormat(int format);
86
87     int  fps;    // 0-5
88     int  mode;   // 0-7
89     int  format; // 0-2, 7 ?
90     int  index;
91     IplImage* image;
92 };
93
94 // CMU 1394 camera stuff.
95 // This firewire capability added by Philip Gruebele (pgruebele@cox.net) 
96 // and modified by Roman Stanchak (rstanchak@yahoo.com).
97 // For this to work you need to install the CMU firewire DCAM drivers,
98 // located at http://www-2.cs.cmu.edu/~iwan/1394/.
99 #define CMU_MAX_CAMERAS     20
100 int             CMU_numCameras = 0;
101 int             CMU_numActiveCameras = 0;
102 bool            CMU_useCameraFlags[CMU_MAX_CAMERAS];
103 C1394Camera     *CMU_theCamera = 0;
104
105 // stupid defines for mode, format, FPS
106 #define CV_CAP_IEEE1394_FPS_1_875 0
107 #define CV_CAP_IEEE1394_FPS_3_75 1
108 #define CV_CAP_IEEE1394_FPS_7_5 2
109 #define CV_CAP_IEEE1394_FPS_15 3
110 #define CV_CAP_IEEE1394_FPS_30 4
111 #define CV_CAP_IEEE1394_FPS_60 5
112
113 // index by size, color
114 #define CV_CAP_IEEE1394_COLOR_MONO 0
115 #define CV_CAP_IEEE1394_COLOR_MONO16 1
116 #define CV_CAP_IEEE1394_COLOR_YUV444 2
117 #define CV_CAP_IEEE1394_COLOR_YUV422 3
118 #define CV_CAP_IEEE1394_COLOR_YUV411 4
119 #define CV_CAP_IEEE1394_COLOR_RGB 5
120
121 #define CV_CAP_IEEE1394_SIZE_160X120 0
122 #define CV_CAP_IEEE1394_SIZE_320X240 1 
123 #define CV_CAP_IEEE1394_SIZE_640X480 2
124 #define CV_CAP_IEEE1394_SIZE_800X600 3
125 #define CV_CAP_IEEE1394_SIZE_1024X768 4
126 #define CV_CAP_IEEE1394_SIZE_1280X960 5
127 #define CV_CAP_IEEE1394_SIZE_1600X1200 6
128
129 // given color, size, output format
130 // 1 16  444 422 411 RGB
131 static char CV_CAP_IEEE1394_FORMAT[7][6] =
132 {
133     {-1, -1,  0, -1, -1, -1}, // 160x120
134     {-1, -1, -1,  0, -1, -1}, // 320x240
135     { 0,  0, -1,  0,  0,  0}, // 640x480
136     { 1,  1, -1,  1, -1,  1}, // 800x600
137     { 1,  1, -1,  1, -1,  1}, // 1024x768
138     { 2,  2, -1,  2, -1,  2}, // 1280x960
139     { 2,  2, -1,  2, -1,  2}  // 1600x1200
140 };
141
142 // given color, size, output corresponding mode 
143 static char CV_CAP_IEEE1394_MODE[7][6] =
144 {
145     {-1, -1,  0, -1, -1, -1}, // 160x120
146     {-1, -1, -1,  1, -1, -1}, // 320x240
147     { 5,  6, -1,  3,  2,  4}, // 640x480
148     { 2,  6, -1,  0, -1,  1}, // 800x600
149     { 5,  7, -1,  3, -1,  4}, // 1024x768
150     { 2,  6, -1,  0, -1,  1}, // 1280x960
151     { 5,  7, -1,  3, -1,  4}  // 1600x1200
152 };
153
154 // given format, mode, return COLOR
155 static char CV_CAP_IEEE1394_COLOR[2][8] =
156 {
157     {
158     CV_CAP_IEEE1394_COLOR_YUV444, 
159     CV_CAP_IEEE1394_COLOR_YUV422, 
160     CV_CAP_IEEE1394_COLOR_YUV411, 
161     CV_CAP_IEEE1394_COLOR_YUV422,
162     CV_CAP_IEEE1394_COLOR_RGB,
163     CV_CAP_IEEE1394_COLOR_MONO, 
164     CV_CAP_IEEE1394_COLOR_MONO16
165     },
166     {
167     CV_CAP_IEEE1394_COLOR_YUV422,
168     CV_CAP_IEEE1394_COLOR_RGB,
169     CV_CAP_IEEE1394_COLOR_MONO,
170     CV_CAP_IEEE1394_COLOR_YUV422,
171     CV_CAP_IEEE1394_COLOR_RGB,
172     CV_CAP_IEEE1394_COLOR_MONO,
173     CV_CAP_IEEE1394_COLOR_MONO16,
174     CV_CAP_IEEE1394_COLOR_MONO16
175     }
176 };
177
178 // convert frame rate to suitable enum
179 /*static int icvFrameRateToIndex_CMU(double framerate){
180     if(framerate > 30)       return CV_CAP_IEEE1394_FPS_60;
181     else if(framerate > 15)  return CV_CAP_IEEE1394_FPS_30;
182     else if(framerate > 7.5) return CV_CAP_IEEE1394_FPS_15;
183     else if(framerate > 3.75) return CV_CAP_IEEE1394_FPS_7_5;
184     else if(framerate > 1.875) return CV_CAP_IEEE1394_FPS_3_75;
185     return CV_CAP_IEEE1394_FPS_1_875;
186 }*/
187
188 #if _MSC_VER >= 1200
189 #pragma comment(lib,"1394camera.lib")
190 #endif
191
192 C1394Camera* CvCaptureCAM_CMU::camera()
193 {
194     return CMU_theCamera && index >= 0 ? &CMU_theCamera[index] : 0;
195 }
196
197 // return the size of the image
198 CvSize CvCaptureCAM_CMU::getSize()
199 {
200     C1394Camera* cmucam = camera();
201     unsigned long width = 0, height = 0;
202     cmucam->GetVideoFrameDimensions( &width, &height );
203     return cvSize((int)width, (int)height);
204 }
205
206 // return the opencv depth flag corresponding to the camera format
207 int CvCaptureCAM_CMU::getDepth()
208 {
209     C1394Camera* cmucam = camera();
210     int format = cmucam->GetVideoFormat();
211     int mode = cmucam->GetVideoMode();
212
213     // TODO
214     if( format==7 ) {
215         assert(0);
216         return 1;
217     }
218     // irrelvant to depth
219     if( format > 1 )
220         format = 1;
221
222     if( CV_CAP_IEEE1394_COLOR[format][mode]==CV_CAP_IEEE1394_COLOR_MONO16 )
223         return IPL_DEPTH_16S;
224
225     return IPL_DEPTH_8U;
226 }
227
228 // return the number of channels for camera
229 int CvCaptureCAM_CMU::getNChannels()
230 {
231     C1394Camera* cmucam = camera();     
232     int format = cmucam->GetVideoFormat();
233     int mode = cmucam->GetVideoMode();
234
235     if( format==7 ){
236         assert(0);
237         return 1;
238     }
239
240     // irrelvant to nchannels 
241     if( format > 1 )
242         format = 1;
243
244     switch(CV_CAP_IEEE1394_COLOR[format][mode]){
245     case CV_CAP_IEEE1394_COLOR_RGB:
246         return 3;
247     case CV_CAP_IEEE1394_COLOR_MONO:
248     case CV_CAP_IEEE1394_COLOR_MONO16:
249         return 1;
250     case CV_CAP_IEEE1394_COLOR_YUV422:
251     case CV_CAP_IEEE1394_COLOR_YUV444:
252     case CV_CAP_IEEE1394_COLOR_YUV411:
253         return 3;
254     default:
255         ;
256     }
257     return -1;
258 }
259
260 bool CvCaptureCAM_CMU::open( int _index )
261 {
262     close();
263     
264     // if first time, then allocate all available cameras
265     if( CMU_numCameras == 0 )
266     {
267         CMU_numActiveCameras = 0;
268         CMU_theCamera = new C1394Camera[CMU_MAX_CAMERAS];
269
270         ////////////////////////////////////////////////////////////////////////////////////////////////////////
271         // create all cameras
272         try
273         {
274             // create camera0
275             if( CMU_theCamera[0].CheckLink() != CAM_SUCCESS )
276                 throw 1;
277
278             // we have one pin per camera
279             CMU_numCameras = CMU_theCamera[0].GetNumberCameras();
280
281             // allocate remaining cameras
282             for(int i = 1; i < CMU_numCameras && i<CMU_MAX_CAMERAS; i++ )
283             {
284                 CMU_useCameraFlags[i] = false;
285                 if (CMU_theCamera[i].CheckLink() != CAM_SUCCESS)
286                     throw 1;
287             }
288         }
289         catch (...)
290         {
291             // free any allocated cameras
292             // ...
293             CMU_numCameras = 0;
294             return false;
295         }
296     }
297
298     try
299     {
300         CvSize size;
301
302         // pick first unused camera
303         if(_index==-1){
304             for(int i = 0; i < CMU_numCameras; i++ )
305             {
306                 if( !CMU_useCameraFlags[i] ){
307                     _index = i;
308                     break;
309                 }
310             }
311         }
312
313         // no empty camera found 
314         if (_index==-1)
315             throw 1;
316
317         if (CMU_theCamera[_index].SelectCamera(_index) != CAM_SUCCESS)
318             throw 2;
319
320         if (CMU_theCamera[_index].InitCamera() != CAM_SUCCESS)
321             throw 3;
322         
323         // set initial format -- try to pick best frame rate first, then color, then size
324         bool found_format = false;
325         for (int rate=5; rate>=0 && !found_format; rate--)
326         {
327             for (int color=CV_CAP_IEEE1394_COLOR_RGB; color>=0 && !found_format; color--)
328             {
329                 for (int size=CV_CAP_IEEE1394_SIZE_1600X1200; size>=0 && !found_format; size--)
330                 {
331                     int format = CV_CAP_IEEE1394_FORMAT[size][color];
332                     int mode = CV_CAP_IEEE1394_MODE[size][color];
333                     if (format!=-1 && mode!=-1 &&
334                         CMU_theCamera[_index].HasVideoFrameRate(format,mode,rate))
335                     {
336                         CMU_theCamera[_index].SetVideoFormat(format);
337                         CMU_theCamera[_index].SetVideoMode(mode);
338                         CMU_theCamera[_index].SetVideoFrameRate(rate);
339                         found_format = (CMU_theCamera[_index].StartImageAcquisition() == CAM_SUCCESS);
340                     }
341                 }
342             }
343         }
344
345         // try format 7
346         if(!found_format){
347             CMU_theCamera[_index].SetVideoFormat(7);
348             CMU_theCamera[_index].SetVideoMode(0);
349             if(CMU_theCamera[_index].StartImageAcquisition() != CAM_SUCCESS){
350                 // no format found
351                 throw 9;
352             }
353         }
354
355         index = _index;
356         size = getSize();
357         // allocate image frame
358         image = cvCreateImage( size, 8, 3 );
359         cvZero(image);
360
361         // successfully activated camera
362         CMU_numActiveCameras++;
363         CMU_useCameraFlags[_index] = true;
364     }
365     catch ( int )
366     {
367         return false;
368     }
369
370     return true;
371 }
372
373 void CvCaptureCAM_CMU::close()
374 {
375     C1394Camera* cmucam = camera();
376     if( cmucam )
377     {
378         cvReleaseImage( &image );
379         cmucam->StopImageAcquisition();
380         CMU_useCameraFlags[index] = false;
381         index = -1;
382
383         if( --CMU_numActiveCameras == 0 )
384         {
385             delete[] CMU_theCamera;
386             CMU_theCamera = 0;
387             CMU_numCameras = 0;
388         }
389     }
390 }
391
392
393 bool CvCaptureCAM_CMU::grabFrame()
394 {
395     C1394Camera* cmucam = camera();
396     return cmucam ? cmucam->AcquireImage() == CAM_SUCCESS : false;
397 }
398
399 /*static void swapRedBlue(IplImage * im)
400 {
401         uchar * ptr = (uchar *) im->imageData;
402         uchar t;
403         for(int i=0; i<im->height; i++){
404                 ptr = (uchar *) im->imageData+im->widthStep*i;
405                 for(int j=0; j<im->width; j++){
406                         t = ptr[0];
407                         ptr[0] = ptr[2];
408                         ptr[2] = t;
409                         ptr+=3;
410                 }
411         }
412 }*/
413
414 IplImage* CvCaptureCAM_CMU::retrieveFrame()
415 {
416     C1394Camera* cmucam = camera();
417     if( !cmucam )
418         return 0;
419     cmucam->getRGB((uchar*)image->imageData, image->imageSize);
420     cvConvertImage( image, image, CV_CVTIMG_SWAP_RB );
421     return image;
422 }
423
424
425 double CvCaptureCAM_CMU::getProperty( int property_id )
426 {
427     C1394Camera* cmucam = camera();
428     if( !cmucam )
429         return 0;
430     switch( property_id )
431     {
432     case CV_CAP_PROP_FRAME_WIDTH:
433         return image->width;
434     case CV_CAP_PROP_FRAME_HEIGHT:
435         return image->height;
436     case CV_CAP_PROP_FPS:
437         return cmucam->GetVideoFrameRate();
438     case CV_CAP_PROP_MODE:
439         return cmucam->GetVideoMode();
440     case CV_CAP_PROP_FORMAT:
441         return cmucam->GetVideoFormat();
442     }
443     return 0;
444 }
445
446 bool CvCaptureCAM_CMU::setVideoSize(int, int)
447 {
448     return false;
449 }
450
451 bool CvCaptureCAM_CMU::setMode(int mode)
452 {
453     int format;
454     C1394Camera* cmucam = camera();
455     if( !cmucam )
456         return false;
457     format = cmucam->GetVideoFormat();
458     if( mode < 0 || mode > 7 || !cmucam->HasVideoMode(format, mode))
459         return false;
460     cmucam->StopImageAcquisition();
461     cmucam->SetVideoMode(mode);
462     cmucam->StartImageAcquisition();
463     return true;        
464 }
465
466 bool CvCaptureCAM_CMU::setFrameRate(int rate)
467 {
468     int format, mode;
469     C1394Camera* cmucam = camera();
470     if( !cmucam )
471         return false;
472     mode = cmucam->GetVideoMode();
473     format = cmucam->GetVideoFormat();
474     if( rate < 0 || rate > 5 || !cmucam->HasVideoFrameRate(format, mode, rate) )
475         return false;
476     cmucam->StopImageAcquisition();
477     cmucam->SetVideoFrameRate(rate);
478     cmucam->StartImageAcquisition();
479     return true;        
480 }
481
482 bool CvCaptureCAM_CMU::setFormat(int format)
483 {
484     C1394Camera* cmucam = camera();
485     if( !cmucam )
486         return false;
487     if( format < 0 || format > 2 || !cmucam->HasVideoFormat(format) )
488         return false;
489     cmucam->StopImageAcquisition();
490     cmucam->SetVideoFormat(format);
491     cmucam->StartImageAcquisition();
492     return true;        
493 }
494
495 bool CvCaptureCAM_CMU::setProperty( int property_id, double value )
496 {
497     bool retval = false;
498     int ival = cvRound(value);
499     C1394Camera* cmucam = camera();
500     if( !cmucam )
501         return false;
502
503     switch (property_id) {
504         case CV_CAP_PROP_FRAME_WIDTH:
505         case CV_CAP_PROP_FRAME_HEIGHT:
506             {
507                 int width, height;
508                 if (property_id == CV_CAP_PROP_FRAME_WIDTH)
509                 {
510                     width = ival;
511                     height = width*3/4;
512                 }
513                 else {
514                     height = ival;
515                     width = height*4/3;
516                 }
517                 retval = setVideoSize(width, height);
518             }
519             break;
520         case CV_CAP_PROP_FPS:
521             retval = setFrameRate(ival);
522             break;
523         case CV_CAP_PROP_MODE:
524             retval = setMode(ival);
525             break;
526         case CV_CAP_PROP_FORMAT:
527             retval = setFormat(ival);
528             break;
529     }
530
531     // resize image if its not the right size anymore
532     CvSize size = getSize();
533     if( !image || image->width != size.width || image->height != size.height )
534     {
535         cvReleaseImage( &image );
536         image = cvCreateImage( size, 8, 3 );
537     }
538     return retval;
539 }
540
541 CvCapture * cvCreateCameraCapture_CMU (int index)
542 {
543     CvCaptureCAM_CMU* capture = new CvCaptureCAM_CMU;
544     if( !capture->open(index) )
545         return capture;
546     delete capture;
547     return 0;
548 }
549
550 #endif // CMU
551 #endif // WIN32