直接显示视频捕获性能

时间:2019-04-25 12:18:06

标签: c++ ffmpeg c++builder

最初,我开始寻找一个示例,说明由于性能不佳,我如何在c ++ Builder中使用FFMPEG创建一个应用程序以从USB捕获设备进行录制并播放视频

我尝试了使用DirectShow的Mitov组件,Datastead,FFMPEGVCL和Winsoft相机,但是它们的捕获性能似乎很差。

我需要以60fps的速度捕获1920x1080的压缩格式,然后以正常速度和慢速播放。

我发现DirectShow本身有很多限制,可以通过添加FFMPEG之类的东西来改善这些限制,但是最终添加PC硬件,尤其是HDD和处理器限制捕获功能。

1920x1080 60fps基本上是DirectShow的高端产品,因此您需要具有最佳性能的硬件才能实现这种性能。@ Spektre好心地给我提供了使用API​​ Direct的DirectShow示例,这些示例可以与购买的组件进行比较。

使用此方法并将其与组件进行比较,我发现MITOV在较大的视频尺寸和帧频方面存在一个主要问题。使用此1920x108,可以预览30fps和60fps,但它们在视频源和预览之间会有很大的延迟(5或6秒)。其他组件的执行类似于API直接方法,只是性能略有不同。没有任何一种压缩过滤器可以捕获和记录1920x108 60fps,而没有大的帧丢失和非常生硬的预览。

1 个答案:

答案 0 :(得分:1)

我认为您的问题不是视频捕获组件本身还是FFMPEG。主要问题是从摄像机获取图像的 Directshow VFW API 相对较慢。可以通过设置适当的图像格式来提高速度,例如:

  • 较小的分辨率
  • 不同的颜色编码(RGB 24bpp不是一个好主意)
  • 使用相机JPEG格式(并非所有相机都支持)

没有 JPEG 输出格式,即使在小分辨率下,我也无法通过 15 fps 。我的经验还表明, DirectShow VFW 慢一点(至少对于我的相机而言)。但是,并非所有相机都提供 VFW 驱动程序:(不再。

还请确保使用正确版本的 USB端口来确保 USB带宽,并且不要减少与同一HUB上其他设备的带宽!

这就是我在Borland / Embarcadero BDS 2006 C ++中用于摄像机捕获(几年前编码的 VFW )的作用:

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,因为它太大了,不能超过30K,但速度较慢(但是ist只是一个头文件+ lib文件,没有第3方组件)。我在表单上有这些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的链接,其中包含Embarcadero BDS2006 C ++中的VFWDirectShow示例(源代码和Win32二进制文件)。

[Edit2]您不受支持的格式

文件大小恰好为1920*1080*3字节,表明原始的24bpp RGB提要。当我尝试对其进行可视化处理时(是的,Y翻转了),请参见该代码(这次表单上没有任何组件):

//$$---- 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);
    }
//---------------------------------------------------------------------------

以及出现的屏幕:

decoded image

请注意,我将文件名重命名为maybe_RGB24.dat。您可以仅通过帧大小来解码此文件格式,但其信息应类似于

AM_MEDIA_TYPE* mt;

结构,但不要问我,我很早以前在哪里编写代码,因为我很久以前就编写了此代码,因此不使用 DirectX ,因为(因为我过去的所有尝试都显示出其与众不同的劣势api的声音或gfx或抓取都没有关系...)