• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &params, 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, &params, sizeof(params)) )
588             {
589                 params.dwRequestMicroSecPerFrame = cvRound(1e6/value);
590                 return capCaptureSetSetup(capWnd, &params, 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