VFWCapture.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002     Title............... Video For Windows Class Interface
00003     Programmer.......... Ken Varn
00004     Date Created........ 9/20/2000
00005     Operating System.... Windows NT 4
00006     Compiler............ Microsoft Visual C++ 6
00007     File Type........... C++ Source
00008 
00009     Description:
00010        Class interface to Video For Windows.
00011 
00012        Before using any functions in this class, the Initialize() member
00013        function must be called on the instantiated object.
00014 
00015        When finished using this class, the Destroy() member function should
00016        be used.
00017 
00018     Revision History:
00019        Revision Date.... 8/12/2003
00020        Programmer....... Audrey Mbogho
00021        Comments......... No MFC, no Capture to file, no threads, no dialogs.
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 // Construction/Destruction
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    Function   : Initialize
00060    Arguments  : DriverIndex (input) - Index of VFW driver.
00061    Return     : TRUE Success, FALSE Failure
00062    Description: Inititlizes the object for using VFW interface to capture
00063                 device.
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    // Reset any error conditions.
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       // Construct list of valid video drivers.
00088       // This creates a contiguous virtual driver table.
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       // Reset any error conditions.
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    Function   : GetCapWindow
00131    Arguments  : none
00132    Return     : HWND of VFW window.
00133    Description: Used to retrieve the handle used for VFW image processing.
00134 *******************************************************************************/
00135 HWND CVFWCapture::GetCapWindow()
00136 {
00137    return m_hWndVideo;
00138 }
00139 
00140 //
00141 // Copy Constructor
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 // Copy class using operator=
00158 //
00159 CVFWCapture &CVFWCapture::operator =(const CVFWCapture &CopyFrom)
00160 {
00161    return Copy(CopyFrom);
00162 }
00163 
00164 
00165 /*******************************************************************************
00166    Function   : Destroy
00167    Arguments  : none
00168    Return     : none
00169    Description: Closes up the interface for VFW of capture device.
00170 *******************************************************************************/
00171 VOID CVFWCapture::Destroy()
00172 {
00173    // Reset any error conditions.
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    Function   : CaptureDIB
00201    Arguments  : Bitmap (output) - Pointer to bitmap to receive image.
00202                                   If *Bitmap = NULL, then allocation will
00203                                   be performed automatically.
00204                 BitmapLength (input) - Size of Bitmap if *Bitmap is not NULL.
00205                 RetBitmapLength (output) - Actual size of image.
00206    Return     : TRUE Success, FALSE Failed.
00207    Description: Captures a DIB image from video capture device.
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    // Reset any error conditions.
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       // Must assign pointer to class member variable so that the
00238       // callback function can get to it.
00239       m_TransferBitmapInfo = *Bitmap;
00240       m_TransferBitmapInfoSize = BitmapLength;
00241 
00242       // Start capturing now.  Callback function will capture and signal us when done.
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 // Private function used to copy objects.
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          // Find the device id in the virtual device list.
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    Function   : SetDriver
00302    Arguments  : DriverIndex (input) - Driver to set
00303    Return     : TRUE Success, FALSE Failed.
00304    Description: Sets curretn capture driver.
00305 *******************************************************************************/
00306 BOOL CVFWCapture::SetDriver(SHORT DriverIndex)
00307 {
00308    BOOL Ret = TRUE;
00309    CAPTUREPARMS CapParms = {0};
00310 
00311    // Reset any error conditions.
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    Function   : GetPreviousError
00358    Arguments  : ErrorID (output) - ID of Error
00359                 ErrorString (output) - Description of error.
00360                 ResetError (input) - TRUE Reset error condition.
00361    Return     : none
00362    Description: Gets the last Error ID and Error Description.
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    Function   : EnablePreviewVideo
00382    Arguments  : Parent (input) - Parent window that will display video.
00383                 x (input) - X Location in parent where video will be shown.
00384                 y (input) - Y location in parent where video will be shown.
00385                 PreviewRate (input) - Rate of preview in FPS.
00386    Return     : TRUE Success, FALSE Failed.
00387    Description: Enables preview video mode.
00388 *******************************************************************************/
00389 BOOL CVFWCapture::EnablePreviewVideo(HWND Parent, INT x, INT y, INT PreviewRate)
00390 {
00391    // Reset any error conditions.
00392    return EnablePreviewVideo(Parent,
00393                              x,y,
00394                              m_BitmapInfoHeader.biWidth,
00395                              m_BitmapInfoHeader.biHeight,
00396                              PreviewRate);
00397 }
00398 
00399 
00400 /*******************************************************************************
00401    Function   : EnablePreviewVideo
00402    Arguments  : Parent (input) - Parent window that will display video.
00403                 x (input) - X Location in parent where video will be shown.
00404                 y (input) - Y location in parent where video will be shown.
00405                 Width (input) - Width of preview window.
00406                 Height (input) - Height of preview window.
00407                 PreviewRate (input) - Rate of preview in FPS.
00408    Return     : TRUE Success, FALSE Failed.
00409    Description: Enables preview video mode.
00410 *******************************************************************************/
00411 BOOL CVFWCapture::EnablePreviewVideo(HWND Parent, INT x, INT y, INT Width, INT Height, INT PreviewRate)
00412 {
00413    // Reset any error conditions.
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    Function   : DisablePreviewVideo
00434    Arguments  : none
00435    Return     : TRUE Success, FALSE Failed.
00436    Description: Disables preview video.
00437 *******************************************************************************/
00438 BOOL CVFWCapture::DisablePreviewVideo()
00439 {
00440    // Reset any error conditions.
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    Function   : DriverGetCaps
00455    Arguments  : Caps (output)
00456    Return     : See capDriverGetCaps()
00457    Description: Wrapper function for capDriverGetCaps().
00458 *******************************************************************************/
00459 BOOL CVFWCapture::DriverGetCaps(CAPDRIVERCAPS *Caps)
00460 {
00461    // Reset any error conditions.
00462   GetPreviousError(NULL,NULL,TRUE);
00463 
00464   return capDriverGetCaps(m_hWndVideo,Caps,sizeof(*Caps));
00465 }
00466 
00467 
00468 
00469 /*******************************************************************************
00470    Function   : CancelCapture
00471    Arguments  : none
00472    Return     : none
00473    Description: Cancels current AVI capture.
00474 *******************************************************************************/
00475 VOID CVFWCapture::CancelCapture()
00476 {
00477    capCaptureAbort(m_hWndVideo);
00478 }
00479 
00480 
00481 /*******************************************************************************
00482    Function   : AllocDIBImage
00483    Arguments  : ppImageData (output)     - Return pointer to allocated
00484                                            memory.  If passed as NULL,
00485                                            not used.
00486                 AllocatedSize (output)   - Size of allocated block.
00487                                            If passed as NULL, not used.
00488    Return     : none
00489    Description: Allocates image buffer for DIB capture.
00490 *******************************************************************************/
00491 BOOL CVFWCapture::AllocDIBImage(PBITMAPINFO *ppImageData,
00492                                        ULONG *AllocatedSize)
00493 {
00494    BOOL Ret = TRUE;
00495    DWORD Size = 0;
00496 
00497    // Reset any error conditions.
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    Function   : GetBitmapInfoHeader()
00527    Arguments  : none
00528    Return     : BitmapInfo of capture device.
00529    Description: See return.
00530 *******************************************************************************/
00531 BITMAPINFOHEADER CVFWCapture::GetBitmapInfoHeader()
00532 {
00533    return m_BitmapInfoHeader;
00534 }
00535 
00536 
00537 
00538 /*******************************************************************************
00539    Function   : CalcBitmapSize()
00540    Arguments  : bmiHeader (input) - BITMAPINFOHEADER from which to calculate
00541                                     bitmap size.
00542    Return     : Size of Bitmap.
00543    Description: Calculates the size of a bitmap based upon the contents of
00544                 the BITMAPINFOHEADER passed in.
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    Function   : CalcBitmapInfoSize()
00568    Arguments  : bmiHeader (input) - BITMAPINFOHEADER from which to calculate
00569                                     bitmap size.
00570    Return     : Size of Bitmap Info Header.
00571    Description: Calculates the size of a bitmap info header based upon the
00572                 contents of the BITMAPINFOHEADER passed in.  This function
00573                 can be used to determine the offset from the BITMAPINFOHEADER
00574                 to the actual bitmap data.
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 // Internal callback functions.
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 }

Generated on Wed Nov 29 01:27:41 2006 by  doxygen 1.4.6