1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
46 #pragma warning( disable: 4711 )
49 #if defined WIN64 && defined EM64T && defined _MSC_VER && !defined __ICL
50 #pragma optimize("",off)
53 /********************* Capturing video from AVI via VFW ************************/
55 static BITMAPINFOHEADER icvBitmapHeader( int width, int height, int bpp, int compression = BI_RGB )
57 BITMAPINFOHEADER bmih;
58 memset( &bmih, 0, sizeof(bmih));
59 bmih.biSize = sizeof(bmih);
61 bmih.biHeight = height;
62 bmih.biBitCount = (WORD)bpp;
63 bmih.biCompression = compression;
70 static void icvInitCapture_VFW()
72 static int isInitialized = 0;
81 class CvCaptureAVI_VFW : public CvCapture
89 virtual ~CvCaptureAVI_VFW()
94 virtual bool open( const char* filename );
97 virtual double getProperty(int);
98 virtual bool setProperty(int, double);
99 virtual bool grabFrame();
100 virtual IplImage* retrieveFrame();
106 PAVISTREAM avistream;
108 AVISTREAMINFO aviinfo;
109 BITMAPINFOHEADER * bmih;
119 void CvCaptureAVI_VFW::init()
124 memset( &aviinfo, 0, sizeof(aviinfo) );
126 film_range = cvSlice(0,0);
135 void CvCaptureAVI_VFW::close()
138 AVIStreamGetFrameClose( getframe );
141 AVIStreamRelease( avistream );
144 AVIFileRelease( avifile );
146 cvReleaseImage( &frame );
151 bool CvCaptureAVI_VFW::open( const char* filename )
154 icvInitCapture_VFW();
159 HRESULT hr = AVIFileOpen( &avifile, filename, OF_READ, NULL );
162 hr = AVIFileGetStream( avifile, &avistream, streamtypeVIDEO, 0 );
165 hr = AVIStreamInfo( avistream, &aviinfo, sizeof(aviinfo));
168 //int fcc = aviinfo.fccHandler;
170 size.width = aviinfo.rcFrame.right - aviinfo.rcFrame.left;
171 size.height = aviinfo.rcFrame.bottom - aviinfo.rcFrame.top;
172 BITMAPINFOHEADER bmih = icvBitmapHeader( size.width, size.height, 24 );
174 film_range.start_index = (int)aviinfo.dwStart;
175 film_range.end_index = film_range.start_index + (int)aviinfo.dwLength;
176 fps = (double)aviinfo.dwRate/aviinfo.dwScale;
177 pos = film_range.start_index;
178 getframe = AVIStreamGetFrameOpen( avistream, &bmih );
189 bool CvCaptureAVI_VFW::grabFrame()
192 bmih = (BITMAPINFOHEADER*)AVIStreamGetFrame( getframe, pos++ );
196 IplImage* CvCaptureAVI_VFW::retrieveFrame()
198 if( avistream && bmih )
201 cvInitImageHeader( &src, cvSize( bmih->biWidth, bmih->biHeight ),
202 IPL_DEPTH_8U, 3, IPL_ORIGIN_BL, 4 );
203 cvSetData( &src, (char*)(bmih + 1) + data_offset, src.widthStep );
204 if( !frame || frame->width != src.width || frame->height != src.height )
206 cvReleaseImage( &frame );
207 frame = cvCreateImage( cvGetSize(&src), 8, 3 );
210 cvFlip( &src, frame, 0 );
217 double CvCaptureAVI_VFW::getProperty( int property_id )
219 switch( property_id )
221 case CV_CAP_PROP_POS_MSEC:
222 return cvRound(pos*1000./fps);
223 case CV_CAP_PROP_POS_FRAMES:
225 case CV_CAP_PROP_POS_AVI_RATIO:
226 return (pos - film_range.start_index)/
227 (film_range.end_index - film_range.start_index + 1e-10);
228 case CV_CAP_PROP_FRAME_WIDTH:
230 case CV_CAP_PROP_FRAME_HEIGHT:
232 case CV_CAP_PROP_FPS:
234 case CV_CAP_PROP_FOURCC:
235 return aviinfo.fccHandler;
236 case CV_CAP_PROP_FRAME_COUNT:
237 return film_range.end_index - film_range.start_index;
242 bool CvCaptureAVI_VFW::setProperty( int property_id, double value )
244 switch( property_id )
246 case CV_CAP_PROP_POS_MSEC:
247 case CV_CAP_PROP_POS_FRAMES:
248 case CV_CAP_PROP_POS_AVI_RATIO:
250 switch( property_id )
252 case CV_CAP_PROP_POS_MSEC:
253 pos = cvRound(value*fps*0.001);
255 case CV_CAP_PROP_POS_AVI_RATIO:
256 pos = cvRound(value*(film_range.end_index -
257 film_range.start_index) +
258 film_range.start_index);
261 pos = cvRound(value);
263 if( pos < film_range.start_index )
264 pos = film_range.start_index;
265 if( pos > film_range.end_index )
266 pos = film_range.end_index;
276 CvCapture* cvCreateFileCapture_VFW (const char* filename)
278 CvCaptureAVI_VFW* capture = new CvCaptureAVI_VFW;
279 if( capture->open(filename) )
286 /********************* Capturing video from camera via VFW *********************/
288 class CvCaptureCAM_VFW : public CvCapture
291 CvCaptureCAM_VFW() { init(); }
292 virtual ~CvCaptureCAM_VFW() { close(); }
294 virtual bool open( int index );
295 virtual void close();
296 virtual double getProperty(int);
297 virtual bool setProperty(int, double) { return false; }
298 virtual bool grabFrame();
299 virtual IplImage* retrieveFrame();
304 static LRESULT PASCAL frameCallback( HWND hWnd, VIDEOHDR* hdr );
315 void CvCaptureCAM_VFW::init()
317 memset( &caps, 0, sizeof(caps) );
325 void CvCaptureCAM_VFW::closeHIC()
329 ICDecompressEnd( hic );
336 LRESULT PASCAL CvCaptureCAM_VFW::frameCallback( HWND hWnd, VIDEOHDR* hdr )
338 CvCaptureCAM_VFW* capture = 0;
340 if (!hWnd) return FALSE;
342 capture = (CvCaptureCAM_VFW*)capGetUserData(hWnd);
345 return (LRESULT)TRUE;
349 // Initialize camera input
350 bool CvCaptureCAM_VFW::open( int wIndex )
352 char szDeviceName[80];
353 char szDeviceVersion[80];
358 if( (unsigned)wIndex >= 10 )
361 for( ; wIndex < 10; wIndex++ )
363 if( capGetDriverDescription( wIndex, szDeviceName,
364 sizeof (szDeviceName), szDeviceVersion,
365 sizeof (szDeviceVersion)))
367 hWndC = capCreateCaptureWindow ( "My Own Capture Window",
368 WS_POPUP | WS_CHILD, 0, 0, 320, 240, 0, 0);
369 if( capDriverConnect (hWndC, wIndex))
371 DestroyWindow( hWndC );
383 memset( &caps, 0, sizeof(caps));
384 capDriverGetCaps( hWndC, &caps, sizeof(&caps));
385 ::MoveWindow( hWndC, 0, 0, 320, 240, TRUE );
386 capSetUserData( hWndC, (size_t)this );
387 capSetCallbackOnFrame( hWndC, frameCallback );
389 capCaptureGetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
390 p.dwRequestMicroSecPerFrame = 66667/2;
391 capCaptureSetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
392 //capPreview( hWndC, 1 );
393 capPreviewScale(hWndC,FALSE);
394 capPreviewRate(hWndC,1);
400 void CvCaptureCAM_VFW::close()
404 capSetCallbackOnFrame( capWnd, NULL );
405 capDriverDisconnect( capWnd );
406 DestroyWindow( capWnd );
409 cvReleaseImage( &frame );
414 bool CvCaptureCAM_VFW::grabFrame()
418 SendMessage( capWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0 );
425 IplImage* CvCaptureCAM_VFW::retrieveFrame()
428 memset( &vfmt, 0, sizeof(vfmt));
429 BITMAPINFOHEADER& vfmt0 = vfmt.bmiHeader;
430 int sz, prevWidth, prevHeight;
435 sz = capGetVideoFormat( capWnd, &vfmt, sizeof(vfmt));
436 prevWidth = frame ? frame->width : 0;
437 prevHeight = frame ? frame->height : 0;
439 if( !hdr || hdr->lpData == 0 || sz == 0 )
442 if( !frame || frame->width != vfmt0.biWidth || frame->height != vfmt0.biHeight )
444 cvReleaseImage( &frame );
445 frame = cvCreateImage( cvSize( vfmt0.biWidth, vfmt0.biHeight ), 8, 3 );
448 if( vfmt.bmiHeader.biCompression != BI_RGB ||
449 vfmt.bmiHeader.biBitCount != 24 )
451 BITMAPINFOHEADER vfmt1 = icvBitmapHeader( vfmt0.biWidth, vfmt0.biHeight, 24 );
453 if( hic == 0 || fourcc != vfmt0.biCompression ||
454 prevWidth != vfmt0.biWidth || prevHeight != vfmt0.biHeight )
457 hic = ICOpen( MAKEFOURCC('V','I','D','C'),
458 vfmt0.biCompression, ICMODE_DECOMPRESS );
461 if( ICDecompressBegin( hic, &vfmt0, &vfmt1 ) != ICERR_OK )
469 if( !hic || ICDecompress( hic, 0, &vfmt0, hdr->lpData,
470 &vfmt1, frame->imageData ) != ICERR_OK )
476 cvFlip( frame, frame, 0 );
481 cvInitImageHeader( &src, cvSize(vfmt0.biWidth, vfmt0.biHeight),
482 IPL_DEPTH_8U, 3, IPL_ORIGIN_BL, 4 );
483 cvSetData( &src, hdr->lpData, src.widthStep );
484 cvFlip( &src, frame, 0 );
491 double CvCaptureCAM_VFW::getProperty( int property_id )
493 switch( property_id )
495 case CV_CAP_PROP_FRAME_WIDTH:
496 return frame ? frame->width : 0;
497 case CV_CAP_PROP_FRAME_HEIGHT:
498 return frame ? frame->height : 0;
499 case CV_CAP_PROP_FOURCC:
506 CvCapture* cvCreateCameraCapture_VFW( int index )
508 CvCaptureCAM_VFW* capture = new CvCaptureCAM_VFW;
510 if( capture->open( index ))
518 /*************************** writing AVIs ******************************/
520 class CvVideoWriter_VFW : public CvVideoWriter
523 CvVideoWriter_VFW() { init(); }
524 virtual ~CvVideoWriter_VFW() { close(); }
526 virtual bool open( const char* filename, int fourcc,
527 double fps, CvSize frameSize, bool isColor );
528 virtual void close();
529 virtual bool writeFrame( const IplImage* );
533 bool createStreams( CvSize frameSize, bool isColor );
536 PAVISTREAM compressed;
537 PAVISTREAM uncompressed;
545 void CvVideoWriter_VFW::init()
548 compressed = uncompressed = 0;
555 void CvVideoWriter_VFW::close()
558 AVIStreamRelease( uncompressed );
560 AVIStreamRelease( compressed );
562 AVIFileRelease( avifile );
563 cvReleaseImage( &tempFrame );
568 // philipg. Made this code capable of writing 8bpp gray scale bitmaps
569 struct BITMAPINFO_8Bit
571 BITMAPINFOHEADER bmiHeader;
572 RGBQUAD bmiColors[256];
576 bool CvVideoWriter_VFW::open( const char* filename, int _fourcc, double _fps, CvSize frameSize, bool isColor )
580 icvInitCapture_VFW();
581 if( AVIFileOpen( &avifile, filename, OF_CREATE | OF_WRITE, 0 ) == AVIERR_OK )
585 if( frameSize.width > 0 && frameSize.height > 0 &&
586 !createStreams( frameSize, isColor ) )
596 bool CvVideoWriter_VFW::createStreams( CvSize frameSize, bool isColor )
600 AVISTREAMINFO aviinfo;
602 BITMAPINFO_8Bit bmih;
603 bmih.bmiHeader = icvBitmapHeader( frameSize.width, frameSize.height, isColor ? 24 : 8 );
604 for( int i = 0; i < 256; i++ )
606 bmih.bmiColors[i].rgbBlue = (BYTE)i;
607 bmih.bmiColors[i].rgbGreen = (BYTE)i;
608 bmih.bmiColors[i].rgbRed = (BYTE)i;
609 bmih.bmiColors[i].rgbReserved = 0;
612 memset( &aviinfo, 0, sizeof(aviinfo));
613 aviinfo.fccType = streamtypeVIDEO;
614 aviinfo.fccHandler = 0;
615 // use highest possible accuracy for dwRate/dwScale
616 aviinfo.dwScale = (DWORD)((double)0x7FFFFFFF / fps);
617 aviinfo.dwRate = cvRound(fps * aviinfo.dwScale);
618 aviinfo.rcFrame.top = aviinfo.rcFrame.left = 0;
619 aviinfo.rcFrame.right = frameSize.width;
620 aviinfo.rcFrame.bottom = frameSize.height;
622 if( AVIFileCreateStream( avifile, &uncompressed, &aviinfo ) == AVIERR_OK )
624 AVICOMPRESSOPTIONS copts, *pcopts = &copts;
625 copts.fccType = streamtypeVIDEO;
626 copts.fccHandler = fourcc != -1 ? fourcc : 0;
627 copts.dwKeyFrameEvery = 1;
628 copts.dwQuality = (DWORD)-1;
629 copts.dwBytesPerSecond = 0;
630 copts.dwFlags = AVICOMPRESSF_VALID;
631 copts.lpFormat = &bmih;
632 copts.cbFormat = (isColor ? sizeof(BITMAPINFOHEADER) : sizeof(bmih));
635 copts.dwInterleaveEvery = 0;
637 if( fourcc != -1 || AVISaveOptions( 0, 0, 1, &uncompressed, &pcopts ) == TRUE )
639 if( AVIMakeCompressedStream( &compressed, uncompressed, pcopts, 0 ) == AVIERR_OK &&
640 AVIStreamSetFormat( compressed, 0, &bmih, sizeof(bmih)) == AVIERR_OK )
643 fourcc = (int)copts.fccHandler;
644 frameSize = frameSize;
645 tempFrame = cvCreateImage( frameSize, 8, (isColor ? 3 : 1) );
654 bool CvVideoWriter_VFW::writeFrame( const IplImage* image )
657 CV_FUNCNAME( "CvVideoWriter_VFW::writeFrame" );
664 if( !compressed && !createStreams( cvGetSize(image), image->nChannels > 1 ))
667 if( image->width != tempFrame->width || image->height != tempFrame->height )
668 CV_ERROR( CV_StsUnmatchedSizes,
669 "image size is different from the currently set frame size" );
671 if( image->nChannels != tempFrame->nChannels ||
672 image->depth != tempFrame->depth ||
673 image->origin == 0 ||
674 image->widthStep != cvAlign(image->width*image->nChannels*((image->depth & 255)/8), 4))
676 cvConvertImage( image, tempFrame, image->origin == 0 ? CV_CVTIMG_FLIP : 0 );
677 image = (const IplImage*)tempFrame;
680 result = AVIStreamWrite( compressed, pos++, 1, image->imageData,
681 image->imageSize, AVIIF_KEYFRAME, 0, 0 ) == AVIERR_OK;
688 CvVideoWriter* cvCreateVideoWriter_VFW( const char* filename, int fourcc,
689 double fps, CvSize frameSize, int isColor )
691 CvVideoWriter_VFW* writer = new CvVideoWriter_VFW;
692 if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 ))