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 58static 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 73static void icvInitCapture_VFW() 74{ 75 static int isInitialized = 0; 76 if( !isInitialized ) 77 { 78 AVIFileInit(); 79 isInitialized = 1; 80 } 81} 82 83 84class CvCaptureAVI_VFW : public CvCapture 85{ 86public: 87 CvCaptureAVI_VFW() 88 { 89 CoInitialize(NULL); 90 init(); 91 } 92 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); 106 virtual int getCaptureDomain() { return CV_CAP_VFW; } // Return the type of the capture object: CV_CAP_VFW, etc... 107 108protected: 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 124void 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 139void 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 157bool 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 199bool CvCaptureAVI_VFW::grabFrame() 200{ 201 if( avistream ) 202 bmih = (BITMAPINFOHEADER*)AVIStreamGetFrame( getframe, pos++ ); 203 return bmih != 0; 204} 205 206IplImage* 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 241double 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 266bool 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 300CvCapture* 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 312class CvCaptureCAM_VFW : public CvCapture 313{ 314public: 315 CvCaptureCAM_VFW() { init(); } 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); 324 virtual int getCaptureDomain() { return CV_CAP_VFW; } // Return the type of the capture object: CV_CAP_VFW, etc... 325 326protected: 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 342void 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 354void CvCaptureCAM_VFW::closeHIC() 355{ 356 if( hic ) 357 { 358 ICDecompressEnd( hic ); 359 ICClose( hic ); 360 hic = 0; 361 } 362} 363 364 365LRESULT 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 379bool 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 456void 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 470bool CvCaptureCAM_VFW::grabFrame() 471{ 472 if( capWnd ) 473 return capGrabFrameNoStop(capWnd) == TRUE; 474 475 return false; 476} 477 478 479IplImage* 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 544double 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 567bool 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 650CvCapture* 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 664class CvVideoWriter_VFW : public CvVideoWriter 665{ 666public: 667 CvVideoWriter_VFW() { init(); } 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 675protected: 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 689void 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 699void 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 713struct BITMAPINFO_8Bit 714{ 715 BITMAPINFOHEADER bmiHeader; 716 RGBQUAD bmiColors[256]; 717}; 718 719 720bool 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 742bool 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 800bool 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 834CvVideoWriter* 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