/**************************************************************************** video.c Contains video APIs Copyright (c) Microsoft Corporation 1992 - 1995. All rights reserved. ****************************************************************************/ #include #include #include "win32.h" #include "msviddrv.h" #include #include #include "msvideoi.h" #ifdef DEBUG extern void FAR CDECL dprintf(LPSTR, ...); #else #define dprintf ; / ## / #endif #ifdef WIN32 #include #include #endif /***************************************************************************** * Variables * ****************************************************************************/ SZCODE szNull[] = TEXT(""); SZCODE szVideo[] = TEXT("msvideo"); #ifndef WIN32 SZCODE szDrivers[] = "Drivers"; #else STATICDT SZCODE szDrivers[] = DRIVERS_SECTION; #endif SZCODE szDriversDescRegKey[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\drivers.desc"); STATICDT SZCODE szSystemIni[] = TEXT("system.ini"); UINT wTotalVideoDevs; // total video devices extern HINSTANCE ghInstDll; // our module handle // ----------------------------------------------------------- // If the following structure changes, update AVICAP and AVICAP.32 also!!! typedef struct tCapDriverInfo { TCHAR szKeyEnumName[MAX_PATH]; TCHAR szDriverName[MAX_PATH]; TCHAR szDriverDescription[MAX_PATH]; TCHAR szDriverVersion[80]; TCHAR szSoftwareKey[MAX_PATH]; DWORD dnDevNode; // Set if this is a PnP device BOOL fOnlySystemIni; // If the [path]drivername is only in system.ini BOOL fDisabled; // User has disabled driver in the control panel BOOL fActive; // Reserved } CAPDRIVERINFO, FAR *LPCAPDRIVERINFO; #ifndef DEVNODE typedef DWORD DEVNODE; // Devnode. #endif #ifndef LPHKEY typedef HKEY FAR * LPHKEY; #endif // Registry settings of interest to capture drivers SZCODE szRegKey[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\MediaResources\\msvideo"); SZCODE szRegActive[] = TEXT("Active"); SZCODE szRegDisabled[] = TEXT("Disabled"); SZCODE szRegDescription[] = TEXT("Description"); SZCODE szRegDevNode[] = TEXT("DevNode"); SZCODE szRegDriver[] = TEXT("Driver"); SZCODE szRegSoftwareKey[] = TEXT("SOFTWAREKEY"); LPCAPDRIVERINFO aCapDriverList[MAXVIDEODRIVERS]; // Array of all capture drivers /***************************************************************************** * @doc INTERNAL VIDEO * * @api BOOL | videoRegOpenMSVideoKey | This function returns a key * for the msvideo node in the registry. * If the key does not exist it will be created, * and the default entries made. * * @rdesc Returns Key on success, else NULL. ****************************************************************************/ HKEY videoRegOpenMSVideoKey (void) { HKEY hKey = NULL; // Get the key if it already exists if (RegOpenKey ( HKEY_LOCAL_MACHINE, szRegKey, &hKey) != ERROR_SUCCESS) { // Otherwise make a new key if (RegCreateKey ( HKEY_LOCAL_MACHINE, szRegKey, &hKey) == ERROR_SUCCESS) { // Add the default entries to the msvideo node? } } return hKey; } /***************************************************************************** * @doc INTERNAL VIDEO * * @api BOOL | videoRegGetDriverByIndex | This function returns information * about a capture driver by index from the registry. * * @parm DWORD | dwDeviceID | Identifies the video device to open. * The value of

varies from zero to one less * than the number of video capture devices installed in the system. * * @parm LPDEVNODE | lpDevnode | Specifies a far pointer to a buffer * used to return an handle. For non Plug-and-Play devices, * this return value will be NULL. * * @parm LPBOOL | lpEnabled | Specifies a far pointer to a buffer * used to return a flag. If this value is TRUE, the driver is * enabled, if FALSE, the corresponding device is disabled. * * @rdesc Returns TRUE if successful, or FALSE if a driver was not found * with the

index. * * @comm Because the indexes of the MSVIDEO devices in the SYSTEM.INI * file can be non-contiguous, applications should not assume * the indexes range between zero and the number of devices minus * one. * ****************************************************************************/ BOOL videoRegGetKeyByIndex ( HKEY hKeyMSVideoRoot, DWORD dwDeviceID, LPCAPDRIVERINFO lpCapDriverInfo, LPHKEY phKeyChild) { BOOL fOK = FALSE; HKEY hKeyEnum; int i; *phKeyChild = (HKEY) 0; for (i=0; i < MAXVIDEODRIVERS; i++) { if (RegEnumKey ( hKeyMSVideoRoot, i, lpCapDriverInfo-> szKeyEnumName, sizeof(lpCapDriverInfo->szKeyEnumName)/sizeof(TCHAR)) != ERROR_SUCCESS) break; // Found a subkey, does it match the requested index? if (i == (int) dwDeviceID) { if (RegOpenKey ( hKeyMSVideoRoot, lpCapDriverInfo-> szKeyEnumName, &hKeyEnum) == ERROR_SUCCESS) { *phKeyChild = hKeyEnum; // Found it!!! fOK = TRUE; } break; } } // endof all driver indices return fOK; } // Fetches driver info listed in the registry. // Returns: TRUE if the index was valid, FALSE if no driver at that index // Note: Registry entry ordering is random. BOOL videoRegGetDriverByIndex ( DWORD dwDeviceID, LPCAPDRIVERINFO lpCapDriverInfo) { DWORD dwType; DWORD dwSize; BOOL fOK; HKEY hKeyChild; HKEY hKeyMSVideoRoot; // Always start clean since the entry may be recycled _fmemset (lpCapDriverInfo, 0, sizeof (CAPDRIVERINFO)); if (!(hKeyMSVideoRoot = videoRegOpenMSVideoKey())) return FALSE; if (fOK = videoRegGetKeyByIndex ( hKeyMSVideoRoot, dwDeviceID, lpCapDriverInfo, &hKeyChild)) { // Fetch the values: // Active // Disabled // Description // DEVNODE // Driver // SOFTWAREKEY dwSize = sizeof(BOOL); // Active RegQueryValueEx( hKeyChild, szRegActive, NULL, &dwType, (LPBYTE) &lpCapDriverInfo->fActive, &dwSize); dwSize = sizeof(BOOL); // Enabled RegQueryValueEx( hKeyChild, szRegDisabled, NULL, &dwType, (LPBYTE) &lpCapDriverInfo->fDisabled, &dwSize); // Convert this thing to a bool lpCapDriverInfo->fDisabled = (lpCapDriverInfo->fDisabled == '1'); // DriverDescription dwSize = sizeof (lpCapDriverInfo->szDriverDescription) / sizeof (TCHAR); RegQueryValueEx( hKeyChild, szRegDescription, NULL, &dwType, (LPBYTE) lpCapDriverInfo->szDriverDescription, &dwSize); // DEVNODE dwSize = sizeof(DEVNODE); RegQueryValueEx( hKeyChild, szRegDevNode, NULL, &dwType, (LPBYTE) &lpCapDriverInfo->dnDevNode, &dwSize); // DriverName dwSize = sizeof (lpCapDriverInfo->szDriverName) / sizeof (TCHAR); RegQueryValueEx( hKeyChild, szRegDriver, NULL, &dwType, (LPBYTE) lpCapDriverInfo->szDriverName, &dwSize); // SoftwareKey dwSize = sizeof (lpCapDriverInfo->szSoftwareKey) / sizeof (TCHAR); RegQueryValueEx( hKeyChild, szRegSoftwareKey, NULL, &dwType, (LPBYTE) lpCapDriverInfo->szSoftwareKey, &dwSize); RegCloseKey (hKeyChild); } // if the subkey could be opened RegCloseKey (hKeyMSVideoRoot); return fOK; } // Fetches driver info listed in system.ini // Returns: TRUE if the index was valid, FALSE if no driver at that index BOOL videoIniGetDriverByIndex ( DWORD dwDeviceID, LPCAPDRIVERINFO lpCapDriverInfo) { TCHAR szKey[sizeof(szVideo)/sizeof(TCHAR) + 2]; int w = (int) dwDeviceID; BOOL fOK = FALSE; // Always start clean since the entry may be recycled _fmemset (lpCapDriverInfo, 0, sizeof (CAPDRIVERINFO)); lstrcpy(szKey, szVideo); szKey[(sizeof(szVideo)/sizeof(TCHAR)) - 1] = (TCHAR)0; if( w > 0 ) { szKey[(sizeof(szVideo)/sizeof(TCHAR))] = (TCHAR)0; szKey[(sizeof(szVideo)/sizeof(TCHAR))-1] = (TCHAR) TEXT('1' + (w-1) ); // driver ordinal } // Only get its driver name if (GetPrivateProfileString(szDrivers, szKey, szNull, lpCapDriverInfo->szDriverName, sizeof(lpCapDriverInfo->szDriverName)/sizeof(TCHAR), szSystemIni)) { HKEY hKey = NULL; DWORD dwSize, dwType; // Get the key if it already exists // Get Drivers.Desc from its Drivers32 driver name if (ERROR_SUCCESS == RegOpenKey ( HKEY_LOCAL_MACHINE, szDriversDescRegKey, &hKey) != ERROR_SUCCESS) { // DriverDescription dwSize = sizeof (lpCapDriverInfo->szDriverDescription) / sizeof (TCHAR); // [drivers.desc] // DriverName = DriverDescription dwType = REG_SZ; RegQueryValueEx( hKey, lpCapDriverInfo->szDriverName, NULL, &dwType, (LPBYTE) lpCapDriverInfo->szDriverDescription, &dwSize); RegCloseKey (hKey); } else { dprintf("videoIniGetDriverByIndex: RegOpenKey of Drivers.Desc failed !!\n"); } // Found an entry at the requested index // The description and version info will be inserted as // requested by the client app. lpCapDriverInfo-> fOnlySystemIni = TRUE; fOK = TRUE; } return fOK; } DWORD videoFreeDriverList (void) { int i; // Free the driver list for (i = 0; i < MAXVIDEODRIVERS; i++) { if (aCapDriverList[i]) GlobalFreePtr (aCapDriverList[i]); aCapDriverList[i] = NULL; } wTotalVideoDevs = 0; return DV_ERR_OK; } // This function may be called a number of times to create the // current driver array. Since Capscrn assumes it can throw a // driver into system.ini on the fly and have it immediately accessible, // this routine is called on videoGetNumDevs() and when AVICapx.dll // tries to get the driver description and version. // // Drivers in the registry will be the first entries in the list. // // If a driver is listed in the registry AND in system.ini AND // the full path to the drivers match, the system.ini entry will NOT // be in the resulting list. // The variable wTotalVideoDevs is set as a byproduct of this function. // Returns DV_ERR_OK on success, even if no drivers are installed. // DWORD videoCreateDriverList (void) { int i, j, k; // Delete the existing list videoFreeDriverList (); // Allocate an array of pointers to all possible capture drivers for (i = 0; i < MAXVIDEODRIVERS; i++) { aCapDriverList[i] = (LPCAPDRIVERINFO) GlobalAllocPtr ( GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof (CAPDRIVERINFO)); if (aCapDriverList[i] == NULL) { videoFreeDriverList (); return DV_ERR_NOMEM; } } // Walk the list of Registry drivers and get each entry // Get VFW drivers from MediaResource\MsVideo for (i = 0; i < MAXVIDEODRIVERS; i++) { if (videoRegGetDriverByIndex ( (DWORD) i, aCapDriverList[wTotalVideoDevs])) { dprintf("MediaResource: idx %d, DriverName %x, Desc %x\n", wTotalVideoDevs, aCapDriverList[wTotalVideoDevs]->szDriverName, aCapDriverList[wTotalVideoDevs]->szDriverDescription); wTotalVideoDevs++; } else break; } if (wTotalVideoDevs == MAXVIDEODRIVERS) goto AllDone; // Now add the entries listed in system.ini, [Drivers#2] section, (msvideo[0-9] = driver.drv) // to the driver array, ONLY if the entry doesn't exactly match // an existing registry entry. for (j = 0; j < MAXVIDEODRIVERS; j++) { // Get driver name such as *.dll if (videoIniGetDriverByIndex ((DWORD) j, aCapDriverList[wTotalVideoDevs])) { // Found an entry, now see if it is a duplicate of an existing // registry entry for (k = 0; k < (int) wTotalVideoDevs; k++) { if (lstrcmpi (aCapDriverList[k]->szDriverName, aCapDriverList[wTotalVideoDevs]->szDriverName) == 0) { // Found an exact match, so skip it! goto SkipThisEntry; } } if (wTotalVideoDevs >= MAXVIDEODRIVERS - 1) break; dprintf("Drivers32: idx %d, DriverName %x\n", wTotalVideoDevs, aCapDriverList[wTotalVideoDevs]->szDriverName); wTotalVideoDevs++; SkipThisEntry: ; } // If sytem.ini entry was found } // For all system.ini possibilities AllDone: // Decrement wTotalVideoDevs for any entries which are marked as disabled // And remove disabled entries from the list for (i = 0; i < MAXVIDEODRIVERS; ) { if (aCapDriverList[i] && aCapDriverList[i]->fDisabled) { GlobalFreePtr (aCapDriverList[i]); // Shift down the remaining drivers for (j = i; j < MAXVIDEODRIVERS - 1; j++) { aCapDriverList[j] = aCapDriverList[j + 1]; } aCapDriverList[MAXVIDEODRIVERS - 1] = NULL; wTotalVideoDevs--; } else i++; } // Free the unused pointers for (i = wTotalVideoDevs; i < MAXVIDEODRIVERS; i++) { if (aCapDriverList[i]) GlobalFreePtr (aCapDriverList[i]); aCapDriverList[i] = NULL; } // Put PnP drivers first in the list // These are the only entries that have a DevNode for (k = i = 0; i < (int) wTotalVideoDevs; i++) { if (aCapDriverList[i]-> dnDevNode) { LPCAPDRIVERINFO lpCDTemp; if (k != i) { // Swap the entries lpCDTemp = aCapDriverList[k]; aCapDriverList[k] = aCapDriverList[i]; aCapDriverList[i] = lpCDTemp; } k++; // Index of first non-PnP driver } } dprintf("videoCreateDriverList: DeviceList contains %d Video Device(s).\n", wTotalVideoDevs); return DV_ERR_OK; } // ---------------------------------------------------------------------- // // To clean up when a WOW app exits, we need to maintain a list of // open devices. A list of HANDLEINFO structs is hung off g_pHandles. // An item is added to the head of this list in videoOpen, and removed // in videoClose. When a WOW app exits, winmm will call our WOWAppExit // function: for each entry in the list that is owned by the exiting thread, // we call videoClose to close the device and remove the handle entry. // // one of these per open handle typedef struct _HANDLEINFO { HVIDEO hv; HANDLE hThread; struct _HANDLEINFO * pNext; } HANDLEINFO, * PHANDLEINFO; // head of global list of open handles PHANDLEINFO g_pHandles; // critical section that protects global list CRITICAL_SECTION csHandles; // init list and critsec void videoInitHandleList() { g_pHandles = NULL; InitializeCriticalSection(&csHandles); } // finished with critsec list void videoDeleteHandleList() { // don't need critical section as no-one else can be using // it now (we are about to delete the critsec) // empty everything out of the list while (g_pHandles) { videoClose(g_pHandles->hv); } DeleteCriticalSection(&csHandles); } // add a handle to the list void videoAddHandle(HVIDEO hv) { PHANDLEINFO pinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLEINFO)); if (!pinfo) { // couldn't allocate the memory - best thing to do is // forget it - nothing bad will happen except that we // might possibly fail to clean up if this is a wow app and // it exits without closing the capture device. return; } pinfo->hv = hv; pinfo->hThread = GetCurrentTask(); EnterCriticalSection(&csHandles); pinfo->pNext = g_pHandles; g_pHandles = pinfo; LeaveCriticalSection(&csHandles); } // delete an entry from the handle list given the HVIDEO. // caller must close the HVIDEO // should be called before closing (in case the HVIDEO is reassigned after // closing and before removing from the list void videoDelete(HVIDEO hv) { PHANDLEINFO * ppNext; PHANDLEINFO pinfo; EnterCriticalSection(&csHandles); ppNext = &g_pHandles; while (*ppNext) { if ((*ppNext)->hv == hv) { pinfo = *ppNext; *ppNext = pinfo->pNext; HeapFree(GetProcessHeap(), 0, pinfo); break; } else { ppNext = &(*ppNext)->pNext; } } LeaveCriticalSection(&csHandles); } // close any handles open by this task void AppCleanup(HANDLE hTask) { PHANDLEINFO pinfo; EnterCriticalSection(&csHandles); pinfo = g_pHandles; while (pinfo) { if (pinfo->hThread == hTask) { // get the next pointer before videoClose deletes the entry HVIDEO hv = pinfo->hv; pinfo = pinfo->pNext; videoClose(hv); } else { pinfo = pinfo->pNext; } } LeaveCriticalSection(&csHandles); } // ---------------------------------------------------------------------- /***************************************************************************** * @doc INTERNAL VIDEO validation code for VIDEOHDRs ****************************************************************************/ #define IsVideoHeaderPrepared(hVideo, lpwh) ((lpwh)->dwFlags & VHDR_PREPARED) #define MarkVideoHeaderPrepared(hVideo, lpwh) ((lpwh)->dwFlags |= VHDR_PREPARED) #define MarkVideoHeaderUnprepared(hVideo, lpwh) ((lpwh)->dwFlags &=~VHDR_PREPARED) /***************************************************************************** * @doc EXTERNAL VIDEO * * @func DWORD | videoMessage | This function sends messages to a * video device channel. * * @parm HVIDEO | hVideo | Specifies the handle to the video device channel. * * @parm UINT | wMsg | Specifies the message to send. * * @parm DWORD | dwP1 | Specifies the first parameter for the message. * * @parm DWORD | dwP2 | Specifies the second parameter for the message. * * @rdesc Returns the message specific value returned from the driver. * * @comm This function is used for configuration messages such as * and , and * device specific messages. * * @xref * ****************************************************************************/ LRESULT WINAPI videoMessage(HVIDEO hVideo, UINT msg, LPARAM dwP1, LPARAM dwP2) { if (!hVideo) return DV_ERR_INVALHANDLE; return SendDriverMessage ((HDRVR)hVideo, msg, dwP1, dwP2); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoGetNumDevs | This function returns the number of MSVIDEO * devices installed. * * @rdesc Returns the number of MSVIDEO devices listed in the * [drivers] (or [drivers32] for NT) section of the SYSTEM.INI file. * * @comm Because the indexes of the MSVIDEO devices in the SYSTEM.INI * file can be non-contiguous, applications should not assume * the indexes range between zero and the number of devices minus * one. * * @xref ****************************************************************************/ DWORD WINAPI videoGetNumDevs(void) { DWORD dwNumDevs = 0; if(DV_ERR_OK == videoCreateDriverList ()) { dwNumDevs = wTotalVideoDevs; // Save it before reseting to 0 in videoFreeDriverList. videoFreeDriverList (); } return dwNumDevs; } /***************************************************************************** * @doc EXTERNAL VIDEO * * @func DWORD | videoGetErrorText | This function retrieves a * description of the error identified by the error number. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * This might be NULL if the error is not device specific. * * @parm UINT | wError | Specifies the error number. * * @parm LPSTR | lpText | Specifies a far pointer to a buffer used to * return the zero-terminated string corresponding to the error number. * * @parm UINT | wSize | Specifies the length, in bytes, of the buffer * referenced by

. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following error is defined: * @flag DV_ERR_BADERRNUM | Specified error number is out of range. * @flag DV_ERR_SIZEFIELD | The return buffer is not large enough * to handle the error text. * * @comm If the error description is longer than the buffer, * the description is truncated. The returned error string is always * zero-terminated. If

is zero, nothing is copied and zero * is returned. ****************************************************************************/ #ifdef UNICODE // Translate UNICODE response to ansi DWORD WINAPI videoGetErrorTextA(HVIDEO hVideo, UINT wError, LPSTR lpText, UINT wSize) { VIDEO_GETERRORTEXT_PARMS vet; if (IsBadWritePtr (lpText, wSize)) return DV_ERR_PARAM1; lpText[0] = 0; if (((wError >= DV_ERR_BASE) && (wError <= DV_ERR_LASTERROR))) { if (wSize > 1) { if (!LoadStringA(ghInstDll, wError, lpText, wSize)) return DV_ERR_BADERRNUM; else return DV_ERR_OK; } else return DV_ERR_SIZEFIELD; } else if (wError >= DV_ERR_USER_MSG && hVideo) { DWORD dwResult; LPWSTR lpwstr = LocalAlloc(LPTR, wSize*sizeof(WCHAR)); if (NULL == lpwstr) { return(DV_ERR_NOMEM); } vet.dwError = (DWORD) wError; vet.lpText = lpwstr; vet.dwLength = (DWORD) wSize; dwResult = (DWORD) videoMessage (hVideo, DVM_GETERRORTEXT, (DWORD_PTR) (LPVOID) &vet, (DWORD_PTR) NULL); if (DV_ERR_OK == dwResult) { Iwcstombs(lpText, lpwstr, wSize); } LocalFree(lpwstr); return(dwResult); } else return DV_ERR_BADERRNUM; } #endif //UNICODE // // The unicode/Win16 equivalent of the above // DWORD WINAPI videoGetErrorText(HVIDEO hVideo, UINT wError, LPTSTR lpText, UINT wSize) { VIDEO_GETERRORTEXT_PARMS vet; lpText[0] = 0; if (((wError > DV_ERR_BASE) && (wError <= DV_ERR_LASTERROR))) { if (wSize > 1) { if (!LoadString(ghInstDll, wError, lpText, wSize)) return DV_ERR_BADERRNUM; else return DV_ERR_OK; } else return DV_ERR_SIZEFIELD; } else if (wError >= DV_ERR_USER_MSG && hVideo) { vet.dwError = (DWORD) wError; vet.lpText = lpText; vet.dwLength = (DWORD) wSize; return (DWORD) videoMessage (hVideo, DVM_GETERRORTEXT, (DWORD_PTR) (LPVOID) &vet, (DWORD_PTR) NULL); } else return DV_ERR_BADERRNUM; } /***************************************************************************** * @doc EXTERNAL VIDEO * * @func DWORD | videoGetChannelCaps | This function retrieves a * description of the capabilities of a channel. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm LPCHANNEL_CAPS | lpChannelCaps | Specifies a far pointer to a * structure. * * @parm DWORD | dwSize | Specifies the size, in bytes, of the * structure. * * @rdesc Returns zero if the function is successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Specified device handle is invalid. * @flag DV_ERR_UNSUPPORTED | Function is not supported. * * @comm The structure returns the capability * information. For example, capability information might * include whether or not the channel can crop and scale images, * or show overlay. ****************************************************************************/ DWORD WINAPI videoGetChannelCaps(HVIDEO hVideo, LPCHANNEL_CAPS lpChannelCaps, DWORD dwSize) { if (!hVideo) return DV_ERR_INVALHANDLE; if (IsBadWritePtr (lpChannelCaps, sizeof (CHANNEL_CAPS))) return DV_ERR_PARAM1; // _fmemset (lpChannelCaps, 0, sizeof (CHANNEL_CAPS)); lpChannelCaps->dwFlags = 0; lpChannelCaps->dwSrcRectXMod = 0; lpChannelCaps->dwSrcRectYMod = 0; lpChannelCaps->dwSrcRectWidthMod = 0; lpChannelCaps->dwSrcRectHeightMod = 0; lpChannelCaps->dwDstRectXMod = 0; lpChannelCaps->dwDstRectYMod = 0; lpChannelCaps->dwDstRectWidthMod = 0; lpChannelCaps->dwDstRectHeightMod = 0; return (DWORD) videoMessage(hVideo, DVM_GET_CHANNEL_CAPS, (DWORD_PTR) lpChannelCaps, (DWORD_PTR) dwSize); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @func DWORD | videoUpdate | This function directs a channel to * repaint the display. It applies only to VIDEO_EXTERNALOUT channels. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm HWND | hWnd | Specifies the handle of the window to be used * by the channel for image display. * * @parm HDC | hDC | Specifies a handle to a device context. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_UNSUPPORTED | Specified message is unsupported. * @flag DV_ERR_INVALHANDLE | Indicates the device handle specified is invalid. * * @comm This message is normally sent * whenever the client window receives a , , * or message. ****************************************************************************/ DWORD WINAPI videoUpdate (HVIDEO hVideo, HWND hWnd, HDC hDC) { if ((!hVideo) || (!hWnd) || (!hDC) ) return DV_ERR_INVALHANDLE; return (DWORD) videoMessage(hVideo, DVM_UPDATE, (DWORD_PTR) hWnd, (DWORD_PTR) hDC); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoOpen | This function opens a channel on the * specified video device. * * @parm LPHVIDEO | lphvideo | Specifies a far pointer to a buffer * used to return an handle. The video capture driver * uses this location to return * a handle that uniquely identifies the opened video device channel. * Use the returned handle to identify the device channel when * calling other video functions. * * @parm DWORD | dwDeviceID | Identifies the video device to open. * The value of

varies from zero to one less * than the number of video capture devices installed in the system. * * @parm DWORD | dwFlags | Specifies flags for opening the device. * The following flags are defined: * * @flag VIDEO_EXTERNALIN| Specifies the channel is opened * for external input. Typically, external input channels * capture images into a frame buffer. * * @flag VIDEO_EXTERNALOUT| Specifies the channel is opened * for external output. Typically, external output channels * display images stored in a frame buffer on an auxilary monitor * or overlay. * * @flag VIDEO_IN| Specifies the channel is opened * for video input. Video input channels transfer images * from a frame buffer to system memory buffers. * * @flag VIDEO_OUT| Specifies the channel is opened * for video output. Video output channels transfer images * from system memory buffers to a frame buffer. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_BADDEVICEID | Indicates the specified device ID is out of range. * @flag DV_ERR_ALLOCATED | Indicates the specified resource is already allocated. * @flag DV_ERR_NOMEM | Indicates the device is unable to allocate or lock memory. * * @comm * At a minimum, all capture drivers support a VIDEO_EXTERNALIN * and a VIDEO_IN channel. * Use to determine the number of video * devices present in the system. * * @xref ****************************************************************************/ DWORD WINAPI videoOpen (LPHVIDEO lphVideo, DWORD dwDeviceID, DWORD dwFlags) { TCHAR szKey[MAX_PATH]; TCHAR szbuf[MAX_PATH]; UINT w; VIDEO_OPEN_PARMS vop; // Same as IC_OPEN struct!!! DWORD dwVersion = VIDEOAPIVERSION; DWORD dwErr; DWORD dwNumDevs = 0; if (IsBadWritePtr ((LPVOID) lphVideo, sizeof (HVIDEO)) ) return DV_ERR_PARAM1; vop.dwSize = sizeof (VIDEO_OPEN_PARMS); vop.fccType = OPEN_TYPE_VCAP; // "vcap" vop.fccComp = 0L; vop.dwVersion = VIDEOAPIVERSION; vop.dwFlags = dwFlags; // In, Out, External In, External Out vop.dwError = DV_ERR_OK; w = (UINT)dwDeviceID; *lphVideo = NULL; dwNumDevs = videoGetNumDevs(); // No drivers installed if (dwNumDevs == 0) return DV_ERR_BADINSTALL; if (w >= MAXVIDEODRIVERS) return DV_ERR_BADDEVICEID; dwErr = videoCreateDriverList (); if(DV_ERR_OK != dwErr) return dwErr; if(w < dwNumDevs) { lstrcpyn(szKey, aCapDriverList[w]->szDriverName, MAX_PATH); lstrcpyn(szbuf, aCapDriverList[w]->szDriverName, MAX_PATH); videoFreeDriverList (); dprintf("szKey %x, szDrivers %x, szbuf %x\n", szKey, szDrivers, szbuf); #ifdef THIS_IS_ANCIENT_CODE // Removed for VFW1.1 // Only early Alpha 1.0 drivers required this... // Check driver version number by doing a configuration open... // Version 1 used LPARAM = dwFlags // Version 2 uses LPARAM = LPVIDEO_OPEN_PARMS if (hVideoTemp = OpenDriver(szKey, szDrivers, (LPARAM) NULL)) { HVIDEO hVideoTemp; // Version 1 drivers had the added bug of returning // the version from this message, instead of in // lParam1 if (videoMessage (hVideoTemp, DVM_GETVIDEOAPIVER, (LPARAM) (LPVOID) &dwVersion, 0L) == 1) dwVersion = 1; CloseDriver(hVideoTemp, 0L, 0L ); } if (dwVersion == 1) *lphVideo = OpenDriver(szKey, szDrivers, dwFlags); else #endif // THIS_IS_ANCIENT_CODE *lphVideo = (HVIDEO)OpenDriver(szKey, szDrivers, (LPARAM) (LPVOID) &vop); if( ! *lphVideo ) { if (vop.dwError) // if driver returned an error code... return vop.dwError; else { #ifdef WIN32 if (GetFileAttributes(szbuf) == (DWORD) -1) #else OFSTRUCT of; if (OpenFile (szbuf, &of, OF_EXIST) == HFILE_ERROR) #endif return (DV_ERR_BADINSTALL); else return (DV_ERR_NOTDETECTED); } } } else { videoFreeDriverList (); return( DV_ERR_BADINSTALL ); } videoAddHandle(*lphVideo); return DV_ERR_OK; } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoClose | This function closes the specified video * device channel. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * If this function is successful, the handle is invalid * after this call. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Specified device handle is invalid. * @flag DV_ERR_NONSPECIFIC | The driver failed to close the channel. * * @comm If buffers have been sent with and * they haven't been returned to the application, * the close operation fails. You can use to mark all * pending buffers as done. * * @xref ****************************************************************************/ DWORD WINAPI videoClose (HVIDEO hVideo) { if (!hVideo) return DV_ERR_INVALHANDLE; videoDelete(hVideo); return (CloseDriver((HDRVR)hVideo, 0L, 0L ) ? DV_ERR_OK : DV_ERR_NONSPECIFIC); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoConfigure | This function sets or retrieves * the options for a configurable driver. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm UINT | msg | Specifies the option to set or retrieve. The * following options are defined: * * @flag DVM_PALETTE | Indicates a palette is being sent to the driver * or retrieved from the driver. * * @flag DVM_PALETTERGB555 | Indicates an RGB555 palette is being * sent to the driver. * * @flag DVM_FORMAT | Indicates format information is being sent to * the driver or retrieved from the driver. * * @parm DWORD | dwFlags | Specifies flags for configuring or * interrogating the device driver. The following flags are defined: * * @flag VIDEO_CONFIGURE_SET | Indicates values are being sent to the driver. * * @flag VIDEO_CONFIGURE_GET | Indicates values are being obtained from the driver. * * @flag VIDEO_CONFIGURE_QUERY | Determines if the * driver supports the option specified by

. This flag * should be combined with either the VIDEO_CONFIGURE_SET or * VIDEO_CONFIGURE_GET flag. If this flag is * set, the

,

,

, and

* parameters are ignored. * * @flag VIDEO_CONFIGURE_QUERYSIZE | Returns the size, in bytes, * of the configuration option in

. This flag is only valid if * the VIDEO_CONFIGURE_GET flag is also set. * * @flag VIDEO_CONFIGURE_CURRENT | Requests the current value. * This flag is valid only if the VIDEO_CONFIGURE_GET flag is also set. * @flag VIDEO_CONFIGURE_NOMINAL | Requests the nominal value. * This flag is valid only if the VIDEO_CONFIGURE_GET flag is also set. * @flag VIDEO_CONFIGURE_MIN | Requests the minimum value. * This flag is valid only if the VIDEO_CONFIGURE_GET flag is also set. * @flag VIDEO_CONFIGURE_MAX | Get the maximum value. * This flag is valid only if the VIDEO_CONFIGURE_GET flag is also set. * * @parm LPDWORD | lpdwReturn | Points to a DWORD used for returning information * from the driver. If * the VIDEO_CONFIGURE_QUERYSIZE flag is set,

is * filled with the size of the configuration option. * * @parm LPVOID | lpData1 |Specifies a pointer to message specific data. * * @parm DWORD | dwSize1 | Specifies the size, in bytes, of the

* buffer. * * @parm LPVOID | lpData2 | Specifies a pointer to message specific data. * * @parm DWORD | dwSize2 | Specifies the size, in bytes, of the

* buffer. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Specified device handle is invalid. * @flag DV_ERR_NOTSUPPORTED | Function is not supported. * * @xref * ****************************************************************************/ DWORD WINAPI videoConfigure (HVIDEO hVideo, UINT msg, DWORD dwFlags, LPDWORD lpdwReturn, LPVOID lpData1, DWORD dwSize1, LPVOID lpData2, DWORD dwSize2) { VIDEOCONFIGPARMS vcp; if (!hVideo) return DV_ERR_INVALHANDLE; if (lpData1) if (IsBadHugeReadPtr (lpData1, dwSize1)) return DV_ERR_CONFIG1; if (lpData2) if (IsBadHugeReadPtr (lpData2, dwSize2)) return DV_ERR_CONFIG2; if (dwFlags & VIDEO_CONFIGURE_QUERYSIZE) { if (!lpdwReturn) return DV_ERR_NONSPECIFIC; if (IsBadWritePtr (lpdwReturn, sizeof (*lpdwReturn)) ) return DV_ERR_NONSPECIFIC; } vcp.lpdwReturn = lpdwReturn; vcp.lpData1 = lpData1; vcp.dwSize1 = dwSize1; vcp.lpData2 = lpData2; vcp.dwSize2 = dwSize2; return (DWORD) videoMessage(hVideo, msg, dwFlags, (DWORD_PTR)(LPVIDEOCONFIGPARMS)&vcp ); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoConfigureStorage | This function saves or loads * all configurable options for a channel. Options * can be saved and recalled for each application or each application * instance. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm LPSTR | lpstrIdent | Identifies the application or instance. * Use an arbitrary string which uniquely identifies your application * or instance. * * @parm DWORD | dwFlags | Specifies any flags for the function. The following * flags are defined: * @flag VIDEO_CONFIGURE_GET | Requests that the values be loaded. * @flag VIDEO_CONFIGURE_SET | Requests that the values be saved. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Specified device handle is invalid. * @flag DV_ERR_NOTSUPPORTED | Function is not supported. * * @comm The method used by a driver to save configuration options is * device dependent. * * @xref ****************************************************************************/ #ifdef UNICODE DWORD WINAPI videoConfigureStorageA(HVIDEO hVideo, LPSTR lpstrIdent, DWORD dwFlags) { DWORD ret; LPWSTR lpwstr; if (!hVideo) return DV_ERR_INVALHANDLE; // Convert the input string to Unicode // Call the driver, free the Unicode string and return the result ret = strlen(lpstrIdent); lpwstr = LocalAlloc(LPTR, ret*sizeof(WCHAR)); if (!lpwstr) { return(DV_ERR_NOMEM); } Imbstowcs(lpwstr, lpstrIdent, ret); ret = (DWORD) videoMessage(hVideo, DVM_CONFIGURESTORAGE, (DWORD_PTR)lpwstr, dwFlags); LocalFree(lpwstr); return(ret); } #endif // On NT the header file will have ensured that videoConfigureStorage is // defined by a macro to videoConfigureStorageW DWORD WINAPI videoConfigureStorage(HVIDEO hVideo, LPWSTR lpstrIdent, DWORD dwFlags) { if (!hVideo) return DV_ERR_INVALHANDLE; return (DWORD) videoMessage(hVideo, DVM_CONFIGURESTORAGE, (DWORD_PTR)lpstrIdent, dwFlags); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoDialog | This function displays a channel-specific * dialog box used to set configuration parameters. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm HWND | hWndParent | Specifies the parent window handle. * * @parm DWORD | dwFlags | Specifies flags for the dialog box. The * following flag is defined: * @flag VIDEO_DLG_QUERY | If this flag is set, the driver immediately * returns zero if it supplies a dialog box for the channel, * or DV_ERR_NOTSUPPORTED if it does not. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Specified device handle is invalid. * @flag DV_ERR_NOTSUPPORTED | Function is not supported. * * @comm Typically, each dialog box displayed by this * function lets the user select options appropriate for the channel. * For example, a VIDEO_IN channel dialog box lets the user select * the image dimensions and bit depth. * * @xref ****************************************************************************/ DWORD WINAPI videoDialog (HVIDEO hVideo, HWND hWndParent, DWORD dwFlags) { if (!hVideo) return DV_ERR_INVALHANDLE; if ((!hWndParent) || (!IsWindow (hWndParent)) ) return DV_ERR_INVALHANDLE; return (DWORD) videoMessage(hVideo, DVM_DIALOG, (DWORD_PTR)hWndParent, dwFlags); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// /***************************************************************************** * @doc INTERNAL VIDEO * * @api DWORD | videoPrepareHeader | This function prepares the * header and data * by performing a . * * @rdesc Returns zero if the function was successful. Otherwise, it * specifies an error number. ****************************************************************************/ DWORD WINAPI videoPrepareHeader(LPVIDEOHDR lpVideoHdr, DWORD dwSize) { if (!HugePageLock(lpVideoHdr, (DWORD_PTR)sizeof(VIDEOHDR))) return DV_ERR_NOMEM; if (!HugePageLock(lpVideoHdr->lpData, lpVideoHdr->dwBufferLength)) { HugePageUnlock(lpVideoHdr, (DWORD_PTR)sizeof(VIDEOHDR)); return DV_ERR_NOMEM; } lpVideoHdr->dwFlags |= VHDR_PREPARED; return DV_ERR_OK; } /***************************************************************************** * @doc INTERNAL VIDEO * * @api DWORD | videoUnprepareHeader | This function unprepares the header and * data if the driver returns DV_ERR_NOTSUPPORTED. * * @rdesc Currently always returns DV_ERR_OK. ****************************************************************************/ DWORD WINAPI videoUnprepareHeader(LPVIDEOHDR lpVideoHdr, DWORD dwSize) { HugePageUnlock(lpVideoHdr->lpData, lpVideoHdr->dwBufferLength); HugePageUnlock(lpVideoHdr, (DWORD_PTR)sizeof(VIDEOHDR)); lpVideoHdr->dwFlags &= ~VHDR_PREPARED; return DV_ERR_OK; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamAllocHdrAndBuffer | This function is used to allow * drivers to optionally allocate video buffers. Normally, the client * application is responsible for allocating buffer memory, but devices * which have on-board memory may optionally allocate headers and buffers * using this function. Generally, this will avoid an additional data copy, * resulting in faster capture rates. * * @parm HVIDEO | hVideo | Specifies a handle to the video * device channel. * * @parm LPVIDEOHDR FAR * | plpvideoHdr | Specifies a pointer to the address of a * structure. The driver saves the buffer address in this * location, or NULL if it cannot allocate a buffer. * * @parm DWORD | dwSize | Specifies the size of the structure * and associated video buffer in bytes. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Indicates the specified device handle is invalid. * @flag DV_ERR_NOMEM | Indicates the device is unable to allocate or lock memory. * @flag DV_ERR_NOTSUPPORTED | Indicates the driver does not have on-board memory. * * @comm If the driver * allocates buffers via this method, the and * functions should be used. * * The buffer allocated must be accessible for DMA by the host. * * @xref ****************************************************************************/ DWORD WINAPI videoStreamAllocHdrAndBuffer(HVIDEO hVideo, LPVIDEOHDR FAR * plpvideoHdr, DWORD dwSize) { #ifdef OBSOLETE DWORD wRet; if (!hVideo) return DV_ERR_INVALHANDLE; if (IsBadWritePtr (plpvideoHdr, sizeof (VIDEOHDR *)) ) return DV_ERR_PARAM1; *plpvideoHdr = NULL; // Init to NULL ptr wRet = (DWORD)videoMessage((HVIDEO)hVideo, DVM_STREAM_ALLOCHDRANDBUFFER, (DWORD_PTR)plpvideoHdr, (DWORD_PTR)dwSize); if (*plpvideoHdr == NULL || IsBadHugeWritePtr (*plpvideoHdr, dwSize)) { DebugErr(DBF_WARNING,"videoStreamAllocHdrAndBuffer: Allocation failed."); *plpvideoHdr = NULL; return wRet; } if (IsVideoHeaderPrepared(HVIDEO, *plpvideoHdr)) { DebugErr(DBF_WARNING,"videoStreamAllocHdrAndBuffer: header is already prepared."); return DV_ERR_OK; } (*plpvideoHdr)->dwFlags = 0; if (wRet == DV_ERR_OK) MarkVideoHeaderPrepared(hVideo, *plpvideoHdr); return wRet; #endif return DV_ERR_NOTSUPPORTED; } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamFreeHdrAndBuffer | This function is used to free * buffers allocated by the driver using the * function. * * @parm HVIDEO | hVideo | Specifies a handle to the video * device channel. * * @parm LPVIDEOHDR | lpvideoHdr | Specifies a pointer to the * structure and associated buffer to be freed. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Indicates the specified device handle is invalid. * @flag DV_ERR_NOTSUPPORTED | Indicates the driver does not have on-board memory. * * @comm If the driver * allocates buffers via this method, the and * functions should be used. * * @xref ****************************************************************************/ DWORD WINAPI videoStreamFreeHdrAndBuffer(HVIDEO hVideo, LPVIDEOHDR lpvideoHdr) { #ifdef OBSOLETE DWORD wRet; if (!hVideo) return DV_ERR_INVALHANDLE; if (IsBadWritePtr (lpvideoHdr, sizeof (VIDEOHDR)) ) return DV_ERR_PARAM1; if (lpvideoHdr->dwFlags & VHDR_INQUEUE) { DebugErr(DBF_WARNING, "videoStreamFreeHdrAndBuffer: buffer still in queue."); return DV_ERR_STILLPLAYING; } if (!IsVideoHeaderPrepared(hVideo, lpvideoHdr)) { DebugErr(DBF_WARNING,"videoStreamFreeHdrAndBuffer: header is not prepared."); } wRet = (DWORD)videoMessage((HVIDEO)hVideo, DVM_STREAM_FREEHDRANDBUFFER, (DWORD_PTR)lpvideoHdr, (DWORD_PTR)0); if (wRet != DV_ERR_OK) { DebugErr(DBF_WARNING,"videoStreamFreeHdrAndBuffer: Error freeing buffer."); } return wRet; #endif return DV_ERR_NOTSUPPORTED; } DWORD WINAPI videoStreamAllocBuffer(HVIDEO hVideo, LPVOID FAR * plBuffer, DWORD dwSize) { DWORD wRet; if (!hVideo) return DV_ERR_INVALHANDLE; // as this code is internal to our dll we do not need to check access rights // if (IsBadWritePtr (plpvideoHdr, sizeof (VIDEOHDR *)) ) // return DV_ERR_PARAM1; *plBuffer = NULL; // Init to NULL ptr wRet = (DWORD)videoMessage((HVIDEO)hVideo, DVM_STREAM_ALLOCBUFFER, (DWORD_PTR)plBuffer, (DWORD_PTR)dwSize); if (*plBuffer == NULL) { DebugErr(DBF_WARNING,"videoStreamAllocBuffer: Allocation failed."); dprintf("videoStreamAllocBuffer: Allocation failed, wRet=0x%d",wRet); *plBuffer = NULL; return wRet; } return wRet; } DWORD WINAPI videoStreamFreeBuffer(HVIDEO hVideo, LPVOID lpBuffer) { DWORD wRet; if (!hVideo) return DV_ERR_INVALHANDLE; wRet = (DWORD)videoMessage((HVIDEO)hVideo, DVM_STREAM_FREEBUFFER, (DWORD_PTR)lpBuffer, (DWORD_PTR)0); if (wRet != DV_ERR_OK) { DebugErr(DBF_WARNING,"videoStreamFreeBuffer: Error freeing buffer."); dprintf("videoStreamFreeBuffer: error %d freeing buffer", wRet); } return wRet; } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamPrepareHeader | This function prepares a buffer * for video streaming. * * @parm HVIDEO | hVideo | Specifies a handle to the video * device channel. * * @parm LPVIDEOHDR | lpvideoHdr | Specifies a pointer to a * structure identifying the buffer to be prepared. * * @parm DWORD | dwSize | Specifies the size of the structure in bytes. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Indicates the specified device handle is invalid. * @flag DV_ERR_NOMEM | Indicates the device is unable to allocate or lock memory. * * @comm Use this function after or * after to prepare the data buffers * for streaming data. * * The data structure and the data block pointed to by its * member must be allocated with using the * GMEM_MOVEABLE and GMEM_SHARE flags, and locked with . * Preparing a header that has already been prepared will have no effect * and the function will return zero. Typically, this function is used * to ensure that the buffer will be available for use at interrupt time. * * @xref ****************************************************************************/ DWORD WINAPI videoStreamPrepareHeader(HVIDEO hVideo, LPVIDEOHDR lpvideoHdr, DWORD dwSize) { DWORD wRet; if (!hVideo) return DV_ERR_INVALHANDLE; if (IsBadWritePtr (lpvideoHdr, sizeof (VIDEOHDR)) ) return DV_ERR_PARAM1; if (IsVideoHeaderPrepared(HVIDEO, lpvideoHdr)) { DebugErr(DBF_WARNING,"videoStreamPrepareHeader: header is already prepared."); return DV_ERR_OK; } lpvideoHdr->dwFlags = 0; wRet = (DWORD)videoMessage((HVIDEO)hVideo, DVM_STREAM_PREPAREHEADER, (DWORD_PTR)lpvideoHdr, (DWORD_PTR)dwSize); if (wRet == DV_ERR_NOTSUPPORTED) wRet = videoPrepareHeader(lpvideoHdr, dwSize); if (wRet == DV_ERR_OK) MarkVideoHeaderPrepared(hVideo, lpvideoHdr); return wRet; } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamUnprepareHeader | This function clears the * preparation performed by . * * @parm HVIDEO | hVideo | Specifies a handle to the video * device channel. * * @parm LPVIDEOHDR | lpvideoHdr | Specifies a pointer to a * structure identifying the data buffer to be unprepared. * * @parm DWORD | dwSize | Specifies the size of the structure in bytes. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Indicates the device handle specified is invalid. * @flag DV_ERR_STILLPLAYING | Indicates the structure identified by

* is still in the queue. * * @comm This function is the complementary function to . * You must call this function before freeing the data buffer with . * After passing a buffer to the device driver with , you * must wait until the driver is finished with the buffer before calling * . Unpreparing a buffer that has not been * prepared or has been already unprepared has no effect, * and the function returns zero. * * @xref ****************************************************************************/ DWORD WINAPI videoStreamUnprepareHeader(HVIDEO hVideo, LPVIDEOHDR lpvideoHdr, DWORD dwSize) { DWORD wRet; if (!hVideo) return DV_ERR_INVALHANDLE; if (IsBadWritePtr (lpvideoHdr, sizeof (VIDEOHDR)) ) return DV_ERR_PARAM1; if (lpvideoHdr->dwFlags & VHDR_INQUEUE) { DebugErr(DBF_WARNING, "videoStreamUnprepareHeader: buffer still in queue."); return DV_ERR_STILLPLAYING; } if (!IsVideoHeaderPrepared(hVideo, lpvideoHdr)) { DebugErr(DBF_WARNING,"videoStreamUnprepareHeader: header is not prepared."); return DV_ERR_OK; } wRet = (DWORD)videoMessage((HVIDEO)hVideo, DVM_STREAM_UNPREPAREHEADER, (DWORD_PTR)lpvideoHdr, (DWORD_PTR)dwSize); if (wRet == DV_ERR_NOTSUPPORTED) wRet = videoUnprepareHeader(lpvideoHdr, dwSize); if (wRet == DV_ERR_OK) MarkVideoHeaderUnprepared(hVideo, lpvideoHdr); return wRet; } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamAddBuffer | This function sends a buffer to a * video-capture device. After the buffer is filled by the device, * the device sends it back to the application. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm LPVIDEOHDR | lpvideoHdr | Specifies a far pointer to a * structure that identifies the buffer. * * @parm DWORD | dwSize | Specifies the size of the structure in bytes. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Indicates the device handle specified is invalid. * @flag DV_ERR_UNPREPARED | Indicates the

structure hasn't been prepared. * @flag DV_ERR_STILLPLAYING | Indicates a buffer is still in the queue. * @flag DV_ERR_PARAM1 | The

parameter is invalid or * the member of the * structure is not set to the proper value. * * @comm The data buffer must be prepared with * before it is passed to . The data * structure and the data buffer referenced by its * member must be allocated with using the GMEM_MOVEABLE * and GMEM_SHARE flags, and locked with . Set the * member to the size of the header. * * @xref ****************************************************************************/ DWORD WINAPI videoStreamAddBuffer(HVIDEO hVideo, LPVIDEOHDR lpvideoHdr, DWORD dwSize) { if (!hVideo) return DV_ERR_INVALHANDLE; if (IsBadWritePtr (lpvideoHdr, sizeof (VIDEOHDR)) ) return DV_ERR_PARAM1; if (!IsVideoHeaderPrepared(hVideo, lpvideoHdr)) { DebugErr(DBF_WARNING, "videoStreamAddBuffer: buffer not prepared."); return DV_ERR_UNPREPARED; } if (lpvideoHdr->dwFlags & VHDR_INQUEUE) { DebugErr(DBF_WARNING, "videoStreamAddBuffer: buffer already in queue."); return DV_ERR_STILLPLAYING; } return (DWORD)videoMessage((HVIDEO)hVideo, DVM_STREAM_ADDBUFFER, (DWORD_PTR)lpvideoHdr, (DWORD_PTR)dwSize); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamStop | This function stops streaming on a video channel. * * @parm HVIDEO | hVideo | Specifies a handle to the video * device channel. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following error is defined: * @flag DV_ERR_INVALHANDLE | Indicates the specified device handle is invalid. * * @flag DV_ERR_NOTSUPPORTED | Indicates the device does not support this * function. * @comm If there are any buffers in the queue, the current buffer will be * marked as done (the member in * the header will contain the actual length of data), but any * empty buffers in the queue will remain there. Calling this * function when the channel is not started has no effect, and the * function returns zero. * * @xref ****************************************************************************/ DWORD WINAPI videoStreamStop(HVIDEO hVideo) { if (!hVideo) return DV_ERR_INVALHANDLE; return (DWORD) videoMessage((HVIDEO)hVideo, DVM_STREAM_STOP, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamReset | This function stops streaming * on the specified video device channel and resets the current position * to zero. All pending buffers are marked as done and * are returned to the application. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * * @flag DV_ERR_INVALHANDLE | Indicates the device handle specified is invalid. * * @flag DV_ERR_NOTSUPPORTED | Indicates the device does not support this * function. * * @xref /****************************************************************************/ DWORD WINAPI videoStreamReset(HVIDEO hVideo) { if (!hVideo) return DV_ERR_INVALHANDLE; return (DWORD) videoMessage((HVIDEO)hVideo, DVM_STREAM_RESET, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamGetPosition | This function retrieves the current * position of the specified video device channel. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm LPMMTIME | lpInfo | Specifies a far pointer to an * structure. * * @parm DWORD | dwSize | Specifies the size of the structure in bytes. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * * @flag DV_ERR_INVALHANDLE | Indicates the specified device handle is invalid. * * @comm Before using , set the * member of the structure to indicate * the time format desired. After * returns, check the * member to determine if the your time format is supported. If * not, specifies an alternate format. * Video capture drivers typically provide the millisecond time * format. * * The position is set to zero when streaming is started with * . ****************************************************************************/ DWORD WINAPI videoStreamGetPosition(HVIDEO hVideo, LPMMTIME lpInfo, DWORD dwSize) { if (!hVideo) return DV_ERR_INVALHANDLE; if (IsBadWritePtr (lpInfo, sizeof (MMTIME)) ) return DV_ERR_PARAM1; return (DWORD) videoMessage(hVideo, DVM_STREAM_GETPOSITION, (DWORD_PTR)lpInfo, (DWORD_PTR)dwSize); } // ============================================ /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamInit | This function initializes a video * device channel for streaming. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm DWORD | dwMicroSecPerFrame | Specifies the number of microseconds * between frames. * * @parm DWORD | dwCallback | Specifies the address of a callback * function or a handle to a window called during video * streaming. The callback function or window processes * messages related to the progress of streaming. * * @parm DWORD | dwCallbackInstance | Specifies user * instance data passed to the callback function. This parameter is not * used with window callbacks. * * @parm DWORD | dwFlags | Specifies flags for opening the device channel. * The following flags are defined: * @flag CALLBACK_WINDOW | If this flag is specified,

is * a window handle. * @flag CALLBACK_FUNCTION | If this flag is specified,

is * a callback procedure address. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_BADDEVICEID | Indicates the device ID specified in *

is not valid. * @flag DV_ERR_ALLOCATED | Indicates the resource specified is already allocated. * @flag DV_ERR_NOMEM | Indicates the device is unable to allocate or lock memory. * * @comm If a window or function is chosen to receive callback information, the following * messages are sent to it to indicate the * progress of video input: * * is sent at the time of * * is sent at the time of * * is sent when a buffer of image data is available * * is sent when an error occurs * * Callback functions must reside in a DLL. * You do not have to use to get * a procedure-instance address for the callback function. * * @cb void CALLBACK | videoFunc | is a placeholder for an * application-supplied function name. The actual name must be exported by * including it in an EXPORTS statement in the DLL's module-definition file. * This is used only when a callback function is specified in * . * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel * associated with the callback. * * @parm DWORD | wMsg | Specifies the messages. Messages indicate * errors and when image data is available. For information on * these messages, see . * * @parm DWORD | dwInstance | Specifies the user instance * data specified with . * * @parm DWORD | dwParam1 | Specifies a parameter for the message. * * @parm DWORD | dwParam2 | Specifies a parameter for the message. * * @comm Because the callback is accessed at interrupt time, it must reside * in a DLL and its code segment must be specified as FIXED in the * module-definition file for the DLL. Any data the callback accesses * must be in a FIXED data segment as well. The callback may not make any * system calls except for , , * , , , * , , and . * * @xref ****************************************************************************/ DWORD WINAPI videoStreamInit(HVIDEO hVideo, DWORD dwMicroSecPerFrame, DWORD_PTR dwCallback, DWORD_PTR dwCallbackInst, DWORD dwFlags) { VIDEO_STREAM_INIT_PARMS vsip; if (!hVideo) return DV_ERR_INVALHANDLE; if (dwCallback && ((dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION) ) { if (IsBadCodePtr ((FARPROC) dwCallback) ) return DV_ERR_PARAM2; if (!dwCallbackInst) return DV_ERR_PARAM2; } if (dwCallback && ((dwFlags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW) ) { if (!IsWindow((HWND)(dwCallback)) ) return DV_ERR_PARAM2; } vsip.dwMicroSecPerFrame = dwMicroSecPerFrame; vsip.dwCallback = dwCallback; vsip.dwCallbackInst = dwCallbackInst; vsip.dwFlags = dwFlags; vsip.hVideo = (DWORD_PTR)hVideo; return (DWORD) videoMessage(hVideo, DVM_STREAM_INIT, (DWORD_PTR) (LPVIDEO_STREAM_INIT_PARMS) &vsip, (DWORD_PTR) sizeof (VIDEO_STREAM_INIT_PARMS)); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamFini | This function terminates streaming * from the specified device channel. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Indicates the device handle specified is invalid. * @flag DV_ERR_STILLPLAYING | Indicates there are still buffers in the queue. * * @comm If there are buffers that have been sent with * that haven't been returned to the application, * this operation will fail. Use to return all * pending buffers. * * Each call to must be matched with a call to * . * * For VIDEO_EXTERNALIN channels, this function is used to * halt capturing of data to the frame buffer. * * For VIDEO_EXTERNALOUT channels supporting overlay, * this function is used to disable the overlay. * * @xref ****************************************************************************/ DWORD WINAPI videoStreamFini(HVIDEO hVideo) { if (!hVideo) return DV_ERR_INVALHANDLE; return (DWORD) videoMessage(hVideo, DVM_STREAM_FINI, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamStart | This function starts streaming on the * specified video device channel. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Indicates the device handle specified is invalid. * * @flag DV_ERR_NOTSUPPORTED | Indicates the device does not support this * function. * * @xref /****************************************************************************/ DWORD WINAPI videoStreamStart(HVIDEO hVideo) { if (!hVideo) return DV_ERR_INVALHANDLE; return (DWORD) videoMessage(hVideo, DVM_STREAM_START, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoStreamGetError | This function returns the error * most recently encountered. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * * @parm LPDWORD | lpdwErrorID | Specifies a far pointer to the * used to return the error ID. * * @parm LPDWORD | lpdwErrorValue | Specifies a far pointer to the * used to return the number of frames skipped. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following error is defined: * @flag DV_ERR_INVALHANDLE | Indicates the device handle specified is invalid. * * @comm While streaming video data, a capture * driver can fill buffers faster than the client application can * save the buffers to disk. In this case, the * DV_ERR_NO_BUFFERS error is returned in

* and

contains a count of the number of * frames missed. After * receiving this message and returning the error status, a driver * should reset its internal error flag to DV_ERR_OK and * the count of missed frames to zero. * * Applications should send this message frequently during capture * since some drivers which do not have access to interrupts use * this message to trigger buffer processing. * * @xref /****************************************************************************/ DWORD WINAPI videoStreamGetError(HVIDEO hVideo, LPDWORD lpdwError, LPDWORD lpdwFramesSkipped) { if (!hVideo) return DV_ERR_INVALHANDLE; if (IsBadWritePtr (lpdwError, sizeof (DWORD)) ) return DV_ERR_PARAM1; if (IsBadWritePtr (lpdwFramesSkipped, sizeof (DWORD)) ) return DV_ERR_PARAM2; return (DWORD) videoMessage(hVideo, DVM_STREAM_GETERROR, (DWORD_PTR) lpdwError, (DWORD_PTR) lpdwFramesSkipped); } /***************************************************************************** * @doc EXTERNAL VIDEO * * @api DWORD | videoFrame | This function transfers a single frame * to or from a video device channel. * * @parm HVIDEO | hVideo | Specifies a handle to the video device channel. * The channel must be of type VIDEO_IN or VIDEO_OUT. * * @parm LPVIDEOHDR | lpVHdr | Specifies a far pointer to an * structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. The following errors are defined: * @flag DV_ERR_INVALHANDLE | Specified device handle is invalid. * @flag DV_ERR_PARAM1 | The

parameter is invalid or * the member of the * structure is not set to the proper value. * * @comm Use this function with a VIDEO_IN channel to transfer a single * image from the frame buffer. * Use this function with a VIDEO_OUT channel to transfer a single * image to the frame buffer. * * @xref /****************************************************************************/ DWORD WINAPI videoFrame (HVIDEO hVideo, LPVIDEOHDR lpVHdr) { if (!hVideo) return DV_ERR_INVALHANDLE; if (!lpVHdr) return DV_ERR_PARAM1; if (IsBadWritePtr (lpVHdr, sizeof (VIDEOHDR)) ) return DV_ERR_PARAM1; return (DWORD) videoMessage(hVideo, DVM_FRAME, (DWORD_PTR) lpVHdr, sizeof(VIDEOHDR)); } /************************************************************************** * @doc INTERNAL VIDEO * * @api void | videoCleanup | clean up video stuff * called in MSVIDEOs WEP() * **************************************************************************/ void FAR PASCAL videoCleanup(HTASK hTask) { } // // Assist with unicode conversions // int Iwcstombs(LPSTR lpstr, LPCWSTR lpwstr, int len) { return WideCharToMultiByte(GetACP(), 0, lpwstr, -1, lpstr, len, NULL, NULL); } int Imbstowcs(LPWSTR lpwstr, LPCSTR lpstr, int len) { return MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, lpstr, -1, lpwstr, len); }