📄 usbcam.c
字号:
DWORD nStreamID = -1;
PDEVICECONTEXT pPDD = NULL;
DEBUGMSG(1, (TEXT("Looking for Stream Interfaces %d %d\r\n"), bIFStrm, bIFSubStrm));
__try {
if (lpUsbDev->lpConfigs->dwCount != sizeof (USB_CONFIGURATION))
{
RETAILMSG(1, (TEXT("Unexpected CUSB_CONFIGURATION dwCount: %d ***********\r\n"), lpUsbDev->lpConfigs->dwCount));
return FALSE;
}
// Walk interface table to find the number of Video stream interface alternates and if there are
// other video streams that aren't alts.
DEBUGMSG(1,(TEXT("There are %d interfaces.\r\n"),lpUsbDev->lpConfigs->dwNumInterfaces));
for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; i++)
{
lpIF = &lpUsbDev->lpConfigs->lpInterfaces[i];
if ((lpIF->Descriptor.bInterfaceClass == bIFStrm) && (lpIF->Descriptor.bInterfaceSubClass == bIFSubStrm))
{
// Is first stream?
if (nStreamID == -1)
{
nStreamID = lpIF->Descriptor.bInterfaceNumber;
}
else if (nStreamID == lpIF->Descriptor.bInterfaceNumber)
{
nStreamAlts++;
}
else
{
nOtherStreams++;
}
}
}
if (nStreamID == -1)
{
DEBUGMSG(1, (TEXT("No stream interfaces\r\n")));
return FALSE;
}
//设备可以使用,创建设备上下文
pPDD = (PDEVICECONTEXT)VirtualAlloc (NULL, sizeof (PDEVICECONTEXT), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (pPDD == 0)
{
RETAILMSG(1, (TEXT("Not enough memory!\r\n")));
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
pPDD->nInterfaces = nStreamAlts + 1;
pPDD->hVendorEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
DEBUGMSG(1, (TEXT("Found %d stream interfaces. ID %d\r\n"), pPDD->nInterfaces, nStreamID));
if (nOtherStreams)
{
DEBUGMSG(1, (TEXT("Multiple stream interfaces found on device. Using first one.\r\n")));
}
// Allocate the array for the stream interface descriptors
//保存视频传输接口
if (pPDD->nInterfaces > 0)
{
DEBUGMSG(1,(TEXT("%d interfaces will be saved!\r\n"),pPDD->nInterfaces));
pPDD->usbVideoIF = (PUSBIF)VirtualAlloc (NULL, sizeof(USBIF), MEM_COMMIT, PAGE_EXECUTE_READWRITE);;/*pPDD->nInterfaces **/
}
//保存接口
//OV511有8套接口设置,对应不同的传输Packet Size
//PUSBIF temp;
for (i = 0; i < lpUsbDev->lpConfigs->dwNumInterfaces; i++)
{
lpIF = &lpUsbDev->lpConfigs->lpInterfaces[i];
//保存接口
//作为测试,只保存第7个接口设置以及使用
if(i==7)
{
pPDD->usbVideoIF->ifDesc=lpIF->Descriptor;
if (lpIF->lpEndpoints)
{
pPDD->usbVideoIF->epDesc = lpIF->lpEndpoints->Descriptor;
pPDD->usbVideoIF->fEndpoint = TRUE;
}
else
{
pPDD->usbVideoIF->fEndpoint = FALSE;
}
DEBUGMSG(1,(TEXT("Saving interface %d...\r\n"),lpIF->Descriptor.bAlternateSetting));
}
}
DEBUGMSG(1, (TEXT("Device interfaces saved!\r\n")));
*pdwContext = (DWORD)pPDD;
return TRUE;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(1, (TEXT("Exception walking device interfaces\r\n")));
return FALSE;
}
}
//停止OV511视频采集
BOOL OV51xStop(PDRVCONTEXT pDrv)
{
DEBUGMSG(1,(TEXT("Stopping streaming...\r\n")));
pDrv->bStopped = TRUE;
if(RegisterWrite(pDrv, 0x50, 0x3d) == TRUE)
{
return TRUE;
}
else
{
return FALSE;
}
}
//重新开始OV511采集
BOOL OV51xRestart(PDRVCONTEXT pDrv)
{
if(pDrv->bStopped)
{
pDrv->bStopped=FALSE;
if(RegisterWrite(pDrv, 0x50, 0x00) == TRUE)
{
return TRUE;
}
}
return FALSE;
}
//重置OV511
BOOL OV51xReset(PDRVCONTEXT pDrv,BYTE reset_type)
{
BOOL bRc;
bRc = RegisterWrite(pDrv, 0x50, reset_type);
bRc = RegisterWrite(pDrv, 0x50, 0);
return bRc;
}
//设置视频接口
DWORD SetStreamInterface(PDRVCONTEXT pDrv,BYTE nInterFace)
{
USB_TRANSFER hTransfer;
PUSBIF lpIF;
DWORD rc;
PDEVICECONTEXT pPDD= (PDEVICECONTEXT)pDrv->dwDeviceContext;
//如果管道已经打开,就先关闭
if (pPDD->pipeVideo.hEvent != 0)
{
pDrv->lpUsbFuncs->lpClosePipe (pPDD->pipeVideo.hPipe);
CloseHandle (pPDD->pipeVideo.hEvent);
pPDD->pipeVideo.hEvent = 0;
}
lpIF=pPDD->usbVideoIF;
//打开第7个接口
DEBUGMSG(1, (TEXT("Set Interface %d\r\n"),lpIF->ifDesc.bAlternateSetting));
hTransfer = pDrv->lpUsbFuncs->lpSetInterface (pDrv->hDevice, NULL, NULL, 0, lpIF->ifDesc.bInterfaceNumber,
lpIF->ifDesc.bAlternateSetting);
if (hTransfer == 0)
{
DEBUGMSG(1, (TEXT("Error calling SetInterface rc=%d\r\n"), GetLastError()));
return GetLastError();
}
if (!CloseTransferHandle (pDrv->lpUsbFuncs, hTransfer))
{
rc = GetLastError();
}
rc = 0;
// Open a pipe to the end point
// 依据这个接口的Endpoint Descriptor,打开传输管道
if (lpIF->fEndpoint)
{
DEBUGMSG(1, (TEXT("End Point 0x%x!\r\n"), lpIF->fEndpoint));
DEBUGMSG(1, (TEXT("Open pipe!\r\n")));
// Open the pipe
pPDD->pipeVideo.hPipe = pDrv->lpUsbFuncs->lpOpenPipe (pDrv->hDevice, &lpIF->epDesc);
// Check for sucessful open
DEBUGMSG(1, (TEXT("Pipe: 0x%x!\r\n"), pPDD->pipeVideo.hPipe));
if (pPDD->pipeVideo.hPipe != NULL)
{
// Copy some pipe attributes
pPDD->pipeVideo.ucAddr = lpIF->epDesc.bEndpointAddress;
pPDD->pipeVideo.wPacketSize = lpIF->epDesc.wMaxPacketSize;
DEBUGMSG(1,(TEXT("Actual Packet Size %d\r\n"),pPDD->pipeVideo.wPacketSize));
// First, create an event for handshaking
// 创建传输完成的回调事件
pPDD->pipeVideo.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
}
else
{
rc = GetLastError();
if (rc == 0)
{
rc = ERROR_NOT_ENOUGH_MEMORY; // Sometimes, there isn't an extended error here
}
DEBUGMSG(1, (TEXT("Error opening pipe rc: %d\r\n"), rc));
}
}
if (rc)
{
DEBUGMSG(1, (TEXT("Error in SetStreamInterface rc: %d ExtErr: %d\r\n"), rc, GetLastError()));
}
DEBUGMSG(1, (TEXT("SetStreamInterface-- rc %d\r\n"), rc));
if(rc==0)
{
return 1;
}
else
{
return 0;
}
}
//设置OV511传输包大小
BOOL OV511SetPacketSize(PDRVCONTEXT pDrv, DWORD size)
{
DWORD alt,mult;
mult = size >> 5;
if (!OV51xStop(pDrv))
{
return 0;
}
switch(size)
{
case 0:
alt=0;
break;
case 33:
alt=1;
break;
case 129:
alt=2;
break;
case 257:
alt=3;
break;
case 385:
alt=4;
break;
case 513:
alt=5;
break;
case 769:
alt=6;
break;
case 961:
alt=7;
break;
default:
return 0;
break;
}
DEBUGMSG(1,(TEXT("Alt %d,mult %d,size %d\r\n"),alt,mult,size));
if (RegisterWrite(pDrv, 0x30, (BYTE)mult) == FALSE)
{
return FALSE;
}
/*
if (usb_set_interface(pDrv->dev, pDrv->iface, alt) < 0) {
err("Set packet size: set interface error");
return -EBUSY;
}
*/
//设置接口,这里硬编码为使用第3套设置
SetStreamInterface(pDrv,3);
DEBUGMSG(1,(TEXT("Reset!\r\n"),alt,mult,size));
if (OV51xReset(pDrv, 0x3F) == FALSE)
{
return FALSE;
}
pDrv->nPacketSize = size;
DEBUGMSG(1,(TEXT("Restart!\r\n"),alt,mult,size));
if (OV51xRestart(pDrv) == FALSE)
{
return FALSE;
}
return TRUE;
}
DWORD OV51xReadOneFrame(PDRVCONTEXT pDrv, BYTE *pBuff, DWORD startaddress)
{
PBYTE pDataBuff, pBuf, ptr;
DWORD nNumPackets;
DWORD dw;
DWORD dwFrameLen[MAXPACKETS];
DWORD dwUsbRc[MAXPACKETS];
DWORD dwBytes;
DWORD dwPacketIndex;
DWORD nPacketSize;
DWORD address = 0;
DWORD i, j, k, k1 ,k2;
DWORD pack = 0;
BOOL Frame = FALSE;
PDEVICECONTEXT pPDD=(PDEVICECONTEXT)pDrv->dwDeviceContext;
memset(RawFrameData, 0x00, 115223);
memset(RealFrameData, 0x00, 115712);
ptr = RawFrameData;
for(i = 0; i < 25; i++)
{
pDataBuff = DataBuf;
if(pDataBuff == NULL)
{
return 0;
}
memset(pDataBuff, 0x00, 961 * 10);
nNumPackets = MAXPACKETS;
nPacketSize = pPDD->pipeVideo.wPacketSize;
for (dwPacketIndex = 0; dwPacketIndex < MAXPACKETS; dwPacketIndex++)
{
dwFrameLen[dwPacketIndex] = 961;
}
__try {
dw = IssueIsochTransfer ( pDrv->lpUsbFuncs,
pPDD->pipeVideo.hPipe,
DefaultTransferComplete,
pPDD->pipeVideo.hEvent,
USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK | USB_START_ISOCH_ASAP | USB_COMPRESS_ISOCH,
0, // Using USB_START_ISOCH_ASAP precludes the need for a start frame
nNumPackets, // Number of frames to read
dwFrameLen, // Array that receives the length of each frame
pDataBuff, // Pointer to transfer buffer
0, // Specifies the physical address, which may be NULL, of the data buffer
&dwBytes, // Number of bytes transferred by USB
1500, // Timeout in msec
dwUsbRc); // Returns USB_ERROR or USB_TRANSFER
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DEBUGMSG(1, (TEXT ("Exception calling IssueIsochTransfer %d %d\r\n"), dw, GetLastError()));
return 0;
}
if (dw)
{
DEBUGMSG(1,(TEXT ("Error calling IssueIsochTransfer %d %d\r\n"), dw, GetLastError()));
}
if (dwBytes == 0)
{
DEBUGMSG(1,(TEXT("packet size read if %d bytes! :(\r\n"), dwBytes));
}
else
{
address += dwBytes;
pBuf = DataBuf;
for(j = 0; j < dwBytes / 961; j++)
{
//查找帧开始标志
k = (pBuf[0] | pBuf[1] | pBuf[2] | pBuf[3] | pBuf[4] | pBuf[5] | pBuf[6] | pBuf[7]);
k1 = (pBuf[8] & 0xff);
k2 = (pBuf[8] & 0xff);
if (k == 0 && (k1 == 24 || k2 ==25))
{
Frame = TRUE;
break;
}
else
{
pBuf += 961;
}
}
}
j++;
pack = 1;
if(Frame == TRUE)
{
pBuf += 9;
memmove(ptr, pBuf, 951); //复制第一包
ptr += 951;
pBuf += 952;
for(; j < 10; j++)
{
memmove(ptr, pBuf, 960);
ptr += 960;
pBuf += 961;
pack += 1;
}
for(i = 0; i < 11; i++)
{
memset(DataBuf, 0x00, 961 * 10);
pDataBuff = DataBuf;
if(pDataBuff == NULL)
{
return 0;
}
__try {
dw = IssueIsochTransfer ( pDrv->lpUsbFuncs,
pPDD->pipeVideo.hPipe,
DefaultTransferComplete,
pPDD->pipeVideo.hEvent,
USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK | USB_START_ISOCH_ASAP | USB_COMPRESS_ISOCH,
0, // Using USB_START_ISOCH_ASAP precludes the need for a start frame
nNumPackets, // Number of frames to read
dwFrameLen, // Array that receives the length of each frame
pDataBuff, // Pointer to transfer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -