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)
54 CvCapture* cvCaptureFromFile_VFW (const char* filename);
55 CvCapture* cvCaptureFromCAM_VFW (int index);
57 /********************* Capturing video from AVI via VFW ************************/
59 static BITMAPINFOHEADER icvBitmapHeader( int width, int height, int bpp, int compression = BI_RGB )
61 BITMAPINFOHEADER bmih;
62 memset( &bmih, 0, sizeof(bmih));
63 bmih.biSize = sizeof(bmih);
65 bmih.biHeight = height;
66 bmih.biBitCount = (WORD)bpp;
67 bmih.biCompression = compression;
73 static void icvInitCapture_VFW()
75 static int isInitialized = 0;
84 typedef struct CvCaptureAVI_VFW
86 CvCaptureVTable * vtable;
90 AVISTREAMINFO aviinfo;
91 BITMAPINFOHEADER * bmih;
102 static void icvCloseAVI_VFW( CvCaptureAVI_VFW* capture )
104 if( capture->getframe )
106 AVIStreamGetFrameClose( capture->getframe );
107 capture->getframe = 0;
109 if( capture->avistream )
111 AVIStreamRelease( capture->avistream );
112 capture->avistream = 0;
114 if( capture->avifile )
116 AVIFileRelease( capture->avifile );
117 capture->avifile = 0;
121 capture->film_range.start_index = capture->film_range.end_index = 0;
122 memset( &capture->frame, 0, sizeof(capture->frame));
125 static int icvOpenAVI_VFW( CvCaptureAVI_VFW* capture, const char* filename )
129 icvInitCapture_VFW();
134 hr = AVIFileOpen( &capture->avifile, filename, OF_READ, NULL );
137 hr = AVIFileGetStream( capture->avifile, &capture->avistream, streamtypeVIDEO, 0 );
140 hr = AVIStreamInfo( capture->avistream, &capture->aviinfo,
141 sizeof(capture->aviinfo));
144 //int fcc = capture->aviinfo.fccHandler;
145 capture->data_offset = 0;
146 capture->size.width = capture->aviinfo.rcFrame.right -
147 capture->aviinfo.rcFrame.left;
148 capture->size.height = capture->aviinfo.rcFrame.bottom -
149 capture->aviinfo.rcFrame.top;
150 BITMAPINFOHEADER bmih = icvBitmapHeader(
151 capture->size.width, capture->size.height, 24 );
153 capture->film_range.start_index = (int)capture->aviinfo.dwStart;
154 capture->film_range.end_index = capture->film_range.start_index +
155 (int)capture->aviinfo.dwLength;
156 capture->fps = ((double)capture->aviinfo.dwRate)/capture->aviinfo.dwScale;
157 capture->pos = capture->film_range.start_index;
158 capture->getframe = AVIStreamGetFrameOpen( capture->avistream, &bmih );
159 if( capture->getframe != 0 )
165 icvCloseAVI_VFW( capture );
169 static int icvGrabFrameAVI_VFW( CvCaptureAVI_VFW* capture )
171 if( capture->avistream )
173 capture->bmih = (BITMAPINFOHEADER*)
174 AVIStreamGetFrame( capture->getframe, capture->pos++ );
177 return capture->bmih != 0;
180 static const IplImage* icvRetrieveFrameAVI_VFW( CvCaptureAVI_VFW* capture )
182 if( capture->avistream && capture->bmih )
184 cvInitImageHeader( &capture->frame,
185 cvSize( capture->bmih->biWidth,
186 capture->bmih->biHeight ),
187 IPL_DEPTH_8U, 3, IPL_ORIGIN_BL, 4 );
188 capture->frame.imageData = capture->frame.imageDataOrigin =
189 (char*)(capture->bmih + 1) + capture->data_offset;
190 return &capture->frame;
196 static double icvGetPropertyAVI_VFW( CvCaptureAVI_VFW* capture, int property_id )
198 switch( property_id )
200 case CV_CAP_PROP_POS_MSEC:
201 return cvRound(capture->pos*1000./capture->fps);
202 case CV_CAP_PROP_POS_FRAMES:
204 case CV_CAP_PROP_POS_AVI_RATIO:
205 return (capture->pos - capture->film_range.start_index)/
206 (capture->film_range.end_index - capture->film_range.start_index + 1e-10);
207 case CV_CAP_PROP_FRAME_WIDTH:
208 return capture->size.width;
209 case CV_CAP_PROP_FRAME_HEIGHT:
210 return capture->size.height;
211 case CV_CAP_PROP_FPS:
213 case CV_CAP_PROP_FOURCC:
214 return capture->aviinfo.fccHandler;
215 case CV_CAP_PROP_FRAME_COUNT:
216 return capture->film_range.end_index - capture->film_range.start_index;
222 static int icvSetPropertyAVI_VFW( CvCaptureAVI_VFW* capture,
223 int property_id, double value )
225 switch( property_id )
227 case CV_CAP_PROP_POS_MSEC:
228 case CV_CAP_PROP_POS_FRAMES:
229 case CV_CAP_PROP_POS_AVI_RATIO:
232 switch( property_id )
234 case CV_CAP_PROP_POS_MSEC:
235 pos = cvRound(value*capture->fps*0.001);
237 case CV_CAP_PROP_POS_AVI_RATIO:
238 pos = cvRound(value*(capture->film_range.end_index -
239 capture->film_range.start_index) +
240 capture->film_range.start_index);
243 pos = cvRound(value);
245 if( pos < capture->film_range.start_index )
246 pos = capture->film_range.start_index;
247 if( pos > capture->film_range.end_index )
248 pos = capture->film_range.end_index;
259 static CvCaptureVTable captureAVI_VFW_vtable =
262 (CvCaptureCloseFunc) icvCloseAVI_VFW,
263 (CvCaptureGrabFrameFunc) icvGrabFrameAVI_VFW,
264 (CvCaptureRetrieveFrameFunc) icvRetrieveFrameAVI_VFW,
265 (CvCaptureGetPropertyFunc) icvGetPropertyAVI_VFW,
266 (CvCaptureSetPropertyFunc) icvSetPropertyAVI_VFW,
267 (CvCaptureGetDescriptionFunc) 0
271 CvCapture* cvCaptureFromFile_VFW (const char* filename)
273 CvCaptureAVI_VFW* capture = 0;
277 capture = (CvCaptureAVI_VFW*)cvAlloc( sizeof(*capture));
278 memset( capture, 0, sizeof(*capture));
280 capture->vtable = &captureAVI_VFW_vtable;
282 if( !icvOpenAVI_VFW( capture, filename ))
283 cvReleaseCapture( (CvCapture**)&capture );
286 return (CvCapture*)capture;
289 /********************* Capturing video from camera via VFW *********************/
291 typedef struct CvCaptureCAM_VFW
293 CvCaptureVTable* vtable;
305 static LRESULT PASCAL FrameCallbackProc( HWND hWnd, VIDEOHDR* hdr )
307 CvCaptureCAM_VFW* capture = 0;
309 if (!hWnd) return FALSE;
311 capture = (CvCaptureCAM_VFW*)capGetUserData(hWnd);
314 return (LRESULT)TRUE;
318 // Initialize camera input
319 static int icvOpenCAM_VFW( CvCaptureCAM_VFW* capture, int wIndex )
321 char szDeviceName[80];
322 char szDeviceVersion[80];
325 if( (unsigned)wIndex >= 10 )
328 for( ; wIndex < 10; wIndex++ )
330 if( capGetDriverDescription( wIndex, szDeviceName,
331 sizeof (szDeviceName), szDeviceVersion,
332 sizeof (szDeviceVersion)))
334 hWndC = capCreateCaptureWindow ( "My Own Capture Window",
335 WS_POPUP | WS_CHILD, 0, 0, 320, 240, 0, 0);
336 if( capDriverConnect (hWndC, wIndex))
338 DestroyWindow( hWndC );
345 capture->capWnd = hWndC;
348 capture->fourcc = (DWORD)-1;
349 capture->rgb_frame = 0;
351 memset( &capture->caps, 0, sizeof(capture->caps));
352 capDriverGetCaps( hWndC, &capture->caps, sizeof(&capture->caps));
353 ::MoveWindow( hWndC, 0, 0, 320, 240, TRUE );
354 capSetUserData( hWndC, (size_t)capture );
355 capSetCallbackOnFrame( hWndC, FrameCallbackProc );
357 capCaptureGetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
358 p.dwRequestMicroSecPerFrame = 66667/2;
359 capCaptureSetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
360 //capPreview( hWndC, 1 );
361 capPreviewScale(hWndC,FALSE);
362 capPreviewRate(hWndC,1);
364 return capture->capWnd != 0;
367 static void icvCloseCAM_VFW( CvCaptureCAM_VFW* capture )
369 if( capture && capture->capWnd )
371 capSetCallbackOnFrame( capture->capWnd, NULL );
372 capDriverDisconnect( capture->capWnd );
373 DestroyWindow( capture->capWnd );
374 cvReleaseImage( &capture->rgb_frame );
377 ICDecompressEnd( capture->hic );
378 ICClose( capture->hic );
385 capture->rgb_frame = 0;
386 memset( &capture->frame, 0, sizeof(capture->frame));
391 static int icvGrabFrameCAM_VFW( CvCaptureCAM_VFW* capture )
393 if( capture->capWnd )
395 SendMessage( capture->capWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0 );
402 static IplImage* icvRetrieveFrameCAM_VFW( CvCaptureCAM_VFW* capture )
404 if( capture->capWnd )
407 memset( &vfmt, 0, sizeof(vfmt));
408 int sz = capGetVideoFormat( capture->capWnd, &vfmt, sizeof(vfmt));
410 if( capture->hdr && capture->hdr->lpData && sz != 0 )
412 long code = ICERR_OK;
413 char* frame_data = (char*)capture->hdr->lpData;
415 if( vfmt.bmiHeader.biCompression != BI_RGB ||
416 vfmt.bmiHeader.biBitCount != 24 )
418 BITMAPINFOHEADER& vfmt0 = vfmt.bmiHeader;
419 BITMAPINFOHEADER vfmt1 = icvBitmapHeader( vfmt0.biWidth, vfmt0.biHeight, 24 );
422 if( capture->hic == 0 ||
423 capture->fourcc != vfmt0.biCompression ||
424 capture->rgb_frame == 0 ||
425 vfmt0.biWidth != capture->rgb_frame->width ||
426 vfmt0.biHeight != capture->rgb_frame->height )
430 ICDecompressEnd( capture->hic );
431 ICClose( capture->hic );
433 capture->hic = ICOpen( MAKEFOURCC('V','I','D','C'),
434 vfmt0.biCompression, ICMODE_DECOMPRESS );
436 ICDecompressBegin( capture->hic, &vfmt0, &vfmt1 ) == ICERR_OK )
438 cvReleaseImage( &capture->rgb_frame );
439 capture->rgb_frame = cvCreateImage(
440 cvSize( vfmt0.biWidth, vfmt0.biHeight ), IPL_DEPTH_8U, 3 );
441 capture->rgb_frame->origin = IPL_ORIGIN_BL;
443 code = ICDecompress( capture->hic, 0,
444 &vfmt0, capture->hdr->lpData,
445 &vfmt1, capture->rgb_frame->imageData );
446 frame_data = capture->rgb_frame->imageData;
451 if( code == ICERR_OK )
453 cvInitImageHeader( &capture->frame,
454 cvSize(vfmt.bmiHeader.biWidth,
455 vfmt.bmiHeader.biHeight),
456 IPL_DEPTH_8U, 3, IPL_ORIGIN_BL, 4 );
457 capture->frame.imageData = capture->frame.imageDataOrigin = frame_data;
458 return &capture->frame;
467 static double icvGetPropertyCAM_VFW( CvCaptureCAM_VFW* capture, int property_id )
469 switch( property_id )
471 case CV_CAP_PROP_FRAME_WIDTH:
472 return capture->frame.width;
473 case CV_CAP_PROP_FRAME_HEIGHT:
474 return capture->frame.height;
475 case CV_CAP_PROP_FOURCC:
476 return capture->fourcc;
483 static CvCaptureVTable captureCAM_VFW_vtable =
486 (CvCaptureCloseFunc)icvCloseCAM_VFW,
487 (CvCaptureGrabFrameFunc)icvGrabFrameCAM_VFW,
488 (CvCaptureRetrieveFrameFunc)icvRetrieveFrameCAM_VFW,
489 (CvCaptureGetPropertyFunc)icvGetPropertyCAM_VFW,
490 (CvCaptureSetPropertyFunc)0,
491 (CvCaptureGetDescriptionFunc)0
495 CvCapture* cvCaptureFromCAM_VFW( int index )
497 CvCaptureCAM_VFW * capture = (CvCaptureCAM_VFW*)cvAlloc( sizeof(*capture));
498 memset( capture, 0, sizeof(*capture));
499 capture->vtable = &captureCAM_VFW_vtable;
501 if( icvOpenCAM_VFW( capture, index ))
502 return (CvCapture*)capture;
504 cvReleaseCapture( (CvCapture**)&capture );
509 /*************************** writing AVIs ******************************/
511 typedef struct CvAVI_VFW_Writer
514 PAVISTREAM compressed;
515 PAVISTREAM uncompressed;
518 IplImage * tempFrame;
524 static void icvCloseAVIWriter( CvAVI_VFW_Writer* writer )
528 if( writer->uncompressed )
529 AVIStreamRelease( writer->uncompressed );
530 if( writer->compressed )
531 AVIStreamRelease( writer->compressed );
532 if( writer->avifile )
533 AVIFileRelease( writer->avifile );
534 cvReleaseImage( &writer->tempFrame );
535 memset( writer, 0, sizeof(*writer));
540 // philipg. Made this code capable of writing 8bpp gray scale bitmaps
541 typedef struct tagBITMAPINFO_8Bit
543 BITMAPINFOHEADER bmiHeader;
544 RGBQUAD bmiColors[256];
545 } BITMAPINFOHEADER_8BIT;
547 static int icvInitAVIWriter( CvAVI_VFW_Writer* writer, int fourcc,
548 double fps, CvSize frameSize, int is_color )
550 if( writer && writer->avifile )
552 AVICOMPRESSOPTIONS copts, *pcopts = &copts;
553 AVISTREAMINFO aviinfo;
555 assert( frameSize.width > 0 && frameSize.height > 0 );
557 BITMAPINFOHEADER_8BIT bmih;
560 bmih.bmiHeader = icvBitmapHeader( frameSize.width, frameSize.height, is_color ? 24 : 8 );
561 for( i = 0; i < 256; i++ )
563 bmih.bmiColors[i].rgbBlue = (BYTE)i;
564 bmih.bmiColors[i].rgbGreen = (BYTE)i;
565 bmih.bmiColors[i].rgbRed = (BYTE)i;
566 bmih.bmiColors[i].rgbReserved = 0;
569 memset( &aviinfo, 0, sizeof(aviinfo));
570 aviinfo.fccType = streamtypeVIDEO;
571 aviinfo.fccHandler = 0;
572 // use highest possible accuracy for dwRate/dwScale
573 aviinfo.dwScale = (DWORD)((double)0x7FFFFFFF / fps);
574 aviinfo.dwRate = cvRound(fps * aviinfo.dwScale);
575 aviinfo.rcFrame.top = aviinfo.rcFrame.left = 0;
576 aviinfo.rcFrame.right = frameSize.width;
577 aviinfo.rcFrame.bottom = frameSize.height;
579 if( AVIFileCreateStream( writer->avifile,
580 &writer->uncompressed, &aviinfo ) == AVIERR_OK )
582 copts.fccType = streamtypeVIDEO;
583 copts.fccHandler = fourcc != -1 ? fourcc : 0;
584 copts.dwKeyFrameEvery = 1;
585 copts.dwQuality = (DWORD)-1;
586 copts.dwBytesPerSecond = 0;
587 copts.dwFlags = AVICOMPRESSF_VALID;
588 copts.lpFormat = &bmih;
589 copts.cbFormat = (is_color ? sizeof(BITMAPINFOHEADER) : sizeof(bmih));
592 copts.dwInterleaveEvery = 0;
595 AVISaveOptions( 0, 0, 1, &writer->uncompressed, &pcopts ) == TRUE )
597 if( AVIMakeCompressedStream( &writer->compressed,
598 writer->uncompressed, pcopts, 0 ) == AVIERR_OK &&
599 // check that the resolution was not changed
600 bmih.bmiHeader.biWidth == frameSize.width &&
601 bmih.bmiHeader.biHeight == frameSize.height &&
602 AVIStreamSetFormat( writer->compressed, 0, &bmih, sizeof(bmih)) == AVIERR_OK )
605 writer->fourcc = (int)copts.fccHandler;
606 writer->frameSize = frameSize;
607 writer->tempFrame = cvCreateImage( frameSize, 8, (is_color ? 3 : 1) );
613 icvCloseAVIWriter( writer );
617 CvVideoWriter* cvCreateVideoWriter_VFW( const char* filename, int fourcc,
618 double fps, CvSize frameSize, int is_color )
620 CvAVI_VFW_Writer* writer = (CvAVI_VFW_Writer*)cvAlloc( sizeof(CvAVI_VFW_Writer));
621 memset( writer, 0, sizeof(*writer));
623 icvInitCapture_VFW();
625 if( AVIFileOpen( &writer->avifile, filename, OF_CREATE | OF_WRITE, 0 ) == AVIERR_OK )
627 if( frameSize.width > 0 && frameSize.height > 0 )
629 if( !icvInitAVIWriter( writer, fourcc, fps, frameSize, is_color ))
630 cvReleaseVideoWriter( (CvVideoWriter**)&writer );
632 else if( fourcc == -1 )
634 icvCloseAVIWriter( writer );
638 /* postpone initialization until the first frame is written */
639 writer->fourcc = fourcc;
641 writer->frameSize = frameSize;
645 return (CvVideoWriter*)writer;
648 int cvWriteFrame_VFW( CvVideoWriter* _writer, const IplImage* image )
650 CvAVI_VFW_Writer* writer = (CvAVI_VFW_Writer*)_writer;
652 if( writer && (writer->compressed ||
653 icvInitAVIWriter( writer, writer->fourcc, writer->fps,
654 writer->frameSize, image->nChannels > 1 )))
656 if (image->nChannels != writer->tempFrame->nChannels)
658 cvConvertImage( image, writer->tempFrame,
659 image->origin == 0 ? CV_CVTIMG_FLIP : 0 );
660 image = (const IplImage*)writer->tempFrame;
662 // If only flipping is needed, do not call cvConvertImage because when source and destination are single channel, cvConvertImage fails.
663 else if (image->origin == 0)
665 cvFlip( image, writer->tempFrame, 0 );
666 image = (const IplImage*)writer->tempFrame;
668 if( AVIStreamWrite( writer->compressed, writer->pos++, 1, image->imageData,
669 image->imageSize, AVIIF_KEYFRAME, 0, 0 ) == AVIERR_OK )
677 void cvReleaseVideoWriter_VFW( CvVideoWriter** writer )
679 if( writer && *writer )
681 icvCloseAVIWriter( (CvAVI_VFW_Writer*)*writer );