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 "precomp.hpp"
43
44 #include <vfw.h>
45
46 #ifdef __GNUC__
47 #define WM_CAP_FIRSTA (WM_USER)
48 #define capSendMessage(hwnd,m,w,l) (IsWindow(hwnd)?SendMessage(hwnd,m,w,l):0)
49 #endif
50
51 #if defined _M_X64 && defined _MSC_VER
52 #pragma optimize("",off)
53 #pragma warning(disable: 4748)
54 #endif
55
56 /********************* Capturing video from AVI via VFW ************************/
57
icvBitmapHeader(int width,int height,int bpp,int compression=BI_RGB)58 static BITMAPINFOHEADER icvBitmapHeader( int width, int height, int bpp, int compression = BI_RGB )
59 {
60 BITMAPINFOHEADER bmih;
61 memset( &bmih, 0, sizeof(bmih));
62 bmih.biSize = sizeof(bmih);
63 bmih.biWidth = width;
64 bmih.biHeight = height;
65 bmih.biBitCount = (WORD)bpp;
66 bmih.biCompression = compression;
67 bmih.biPlanes = 1;
68
69 return bmih;
70 }
71
72
icvInitCapture_VFW()73 static void icvInitCapture_VFW()
74 {
75 static int isInitialized = 0;
76 if( !isInitialized )
77 {
78 AVIFileInit();
79 isInitialized = 1;
80 }
81 }
82
83
84 class CvCaptureAVI_VFW : public CvCapture
85 {
86 public:
CvCaptureAVI_VFW()87 CvCaptureAVI_VFW()
88 {
89 CoInitialize(NULL);
90 init();
91 }
92
~CvCaptureAVI_VFW()93 virtual ~CvCaptureAVI_VFW()
94 {
95 close();
96 CoUninitialize();
97 }
98
99 virtual bool open( const char* filename );
100 virtual void close();
101
102 virtual double getProperty(int) const;
103 virtual bool setProperty(int, double);
104 virtual bool grabFrame();
105 virtual IplImage* retrieveFrame(int);
getCaptureDomain()106 virtual int getCaptureDomain() { return CV_CAP_VFW; } // Return the type of the capture object: CV_CAP_VFW, etc...
107
108 protected:
109 void init();
110
111 PAVIFILE avifile;
112 PAVISTREAM avistream;
113 PGETFRAME getframe;
114 AVISTREAMINFO aviinfo;
115 BITMAPINFOHEADER * bmih;
116 CvSlice film_range;
117 double fps;
118 int pos;
119 IplImage* frame;
120 CvSize size;
121 };
122
123
init()124 void CvCaptureAVI_VFW::init()
125 {
126 avifile = 0;
127 avistream = 0;
128 getframe = 0;
129 memset( &aviinfo, 0, sizeof(aviinfo) );
130 bmih = 0;
131 film_range = cvSlice(0,0);
132 fps = 0;
133 pos = 0;
134 frame = 0;
135 size = cvSize(0,0);
136 }
137
138
close()139 void CvCaptureAVI_VFW::close()
140 {
141 if( getframe )
142 AVIStreamGetFrameClose( getframe );
143
144 if( avistream )
145 AVIStreamRelease( avistream );
146
147 if( avifile )
148 AVIFileRelease( avifile );
149
150 if (frame)
151 cvReleaseImage( &frame );
152
153 init();
154 }
155
156
open(const char * filename)157 bool CvCaptureAVI_VFW::open( const char* filename )
158 {
159 close();
160 icvInitCapture_VFW();
161
162 if( !filename )
163 return false;
164
165 HRESULT hr = AVIFileOpen( &avifile, filename, OF_READ, NULL );
166 if( SUCCEEDED(hr))
167 {
168 hr = AVIFileGetStream( avifile, &avistream, streamtypeVIDEO, 0 );
169 if( SUCCEEDED(hr))
170 {
171 hr = AVIStreamInfo( avistream, &aviinfo, sizeof(aviinfo));
172 if( SUCCEEDED(hr))
173 {
174 size.width = aviinfo.rcFrame.right - aviinfo.rcFrame.left;
175 size.height = aviinfo.rcFrame.bottom - aviinfo.rcFrame.top;
176 BITMAPINFOHEADER bmihdr = icvBitmapHeader( size.width, size.height, 24 );
177
178 film_range.start_index = (int)aviinfo.dwStart;
179 film_range.end_index = film_range.start_index + (int)aviinfo.dwLength;
180 fps = (double)aviinfo.dwRate/aviinfo.dwScale;
181 pos = film_range.start_index;
182 getframe = AVIStreamGetFrameOpen( avistream, &bmihdr );
183 if( getframe != 0 )
184 return true;
185
186 // Attempt to open as 8-bit AVI.
187 bmihdr = icvBitmapHeader( size.width, size.height, 8);
188 getframe = AVIStreamGetFrameOpen( avistream, &bmihdr );
189 if( getframe != 0 )
190 return true;
191 }
192 }
193 }
194
195 close();
196 return false;
197 }
198
grabFrame()199 bool CvCaptureAVI_VFW::grabFrame()
200 {
201 if( avistream )
202 bmih = (BITMAPINFOHEADER*)AVIStreamGetFrame( getframe, pos++ );
203 return bmih != 0;
204 }
205
retrieveFrame(int)206 IplImage* CvCaptureAVI_VFW::retrieveFrame(int)
207 {
208 if( avistream && bmih )
209 {
210 bool isColor = bmih->biBitCount == 24;
211 int nChannels = (isColor) ? 3 : 1;
212 IplImage src;
213 cvInitImageHeader( &src, cvSize( bmih->biWidth, bmih->biHeight ),
214 IPL_DEPTH_8U, nChannels, IPL_ORIGIN_BL, 4 );
215
216 char* dataPtr = (char*)(bmih + 1);
217
218 // Only account for the color map size if we are an 8-bit image and the color map is used
219 if (!isColor)
220 {
221 static int RGBQUAD_SIZE_PER_BYTE = sizeof(RGBQUAD)/sizeof(BYTE);
222 int offsetFromColormapToData = (int)bmih->biClrUsed*RGBQUAD_SIZE_PER_BYTE;
223 dataPtr += offsetFromColormapToData;
224 }
225
226 cvSetData( &src, dataPtr, src.widthStep );
227
228 if( !frame || frame->width != src.width || frame->height != src.height )
229 {
230 cvReleaseImage( &frame );
231 frame = cvCreateImage( cvGetSize(&src), 8, nChannels );
232 }
233
234 cvFlip( &src, frame, 0 );
235 return frame;
236 }
237
238 return 0;
239 }
240
getProperty(int property_id) const241 double CvCaptureAVI_VFW::getProperty( int property_id ) const
242 {
243 switch( property_id )
244 {
245 case CV_CAP_PROP_POS_MSEC:
246 return cvRound(pos*1000./fps);
247 case CV_CAP_PROP_POS_FRAMES:
248 return pos;
249 case CV_CAP_PROP_POS_AVI_RATIO:
250 return (pos - film_range.start_index)/
251 (film_range.end_index - film_range.start_index + 1e-10);
252 case CV_CAP_PROP_FRAME_WIDTH:
253 return size.width;
254 case CV_CAP_PROP_FRAME_HEIGHT:
255 return size.height;
256 case CV_CAP_PROP_FPS:
257 return fps;
258 case CV_CAP_PROP_FOURCC:
259 return aviinfo.fccHandler;
260 case CV_CAP_PROP_FRAME_COUNT:
261 return film_range.end_index - film_range.start_index;
262 }
263 return 0;
264 }
265
setProperty(int property_id,double value)266 bool CvCaptureAVI_VFW::setProperty( int property_id, double value )
267 {
268 switch( property_id )
269 {
270 case CV_CAP_PROP_POS_MSEC:
271 case CV_CAP_PROP_POS_FRAMES:
272 case CV_CAP_PROP_POS_AVI_RATIO:
273 {
274 switch( property_id )
275 {
276 case CV_CAP_PROP_POS_MSEC:
277 pos = cvRound(value*fps*0.001);
278 break;
279 case CV_CAP_PROP_POS_AVI_RATIO:
280 pos = cvRound(value*(film_range.end_index -
281 film_range.start_index) +
282 film_range.start_index);
283 break;
284 default:
285 pos = cvRound(value);
286 }
287 if( pos < film_range.start_index )
288 pos = film_range.start_index;
289 if( pos > film_range.end_index )
290 pos = film_range.end_index;
291 }
292 break;
293 default:
294 return false;
295 }
296
297 return true;
298 }
299
cvCreateFileCapture_VFW(const char * filename)300 CvCapture* cvCreateFileCapture_VFW (const char* filename)
301 {
302 CvCaptureAVI_VFW* capture = new CvCaptureAVI_VFW;
303 if( capture->open(filename) )
304 return capture;
305 delete capture;
306 return 0;
307 }
308
309
310 /********************* Capturing video from camera via VFW *********************/
311
312 class CvCaptureCAM_VFW : public CvCapture
313 {
314 public:
CvCaptureCAM_VFW()315 CvCaptureCAM_VFW() { init(); }
~CvCaptureCAM_VFW()316 virtual ~CvCaptureCAM_VFW() { close(); }
317
318 virtual bool open( int index );
319 virtual void close();
320 virtual double getProperty(int) const;
321 virtual bool setProperty(int, double);
322 virtual bool grabFrame();
323 virtual IplImage* retrieveFrame(int);
getCaptureDomain()324 virtual int getCaptureDomain() { return CV_CAP_VFW; } // Return the type of the capture object: CV_CAP_VFW, etc...
325
326 protected:
327 void init();
328 void closeHIC();
329 static LRESULT PASCAL frameCallback( HWND hWnd, VIDEOHDR* hdr );
330
331 CAPDRIVERCAPS caps;
332 HWND capWnd;
333 VIDEOHDR* hdr;
334 DWORD fourcc;
335 int width, height;
336 int widthSet, heightSet;
337 HIC hic;
338 IplImage* frame;
339 };
340
341
init()342 void CvCaptureCAM_VFW::init()
343 {
344 memset( &caps, 0, sizeof(caps) );
345 capWnd = 0;
346 hdr = 0;
347 fourcc = 0;
348 hic = 0;
349 frame = 0;
350 width = height = -1;
351 widthSet = heightSet = 0;
352 }
353
closeHIC()354 void CvCaptureCAM_VFW::closeHIC()
355 {
356 if( hic )
357 {
358 ICDecompressEnd( hic );
359 ICClose( hic );
360 hic = 0;
361 }
362 }
363
364
frameCallback(HWND hWnd,VIDEOHDR * hdr)365 LRESULT PASCAL CvCaptureCAM_VFW::frameCallback( HWND hWnd, VIDEOHDR* hdr )
366 {
367 CvCaptureCAM_VFW* capture = 0;
368
369 if (!hWnd) return FALSE;
370
371 capture = (CvCaptureCAM_VFW*)capGetUserData(hWnd);
372 capture->hdr = hdr;
373
374 return (LRESULT)TRUE;
375 }
376
377
378 // Initialize camera input
open(int wIndex)379 bool CvCaptureCAM_VFW::open( int wIndex )
380 {
381 char szDeviceName[80];
382 char szDeviceVersion[80];
383 HWND hWndC = 0;
384
385 close();
386
387 if( (unsigned)wIndex >= 10 )
388 wIndex = 0;
389
390 for( ; wIndex < 10; wIndex++ )
391 {
392 if( capGetDriverDescription( wIndex, szDeviceName,
393 sizeof (szDeviceName), szDeviceVersion,
394 sizeof (szDeviceVersion)))
395 {
396 hWndC = capCreateCaptureWindow ( "My Own Capture Window",
397 WS_POPUP | WS_CHILD, 0, 0, 320, 240, 0, 0);
398 if( capDriverConnect (hWndC, wIndex))
399 break;
400 DestroyWindow( hWndC );
401 hWndC = 0;
402 }
403 }
404
405 if( hWndC )
406 {
407 capWnd = hWndC;
408 hdr = 0;
409 hic = 0;
410 fourcc = (DWORD)-1;
411
412 memset( &caps, 0, sizeof(caps));
413 capDriverGetCaps( hWndC, &caps, sizeof(caps));
414 CAPSTATUS status = {};
415 capGetStatus(hWndC, &status, sizeof(status));
416 ::SetWindowPos(hWndC, NULL, 0, 0, status.uiImageWidth, status.uiImageHeight, SWP_NOZORDER|SWP_NOMOVE);
417 capSetUserData( hWndC, (size_t)this );
418 capSetCallbackOnFrame( hWndC, frameCallback );
419 CAPTUREPARMS p;
420 capCaptureGetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
421 p.dwRequestMicroSecPerFrame = 66667/2; // 30 FPS
422 capCaptureSetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
423 //capPreview( hWndC, 1 );
424 capPreviewScale(hWndC,FALSE);
425 capPreviewRate(hWndC,1);
426
427 // Get frame initial parameters.
428 const DWORD size = capGetVideoFormatSize(capWnd);
429 if( size > 0 )
430 {
431 unsigned char *pbi = new unsigned char[size];
432 if( pbi )
433 {
434 if( capGetVideoFormat(capWnd, pbi, size) == size )
435 {
436 BITMAPINFOHEADER& vfmt = ((BITMAPINFO*)pbi)->bmiHeader;
437 widthSet = vfmt.biWidth;
438 heightSet = vfmt.biHeight;
439 fourcc = vfmt.biCompression;
440 }
441 delete []pbi;
442 }
443 }
444 // And alternative way in case of failure.
445 if( widthSet == 0 || heightSet == 0 )
446 {
447 widthSet = status.uiImageWidth;
448 heightSet = status.uiImageHeight;
449 }
450
451 }
452 return capWnd != 0;
453 }
454
455
close()456 void CvCaptureCAM_VFW::close()
457 {
458 if( capWnd )
459 {
460 capSetCallbackOnFrame( capWnd, NULL );
461 capDriverDisconnect( capWnd );
462 DestroyWindow( capWnd );
463 closeHIC();
464 }
465 cvReleaseImage( &frame );
466 init();
467 }
468
469
grabFrame()470 bool CvCaptureCAM_VFW::grabFrame()
471 {
472 if( capWnd )
473 return capGrabFrameNoStop(capWnd) == TRUE;
474
475 return false;
476 }
477
478
retrieveFrame(int)479 IplImage* CvCaptureCAM_VFW::retrieveFrame(int)
480 {
481 BITMAPINFO vfmt;
482 memset( &vfmt, 0, sizeof(vfmt));
483 BITMAPINFOHEADER& vfmt0 = vfmt.bmiHeader;
484
485 if( !capWnd )
486 return 0;
487
488 const DWORD sz = capGetVideoFormat( capWnd, &vfmt, sizeof(vfmt));
489 const int prevWidth = frame ? frame->width : 0;
490 const int prevHeight = frame ? frame->height : 0;
491
492 if( !hdr || hdr->lpData == 0 || sz == 0 )
493 return 0;
494
495 if( !frame || frame->width != vfmt0.biWidth || frame->height != vfmt0.biHeight )
496 {
497 cvReleaseImage( &frame );
498 frame = cvCreateImage( cvSize( vfmt0.biWidth, vfmt0.biHeight ), 8, 3 );
499 }
500
501 if( vfmt0.biCompression != BI_RGB ||
502 vfmt0.biBitCount != 24 )
503 {
504 BITMAPINFOHEADER vfmt1 = icvBitmapHeader( vfmt0.biWidth, vfmt0.biHeight, 24 );
505
506 if( hic == 0 || fourcc != vfmt0.biCompression ||
507 prevWidth != vfmt0.biWidth || prevHeight != vfmt0.biHeight )
508 {
509 closeHIC();
510 hic = ICOpen( MAKEFOURCC('V','I','D','C'),
511 vfmt0.biCompression, ICMODE_DECOMPRESS );
512 if( hic )
513 {
514 if( ICDecompressBegin( hic, &vfmt0, &vfmt1 ) != ICERR_OK )
515 {
516 closeHIC();
517 return 0;
518 }
519 }
520 }
521
522 if( !hic || ICDecompress( hic, 0, &vfmt0, hdr->lpData,
523 &vfmt1, frame->imageData ) != ICERR_OK )
524 {
525 closeHIC();
526 return 0;
527 }
528
529 cvFlip( frame, frame, 0 );
530 }
531 else
532 {
533 IplImage src;
534 cvInitImageHeader( &src, cvSize(vfmt0.biWidth, vfmt0.biHeight),
535 IPL_DEPTH_8U, 3, IPL_ORIGIN_BL, 4 );
536 cvSetData( &src, hdr->lpData, src.widthStep );
537 cvFlip( &src, frame, 0 );
538 }
539
540 return frame;
541 }
542
543
getProperty(int property_id) const544 double CvCaptureCAM_VFW::getProperty( int property_id ) const
545 {
546 switch( property_id )
547 {
548 case CV_CAP_PROP_FRAME_WIDTH:
549 return widthSet;
550 case CV_CAP_PROP_FRAME_HEIGHT:
551 return heightSet;
552 case CV_CAP_PROP_FOURCC:
553 return fourcc;
554 case CV_CAP_PROP_FPS:
555 {
556 CAPTUREPARMS params = {};
557 if( capCaptureGetSetup(capWnd, ¶ms, sizeof(params)) )
558 return 1e6 / params.dwRequestMicroSecPerFrame;
559 }
560 break;
561 default:
562 break;
563 }
564 return 0;
565 }
566
setProperty(int property_id,double value)567 bool CvCaptureCAM_VFW::setProperty(int property_id, double value)
568 {
569 bool handledSize = false;
570
571 switch( property_id )
572 {
573 case CV_CAP_PROP_FRAME_WIDTH:
574 width = cvRound(value);
575 handledSize = true;
576 break;
577 case CV_CAP_PROP_FRAME_HEIGHT:
578 height = cvRound(value);
579 handledSize = true;
580 break;
581 case CV_CAP_PROP_FOURCC:
582 break;
583 case CV_CAP_PROP_FPS:
584 if( value > 0 )
585 {
586 CAPTUREPARMS params;
587 if( capCaptureGetSetup(capWnd, ¶ms, sizeof(params)) )
588 {
589 params.dwRequestMicroSecPerFrame = cvRound(1e6/value);
590 return capCaptureSetSetup(capWnd, ¶ms, sizeof(params)) == TRUE;
591 }
592 }
593 break;
594 default:
595 break;
596 }
597
598 if ( handledSize )
599 {
600 // If both width and height are set then change frame size.
601 if( width > 0 && height > 0 )
602 {
603 const DWORD size = capGetVideoFormatSize(capWnd);
604 if( size == 0 )
605 return false;
606
607 unsigned char *pbi = new unsigned char[size];
608 if( !pbi )
609 return false;
610
611 if( capGetVideoFormat(capWnd, pbi, size) != size )
612 {
613 delete []pbi;
614 return false;
615 }
616
617 BITMAPINFOHEADER& vfmt = ((BITMAPINFO*)pbi)->bmiHeader;
618 bool success = true;
619 if( width != vfmt.biWidth || height != vfmt.biHeight )
620 {
621 // Change frame size.
622 vfmt.biWidth = width;
623 vfmt.biHeight = height;
624 vfmt.biSizeImage = height * ((width * vfmt.biBitCount + 31) / 32) * 4;
625 vfmt.biCompression = BI_RGB;
626 success = capSetVideoFormat(capWnd, pbi, size) == TRUE;
627 }
628 if( success )
629 {
630 // Adjust capture window size.
631 CAPSTATUS status = {};
632 capGetStatus(capWnd, &status, sizeof(status));
633 ::SetWindowPos(capWnd, NULL, 0, 0, status.uiImageWidth, status.uiImageHeight, SWP_NOZORDER|SWP_NOMOVE);
634 // Store frame size.
635 widthSet = width;
636 heightSet = height;
637 }
638 delete []pbi;
639 width = height = -1;
640
641 return success;
642 }
643
644 return true;
645 }
646
647 return false;
648 }
649
cvCreateCameraCapture_VFW(int index)650 CvCapture* cvCreateCameraCapture_VFW( int index )
651 {
652 CvCaptureCAM_VFW* capture = new CvCaptureCAM_VFW;
653
654 if( capture->open( index ))
655 return capture;
656
657 delete capture;
658 return 0;
659 }
660
661
662 /*************************** writing AVIs ******************************/
663
664 class CvVideoWriter_VFW : public CvVideoWriter
665 {
666 public:
CvVideoWriter_VFW()667 CvVideoWriter_VFW() { init(); }
~CvVideoWriter_VFW()668 virtual ~CvVideoWriter_VFW() { close(); }
669
670 virtual bool open( const char* filename, int fourcc,
671 double fps, CvSize frameSize, bool isColor );
672 virtual void close();
673 virtual bool writeFrame( const IplImage* );
674
675 protected:
676 void init();
677 bool createStreams( CvSize frameSize, bool isColor );
678
679 PAVIFILE avifile;
680 PAVISTREAM compressed;
681 PAVISTREAM uncompressed;
682 double fps;
683 IplImage* tempFrame;
684 long pos;
685 int fourcc;
686 };
687
688
init()689 void CvVideoWriter_VFW::init()
690 {
691 avifile = 0;
692 compressed = uncompressed = 0;
693 fps = 0;
694 tempFrame = 0;
695 pos = 0;
696 fourcc = 0;
697 }
698
close()699 void CvVideoWriter_VFW::close()
700 {
701 if( uncompressed )
702 AVIStreamRelease( uncompressed );
703 if( compressed )
704 AVIStreamRelease( compressed );
705 if( avifile )
706 AVIFileRelease( avifile );
707 cvReleaseImage( &tempFrame );
708 init();
709 }
710
711
712 // philipg. Made this code capable of writing 8bpp gray scale bitmaps
713 struct BITMAPINFO_8Bit
714 {
715 BITMAPINFOHEADER bmiHeader;
716 RGBQUAD bmiColors[256];
717 };
718
719
open(const char * filename,int _fourcc,double _fps,CvSize frameSize,bool isColor)720 bool CvVideoWriter_VFW::open( const char* filename, int _fourcc, double _fps, CvSize frameSize, bool isColor )
721 {
722 close();
723
724 icvInitCapture_VFW();
725 if( AVIFileOpen( &avifile, filename, OF_CREATE | OF_WRITE, 0 ) == AVIERR_OK )
726 {
727 fourcc = _fourcc;
728 fps = _fps;
729 if( frameSize.width > 0 && frameSize.height > 0 &&
730 !createStreams( frameSize, isColor ) )
731 {
732 close();
733 return false;
734 }
735 return true;
736 }
737 else
738 return false;
739 }
740
741
createStreams(CvSize frameSize,bool isColor)742 bool CvVideoWriter_VFW::createStreams( CvSize frameSize, bool isColor )
743 {
744 if( !avifile )
745 return false;
746 AVISTREAMINFO aviinfo;
747
748 BITMAPINFO_8Bit bmih;
749 bmih.bmiHeader = icvBitmapHeader( frameSize.width, frameSize.height, isColor ? 24 : 8 );
750 for( int i = 0; i < 256; i++ )
751 {
752 bmih.bmiColors[i].rgbBlue = (BYTE)i;
753 bmih.bmiColors[i].rgbGreen = (BYTE)i;
754 bmih.bmiColors[i].rgbRed = (BYTE)i;
755 bmih.bmiColors[i].rgbReserved = 0;
756 }
757
758 memset( &aviinfo, 0, sizeof(aviinfo));
759 aviinfo.fccType = streamtypeVIDEO;
760 aviinfo.fccHandler = 0;
761 // use highest possible accuracy for dwRate/dwScale
762 aviinfo.dwScale = (DWORD)((double)0x7FFFFFFF / fps);
763 aviinfo.dwRate = cvRound(fps * aviinfo.dwScale);
764 aviinfo.rcFrame.top = aviinfo.rcFrame.left = 0;
765 aviinfo.rcFrame.right = frameSize.width;
766 aviinfo.rcFrame.bottom = frameSize.height;
767
768 if( AVIFileCreateStream( avifile, &uncompressed, &aviinfo ) == AVIERR_OK )
769 {
770 AVICOMPRESSOPTIONS copts, *pcopts = &copts;
771 copts.fccType = streamtypeVIDEO;
772 copts.fccHandler = fourcc != -1 ? fourcc : 0;
773 copts.dwKeyFrameEvery = 1;
774 copts.dwQuality = 10000;
775 copts.dwBytesPerSecond = 0;
776 copts.dwFlags = AVICOMPRESSF_VALID;
777 copts.lpFormat = &bmih;
778 copts.cbFormat = (isColor ? sizeof(BITMAPINFOHEADER) : sizeof(bmih));
779 copts.lpParms = 0;
780 copts.cbParms = 0;
781 copts.dwInterleaveEvery = 0;
782
783 if( fourcc != -1 || AVISaveOptions( 0, 0, 1, &uncompressed, &pcopts ) == TRUE )
784 {
785 if( AVIMakeCompressedStream( &compressed, uncompressed, pcopts, 0 ) == AVIERR_OK &&
786 AVIStreamSetFormat( compressed, 0, &bmih, sizeof(bmih)) == AVIERR_OK )
787 {
788 fps = fps;
789 fourcc = (int)copts.fccHandler;
790 frameSize = frameSize;
791 tempFrame = cvCreateImage( frameSize, 8, (isColor ? 3 : 1) );
792 return true;
793 }
794 }
795 }
796 return false;
797 }
798
799
writeFrame(const IplImage * image)800 bool CvVideoWriter_VFW::writeFrame( const IplImage* image )
801 {
802 bool result = false;
803 CV_FUNCNAME( "CvVideoWriter_VFW::writeFrame" );
804
805 __BEGIN__;
806
807 if( !image )
808 EXIT;
809
810 if( !compressed && !createStreams( cvGetSize(image), image->nChannels > 1 ))
811 EXIT;
812
813 if( image->width != tempFrame->width || image->height != tempFrame->height )
814 CV_ERROR( CV_StsUnmatchedSizes,
815 "image size is different from the currently set frame size" );
816
817 if( image->nChannels != tempFrame->nChannels ||
818 image->depth != tempFrame->depth ||
819 image->origin == 0 ||
820 image->widthStep != cvAlign(image->width*image->nChannels*((image->depth & 255)/8), 4))
821 {
822 cvConvertImage( image, tempFrame, image->origin == 0 ? CV_CVTIMG_FLIP : 0 );
823 image = (const IplImage*)tempFrame;
824 }
825
826 result = AVIStreamWrite( compressed, pos++, 1, image->imageData,
827 image->imageSize, AVIIF_KEYFRAME, 0, 0 ) == AVIERR_OK;
828
829 __END__;
830
831 return result;
832 }
833
cvCreateVideoWriter_VFW(const char * filename,int fourcc,double fps,CvSize frameSize,int isColor)834 CvVideoWriter* cvCreateVideoWriter_VFW( const char* filename, int fourcc,
835 double fps, CvSize frameSize, int isColor )
836 {
837 CvVideoWriter_VFW* writer = new CvVideoWriter_VFW;
838 if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 ))
839 return writer;
840 delete writer;
841 return 0;
842 }
843