Я не думаю, что ваша проблема в самом компоненте захвата видео или FFMPEG. Основная проблема в том, что Directshow и VFW API для получения изображения с камеры относительно медленный. Скорость можно улучшить, установив правильный формат изображения, например:
- меньшее разрешение
- кодировка другого цвета (RGB 24bpp не очень хорошая идея)
- с использованием формата JPEG камеры (не все камеры поддерживают его)
Без JPEG выходного формата Я никогда не получал пропуск 15 кадров в секунду даже при небольших разрешениях. Также мой опыт показывает, что DirectShow немного медленнее, чем VFW (по крайней мере, для моих камер). Однако не все камеры предоставляют драйвер VFW :( больше.
Также убедитесь, что пропускная способность USB обеспечена, используя правильную версию USB-порта , и не уменьшайте ее пропускную способность с другими устройствами на том же концентраторе !!!
Это то, что я использую для захвата камеры ( VFW я кодировал много лет назад) в Borland / Embarcadero BDS 2006 C ++:
VideoCaptureVFW.h:
//---------------------------------------------------------------------------
//--- VFW Video Capture ver: 2.0 --------------------------------------------
//---------------------------------------------------------------------------
#ifndef _VideoCaptureVFW_h
#define _VideoCaptureVFW_h
//---------------------------------------------------------------------------
#include <vfw.h>
#include <jpeg.hpp>
#include <Clipbrd.hpp>
//---------------------------------------------------------------------------
const int _vfw_callbach_onframe=1; // bit mask for each callback
//---------------------------------------------------------------------------
#ifndef _TDirectMemoryStream
#define _TDirectMemoryStream
class TDirectMemoryStream:TMemoryStream // just for accessing protected SetPointer
{
public:
void SetMemory(BYTE *ptr,DWORD siz) { SetPointer(ptr,siz); Position=0; };
};
#endif
//---------------------------------------------------------------------------
#ifndef _avgfps
#define _avgfps
class avgfps
{
public:
int N,N2;
int frame,frame0;
double fps,t0,t1,dt,Ts;
avgfps()
{
N=40; N2=N<<1;
fps=0.0; t0=0.0; frame=0; frame0=0;
LARGE_INTEGER i;
QueryPerformanceFrequency(&i); Ts=1.0/double(i.QuadPart);
}
~avgfps() {}
void update()
{
double t;
LARGE_INTEGER i;
QueryPerformanceCounter(&i); t=double(i.QuadPart)*Ts; dt=t-t0;
if (frame<=0)
{
t0=t; t1=t;
dt=0.0;
frame=0;
frame0=0;
}
if (dt>1e-6) fps=double(frame0)/dt; else fps=0.0;
frame++; frame0++;
if (frame0==N ) t1=t;
if (frame0==N2) { t0=t1; t1=t; frame0=N; }
}
};
#endif
//---------------------------------------------------------------------------
class VideoCaptureVFW
{
private:
HWND hcap,hown; // video capture window
public:
int ins_ix,ins_use; // instance index and usage for callbacks class reference
CAPDRIVERCAPS driver_cp; // driver capabilities
CAPTUREPARMS capture; // capture setup
CAPSTATUS state;
BITMAPINFO format;
// on frame callback
avgfps fps; // average fps
TMemoryStream *mem; // just for loading jpg from memory without copy
Graphics::TBitmap *bmp; // grabbed frame
VideoCaptureVFW();
~VideoCaptureVFW();
void ins_rst();
void ins_inc();
void ins_dec();
void set_owner(HWND _hown);
AnsiString get_video_drivers();
void set_video_driver(int ix);
void dlg_source() { if(driver_cp.fHasDlgVideoSource) capDlgVideoSource(hcap); }
void dlg_format() { if(driver_cp.fHasDlgVideoFormat) capDlgVideoFormat(hcap); get_state(); get_format(); }
void dlg_display(){ if(driver_cp.fHasDlgVideoDisplay)capDlgVideoDisplay(hcap);}
void dlg_compress() { capDlgVideoCompression(hcap); }
void get_capabil(){ capDriverGetCaps (hcap,&driver_cp,sizeof(CAPDRIVERCAPS)); }
void get_setup() { capCaptureGetSetup(hcap,&capture,sizeof(CAPTUREPARMS)); }
void set_setup() { capCaptureSetSetup(hcap,&capture,sizeof(CAPTUREPARMS)); }
void get_state() { capGetStatus (hcap,&state,sizeof(CAPSTATUS)); }
void get_format() { capGetVideoFormat (hcap,&format,sizeof(BITMAPINFO)); }
void preview_start(){ capPreview(hcap,TRUE ); }
void preview_stop() { capPreview(hcap,FALSE); }
void grab_start() { set_callback_on_frame(); capGrabFrameNoStop(hcap); }
void grab_stop() { res_callback_on_frame(); }
void copy_to_clipboard() { capEditCopy(hcap); }
void set_callback_on_frame();
void res_callback_on_frame();
LRESULT _on_frame(HWND hwnd,LPVIDEOHDR hdr);
void (*on_frame)(VideoCaptureVFW &cap);
};
//---------------------------------------------------------------------------
// on frame
const int _VideoCaptureVFW_ins=32;
void* VideoCaptureVFW_ins[_VideoCaptureVFW_ins]=
{
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
};
int VideoCaptureVFW_ins_get()
{
for (int i=0;i<_VideoCaptureVFW_ins;i++)
if (VideoCaptureVFW_ins[i]==NULL) return i;
return -1;
}
LRESULT PASCAL VideoCaptureVFW00_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 0]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW01_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 1]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW02_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 2]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW03_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 3]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW04_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 4]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW05_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 5]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW06_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 6]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW07_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 7]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW08_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 8]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW09_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[ 9]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW10_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[10]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW11_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[11]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW12_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[12]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW13_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[13]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW14_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[14]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW15_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[15]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW16_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[16]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW17_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[17]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW18_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[18]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW19_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[19]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW20_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[20]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW21_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[21]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW22_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[22]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW23_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[23]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW24_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[24]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW25_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[25]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW26_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[26]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW27_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[27]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW28_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[28]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW29_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[29]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW30_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[30]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL VideoCaptureVFW31_on_frame(HWND hwnd,LPVIDEOHDR hdr) { return ((VideoCaptureVFW*)(VideoCaptureVFW_ins[31]))->_on_frame(hwnd,hdr); }
LRESULT PASCAL(*VideoCaptureVFW_on_frame[_VideoCaptureVFW_ins])(HWND hwnd,LPVIDEOHDR hdr)=
{
VideoCaptureVFW00_on_frame,
VideoCaptureVFW01_on_frame,
VideoCaptureVFW02_on_frame,
VideoCaptureVFW03_on_frame,
VideoCaptureVFW04_on_frame,
VideoCaptureVFW05_on_frame,
VideoCaptureVFW06_on_frame,
VideoCaptureVFW07_on_frame,
VideoCaptureVFW08_on_frame,
VideoCaptureVFW09_on_frame,
VideoCaptureVFW10_on_frame,
VideoCaptureVFW11_on_frame,
VideoCaptureVFW12_on_frame,
VideoCaptureVFW13_on_frame,
VideoCaptureVFW14_on_frame,
VideoCaptureVFW15_on_frame,
VideoCaptureVFW16_on_frame,
VideoCaptureVFW17_on_frame,
VideoCaptureVFW18_on_frame,
VideoCaptureVFW19_on_frame,
VideoCaptureVFW20_on_frame,
VideoCaptureVFW21_on_frame,
VideoCaptureVFW22_on_frame,
VideoCaptureVFW23_on_frame,
VideoCaptureVFW24_on_frame,
VideoCaptureVFW25_on_frame,
VideoCaptureVFW26_on_frame,
VideoCaptureVFW27_on_frame,
VideoCaptureVFW28_on_frame,
VideoCaptureVFW29_on_frame,
VideoCaptureVFW30_on_frame,
VideoCaptureVFW31_on_frame,
};
//---------------------------------------------------------------------------
VideoCaptureVFW::VideoCaptureVFW()
{
hcap=NULL;
hown=NULL;
ins_ix=-1; ins_use=0;
on_frame=NULL;
mem=new TMemoryStream();
bmp=new Graphics::TBitmap;
}
//---------------------------------------------------------------------------
VideoCaptureVFW::~VideoCaptureVFW()
{
capDriverDisconnect(hcap);
res_callback_on_frame();
if (mem) delete mem;
if (bmp) delete bmp;
}
//---------------------------------------------------------------------------
void VideoCaptureVFW::set_owner(HWND _hown)
{
hown=_hown;
hcap=capCreateCaptureWindow("",WS_CHILD|WS_VISIBLE,0,0,1,1,hown,1);
}
//---------------------------------------------------------------------------
AnsiString VideoCaptureVFW::get_video_drivers()
{
const int _size=256;
char drv_name[_size];
char drv_ver[_size];
char dev_name[_size];
AnsiString s0,s1,list;
int i;
list="";
for (i=0;;i++)
{
if (!capGetDriverDescription(i,drv_name,_size,drv_ver,_size)) break;
s0=drv_name;
s1=drv_ver;
list+=s0+" "+s1+"\n";
}
return list;
}
//---------------------------------------------------------------------------
void VideoCaptureVFW::set_video_driver(int ix)
{
if (hcap==NULL) return;
capDriverConnect(hcap,ix);
capDriverGetCaps(hcap,&driver_cp,sizeof(CAPDRIVERCAPS));
capCaptureGetSetup(hcap,&capture,sizeof(CAPTUREPARMS));
// capture.dwRequestMicroSecPerFrame=10; // 1/fps [us]
capCaptureSetSetup(hcap,&capture,sizeof(CAPTUREPARMS));
capPreviewRate(hcap,1); // set preview [ms]
capPreviewScale(hcap,FALSE); // stretching off
//preview_start();
}
//---------------------------------------------------------------------------
void VideoCaptureVFW::set_callback_on_frame()
{
if (ins_ix<0) ins_ix=VideoCaptureVFW_ins_get();
if (ins_ix<0) return;
VideoCaptureVFW_ins[ins_ix]=this;
ins_use|=_vfw_callbach_onframe;
capSetCallbackOnFrame(hcap,(void*)(VideoCaptureVFW_on_frame[ins_ix]));
}
//---------------------------------------------------------------------------
void VideoCaptureVFW::res_callback_on_frame()
{
if (ins_ix<0) return;
if (int(ins_use&_vfw_callbach_onframe))
{
ins_use^=_vfw_callbach_onframe;
capSetCallbackOnFrame(hcap,NULL);
}
if (ins_use) return;
VideoCaptureVFW_ins[ins_ix]=NULL;
ins_ix=-1;
}
//---------------------------------------------------------------------------
LRESULT VideoCaptureVFW::_on_frame(HWND hwnd,LPVIDEOHDR hdr)
{
fps.update();
int e=0;
if (hdr->dwBytesUsed<16) return 0; // ignore too small images
((TDirectMemoryStream*)(mem))->SetMemory(hdr->lpData,hdr->dwBytesUsed);
if ((hdr->lpData[6]=='J') // JPEG signature
&&(hdr->lpData[7]=='F')
&&(hdr->lpData[8]=='I')
&&(hdr->lpData[9]=='F'))
{
e=1;
TJPEGImage *jpg=new TJPEGImage;
jpg->LoadFromStream(mem);
bmp->Assign(jpg);
delete jpg;
} else
if ((hdr->lpData[0]=='B') // BMP signature
&&(hdr->lpData[1]=='M'))
{
e=1;
bmp->LoadFromStream(mem);
}
else{ // others
e=1;
copy_to_clipboard();
try {
bmp->LoadFromClipboardFormat(CF_BITMAP,Clipboard()->GetAsHandle(CF_BITMAP),NULL);
}
catch(char *str)
{
e=0;
int hnd=FileCreate("unsuproted_format.dat");
FileWrite(hnd,hdr->lpData,hdr->dwBytesUsed);
FileClose(hnd);
}
}
if (e)
{
if (on_frame) on_frame(*this);
}
return 0;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
У меня есть небольшое тестовое приложение с этим исходным кодом:
//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
// select API:
#define _capture_VFW
// #define _capture_DirectShow
//---------------------------------------------------------------------------
#ifdef _capture_VFW
#include "VideoCaptureVFW.h"
#endif
#ifdef _capture_DirectShow
#include "DirectX92\\VideoCaptureDirectShow.cpp"
#endif
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graphics::TBitmap *bmp=new Graphics::TBitmap;
int _callback=0;
int _frame=0;
int _update=false;
//---------------------------------------------------------------------------
#ifdef _capture_VFW
VideoCaptureVFW vfw;
void on_frame_VFW(VideoCaptureVFW &cap)
{
if (_callback) Form1->Canvas->Draw(0,26,cap.bmp);
else if (!_frame) { bmp->Assign(cap.bmp); _frame=1; }
}
#endif
//---------------------------------------------------------------------------
#ifdef _capture_DirectShow
VideoCaptureDirectShow dsh;
void on_frame_DirectShow(VideoCaptureDirectShow &cap)
{
if (_callback) Form1->Canvas->Draw(0,26,cap.bmp);
else if (!_frame) { bmp->Assign(cap.bmp); _frame=1; }
}
#endif
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
#ifdef _capture_VFW
pan_VFW->Visible=true;
vfw.set_owner(this->Handle);
cb_driver->Items->Clear();
cb_driver->Items->Text=vfw.get_video_drivers();
cb_driver->ItemIndex=0;
vfw.on_frame=on_frame_VFW;
vfw.set_video_driver(cb_driver->ItemIndex);
vfw.grab_start();
#endif
#ifdef _capture_DirectShow
pan_DirectShow->Visible=true;
cb_device->Items->Clear();
cb_device->Items->Text=dsh.get_devices();
dsh.on_frame=on_frame_DirectShow;
_update=1;
cb_device->ItemIndex=0;
_update=0;
cb_device->OnChange(this);
/*
dsh.Select(0);
dsh.Start();
dsh.Stop();
*/
#endif
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
#ifdef _capture_VFW
vfw.grab_stop();
#endif
#ifdef _capture_DirectShow
dsh.Stop();
#endif
delete bmp;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
if ((!_callback)&&(_frame)) { Canvas->Draw(0,26,bmp); _frame=0; }
#ifdef _capture_VFW
Caption=AnsiString().sprintf("frame: %2i fps: %2.1lf",vfw.fps.frame,vfw.fps.fps);
#endif
#ifdef _capture_DirectShow
Caption=AnsiString().sprintf("frame: %2i fps: %2.1lf",dsh.fps.frame,dsh.fps.fps);
#endif
}
//---------------------------------------------------------------------------
//--- VFW -------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::bt_dialog_sourceClick(TObject *Sender)
{
#ifdef _capture_VFW
vfw.dlg_source();
#endif
}
void __fastcall TForm1::bt_dialog_formatClick(TObject *Sender)
{
#ifdef _capture_VFW
vfw.dlg_format();
#endif
}
void __fastcall TForm1::bt_dialog_displayClick(TObject *Sender)
{
#ifdef _capture_VFW
vfw.dlg_display();
#endif
}
void __fastcall TForm1::cb_driverChange(TObject *Sender)
{
#ifdef _capture_VFW
vfw.set_video_driver(cb_driver->ItemIndex);
vfw.grab_start();
#endif
}
//---------------------------------------------------------------------------
//--- DirectShow ------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::cb_deviceChange(TObject *Sender)
{
#ifdef _capture_DirectShow
if (_update) return;
_update=1;
dsh.Select(cb_device->ItemIndex);
cb_format->Items->Clear();
cb_format->Items->Text=dsh.get_formats();
if (cb_format->Items->Count)
cb_format->ItemIndex=0;
_update=0;
cb_format->OnChange(this);
#endif
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cb_formatChange(TObject *Sender)
{
#ifdef _capture_DirectShow
if (_update) return;
_update=1;
dsh.set_format(cb_format->Text);
_update=0;
#endif
}
//---------------------------------------------------------------------------
Единое приложение формы с несколькими кнопками и списками со списком для диалоговых окон и конфигурации (вы можете имитировать их или игнорировать их). Не разделял DirectShow, так как он слишком велик для ограничения в 30 КБ и все равно медленнее (но это просто заголовок + файл lib без сторонних компонентов). У меня есть эти компоненты VCL на форме:
TTimer *Timer1; // 10ms info text update
TPanel *pan_VFW; // just to hold the components for VFW
TSpeedButton *bt_dialog_source; // these 3 buttons configure VFW ...
TSpeedButton *bt_dialog_format;
TSpeedButton *bt_dialog_display;
TComboBox *cb_driver; // this selects VFW device
TPanel *pan_DirectShow; // just to hold DirectShow components
TComboBox *cb_device; // this selects DirectShow device
TComboBox *cb_format; // this selects DirectShow format
Я инкапсулировал VFW и DirectShow в конфигурацию #define
, чтобы вы могли полностью игнорировать DirectShow .
Теперь, когда вы используете это, вы можете играть с разрешением и форматами, чтобы сравнить fps с вашим DirectShow компонентным граббером.
Как видите, я не использую сторонние компоненты для получения данных изображения с камеры, VideoCaptureVFW.h
- единственное, что вам нужно.
[Edit1]
Вот ссылка на Demo , содержащую примеры VFW
и DirectShow
(исходные файлы и файлы win32) в Embarcadero BDS2006 C ++.
[Edit2] ваш неподдерживаемый формат
Размер файла ровно 1920//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graphics::TBitmap *bmp=NULL;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
int xs=1920,ys=1080,x,y,a,hnd,siz;
BYTE *p,*dat=NULL;
// load frame
hnd=FileOpen("maybe_RGB24.dat",fmOpenRead);
siz=FileSeek(hnd,0,2); dat=new BYTE[siz];
FileSeek(hnd,0,0);
FileRead(hnd,dat,siz);
FileClose(hnd);
// convert RGB24 to 32bpp bitmap
bmp=new Graphics::TBitmap;
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf32bit;
bmp->SetSize(xs,ys);
for (a=0,y=ys-1;y>=0;y--) // flip y
{
p=(BYTE*)bmp->ScanLine[y];
for (x=0;x<xs;x++)
{
p[0]=dat[a]; a++;
p[1]=dat[a]; a++;
p[2]=dat[a]; a++;
p[3]=0;
p+=4;
}
}
delete dat;
// resize form
ClientWidth=xs;
ClientHeight=ys;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
if (bmp) delete bmp; bmp=NULL;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
Canvas->Draw(0,0,bmp);
}
//---------------------------------------------------------------------------
3
Байт, что намекает на необработанный канал RGB 24bpp. Когда я попытался визуализировать это, это работает (и да, Y перевернуто), посмотрите код (никаких компонентов в форме на этот раз):
*1080*
И полученный экран:
Остерегайтесь, я переименовал имя файла в maybe_RGB24.dat
. Вы можете декодировать этот формат файла только по размеру кадра, но его информация должна быть где-то как в
AM_MEDIA_TYPE* mt;
структура, но не спрашивайте меня, где именно я понятия не имею, так как я кодировал это давным-давно и не использую DirectX с тех пор (поскольку все мои попытки в прошлом показывают его неполноценность по отношению к другим API-интерфейсам не имеет значения, его звук или gfx или захват ...)