Implement missing features in CvCaptureCAM_VFW class.

Implemented missing CvCaptureCAM_VFW::setProperty() member function (handling CV_CAP_PROP_FRAME_WIDTH, CV_CAP_PROP_FRAME_HEIGHT, CV_CAP_PROP_FPS properties).
Extended CvCaptureCAM_VFW::setProperty()/getProperty() functions to handle also CV_CAP_PROP_FPS property.
Minor refactoring of CvCaptureCAM_VFW class.
This commit is contained in:
Artur Wieczorek 2014-04-20 21:37:29 +02:00
parent 7ba4212529
commit f27a886314

View File

@ -318,7 +318,7 @@ public:
virtual bool open( int index );
virtual void close();
virtual double getProperty(int);
virtual bool setProperty(int, double) { return false; }
virtual bool setProperty(int, double);
virtual bool grabFrame();
virtual IplImage* retrieveFrame(int);
virtual int getCaptureDomain() { return CV_CAP_VFW; } // Return the type of the capture object: CV_CAP_VFW, etc...
@ -332,6 +332,8 @@ protected:
HWND capWnd;
VIDEOHDR* hdr;
DWORD fourcc;
int width, height;
int widthSet, heightSet;
HIC hic;
IplImage* frame;
};
@ -345,6 +347,8 @@ void CvCaptureCAM_VFW::init()
fourcc = 0;
hic = 0;
frame = 0;
width = height = -1;
widthSet = heightSet = 0;
}
void CvCaptureCAM_VFW::closeHIC()
@ -407,16 +411,43 @@ bool CvCaptureCAM_VFW::open( int wIndex )
memset( &caps, 0, sizeof(caps));
capDriverGetCaps( hWndC, &caps, sizeof(caps));
::MoveWindow( hWndC, 0, 0, 320, 240, TRUE );
CAPSTATUS status = {};
capGetStatus(hWndC, &status, sizeof(status));
::SetWindowPos(hWndC, NULL, 0, 0, status.uiImageWidth, status.uiImageHeight, SWP_NOZORDER|SWP_NOMOVE);
capSetUserData( hWndC, (size_t)this );
capSetCallbackOnFrame( hWndC, frameCallback );
CAPTUREPARMS p;
capCaptureGetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
p.dwRequestMicroSecPerFrame = 66667/2;
p.dwRequestMicroSecPerFrame = 66667/2; // 30 FPS
capCaptureSetSetup(hWndC,&p,sizeof(CAPTUREPARMS));
//capPreview( hWndC, 1 );
capPreviewScale(hWndC,FALSE);
capPreviewRate(hWndC,1);
// Get frame initial parameters.
const DWORD size = capGetVideoFormatSize(capWnd);
if( size > 0 )
{
unsigned char *pbi = new unsigned char[size];
if( pbi )
{
if( capGetVideoFormat(capWnd, pbi, size) == size )
{
BITMAPINFOHEADER& vfmt = ((BITMAPINFO*)pbi)->bmiHeader;
widthSet = vfmt.biWidth;
heightSet = vfmt.biHeight;
fourcc = vfmt.biCompression;
}
delete []pbi;
}
}
// And alternative way in case of failure.
if( widthSet == 0 || heightSet == 0 )
{
widthSet = status.uiImageWidth;
heightSet = status.uiImageHeight;
}
}
return capWnd != 0;
}
@ -439,10 +470,8 @@ void CvCaptureCAM_VFW::close()
bool CvCaptureCAM_VFW::grabFrame()
{
if( capWnd )
{
SendMessage( capWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0 );
return true;
}
return capGrabFrameNoStop(capWnd) == TRUE;
return false;
}
@ -452,14 +481,13 @@ IplImage* CvCaptureCAM_VFW::retrieveFrame(int)
BITMAPINFO vfmt;
memset( &vfmt, 0, sizeof(vfmt));
BITMAPINFOHEADER& vfmt0 = vfmt.bmiHeader;
int sz, prevWidth, prevHeight;
if( !capWnd )
return 0;
sz = capGetVideoFormat( capWnd, &vfmt, sizeof(vfmt));
prevWidth = frame ? frame->width : 0;
prevHeight = frame ? frame->height : 0;
const DWORD sz = capGetVideoFormat( capWnd, &vfmt, sizeof(vfmt));
const int prevWidth = frame ? frame->width : 0;
const int prevHeight = frame ? frame->height : 0;
if( !hdr || hdr->lpData == 0 || sz == 0 )
return 0;
@ -470,8 +498,8 @@ IplImage* CvCaptureCAM_VFW::retrieveFrame(int)
frame = cvCreateImage( cvSize( vfmt0.biWidth, vfmt0.biHeight ), 8, 3 );
}
if( vfmt.bmiHeader.biCompression != BI_RGB ||
vfmt.bmiHeader.biBitCount != 24 )
if( vfmt0.biCompression != BI_RGB ||
vfmt0.biBitCount != 24 )
{
BITMAPINFOHEADER vfmt1 = icvBitmapHeader( vfmt0.biWidth, vfmt0.biHeight, 24 );
@ -518,15 +546,106 @@ double CvCaptureCAM_VFW::getProperty( int property_id )
switch( property_id )
{
case CV_CAP_PROP_FRAME_WIDTH:
return frame ? frame->width : 0;
return widthSet;
case CV_CAP_PROP_FRAME_HEIGHT:
return frame ? frame->height : 0;
return heightSet;
case CV_CAP_PROP_FOURCC:
return fourcc;
case CV_CAP_PROP_FPS:
{
CAPTUREPARMS params = {};
if( capCaptureGetSetup(capWnd, &params, sizeof(params)) )
return 1e6 / params.dwRequestMicroSecPerFrame;
}
break;
default:
break;
}
return 0;
}
bool CvCaptureCAM_VFW::setProperty(int property_id, double value)
{
bool handledSize = false;
switch( property_id )
{
case CV_CAP_PROP_FRAME_WIDTH:
width = cvRound(value);
handledSize = true;
break;
case CV_CAP_PROP_FRAME_HEIGHT:
height = cvRound(value);
handledSize = true;
break;
case CV_CAP_PROP_FOURCC:
break;
case CV_CAP_PROP_FPS:
if( value > 0 )
{
CAPTUREPARMS params;
if( capCaptureGetSetup(capWnd, &params, sizeof(params)) )
{
params.dwRequestMicroSecPerFrame = cvRound(1e6/value);
return capCaptureSetSetup(capWnd, &params, sizeof(params)) == TRUE;
}
}
break;
default:
break;
}
if ( handledSize )
{
// If both width and height are set then change frame size.
if( width > 0 && height > 0 )
{
const DWORD size = capGetVideoFormatSize(capWnd);
if( size == 0 )
return false;
unsigned char *pbi = new unsigned char[size];
if( !pbi )
return false;
if( capGetVideoFormat(capWnd, pbi, size) != size )
{
delete []pbi;
return false;
}
BITMAPINFOHEADER& vfmt = ((BITMAPINFO*)pbi)->bmiHeader;
bool success = true;
if( width != vfmt.biWidth || height != vfmt.biHeight )
{
// Change frame size.
vfmt.biWidth = width;
vfmt.biHeight = height;
vfmt.biSizeImage = height * ((width * vfmt.biBitCount + 31) / 32) * 4;
vfmt.biCompression = BI_RGB;
success = capSetVideoFormat(capWnd, pbi, size) == TRUE;
}
if( success )
{
// Adjust capture window size.
CAPSTATUS status = {};
capGetStatus(capWnd, &status, sizeof(status));
::SetWindowPos(capWnd, NULL, 0, 0, status.uiImageWidth, status.uiImageHeight, SWP_NOZORDER|SWP_NOMOVE);
// Store frame size.
widthSet = width;
heightSet = height;
}
delete []pbi;
width = height = -1;
return success;
}
return true;
}
return false;
}
CvCapture* cvCreateCameraCapture_VFW( int index )
{