#include <jpeg.hpp>
#include <vfw.h>
#include "math.h"
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#define MAX_FRAME 4194304
HWND capwnd=NULL; // окно захвата. без него в vfw никак
LPVIDEOHDR vhr; // информация о полученном кадре
HIC hic=NULL; // декомпрессор, нужен если кадр получаем не в формате DIB
bool grabbed;
//---------------------------------------------------------------------------
// это callback, где мы получим от драйвера готовый кадр
LRESULT __stdcall CALLBACK FrameCallback(HWND wnd, LPVIDEOHDR hdr)
{
vhr=hdr;
grabbed=true;
return true;
}
//---------------------------------------------------------------------------
void __fastcall TGetThread::Execute()
{
int n;
int jpgsize;
int capstate=0; // захват: 0=надо запустить, 1=запущено
int lastcount=0;
int lastsize;
BITMAPINFO bmi, bmo;
BITMAPFILEHEADER bfh; // заголовок bmp
CAPDRIVERCAPS caps;
jpg=new TJPEGImage();
stream1=new TMemoryStream();
stream1->Position=0;
stream1->SetSize(MAX_FRAME);
gbm=new Graphics::TBitmap;
buf0=new byte[MAX_FRAME];
capwnd=capCreateCaptureWindow('capture',WS_CHILD/*|WS_VISIBLE*/,0,0,640,480,Form1->Handle,RandomRange(100,1000000));
Sleep(200);
while (!Terminated)
{
Sleep(2);
if (capstate==0) // инициализируем захват
{
CloseCap();
if (Terminated) break;
if (capDriverConnect(capwnd, 0)) // цифра от 0 до 9 - номер драйвера видеозахвата
{
n=0;
while (n==0) // ждем готовность драйвера
{
if (Terminated) break;
Sleep(10);
capDriverGetCaps(capwnd, &caps, sizeof(CAPDRIVERCAPS));
n=caps.fCaptureInitialized;
}
capSetCallbackOnFrame(capwnd, FrameCallback);
capGetVideoFormat(capwnd, &bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biWidth=640;
bmi.bmiHeader.biHeight=480;
bmi.bmiHeader.biSizeImage=bmi.bmiHeader.biWidth*bmi.bmiHeader.biHeight*3;
bmi.bmiHeader.biCompression=BI_RGB;
capSetVideoFormat(capwnd, &bmi, sizeof(BITMAPINFO)); // попытаемся установить интересующий нас формат кадра
capGetVideoFormat(capwnd, &bmi, sizeof(BITMAPINFO));
n=bmi.bmiHeader.biWidth*bmi.bmiHeader.biHeight*3;
if (bmi.bmiHeader.biCompression!=BI_RGB) // если это не DIB, готовим декомпрессию
{
hic=ICOpen(mmioFOURCC('V','I','D','C'),bmi.bmiHeader.biCompression,ICMODE_DECOMPRESS);
ICDecompressGetFormat(hic,&(bmi.bmiHeader),&(bmo.bmiHeader));
ICDecompressBegin(hic,&(bmi.bmiHeader),&(bmo.bmiHeader));
}
bfh.bfType='B'+('M'<<8); // заголовок bmp файла
bfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
bfh.bfSize=n+bfh.bfOffBits;
bfh.bfReserved1=0;
bfh.bfReserved2=0;
lastcount=0;
lastsize=0;
capstate=1; // готов к работе!
}
else
{
Sleep(3000);
}
}
else if (capstate==1 && lastcount<50) // получаем и обрабатываем кадр
{
grabbed=false;
capGrabFrame(capwnd);
while (!grabbed && !Terminated) Sleep(2); // здесь зависнем, если камера изначально отсутствует
if (Terminated) break; // ErrorCallback не помогает
try
{
stream1->Size=0;
stream1->Position=0;
stream1->Write(&bfh, sizeof(BITMAPFILEHEADER));
if (hic==NULL)
{
stream1->Write(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
stream1->Write(vhr->lpData, vhr->dwBytesUsed);
}
else // сначала надо декомпрессировать кадр
{
stream1->Write(&bmo.bmiHeader, sizeof(BITMAPINFOHEADER));
ICDecompress(hic, 0, &(bmi.bmiHeader), vhr->lpData, &(bmo.bmiHeader), buf0);
stream1->Write(buf0, bmo.bmiHeader.biWidth*bmo.bmiHeader.biHeight*3);
}
stream1->Position=0; // теперь в stream1 полноценный bmp, можно его сохранить на диск
stream1->SaveToFile("c:\\001.bmp");
stream1->Position=0;
gbm->LoadFromStream(stream1); // мне нужен jpeg
jpg->CompressionQuality=80; // 1...100
jpg->Assign(gbm); // далее идут легкие извращения
stream1->Position=0;
stream1->Size=0;
jpg->SaveToStream(stream1);
stream1->Position=0;
jpgsize=stream1->Read(buf0, MAX_FRAME);
if (lastsize==jpgsize) lastcount++; // если камеру отключить, драйвер нам об этом не скажет
else {lastsize=jpgsize; lastcount=0;} // поэтому вычисляем зависон косвенно, по большому к-ву одинаковых кадров
}
catch(...)
{
}
}
else // 50 одинаковых по размеру кадров пришли подряд: йа завис
{
jpgsize=0;
capstate=0;
}
}
// здесь мы окажемся, когда пора закрываться
CloseCap();
delete jpg;
delete stream1;
delete gbm;
delete [] buf0;
}
//---------------------------------------------------------------------------
void __fastcall TGetThread::CloseCap(void)
{
capSetCallbackOnFrame(capwnd, NULL);
Sleep(200);
capDriverDisconnect(capwnd);
if (hic!=NULL)
{
ICDecompressEnd(hic);
ICClose(hic);
}
Sleep(50);
}
//---------------------------------------------------------------------------
В начало