00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "VFWCapture.h"
00026
00027 #ifdef _DEBUG
00028 #undef THIS_FILE
00029 static char THIS_FILE[]=__FILE__;
00030 #endif
00031
00032 #pragma comment(lib,"vfw32")
00033
00034 UINT CVFWCapture::m_ValidDriverIndex[MAX_VFW_DEVICES];
00035 USHORT CVFWCapture::m_TotalVideoDrivers = 0;
00036
00037
00039
00041 CVFWCapture::CVFWCapture()
00042
00043 {
00044 m_TransferBitmapInfo = NULL;
00045 m_TransferBitmapInfoSize = 0;
00046 m_hWndVideo = NULL;
00047
00048 m_DriverIndex = -1;
00049
00050 memset(&m_BitmapInfoHeader,0,sizeof(m_BitmapInfoHeader));
00051 }
00052
00053 CVFWCapture::~CVFWCapture()
00054 {
00055 Destroy();
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065 BOOL CVFWCapture::Initialize(SHORT DriverIndex)
00066 {
00067 BOOL Ret = FALSE;
00068 BOOL driverDesc = FALSE;
00069 BOOL driverConn = FALSE;
00070 SHORT Index;
00071
00072 Destroy();
00073
00074
00075 GetPreviousError(NULL,NULL,TRUE);
00076
00077 m_hWndVideo = capCreateCaptureWindow(NULL,WS_POPUP,0,0,1,1,0,0);
00078
00079
00080 if (m_hWndVideo)
00081 {
00082 capSetUserData(m_hWndVideo,this);
00083 capSetCallbackOnError(m_hWndVideo,ErrorCallbackProc);
00084 capSetCallbackOnStatus(m_hWndVideo,StatusCallbackProc);
00085 capSetCallbackOnFrame(m_hWndVideo, FrameCallbackProc);
00086
00087
00088
00089
00090 if (!m_TotalVideoDrivers)
00091 {
00092 char szDeviceName[80];
00093 char szDeviceVersion[80];
00094
00095 for (Index = 0; Index < MAX_VFW_DEVICES; Index++)
00096 {
00097 driverDesc = capGetDriverDescription(Index,
00098 szDeviceName,
00099 sizeof(szDeviceName),
00100 szDeviceVersion,
00101 sizeof(szDeviceVersion));
00102 if (!driverDesc) break;
00103 driverConn = capDriverConnect(m_hWndVideo, Index);
00104 if (!driverConn) break;
00105 m_ValidDriverIndex[m_TotalVideoDrivers] = Index;
00106 m_TotalVideoDrivers++;
00107 capDriverDisconnect(m_hWndVideo);
00108 }
00109 }
00110
00111
00112 GetPreviousError(NULL,NULL,TRUE);
00113
00114 Ret = SetDriver(DriverIndex);
00115 }
00116
00117 if (!Ret)
00118 {
00119 if (m_ErrorID == 0)
00120 m_ErrorID = DV_ERR_NONSPECIFIC;
00121
00122 Destroy();
00123 }
00124
00125 return Ret;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135 HWND CVFWCapture::GetCapWindow()
00136 {
00137 return m_hWndVideo;
00138 }
00139
00140
00141
00142
00143 CVFWCapture::CVFWCapture(const CVFWCapture &CopyFrom)
00144 {
00145 m_TransferBitmapInfo = NULL;
00146 m_TransferBitmapInfoSize = 0;
00147
00148 m_hWndVideo = NULL;
00149 m_DriverIndex = -1;
00150 memset(&m_BitmapInfoHeader,0,sizeof(m_BitmapInfoHeader));
00151
00152 Copy(CopyFrom);
00153 }
00154
00155
00156
00157
00158
00159 CVFWCapture &CVFWCapture::operator =(const CVFWCapture &CopyFrom)
00160 {
00161 return Copy(CopyFrom);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 VOID CVFWCapture::Destroy()
00172 {
00173
00174 GetPreviousError(NULL,NULL,TRUE);
00175
00176 if (m_hWndVideo)
00177 {
00178 DisablePreviewVideo();
00179
00180 capCaptureAbort(m_hWndVideo);
00181 capSetCallbackOnError(m_hWndVideo,NULL);
00182 capSetCallbackOnStatus(m_hWndVideo,NULL);
00183 capSetCallbackOnFrame(m_hWndVideo,NULL);
00184
00185 capSetUserData(m_hWndVideo,NULL);
00186 capDriverDisconnect(m_hWndVideo);
00187 m_hWndVideo = NULL;
00188 }
00189
00190 m_TransferBitmapInfo = NULL;
00191 m_TransferBitmapInfoSize = 0;
00192 m_DriverIndex = -1;
00193
00194 memset(&m_BitmapInfoHeader,0,sizeof(m_BitmapInfoHeader));
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 BOOL CVFWCapture::CaptureDIB(PBITMAPINFO *Bitmap,
00210 ULONG BitmapLength,
00211 ULONG *RetBitmapLength)
00212 {
00213 BOOL Ret = FALSE;
00214
00215 DWORD Size = 0;
00216
00217
00218 GetPreviousError(NULL,NULL,TRUE);
00219
00220 if (*Bitmap == NULL)
00221 {
00222 AllocDIBImage(Bitmap,&Size);
00223 BitmapLength = Size;
00224 }
00225 else
00226 {
00227 AllocDIBImage(NULL,&Size);
00228 }
00229
00230 if (*Bitmap && Size > 0)
00231 {
00232 if (RetBitmapLength)
00233 {
00234 *RetBitmapLength = Size;
00235 }
00236
00237
00238
00239 m_TransferBitmapInfo = *Bitmap;
00240 m_TransferBitmapInfoSize = BitmapLength;
00241
00242
00243 Ret = capGrabFrame(m_hWndVideo);
00244
00245 m_TransferBitmapInfo = NULL;
00246 m_TransferBitmapInfoSize = 0;
00247
00248 if (!Ret)
00249 {
00250 if (RetBitmapLength)
00251 {
00252 *RetBitmapLength = (ULONG) 0;
00253 }
00254 }
00255 }
00256
00257 if (!Ret && m_ErrorID == 0)
00258 {
00259 m_ErrorID = DV_ERR_NONSPECIFIC;
00260 }
00261
00262 return Ret;
00263 }
00264
00265
00266
00267
00268
00269 CVFWCapture &CVFWCapture::Copy(const CVFWCapture &CopyFrom)
00270 {
00271 INT DeviceIdx;
00272
00273 if (&CopyFrom != this)
00274 {
00275 Destroy();
00276 strncpy(m_ErrorText, CopyFrom.m_ErrorText, ERROR_SIZE);
00277
00278 if (CopyFrom.m_hWndVideo)
00279 {
00280 CAPDRIVERCAPS DriverCaps;
00281
00282 capDriverGetCaps(CopyFrom.m_hWndVideo,&DriverCaps,sizeof(DriverCaps));
00283
00284
00285 for (DeviceIdx=0;DeviceIdx<MAX_VFW_DEVICES;++DeviceIdx)
00286 {
00287 if (m_ValidDriverIndex[DeviceIdx] == DriverCaps.wDeviceIndex)
00288 {
00289 Initialize(DeviceIdx);
00290 break;
00291 }
00292 }
00293 }
00294 }
00295
00296 return *this;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306 BOOL CVFWCapture::SetDriver(SHORT DriverIndex)
00307 {
00308 BOOL Ret = TRUE;
00309 CAPTUREPARMS CapParms = {0};
00310
00311
00312 GetPreviousError(NULL,NULL,TRUE);
00313
00314 if (DriverIndex >= m_TotalVideoDrivers)
00315 {
00316 Ret = FALSE;
00317 m_ErrorID = DV_ERR_BADDEVICEID;
00318 }
00319
00320 if (m_hWndVideo && m_DriverIndex != DriverIndex && Ret)
00321 {
00322 if (GetParent(m_hWndVideo) != NULL)
00323 capPreview(m_hWndVideo,FALSE);
00324
00325 DisablePreviewVideo();
00326 capCaptureAbort(m_hWndVideo);
00327
00328 Ret = capDriverConnect(m_hWndVideo, m_ValidDriverIndex[DriverIndex]);
00329
00330 if (Ret)
00331 {
00332 capGetVideoFormat(m_hWndVideo,(PBITMAPINFO) &m_BitmapInfoHeader,sizeof(m_BitmapInfoHeader));
00333 capCaptureGetSetup(m_hWndVideo,&CapParms,sizeof(CapParms));
00334 CapParms.fAbortLeftMouse = FALSE;
00335 CapParms.fAbortRightMouse = FALSE;
00336 CapParms.fYield = TRUE;
00337 CapParms.fCaptureAudio = FALSE;
00338 CapParms.wPercentDropForError = 100;
00339 capCaptureSetSetup(m_hWndVideo,&CapParms,sizeof(CapParms));
00340 m_DriverIndex = DriverIndex;
00341
00342 if (GetParent(m_hWndVideo) != NULL)
00343 capPreview(m_hWndVideo,TRUE);
00344 }
00345 }
00346
00347 if (!Ret && m_ErrorID == 0)
00348 {
00349 m_ErrorID = DV_ERR_NONSPECIFIC;
00350 }
00351
00352 return Ret;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 VOID CVFWCapture::GetPreviousError(INT *ErrorID, char ErrorString[], BOOL ResetError)
00365 {
00366 if (ErrorID)
00367 *ErrorID = m_ErrorID;
00368
00369 if (ErrorString)
00370 strncpy(ErrorString, m_ErrorText, ERROR_SIZE);
00371
00372 if (ResetError)
00373 {
00374 m_ErrorID = 0;
00375 m_ErrorText[0] = '\0';
00376 }
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 BOOL CVFWCapture::EnablePreviewVideo(HWND Parent, INT x, INT y, INT PreviewRate)
00390 {
00391
00392 return EnablePreviewVideo(Parent,
00393 x,y,
00394 m_BitmapInfoHeader.biWidth,
00395 m_BitmapInfoHeader.biHeight,
00396 PreviewRate);
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 BOOL CVFWCapture::EnablePreviewVideo(HWND Parent, INT x, INT y, INT Width, INT Height, INT PreviewRate)
00412 {
00413
00414 GetPreviousError(NULL,NULL,TRUE);
00415
00416 SetParent(m_hWndVideo,Parent);
00417 SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);
00418
00419 SetWindowPos(m_hWndVideo,NULL,x,y,
00420 Width,
00421 Height,
00422 SWP_NOZORDER);
00423 ShowWindow(m_hWndVideo,SW_SHOW);
00424 capPreviewRate(m_hWndVideo, PreviewRate);
00425
00426 return capPreview(m_hWndVideo,TRUE);
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 BOOL CVFWCapture::DisablePreviewVideo()
00439 {
00440
00441 GetPreviousError(NULL,NULL,TRUE);
00442
00443 BOOL Ret = capPreview(m_hWndVideo,FALSE);
00444
00445 SetWindowPos(m_hWndVideo,NULL,0,0,0,0,SWP_NOZORDER);
00446 SetParent(m_hWndVideo,NULL);
00447 SetWindowLong(m_hWndVideo,GWL_STYLE,WS_POPUP);
00448
00449 return Ret;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459 BOOL CVFWCapture::DriverGetCaps(CAPDRIVERCAPS *Caps)
00460 {
00461
00462 GetPreviousError(NULL,NULL,TRUE);
00463
00464 return capDriverGetCaps(m_hWndVideo,Caps,sizeof(*Caps));
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 VOID CVFWCapture::CancelCapture()
00476 {
00477 capCaptureAbort(m_hWndVideo);
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 BOOL CVFWCapture::AllocDIBImage(PBITMAPINFO *ppImageData,
00492 ULONG *AllocatedSize)
00493 {
00494 BOOL Ret = TRUE;
00495 DWORD Size = 0;
00496
00497
00498 GetPreviousError(NULL,NULL,TRUE);
00499
00500 Size = CalcBitmapInfoSize(m_BitmapInfoHeader) + CalcBitmapSize(m_BitmapInfoHeader);
00501
00502 if (Size > 0)
00503 {
00504 if (ppImageData)
00505 {
00506 *ppImageData = (BITMAPINFO *) new BYTE[Size];
00507 (**ppImageData).bmiHeader = m_BitmapInfoHeader;
00508 }
00509 }
00510 else
00511 {
00512 Ret = FALSE;
00513 }
00514
00515 if (AllocatedSize)
00516 {
00517 *AllocatedSize = Size;
00518 }
00519
00520 return Ret;
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 BITMAPINFOHEADER CVFWCapture::GetBitmapInfoHeader()
00532 {
00533 return m_BitmapInfoHeader;
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 ULONG CVFWCapture::CalcBitmapSize(const BITMAPINFOHEADER &bmiHeader)
00547
00548 {
00549 ULONG Size = 0;
00550
00551 if (bmiHeader.biSizeImage == 0)
00552 {
00553 Size = bmiHeader.biWidth *
00554 bmiHeader.biHeight *
00555 bmiHeader.biBitCount / 8;
00556 }
00557 else
00558 {
00559 Size = bmiHeader.biSizeImage;
00560 }
00561
00562 return Size;
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 ULONG CVFWCapture::CalcBitmapInfoSize(const BITMAPINFOHEADER &bmiHeader)
00577
00578 {
00579 UINT bmiSize = (bmiHeader.biSize != 0) ? bmiHeader.biSize : sizeof(BITMAPINFOHEADER);
00580 return bmiSize + bmiHeader.biClrUsed * sizeof (RGBQUAD);
00581 }
00582
00583
00584
00585
00586
00587 static LRESULT CALLBACK ErrorCallbackProc(HWND hWnd, int nErrID, LPSTR lpErrorText)
00588 {
00589 CVFWCapture *VFWObj = (CVFWCapture *) capGetUserData(hWnd);
00590
00591 if (VFWObj)
00592 {
00593 VFWObj->m_ErrorID = nErrID;
00594 strncpy(VFWObj->m_ErrorText, lpErrorText, ERROR_SIZE);
00595 }
00596
00597 return (LRESULT) TRUE;
00598 }
00599
00600
00601 static LRESULT CALLBACK StatusCallbackProc(HWND hWnd, int nID, LPCSTR lpsz)
00602
00603 {
00604 CVFWCapture *VFWObj = (CVFWCapture *) capGetUserData(hWnd);
00605
00606 switch(nID)
00607 {
00608 case IDS_CAP_BEGIN:
00609 break;
00610
00611 case IDS_CAP_END:
00612 break;
00613 }
00614
00615 return (LRESULT) TRUE;
00616 }
00617
00618
00619 static LRESULT CALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
00620
00621 {
00622 CVFWCapture *VFWObj = (CVFWCapture *) capGetUserData(hWnd);
00623 LRESULT Ret = TRUE;
00624
00625 if (VFWObj)
00626 {
00627 if (!VFWObj->m_hWndVideo)
00628 {
00629 Ret = FALSE;
00630 }
00631 else
00632 {
00633 if (VFWObj->m_TransferBitmapInfo)
00634 {
00635 ULONG Size;
00636
00637 VFWObj->m_TransferBitmapInfo->bmiHeader = VFWObj->m_BitmapInfoHeader;
00638
00639 Size = min(VFWObj->m_TransferBitmapInfoSize - VFWObj->CalcBitmapInfoSize(VFWObj->m_TransferBitmapInfo->bmiHeader),
00640 lpVHdr->dwBytesUsed);
00641
00642 memcpy(((CHAR *) VFWObj->m_TransferBitmapInfo) + VFWObj->CalcBitmapInfoSize(VFWObj->m_TransferBitmapInfo->bmiHeader),
00643 lpVHdr->lpData,
00644 Size);
00645 }
00646 }
00647 }
00648 else
00649 {
00650 Ret = FALSE;
00651 }
00652
00653 return Ret;
00654 }