最近的项目用到一个视频模块,要求很简单,就是用本机的摄像头、摄像机或照相机实时拍照获取照片,用 VFW 很容易实现了,不过 avicap 中的函数 capGetDriverDescription 在获取驱动名称的时候,只能获取基本接口驱动的名称 Microsoft WDM Image Capture (Win32),无法获取真实设备的名称,而且没有其它相关函数来实现此功能。

视频相关的开发现在首选 DirectShow,用 Delphi + DirectShow 很容易就实现了:

unit DirectShow;

interface

uses
    Windows, Messages, SysUtils, Variants, Classes, ActiveX;

const
    CLSID_SystemDeviceEnum: TGUID = (D1:$62BE5D10;D2:$60EB;D3:$11D0;D4:($BD,$3B,$00,$A0,$C9,$11,$CE,$86));
    CLSID_VideoInputDeviceCategory: TGUID = (D1:$860BB310;D2:$5D01;D3:$11D0;D4:($BD,$3B,$00,$A0,$C9,$11,$CE,$86));
    IID_ICreateDevEnum: TGUID = '{29840822-5B84-11D0-BD3B-00A0C911CE86}';
    IID_IPropertyBag: TGUID = '{55272A00-42CB-11CE-8135-00AA004BB851}';

type
    ICreateDevEnum = interface(IUnknown)
        ['{29840822-5B84-11D0-BD3B-00A0C911CE86}']
        function CreateClassEnumerator(const clsidDeviceClass: TGUID;
        out ppEnumMoniker: IEnumMoniker; dwFlags: DWORD): HResult; stdcall;
    end;

procedure GetVideoDeviceList(List: TStrings);

implementation

procedure GetVideoDeviceList(List: TStrings);
var
    SysDevEnum: ICreateDevEnum;
    EnumCat: IEnumMoniker;
    Moniker: IMoniker;
    PropBag: IPropertyBag;
    Fetched: LongInt;
    VarName: OleVariant;
begin
    CoCreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC, IID_ICreateDevEnum, SysDevEnum);
    SysDevEnum.CreateClassEnumerator(CLSID_VideoInputDeviceCategory, EnumCat, 0);

    List.Clear;
    while EnumCat.Next(1, Moniker, @Fetched) = S_OK do begin
        Moniker.BindToStorage(nil, nil, IID_IPropertyBag, PropBag);
        PropBag.Read('FriendlyName', VarName, nil);
        List.Add(VarName);
        PropBag := nil;
        Moniker := nil;
    end;

    EnumCat := nil;
    SysDevEnum := nil;
end;

end.