Direct Show Производительность захвата видео - PullRequest
0 голосов
/ 25 апреля 2019

Изначально я искал пример того, как я могу использовать FFMPEG в C ++ Builder для создания приложения для записи с устройства захвата USB и воспроизведения видео из-за низкой производительности

Я пробовал компоненты Mitov, Datastead, FFMPEGVCL и камеру winsoft, которые используют DirectShow, но их производительность захвата казалась плохой.

Мне нужно записать 1920x1080 со скоростью до 60 кадров в секунду в сжатый формат и воспроизвести его позже как на обычной, так и на медленной скорости.

Я обнаружил, что у самого DirectShow есть ряд ограничений, которые можно улучшить, добавив такие вещи, как FFMPEG, но, в конечном счете, аппаратное обеспечение ПК, в частности возможность захвата жесткого диска и процессора.

1920x1080 60fps - это, в основном, верхний предел для DirectShow, поэтому для достижения такого рода производительности вам необходимо иметь наилучшее аппаратное обеспечение. @Spektre любезно предоставил мне примеры DirectShow с использованием API direct, которые были хороши для сравнения с приобретенными компонентами.

Используя это и сравнивая с компонентами, я обнаружил, что MITOV имеет серьезную проблему в отношении больших размеров видео и частоты кадров. При использовании этого разрешения 1920x108 можно просматривать 30 кадров в секунду и 60 кадров в секунду, но они имеют значительную задержку между подачей видео и предварительным просмотром (5 или 6 секунд). Другие компоненты выполнялись аналогично прямому методу API с незначительными изменениями производительности. Никто не смог захватить и записать 1920x108 60 кадров в секунду с любым типом фильтра сжатия без больших кадровых кадров и очень резкого предварительного просмотра.

1 Ответ

1 голос
/ 26 апреля 2019

Я не думаю, что ваша проблема в самом компоненте захвата видео или 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*

И полученный экран:

decoded image

Остерегайтесь, я переименовал имя файла в maybe_RGB24.dat. Вы можете декодировать этот формат файла только по размеру кадра, но его информация должна быть где-то как в

AM_MEDIA_TYPE* mt;

структура, но не спрашивайте меня, где именно я понятия не имею, так как я кодировал это давным-давно и не использую DirectX с тех пор (поскольку все мои попытки в прошлом показывают его неполноценность по отношению к другим API-интерфейсам не имеет значения, его звук или gfx или захват ...)

...