📄 pddvclas.cpp
字号:
// Grab the info we want
pProps->cbSize = sizeof (FORMATPROPS);
pProps->wFormatType = bDescID;
pProps->wFormatIndex = bFormatIndex;
pProps->wFrameIndex = bFrameIndex;
pProps->dwHeight = pFrmMJPEG->wHeight;
pProps->dwWidth = pFrmMJPEG->wWidth;
pProps->dwMaxBuff = pFrmMJPEG->dwMaxVideoFrameBufferSize;
if (pFrmMJPEG->bFrameIntervalType)
{
pProps->nNumInterval = pFrmMJPEG->bFrameIntervalType;
for (int k = 0; k < pFrmMJPEG->bFrameIntervalType; k++)
{
pProps->dwInterval[k] = pFrmMJPEG->Interval.dwDescrete[k];
}
}
else
{
// Cont interval
pProps->nNumInterval = -1;
pProps->dwInterval[0] = pFrmMJPEG->Interval.strCont.dwMinFrameInterval;
pProps->dwInterval[1] = pFrmMJPEG->Interval.strCont.dwMaxFrameInterval;
pProps->dwInterval[2] = pFrmMJPEG->Interval.strCont.dwFrameIntervalStep;
}
*pfFound = TRUE;
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("ProcessFrameFormats--\r\n")));
return 0;
}
pFrmMJPEG = (PUSBVIDSTREAMIF_MJPEGFRAMEDESCRIPTOR)((PBYTE)pFrmMJPEG + pFrmMJPEG->bLen);
}
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("ProcessFrameFormats--\r\n")));
return -3; // We didn't find the index requested
}
//-----------------------------------------------------------------------
// StopReadThread - Stops the isoch read thread
//
void StopReadThread (PPDDCONTEXT pPDD)
{
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("StopReadThread++\r\n")));
// We need to stop the read thread if its running...
if (pPDD->wReadThreadState != STREAMTHD_STOPPED)
{
pPDD->wReadThreadState = STREAMTHD_STOPPED;
int rc = WaitForSingleObject (pPDD->hReadThread, 2000);
if (rc != WAIT_OBJECT_0)
{
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Can't stop read thread!\r\n")));
TerminateThread (pPDD->hReadThread, -1);
}
}
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("StopReadThread--\r\n")));
return;
}
//-----------------------------------------------------------------------
// GetMinMaxQuality - Returns the min, max, and increment values for
// the compression paramter for a given format, frame size, and, frame rate
//
int GetMinMaxQuality (PDRVCONTEXT pDrv, BYTE bFormatIndex, BYTE bFrameIndex, DWORD dwFrameInterval,
WORD *pwCompMin, WORD *pwCompMax, WORD *pwCompInc)
{
BYTE buff[64];
int rc = 0;
BYTE bInterface = VID_IF_STREAM;
BYTE bUnit = 0;
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("GetMinMaxQuality++\r\n")));
// Get our pdd specific context
PPDDCONTEXT pPDD = (PPDDCONTEXT)pDrv->dwPddContext;
memset (buff, 0, sizeof (buff));
PSTREAM_PROBE_CONTROLSTRUCT p = (PSTREAM_PROBE_CONTROLSTRUCT)buff;
// Set current probe vals
memset (p, 0, sizeof (0));
p->bFormatIndex = bFormatIndex;
p->bFrameIndex = bFrameIndex;
p->dwFrameInterval = dwFrameInterval;
rc = DoVendorTransfer (pDrv, USBVID_SET_CUR, USB_VIDEO_VS_CS_PROBE_CTL,
bInterface, bUnit, (PBYTE)p, 22);
if (rc)
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error setting original probe vals rc %d\r\n"), rc));
if (rc == 0)
{
// Get minimum quality value
p->bFormatIndex = bFormatIndex;
p->bFrameIndex = bFrameIndex;
p->dwFrameInterval = dwFrameInterval;
rc = DoVendorTransfer (pDrv, USBVID_GET_MIN, USB_VIDEO_VS_CS_PROBE_CTL,
bInterface, bUnit, (PBYTE)p, 22);
if (rc)
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error getting min value. rc %d\r\n"), rc));
*pwCompMin = p->wCompQuality;
}
if (rc == 0)
{
// Get maximum quality value
p->bFormatIndex = bFormatIndex;
p->bFrameIndex = bFrameIndex;
p->dwFrameInterval = dwFrameInterval;
rc = DoVendorTransfer (pDrv, USBVID_GET_MAX, USB_VIDEO_VS_CS_PROBE_CTL,
bInterface, bUnit, (PBYTE)p, 22);
if (rc)
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error getting max value. rc %d\r\n"), rc));
*pwCompMax = p->wCompQuality;
}
if (rc == 0)
{
// Get maximum quality value
p->bFormatIndex = bFormatIndex;
p->bFrameIndex = bFrameIndex;
p->dwFrameInterval = dwFrameInterval;
rc = DoVendorTransfer (pDrv, USBVID_GET_RES, USB_VIDEO_VS_CS_PROBE_CTL,
bInterface, bUnit, (PBYTE)p, 22);
if (rc)
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error getting inc value. rc %d\r\n"), rc));
*pwCompInc = p->wCompQuality;
}
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("GetMinMaxQuality-- rc %d\r\n"), rc));
return rc;
}
//-----------------------------------------------------------------------
// ProbeCommitVidStream - Negotiates the streaming parameters
//
int ProbeCommitVidStream (PDRVCONTEXT pDrv, BYTE bFormatIndex, BYTE bFrameIndex,
DWORD *pdwFrameInterval, WORD wCompression, PDWORD pdwMaxBandwidth)
{
int rc = 0;
BYTE bInterface = VID_IF_STREAM;
BYTE bUnit = 0;
DEBUGMSG (ZONE_FUNC | ZONE_PROBE,
(DTAG TEXT("ProbeCommitVidStream++ Fmt: %d Frm: %d Interval %d Compression %d\r\n"),
bFormatIndex, bFrameIndex, *pdwFrameInterval, wCompression));
// Get our pdd specific context
PPDDCONTEXT pPDD = (PPDDCONTEXT)pDrv->dwPddContext;
// Clear the buffer. We use this because the USB stack (or camera) sometimes returns more
// data than the size of the STREAM_PROBE_CONTROLSTRUCT structure.
STREAM_PROBE_CONTROLSTRUCT pSPC;
memset (&pSPC, 0, sizeof (STREAM_PROBE_CONTROLSTRUCT));
// Set probe values
pSPC.bFormatIndex = bFormatIndex;
pSPC.bFrameIndex = bFrameIndex;
pSPC.dwFrameInterval = *pdwFrameInterval;
pSPC.wCompQuality = wCompression;
pSPC.bmHint = USB_VIDEO_PROBE_HINT_FRAMEINTERVAL;
rc = DoVendorTransfer (pDrv, USBVID_SET_CUR, USB_VIDEO_VS_CS_PROBE_CTL,
bInterface, bUnit, (PBYTE)&pSPC, 22);
if (rc)
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error setting probe values. rc %d\r\n"), rc));
// Get back probe values
if (rc == 0)
{
rc = DoVendorTransfer (pDrv, USBVID_GET_CUR, USB_VIDEO_VS_CS_PROBE_CTL,
bInterface, bUnit, (PBYTE)&pSPC, 22);
if (rc)
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error getting final probe values. rc %d\r\n"), rc));
}
// Set the commit values
if (rc == 0)
{
rc = DoVendorTransfer (pDrv, USBVID_SET_CUR, USB_VIDEO_VS_CS_COMMIT_CTL,
bInterface, bUnit, (PBYTE)&pSPC, 22);
if (rc)
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Error setting probe values. rc %d\r\n"), rc));
}
if (rc == 0)
{
// Save the max payload value, we need this for choosing the proper interface
*pdwMaxBandwidth = (pSPC.dwMaxVideoFrameSize * 10000) / pSPC.dwFrameInterval;
}
DEBUGMSG (ZONE_FUNC | ZONE_PROBE,
(DTAG TEXT("ProbeCommitVidStream-- Fmt: %d Frm: %d Compression %d Interval %d Transfer size: %d Frame size %d BW %d\r\n"),
pSPC.bFormatIndex, pSPC.bFrameIndex, pSPC.wCompQuality, pSPC.dwFrameInterval, pSPC.dwMaxPayloadTransferSize, pSPC.dwMaxVideoFrameSize, *pdwMaxBandwidth));
return rc;
}
//-----------------------------------------------------------------------
// AllocateInternalStreamBuffers - If a still is requested and no
// stream is currently running, this routine allocates streaming buffers
// internally.
//
int AllocateInternalStreamBuffers (PPDDCONTEXT pPDD, DWORD dwMaxBuff)
{
int i, rc = 0;
//
// See if the new format is too small for the current default
//
if (pPDD->strStreamDefault.dwBuffSize < dwMaxBuff)
{
// We/re changing buffers, stop the current read thread
StopReadThread (pPDD);
// Free old buffers
for (i = 0; i < NUMDEFBUFFS; i++)
{
if (pPDD->strStreamDefault.pFrame[i].pBuff) LocalFree (pPDD->strStreamDefault.pFrame[i].pBuff);
pPDD->strStreamDefault.pFrame[i].pBuff = 0;
}
// Allocate new buffers
for (i = 0; i < NUMDEFBUFFS; i++)
{
pPDD->strStreamDefault.pFrame[i].pBuff = (PBYTE)LocalAlloc (LPTR, dwMaxBuff);
// Check to see if the alloc is successful
if (pPDD->strStreamDefault.pFrame[i].pBuff == 0)
{
// If we've already allocated some buffs, we need to free the ones we did
if (i)
{
// Yes, I'm reusing 'i', but I'm bailing out of this loop
for (i = 0; i < NUMDEFBUFFS; i++)
{
if (pPDD->strStreamDefault.pFrame[i].pBuff) LocalFree (pPDD->strStreamDefault.pFrame[i].pBuff);
pPDD->strStreamDefault.pFrame[i].pBuff = 0;
}
}
DEBUGMSG (ZONE_ERROR, (DTAG TEXT("Failure allocating stream buffers\r\n")));
return ERROR_NOT_ENOUGH_MEMORY;
}
}
// We've set up the default buffs, set the buff ptr.
pPDD->strStreamDefault.dwBuffSize = dwMaxBuff;
// Use the reserved field to store the event handle local to the driver
if (pPDD->strStreamDefault.dwReserved == 0)
pPDD->strStreamDefault.dwReserved = (DWORD)CreateEvent (NULL, FALSE, FALSE, NULL);
}
return rc;
}
//-----------------------------------------------------------------------
// NegotiateQuality - Given a fixed set of format/frame/interval, see if a
// quality setting can be found that allows us to fit into the available
// bus bandwidth.
//
int NegotiateQuality (PDRVCONTEXT pDrv, BYTE bFormatIndex, BYTE bFrameIndex, DWORD dwValidInterval)
{
int rc;
DWORD dwBandwidth;
WORD wQuality, wQualityMin, wQualityMax, wQualityInc;
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("NegotiateQuality++\r\n")));
// Get our pdd specific context
PPDDCONTEXT pPDD = (PPDDCONTEXT)pDrv->dwPddContext;
// Get the range of valid compression values for this format/frame/rate
rc = GetMinMaxQuality (pDrv, bFormatIndex, bFrameIndex, dwValidInterval,
&wQualityMin, &wQualityMax, &wQualityInc);
if (rc == 0)
{
DEBUGMSG (ZONE_PROBE, (DTAG TEXT("Probe/Commit trying interval rate %d Comp: min %d max %d int %d\r\n"),
dwValidInterval, wQualityMin, wQualityMax, wQualityInc));
// Loop through each compression quality setting finding one that works.
for (wQuality = wQualityMax; wQuality >= wQualityMin; wQuality -= wQualityInc)
{
// Send the the paramters to the camera, it'll tell us the bandwidth it needs
rc = ProbeCommitVidStream (pDrv, bFormatIndex, bFrameIndex, &dwValidInterval, wQuality,
&dwBandwidth);
if (rc == 0)
{
// Save the format and stream rate
pPDD->wCurrFormatIndex = bFormatIndex;
pPDD->wCurrFrameIndex = bFrameIndex;
pPDD->dwCurrValidInterval = dwValidInterval;
// Try to find an interface that will support the bandwidth
rc = SetStreamInterface (pDrv, 1, dwBandwidth);
if (rc == 0)
{
//Probe commit worked and we have an interface. Yea! we're done.
DEBUGMSG (ZONE_PROBE, (DTAG TEXT("Probe/Commit complete. Fmt: %d Frm: %d rate %d Compression %d Bandwidth %d\r\n"),
bFormatIndex, bFrameIndex, dwValidInterval, wQuality, dwBandwidth));
break;
}
}
}
}
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("NegotiateQuality-- rc %d\r\n"), rc));
return rc;
}
//-----------------------------------------------------------------------
// FindStreamInterface - Find an interface given packet size needed.
// If fMin is true, it finds the slowest interface that meets the
// packet size. If fMin is false, if finds the fastest interface
// under the specified packet size.
//
PUSBSTRMIF FindStreamInterface (PPDDCONTEXT pPDD, BYTE nInterface,
BOOL fMin, WORD wPacketSize)
{
int i;
PUSBSTRMIF lpFound = 0;
// Find the interface
for (i = 0; i < pPDD->nStreamInterfaces; i++)
{
if (pPDD->usbstrmIF[i].ifDesc.bInterfaceNumber == nInterface)
{
// Does the interface even have an endpoint?
if (pPDD->usbstrmIF[i].fEndpoint)
{
if (fMin)
{
// Find the IF with min packet size that meets the needs
if (pPDD->usbstrmIF[i].epDesc.wMaxPacketSize >= wPacketSize)
{
if (lpFound == 0) lpFound = &pPDD->usbstrmIF[i];
if(pPDD->usbstrmIF[i].epDesc.wMaxPacketSize < lpFound->epDesc.wMaxPacketSize)
{
lpFound = &pPDD->usbstrmIF[i];
}
}
}
else
{
// Find the IF with packet size requested
if (pPDD->usbstrmIF[i].epDesc.wMaxPacketSize < wPacketSize)
{
if (lpFound == 0) lpFound = &pPDD->usbstrmIF[i];
if (pPDD->usbstrmIF[i].epDesc.wMaxPacketSize > lpFound->epDesc.wMaxPacketSize)
{
lpFound = &pPDD->usbstrmIF[i];
}
}
}
}
// See if we want a pipe with no bandwidth
else if (wPacketSize == 0)
return &pPDD->usbstrmIF[i];
}
}
if (lpFound)
return lpFound;
return 0;
}
//-----------------------------------------------------------------------
// SetStreamInterface - Sets the requested stream interface. The
// different stream interfaces have different data bandwidths.
//
BOOL SetStreamInterface (PDRVCONTEXT pDrv, BYTE nInterface, DWORD dwBandwidth)
{
USB_TRANSFER hTransfer;
PUSBSTRMIF lpIF;
int rc;
// Get our pdd specific context
PPDDCONTEXT pPDD = (PPDDCONTEXT)pDrv->dwPddContext;
DEBUGMSG (ZONE_FUNC, (DTAG TEXT("SetStreamInterface++ Interface:%d pktsize:%d\r\n"),
nInterface, dwBandwidth));
// Close the currently opened pipe if any
if (pPDD->pipeStream.hEvent != 0)
{
pDrv->lpUsbFuncs->lpClosePipe (pPDD->pipeStream.hPipe);
CloseHandle (pPDD->pipeStream.hEvent);
pPDD->pipeStream.hEvent = 0;
}
// For USB 1.x, 1 mS frame rate
WORD wPacketSize = (WORD)dwBandwidth;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -