windows-nt/Source/XPSP1/NT/multimedia/media/avi/video/video.c

2021 lines
68 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/****************************************************************************
video.c
Contains video APIs
Copyright (c) Microsoft Corporation 1992. All rights reserved
****************************************************************************/
#include <windows.h>
#include <mmsystem.h>
#include <win32.h>
#include <winerror.h>
#include "msviddrv.h"
#include "ivideo32.h" // includes msvideo.h
#include "msvideoi.h"
#ifdef _WIN32
#include "profile.h"
#include <mmddk.h>
#include <stdlib.h>
#include <winver.h>
#else
#include <ver.h>
#endif
#include "debug.h"
#ifndef DEVNODE
typedef DWORD DEVNODE; // Devnode.
#endif
#ifndef LPHKEY
typedef HKEY FAR * LPHKEY;
#endif
#if defined _WIN32 && !defined UNICODE
HDRVR WINAPI OpenDriverA( LPCSTR szDriverName, LPCSTR szSectionName, LPARAM lParam2);
#endif
/*****************************************************************************
* Variables
*
****************************************************************************/
#ifdef WIN16 // All of this is currently only used in 16 bit land
SZCODE szVideo[] = TEXT("msvideo");
#ifndef UNICODE
// 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");
#endif
#ifndef _WIN32
SZCODE szDrivers[] = "Drivers";
#else
STATICDT SZCODE szDrivers[] = DRIVERS_SECTION;
#endif
STATICDT SZCODE szSystemIni[] = TEXT("system.ini");
static SZCODE szNull[] = TEXT("");
UINT wTotalVideoDevs; // total video devices
LPCAPDRIVERINFO aCapDriverList[MAXVIDEODRIVERS]; // Array of all capture drivers
/*****************************************************************************
* @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 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 <p dwDeviceID> 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 <t DEVNODE> 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 <t BOOL> 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 <p dwDeviceID> 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
}
if (GetPrivateProfileString(szDrivers, szKey, szNull,
lpCapDriverInfo->szDriverName,
sizeof(lpCapDriverInfo->szDriverName)/sizeof(TCHAR),
szSystemIni)) {
// 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;
}
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;
wTotalVideoDevs = 0;
// 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)
return DV_ERR_NOMEM;
}
// Walk the list of Registry drivers and get each entry
for (i = 0; i < MAXVIDEODRIVERS; i++) {
if (videoRegGetDriverByIndex (
(DWORD) i, aCapDriverList[wTotalVideoDevs])) {
wTotalVideoDevs++;
}
else
break;
}
if (wTotalVideoDevs == MAXVIDEODRIVERS)
goto AllDone;
// Now add the entries listed in system.ini, (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++) {
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;
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
}
}
return DV_ERR_OK;
}
typedef struct tagVS_VERSION
{
WORD wTotLen;
WORD wValLen;
char szSig[16];
VS_FIXEDFILEINFO vffInfo;
} VS_VERSION;
typedef struct tagLANGANDCP
{
WORD wLanguage;
WORD wCodePage;
} LANGANDCP;
// Extracts the Description string and version info from a driver.
// Drivers listed in the registry will typically already include a
// description string, but not version info.
// Drivers listed in system.ini will fetch both.
//
// Returns DV_ERR_OK on success, even if no version info was available.
//
DWORD WINAPI videoGetDriverDescAndVer (
LPCAPDRIVERINFO lpCapDriverInfo)
{
LPSTR lpVersion;
WORD wVersionLen;
BOOL bRetCode;
DWORD dwVerInfoSize;
DWORD dwVerHnd;
TCHAR szBuf[MAX_PATH];
BOOL fGetDesc;
BOOL fGetVersion;
// Only get the description if not already supplied by the registry
fGetDesc = (lpCapDriverInfo->szDriverDescription[0] == '\0');
fGetVersion = (lpCapDriverInfo->szDriverVersion[0] == '\0');
if (fGetDesc)
lpCapDriverInfo->szDriverDescription[0] = '\0';
if (fGetVersion)
lpCapDriverInfo->szDriverVersion [0] = '\0';
// Copy in the driver name initially, just in case the driver
// has omitted a description field.
if (fGetDesc)
lstrcpyn (lpCapDriverInfo->szDriverDescription,
lpCapDriverInfo->szDriverName,
sizeof (lpCapDriverInfo->szDriverDescription) / sizeof (TCHAR));
// You must find the size first before getting any file info
dwVerInfoSize =
GetFileVersionInfoSize(lpCapDriverInfo->szDriverName, &dwVerHnd);
if (dwVerInfoSize) {
LPSTR lpstrVffInfo; // Pointer to block to hold info
// Get a block big enough to hold version info
if (lpstrVffInfo = GlobalAllocPtr(GMEM_MOVEABLE, dwVerInfoSize)) {
// Get the File Version first
if(GetFileVersionInfo(lpCapDriverInfo->szDriverName, 0L,
dwVerInfoSize, lpstrVffInfo)) {
VS_VERSION FAR *pVerInfo = (VS_VERSION FAR *) lpstrVffInfo;
// fill in the file version
wsprintf(szBuf,
"Version: %d.%d.%d.%d",
HIWORD(pVerInfo->vffInfo.dwFileVersionMS),
LOWORD(pVerInfo->vffInfo.dwFileVersionMS),
HIWORD(pVerInfo->vffInfo.dwFileVersionLS),
LOWORD(pVerInfo->vffInfo.dwFileVersionLS));
if (fGetVersion)
lstrcpyn (lpCapDriverInfo->szDriverVersion, szBuf,
sizeof (lpCapDriverInfo->szDriverVersion) / sizeof(TCHAR));
}
// Now try to get the FileDescription
// First try this for the "Translation" entry, and then
// try the American english translation.
// Keep track of the string length for easy updating.
// 040904E4 represents the language ID and the four
// least significant digits represent the codepage for
// which the data is formatted. The language ID is
// composed of two parts: the low ten bits represent
// the major language and the high six bits represent
// the sub language.
lstrcpy(szBuf, "\\StringFileInfo\\040904E4\\FileDescription");
wVersionLen = 0;
lpVersion = NULL;
// Look for the corresponding string.
bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
(LPSTR)szBuf,
(void FAR* FAR*)&lpVersion,
(UINT FAR *) &wVersionLen);
if (fGetDesc && bRetCode && wVersionLen && lpVersion)
lstrcpyn (lpCapDriverInfo->szDriverDescription, lpVersion,
sizeof (lpCapDriverInfo->szDriverDescription) / sizeof(TCHAR));
// Let go of the memory
GlobalFreePtr(lpstrVffInfo);
}
else
return DV_ERR_NOMEM;
}
return DV_ERR_OK;
}
// Called by AVICap and AVICap32 to get driver strings
// Returns:
// DV_ERR_OK on success
// DV_ERR_BADINSTALL if the driver at the specified index is not found
DWORD WINAPI videoCapDriverDescAndVer (
DWORD dwDeviceID,
LPTSTR lpszDesc, UINT cbDesc,
LPTSTR lpszVer, UINT cbVer)
{
DWORD dwR = DV_ERR_OK;
if (lpszDesc && IsBadWritePtr (lpszDesc, cbDesc))
return DV_ERR_NONSPECIFIC;
else if (lpszDesc)
*lpszDesc = '\0';
if (lpszVer && IsBadWritePtr (lpszVer, cbVer))
return DV_ERR_NONSPECIFIC;
else if (lpszVer)
*lpszVer = '\0';
if (!wTotalVideoDevs)
dwR = videoCreateDriverList ();
if (dwR != DV_ERR_OK)
return dwR;
if ((WORD) dwDeviceID >= wTotalVideoDevs)
return DV_ERR_BADDEVICEID;
dwR = videoGetDriverDescAndVer (aCapDriverList[(int)dwDeviceID]);
if (dwR == DV_ERR_OK) {
if (lpszDesc)
lstrcpyn (lpszDesc, aCapDriverList[(int)dwDeviceID]->szDriverDescription, cbDesc);
if (lpszVer)
lstrcpyn (lpszVer, aCapDriverList[(int)dwDeviceID]->szDriverVersion, cbVer);
}
return (dwR);
}
/*****************************************************************************
* @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
* <m DVM_SRC_RECT> and <m DVM_DST_RECT>, and
* device specific messages.
*
* @xref <f videoConfigure>
*
****************************************************************************/
DWORD WINAPI videoMessage(HVIDEO hVideo, UINT msg, DWORD dwP1, DWORD 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
* plus drivers listed in the registry.
*
* @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 <f videoOpen>
****************************************************************************/
DWORD WINAPI videoGetNumDevs(void)
{
if (wTotalVideoDevs)
return (DWORD)wTotalVideoDevs;
videoCreateDriverList ();
return (DWORD)wTotalVideoDevs;
}
/*****************************************************************************
* @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 <p lpText>.
*
* @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 <p wSize> is zero, nothing is copied and zero
* is returned.
****************************************************************************/
#if defined _WIN32
//
// for WIN32 this is the ansi entry point
//
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(ghInst, 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 = videoMessage (hVideo, DVM_GETERRORTEXT, (DWORD) (LPVOID) &vet,
(DWORD) NULL);
if (DV_ERR_OK == dwResult) {
wcstombs(lpText, lpwstr, wSize);
}
LocalFree(lpwstr);
return(dwResult);
}
else
return DV_ERR_BADERRNUM;
}
#endif
//
// The unicode/Win16 equivalent of the above
//
#ifdef _WIN32
DWORD WINAPI videoGetErrorTextW (HVIDEO hVideo, UINT wError,
LPWSTR lpText, UINT wSize)
#else
DWORD WINAPI videoGetErrorText (HVIDEO hVideo, UINT wError,
LPSTR lpText, UINT wSize)
#endif
{
VIDEO_GETERRORTEXT_PARMS vet;
lpText[0] = 0;
if (((wError > DV_ERR_BASE) && (wError <= DV_ERR_LASTERROR))) {
if (wSize > 1) {
#ifdef _WIN32
LPSTR lpsz = LocalAlloc (LPTR, wSize);
UINT cch;
if (!lpsz)
return DV_ERR_NOMEM;
cch = LoadString (ghInst, wError, lpsz, wSize);
lpsz[cch] = 0;
mbstowcs (lpText, lpsz, cch+1);
LocalFree (lpsz);
if (!cch)
#else
if (!LoadString(ghInst, wError, lpText, wSize))
#endif
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 = wSize;
return videoMessage (hVideo, DVM_GETERRORTEXT, (DWORD) (LPVOID) &vet,
(DWORD) 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
* <t CHANNEL_CAPS> structure.
*
* @parm DWORD | dwSize | Specifies the size, in bytes, of the
* <t CHANNEL_CAPS> 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 <t CHANNEL_CAPS> 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 videoMessage(hVideo, DVM_GET_CHANNEL_CAPS, (DWORD) lpChannelCaps,
(DWORD) 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 <m WM_MOVE>, <m WM_SIZE>,
* or <m WM_PAINT> message.
****************************************************************************/
DWORD WINAPI videoUpdate (HVIDEO hVideo, HWND hWnd, HDC hDC)
{
if ((!hVideo) || (!hWnd) || (!hDC) )
return DV_ERR_INVALHANDLE;
return videoMessage(hVideo, DVM_UPDATE, (DWORD) hWnd, (DWORD) 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 <t HVIDEO> 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 <p dwDeviceID> 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 <f videoGetNumDevs> to determine the number of video
* devices present in the system.
*
* @xref <f videoClose>
****************************************************************************/
DWORD WINAPI videoOpen (LPHVIDEO lphVideo, DWORD dwDeviceID, DWORD dwFlags)
{
UINT w;
VIDEO_OPEN_PARMS vop; // Same as IC_OPEN struct!!!
DWORD dwVersion = VIDEOAPIVERSION;
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;
if (!wTotalVideoDevs) // trying to open without finding how many devs.
videoGetNumDevs();
if (!wTotalVideoDevs) // No drivers installed
return DV_ERR_BADINSTALL;
if (w >= wTotalVideoDevs)
return DV_ERR_BADDEVICEID;
// New for Chicago, drivers are passed a Devnode if PnP at Open time
vop.dnDevNode = aCapDriverList[w]->dnDevNode;
#ifdef UNICODE
*lphVideo = (HVIDEO) OpenDriver(aCapDriverList[w]->szDriverName,
NULL, (LPARAM) (LPVOID) &vop);
#else
#if defined _WIN32
*lphVideo = (HVIDEO) OpenDriverA(aCapDriverList[w]->szDriverName,
NULL, (LPARAM) (LPVOID) &vop);
#else
*lphVideo = (HVIDEO) OpenDriver(aCapDriverList[w]->szDriverName,
NULL, (LPARAM) (LPVOID) &vop);
#endif
#endif
if( ! *lphVideo ) {
if (vop.dwError) // if driver returned an error code...
return vop.dwError;
else {
#ifdef _WIN32
if (GetFileAttributes(aCapDriverList[w]->szDriverName) == (DWORD) -1)
#else
OFSTRUCT of;
if (OpenFile (aCapDriverList[w]->szDriverName, &of, OF_EXIST) == HFILE_ERROR)
#endif
return (DV_ERR_BADINSTALL);
else
return (DV_ERR_NOTDETECTED);
}
}
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 <f videoStreamAddBuffer> and
* they haven't been returned to the application,
* the close operation fails. You can use <f videoStreamReset> to mark all
* pending buffers as done.
*
* @xref <f videoOpen> <f videoStreamInit> <f videoStreamFini> <f videoStreamReset>
****************************************************************************/
DWORD WINAPI videoClose (HVIDEO hVideo)
{
if (!hVideo)
return DV_ERR_INVALHANDLE;
if (CloseDriver((HDRVR)hVideo, 0L, 0L ))
return DV_ERR_OK;
return 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 <p msg>. This flag
* should be combined with either the VIDEO_CONFIGURE_SET or
* VIDEO_CONFIGURE_GET flag. If this flag is
* set, the <p lpData1>, <p dwSize1>, <p lpData2>, and <p dwSize2>
* parameters are ignored.
*
* @flag VIDEO_CONFIGURE_QUERYSIZE | Returns the size, in bytes,
* of the configuration option in <p lpdwReturn>. 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, <p lpdwReturn> 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 <p lpData1>
* buffer.
*
* @parm LPVOID | lpData2 | Specifies a pointer to message specific data.
*
* @parm DWORD | dwSize2 | Specifies the size, in bytes, of the <p lpData2>
* 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 <f videoOpen> <f videoMessage>
*
****************************************************************************/
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 (DWORD)) )
return DV_ERR_NONSPECIFIC;
}
vcp.lpdwReturn = lpdwReturn;
vcp.lpData1 = lpData1;
vcp.dwSize1 = dwSize1;
vcp.lpData2 = lpData2;
vcp.dwSize2 = dwSize2;
return videoMessage(hVideo, msg, dwFlags,
(DWORD)(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 <f videoOpen>
****************************************************************************/
#if defined _WIN32
//
// for win32 this is the ansi entry point
//
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);
}
mbstowcs(lpwstr, lpstrIdent, ret);
ret = videoMessage(hVideo, DVM_CONFIGURESTORAGE,
(DWORD)lpwstr, dwFlags);
LocalFree(lpwstr);
return(ret);
}
#endif // _WIN32
// this code is correct for WIN32 UNICODE and for win16
// messages we send are expected to contain unicode strings.
// so send them off...
//
#ifdef _WIN32
DWORD WINAPI videoConfigureStorageW (HVIDEO hVideo,
LPWSTR lpstrIdent, DWORD dwFlags)
#else
DWORD WINAPI videoConfigureStorage (HVIDEO hVideo,
LPSTR lpstrIdent, DWORD dwFlags)
#endif
{
if (!hVideo)
return DV_ERR_INVALHANDLE;
return videoMessage(hVideo, DVM_CONFIGURESTORAGE,
(DWORD)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 <f videoOpen> <f videoConfigureStorage>
****************************************************************************/
DWORD WINAPI videoDialog (HVIDEO hVideo, HWND hWndParent, DWORD dwFlags)
{
if (!hVideo)
return DV_ERR_INVALHANDLE;
if ((!hWndParent) || (!IsWindow (hWndParent)) )
return DV_ERR_INVALHANDLE;
return videoMessage(hVideo, DVM_DIALOG, (DWORD)hWndParent, dwFlags);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/*****************************************************************************
* @doc INTERNAL VIDEO
*
* @api DWORD | videoPrepareHeader | This function prepares the
* header and data
* by performing a <f GlobalPageLock>.
*
* @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)sizeof(VIDEOHDR)))
return DV_ERR_NOMEM;
if (!HugePageLock(lpVideoHdr->lpData, lpVideoHdr->dwBufferLength)) {
HugePageUnlock(lpVideoHdr, (DWORD)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)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
* <t VIDEOHDR> 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 <t VIDEOHDR> 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 <f videoStreamPrepareHeader> and
* <f videoStreamUnprepareHeader> functions must not be used.
*
* The buffer allocated must be accessible for DMA by the host.
*
* @xref <f videoStreamFreeHdrAndBuffer>
****************************************************************************/
DWORD WINAPI videoStreamAllocHdrAndBuffer(HVIDEO hVideo,
LPVIDEOHDR FAR * plpvideoHdr, DWORD dwSize)
{
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)plpvideoHdr, (DWORD)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;
}
/*****************************************************************************
* @doc EXTERNAL VIDEO
*
* @api DWORD | videoStreamFreeHdrAndBuffer | This function is used to free
* buffers allocated by the driver using the <f videoStreamAllocHdrAndBuffer>
* function.
*
* @parm HVIDEO | hVideo | Specifies a handle to the video
* device channel.
*
* @parm LPVIDEOHDR | lpvideoHdr | Specifies a pointer to the
* <t VIDEOHDR> 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 <f videoStreamPrepareHeader> and
* <f videoStreamUnprepareHeader> functions must not be used.
*
* @xref <f videoStreamAllocHdrAndBuffer>
****************************************************************************/
DWORD WINAPI videoStreamFreeHdrAndBuffer(HVIDEO hVideo,
LPVIDEOHDR lpvideoHdr)
{
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)lpvideoHdr, (DWORD)0);
if (wRet != DV_ERR_OK)
{
DebugErr(DBF_WARNING,"videoStreamFreeHdrAndBuffer: Error freeing buffer.");
}
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
* <t VIDEOHDR> structure identifying the buffer to be prepared.
*
* @parm DWORD | dwSize | Specifies the size of the <t VIDEOHDR> 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 <f videoStreamInit> or
* after <f videoStreamReset> to prepare the data buffers
* for streaming data.
*
* The <t VIDEOHDR> data structure and the data block pointed to by its
* <e VIDEOHDR.lpData> member must be allocated with <f GlobalAlloc> using the
* GMEM_MOVEABLE and GMEM_SHARE flags, and locked with <f GlobalLock>.
* 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 <f videoStreamUnprepareHeader>
****************************************************************************/
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)lpvideoHdr, (DWORD)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 <f videoStreamPrepareHeader>.
*
* @parm HVIDEO | hVideo | Specifies a handle to the video
* device channel.
*
* @parm LPVIDEOHDR | lpvideoHdr | Specifies a pointer to a <t VIDEOHDR>
* structure identifying the data buffer to be unprepared.
*
* @parm DWORD | dwSize | Specifies the size of the <t VIDEOHDR> 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 <p lpvideoHdr>
* is still in the queue.
*
* @comm This function is the complementary function to <f videoStreamPrepareHeader>.
* You must call this function before freeing the data buffer with <f GlobalFree>.
* After passing a buffer to the device driver with <f videoStreamAddBuffer>, you
* must wait until the driver is finished with the buffer before calling
* <f videoStreamUnprepareHeader>. Unpreparing a buffer that has not been
* prepared or has been already unprepared has no effect,
* and the function returns zero.
*
* @xref <f videoStreamPrepareHeader>
****************************************************************************/
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)lpvideoHdr, (DWORD)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 <t VIDEOHDR>
* structure that identifies the buffer.
*
* @parm DWORD | dwSize | Specifies the size of the <t VIDEOHDR> 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 <p lpvideoHdr> structure hasn't been prepared.
* @flag DV_ERR_STILLPLAYING | Indicates a buffer is still in the queue.
* @flag DV_ERR_PARAM1 | The <p lpvideoHdr> parameter is invalid or
* the <e VIDEOHDR.dwBufferLength> member of the <t VIDEOHDR>
* structure is not set to the proper value.
*
* @comm The data buffer must be prepared with <f videoStreamPrepareHeader>
* before it is passed to <f videoStreamAddBuffer>. The <t VIDEOHDR> data
* structure and the data buffer referenced by its <e VIDEOHDR.lpData>
* member must be allocated with <f GlobalAlloc> using the GMEM_MOVEABLE
* and GMEM_SHARE flags, and locked with <f GlobalLock>. Set the
* <e VIDEOHDR.dwBufferLength> member to the size of the header.
*
* @xref <f videoStreamPrepareHeader>
****************************************************************************/
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)lpvideoHdr, (DWORD)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 <e VIDEOHDR.dwBytesRecorded> member in
* the <t VIDEOHDR> 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 <f videoStreamStart> <f videoStreamReset>
****************************************************************************/
DWORD WINAPI videoStreamStop(HVIDEO hVideo)
{
if (!hVideo)
return DV_ERR_INVALHANDLE;
return 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 <f videoStreamReset> <f videoStreamStop> <f videoStreamAddBuffer> <f videoStreamClose>
/****************************************************************************/
DWORD WINAPI videoStreamReset(HVIDEO hVideo)
{
if (!hVideo)
return DV_ERR_INVALHANDLE;
return 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 <t MMTIME>
* structure.
*
* @parm DWORD | dwSize | Specifies the size of the <t MMTIME> 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 <f videoStreamGetPosition>, set the
* <e MMTIME.wType> member of the <t MMTIME> structure to indicate
* the time format desired. After
* <f videoStreamGetPosition> returns, check the <e MMTIME.wType>
* member to determine if the your time format is supported. If
* not, <e MMTIME.wType> specifies an alternate format.
* Video capture drivers typically provide the millisecond time
* format.
*
* The position is set to zero when streaming is started with
* <f videoStreamStart>.
****************************************************************************/
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 videoMessage(hVideo, DVM_STREAM_GETPOSITION,
(DWORD)lpInfo, (DWORD)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, <p dwCallback> is
* a window handle.
* @flag CALLBACK_FUNCTION | If this flag is specified, <p dwCallback> 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
* <p hVideo> 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:
*
* <m MM_DRVM_OPEN> is sent at the time of <f videoStreamInit>
*
* <m MM_DRVM_CLOSE> is sent at the time of <f videoStreamFini>
*
* <m MM_DRVM_DATA> is sent when a buffer of image data is available
*
* <m MM_DRVM_ERROR> is sent when an error occurs
*
* Callback functions must reside in a DLL.
* You do not have to use <f MakeProcInstance> to get
* a procedure-instance address for the callback function.
*
* @cb void CALLBACK | videoFunc | <f 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
* <f videoStreamInit>.
*
* @parm HVIDEO | hVideo | Specifies a handle to the video device channel
* associated with the callback.
*
* @parm DWORD | wMsg | Specifies the <m MM_DRVM_> messages. Messages indicate
* errors and when image data is available. For information on
* these messages, see <f videoStreamInit>.
*
* @parm DWORD | dwInstance | Specifies the user instance
* data specified with <f videoStreamInit>.
*
* @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 <f PostMessage>, <f timeGetSystemTime>,
* <f timeGetTime>, <f timeSetEvent>, <f timeKillEvent>,
* <f midiOutShortMsg>, <f midiOutLongMsg>, and <f OutputDebugStr>.
*
* @xref <f videoOpen> <f videoStreamFini> <f videoClose>
****************************************************************************/
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 videoMessage(hVideo, DVM_STREAM_INIT,
(DWORD_PTR) (LPVIDEO_STREAM_INIT_PARMS) &vsip,
(DWORD) 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
* <f videoStreamAddBuffer> that haven't been returned to the application,
* this operation will fail. Use <f videoStreamReset> to return all
* pending buffers.
*
* Each call to <f videoStreamInit> must be matched with a call to
* <f videoStreamFini>.
*
* 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 <f videoStreamInit>
****************************************************************************/
DWORD WINAPI videoStreamFini(HVIDEO hVideo)
{
if (!hVideo)
return DV_ERR_INVALHANDLE;
return 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 <f videoStreamReset> <f videoStreamStop> <f videoStreamAddBuffer> <f videoStreamClose>
/****************************************************************************/
DWORD WINAPI videoStreamStart(HVIDEO hVideo)
{
if (!hVideo)
return DV_ERR_INVALHANDLE;
return 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 <t DWORD>
* used to return the error ID.
*
* @parm LPDWORD | lpdwErrorValue | Specifies a far pointer to the <t DWORD>
* 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 <p lpdwErrorID>
* and <p lpdwErrorValue> 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 <f videoOpen>
/****************************************************************************/
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 videoMessage(hVideo, DVM_STREAM_GETERROR, (DWORD) lpdwError,
(DWORD) 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 <t VIDEOHDR>
* 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 <p lpVDHdr> parameter is invalid or
* the <e VIDEOHDR.dwBufferLength> member of the <t VIDEOHDR>
* 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 <f videoOpen>
/****************************************************************************/
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 videoMessage(hVideo, DVM_FRAME, (DWORD) lpVHdr,
sizeof(VIDEOHDR));
}
#endif // ifdef WIN16
/**************************************************************************
* @doc INTERNAL VIDEO
*
* @api void | videoCleanup | clean up video stuff
* called in MSVIDEOs WEP()
*
**************************************************************************/
void FAR PASCAL videoCleanup(HTASK hTask)
{
#ifdef WIN16
videoFreeDriverList();
#endif
}