RAD Studio 10.2.3 测试√


目录

  • 声明:
  • 1.展示设备
  • 2.展示格式
  • 3.打开预览
  • 4.保存图片至本地
  • 5.色彩选择 和 通道选项
  • 附件:untUSBCamera单元文件


声明:

usesDirectShow9, untUSBCamera, Winapi.ActiveXprivate{ Private declarations }// 系统开发人员枚举【基本 Filter】mBaseFilter           : IBaseFilter;// FI图形生成器【图形生成器】mGraphBuilder        : IGraphBuilder;// FI媒体控制【媒体控制】mMediaControl        : IMediaControl;// FI视频窗口【视频窗口】mVideoWindow         : IVideoWindow;// FI捕获图生成器2【捕获图生成器2】mCaptureGraphBuilder2: ICaptureGraphBuilder2;// FI样品采集器【样品采集器】mSampleGrabber       : ISampleGrabber;procedure FreeGraph;procedure mSnapBmp;function ShowFilterPropertyPages(filter: IBaseFilter; hFormHandle: THandle): Boolean;function ShowPinPropertyPages(pin: IPin; hFormHandle: THandle): Boolean;
// 视频预览变量初始化
procedure TForm1.FreeGraph;
beginmBaseFilter            := nil;mGraphBuilder         := nil;mMediaControl         := nil;mVideoWindow          := nil;mCaptureGraphBuilder2 := nil;mSampleGrabber        := nil;
end;// 截图 -- 保存
procedure TForm1.mSnapBmp;
varpfs        : TFilterState;mt         : TAMMediaType;hr         : HResult;pBufferSize: Integer;pBuffer    : PByte;bmp        : TBitmap;vi         : PVideoInfoHeader;
beginif mMediaControl = nil thenExit;// FI媒体控制.获取状态(时间,Filter状态)mMediaControl.GetState(1000, pfs);if pfs = State_Stopped thenExit;{ 获取媒体类型 }// = 样品采集器.获取连接的媒体类型(媒体类型)hr := mSampleGrabber.GetConnectedMediaType(mt);if hr <> S_OK thenExit;// 如果 媒体类型.格式 = nilif mt.pbFormat = nil thenExit;// = 视频信息标题(媒体类型.格式)vi := PVideoInfoHeader(mt.pbFormat);{ 获取当前帧数据大小 }// = 样品采集器.获取当前缓冲区(p缓冲区大小,nil)hr := mSampleGrabber.GetCurrentBuffer(pBufferSize, nil);if hr <> S_OK thenExit;{ 分配内存大小 }pBuffer := AllocMem(pBufferSize);try{ 再一次获取当前帧,获取图像数据 }hr := mSampleGrabber.GetCurrentBuffer(pBufferSize, pBuffer);if hr <> S_OK thenExit;{ 创建位图 }bmp := TBitmap.Create;try// bmp.像素格式 =bmp.PixelFormat := pf24bit;bmp.width       := vi^.bmiHeader.biWidth;bmp.height      := vi^.bmiHeader.biHeight;SetBitmapBits(bmp.Handle, vi^.bmiHeader.biSizeImage, pBuffer);bmp.Canvas.CopyRect(bmp.Canvas.ClipRect, bmp.Canvas, Rect(0, bmp.height, bmp.width, 0));// 把位图信息放在img控件中bmp.SaveToFile(ExtractFilePath(Paramstr(0)) + 'Temp\' + FormatDateTime('YYYYMMDDhhmmss', Now()) + '.jpg');finallybmp.Free;end;finallyFreeMem(pBuffer);end;
end;// 显示 Filter 属性页【调用 Filter 的属性页,窗口的 Windows 本身的】
function TForm1.ShowFilterPropertyPages(filter: IBaseFilter; hFormHandle: THandle): Boolean;
var// 指定属性页pSpecify: ISpecifyPropertyPages;// 全局唯一标识符caGUID  : TCAGUID;
beginResult   := False;pSpecify := nil;filter.QueryInterface(ISpecifyPropertyPages, pSpecify);if pSpecify <> nil thenbegin// 指定属性页.获取页面(全局唯一标识符)pSpecify.GetPages(caGUID);pSpecify := nil;Result   := OleCreatePropertyFrame(hFormHandle, 0, 0, '', 1, Pointer(@filter), caGUID.cElems, PGUID(caGUID.pElems), 0, 0, nil) = S_OK;CoTaskMemFree(caGUID.pElems);end;
end;function TForm1.ShowPinPropertyPages(pin: IPin; hFormHandle: THandle): Boolean;
var// 指定属性页pSpecify: ISpecifyPropertyPages;// 全局唯一标识符caGUID  : TCAGUID;
beginResult   := False;pSpecify := nil;// Filter.查询接口(类型,值【指定属性页】)pin.QueryInterface(ISpecifyPropertyPages, pSpecify);if pSpecify <> nil thenbegin// 指定属性页.获取页面(全局唯一标识符)pSpecify.GetPages(caGUID);pSpecify := nil;Result   := OleCreatePropertyFrame(hFormHandle, 0, 0, '', 1, Pointer(@pin), caGUID.cElems, PGUID(caGUID.pElems), 0, 0, nil) = S_OK;CoTaskMemFree(caGUID.pElems);end;
end;

1.展示设备

begin{ 视频预览变量初始化 }FreeGraph;// 获取所有USB摄像头,存入下面控件的列表中EnumAllUSBCamera(ListBox3.Items);
end;

2.展示格式

beginif ListBox3.ItemIndex = -1 thenbeginShowMessage('请选择设备!');exit;end;{ 枚举视频支持格式 }if not EnumVideoFormat(String(PVideoInputInfo(ListBox3.Items.Objects[ListBox3.ItemIndex])^.strName), PVideoInputInfo(ListBox3.Items.Objects[ListBox3.ItemIndex])^.index, ListBox4.Items) thenExit;ListBox4.ItemIndex := 0;ListBox4.SetFocus;
end;

3.打开预览

beginif mMediaControl = nil thenbegin{ 视频预览 }if USBVideoPreview(mGraphBuilder, mCaptureGraphBuilder2, mBaseFilter, mVideoWindow, mMediaControl, mSampleGrabber, PVideoInputInfo(ListBox3.Items.Objects[ListBox3.ItemIndex]), PVideoFormatInfo(ListBox4.Items.Objects[ListBox4.ItemIndex]), Panel1, True) thenbeginButton14.Caption := '3.停止预览';mMediaControl.Run;end;endelsebeginButton14.Caption := '3.打开预览';mMediaControl.Stop;FreeGraph;end;
end;

4.保存图片至本地

beginmSnapBmp;
end;

5.色彩选择 和 通道选项

// 色彩选择
beginShowFilterPropertyPages(mBaseFilter, Handle);
end;
// 通道选项
varpin: IPin;
beginmCaptureGraphBuilder2.FindPin(mBaseFilter, PINDIR_OUTPUT, nil, nil, False, 0, pin);ShowPinPropertyPages(pin, Handle);
end;

附件:untUSBCamera单元文件

unit untUSBCamera;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, DirectShow9, ActiveX, Dialogs, StdCtrls, ExtCtrls;typePVideoInputInfo  = ^TVideoInputInfo;PVideoFormatInfo = ^TVideoFormatInfo;{ 视频输入设备 }TVideoInputInfo = recordid: TGUID;strName: ShortString;index: Integer;end;{ 视频支持格式 }TVideoFormatInfo = recordid: TGUID;iWidth, iHeight: Integer;iMod: TGUID;Frame: Int64;format: ShortString;end;typeIAMStreamConfig = interface(IUnknown)['{C6E13340-30AC-11d0-A18C-00A0C9118956}']function SetFormat(const pmt: TAMMediaType): HResult; stdcall;function GetFormat(out ppmt: PAMMediaType): HResult; stdcall;function GetNumberOfCapabilities(out piCount, piSize: Integer): HResult; stdcall;{ Delphi 声明有误,修改声明 }function GetStreamCaps(iIndex: Integer; var ppmt: PAMMediaType; pSCC: PVideoStreamConfigCaps): HResult; stdcall;end;ISampleGrabber = interface(IUnknown)['{6B652FFF-11FE-4FCE-92AD-0266B5D7C78F}']function SetOneShot(OneShot: BOOL): HResult; stdcall;{ Delphi 声明有误,修改声明 }function SetMediaType(pType: PAMMediaType): HResult; stdcall;function GetConnectedMediaType(out pType: TAMMediaType): HResult; stdcall;function SetBufferSamples(BufferThem: BOOL): HResult; stdcall;function GetCurrentBuffer(var pBufferSize: longint; pBuffer: Pointer): HResult; stdcall;function GetCurrentSample(out ppSample: IMediaSample): HResult; stdcall;function SetCallback(pCallback: ISampleGrabberCB; WhichMethodToCallback: longint): HResult; stdcall;end;{ 枚举所有视频输入设备 }
/// <summary>
/// 枚举所有视频输入设备
/// </summary>
/// <param name="strsList">设备名称展示的存放地方</param>
procedure EnumAllUSBCamera(strsList: TStrings);{ 枚举视频支持格式 }
/// <summary>
/// 枚举视频支持格式【遍历出支持的视频格式】
/// </summary>
/// <param name="strFriendlyName">传进来的设备名称</param>
/// <param name="intIndex">设备的下标序号</param>
/// <param name="strsList">格式展示的box</param>
/// <returns>布尔类型</returns>
function EnumVideoFormat(const strFriendlyName: String; const intIndex: Integer; strsList: TStrings): Boolean;{ 视频预览 }
/// <summary>
/// 视频预览【USB视频预览】
/// </summary>
/// <param name="FIGraphBuilder">FI图形生成器</param>
/// <param name="FICaptureGraphBuilder2">FI捕获图生成器2</param>
/// <param name="FSysDevEnum">FSys开发枚举【mBaseFilter】</param>
/// <param name="FIVideoWindow">FI视频窗口</param>
/// <param name="FIMediaControl">FI媒体控制</param>
/// <param name="FISampleGrabber">FI样品采集器</param>
/// <param name="pv">P视频输入信息(USB摄像头.列表.对象[pv])</param>
/// <param name="pf">P视频输入信息(USB摄像头支持格式.列表.对象[pf])</param>
/// <param name="pnl">pnl视频【放视频的面板】</param>
/// <param name="bSnapBmp">是否需要截屏功能</param>
/// <returns>布尔类型</returns>
function USBVideoPreview(var FIGraphBuilder: IGraphBuilder; var FICaptureGraphBuilder2: ICaptureGraphBuilder2; var FSysDevEnum: IBaseFilter; var FIVideoWindow: IVideoWindow; var FIMediaControl: IMediaControl; var FISampleGrabber: ISampleGrabber; pv: PVideoInputInfo; pf: PVideoFormatInfo; pnl: TPanel; const bSnapBmp: Boolean = True): Boolean;{ 视频录制 }
/// <summary>
/// 视频录制【USB视频录制】
/// </summary>
/// <param name="FIGraphBuilder">FI图形生成器</param>
/// <param name="FICaptureGraphBuilder2">FI捕获图生成器</param>
/// <param name="FSysDevEnum">FSys开发枚举</param>
/// <param name="FIVideoWindow">FI视频窗口</param>
/// <param name="FIMediaControl">FI媒体控制</param>
/// <param name="FISampleGrabber">FI样品采集器</param>
/// <param name="pv">P视频输入信息(USB摄像头.列表.对象[pv])</param>
/// <param name="pf">P视频输入信息(USB摄像头支持格式.列表.对象[pf])</param>
/// <param name="pnl">pnl视频【放视频的面板】</param>
/// <param name="strSaveFileName">视频文件保存的位置</param>
/// <returns>布尔类型</returns>
function USBVideoRecord(var FIGraphBuilder: IGraphBuilder; var FICaptureGraphBuilder2: ICaptureGraphBuilder2; var FSysDevEnum: IBaseFilter; var FIVideoWindow: IVideoWindow; var FIMediaControl: IMediaControl; var FISampleGrabber: ISampleGrabber; pv: PVideoInputInfo; pf: PVideoFormatInfo; pnl: TPanel; const strSaveFileName: String): Boolean;implementationconstIID_IPropertyBag: TGUID = '{55272A00-42CB-11CE-8135-00AA004BB851}';c_arrVideoFormatGUID: array [0 .. 35] of PGUID = (                                                                                 //@MEDIASUBTYPE_CLPL, @MEDIASUBTYPE_YUYV, @MEDIASUBTYPE_IYUV, @MEDIASUBTYPE_YVU9, @MEDIASUBTYPE_Y411, @MEDIASUBTYPE_Y41P,          //@MEDIASUBTYPE_YUY2, @MEDIASUBTYPE_YVYU, @MEDIASUBTYPE_UYVY, @MEDIASUBTYPE_Y211, @MEDIASUBTYPE_YV12, @MEDIASUBTYPE_CLJR,          //@MEDIASUBTYPE_IF09, @MEDIASUBTYPE_CPLA, @MEDIASUBTYPE_MJPG, @MEDIASUBTYPE_TVMJ, @MEDIASUBTYPE_WAKE, @MEDIASUBTYPE_CFCC,          //@MEDIASUBTYPE_IJPG, @MEDIASUBTYPE_Plum, @MEDIASUBTYPE_DVCS, @MEDIASUBTYPE_DVSD, @MEDIASUBTYPE_MDVF, @MEDIASUBTYPE_RGB1,          //@MEDIASUBTYPE_RGB4, @MEDIASUBTYPE_RGB8, @MEDIASUBTYPE_RGB565, @MEDIASUBTYPE_RGB555, @MEDIASUBTYPE_RGB24, @MEDIASUBTYPE_RGB32,    //@MEDIASUBTYPE_ARGB1555, @MEDIASUBTYPE_ARGB4444, @MEDIASUBTYPE_ARGB32, @MEDIASUBTYPE_AYUV, @MEDIASUBTYPE_AI44, @MEDIASUBTYPE_IA44 //);c_arrVideoFormatName: array [0 .. 35] of AnsiString = (    //'CLPL', 'YUYV', 'IYUV', 'YVU9', 'Y411', 'Y41P',          //'YUY2', 'YVYU', 'UYVY', 'Y211', 'YV12', 'CLJR',          //'IF09', 'CPLA', 'MJPG', 'TVMJ', 'WAKE', 'CFCC',          //'IJPG', 'Plum', 'DVCS', 'DVSD', 'MDVF', 'RGB1',          //'RGB4', 'RGB8', 'RGB565', 'RGB555', 'RGB24', 'RGB32',    //'ARGB1555', 'ARGB4444', 'ARGB32', 'AYUV', 'AI44', 'IA44' //);function GetMaxIndex(const strsList: TStrings; const strUSBCameraName: string): Integer;
varIII, Count: Integer;
beginResult  := 0;Count   := strsList.Count;for III := 0 to Count - 1 dobeginif CompareText(String(PVideoInputInfo(strsList.Objects[III])^.strName), strUSBCameraName) = 0 thenbeginResult := Result + 1;end;end;
end;// 创建 Filter【Filter 实际上它不是物理摄像头,只是模拟摄像头设备可以采集图像】
/// <summary>
/// 创建 Filter【Filter 实际上它不是物理摄像头,只是模拟摄像头设备可以采集图像
/// </summary>
/// <param name="gid">全局唯一标识</param>
/// <param name="FriendlyName">摄像头名字</param>
/// <param name="instanceIndex">摄像头下标序号</param>
/// <returns>基本 Filter</returns>
function CreateFilter(gid: TGUID; FriendlyName: AnsiString; instanceIndex: Integer): IBaseFilter;
varpSysDevEnum: ICreateDevEnum;pEnumCat   : IEnumMoniker;pMoniker   : IMoniker;cFetched   : ULONG;pPropBag   : IPropertyBag;bc         : IBindCtx;mo         : IMoniker;er         : IErrorLog;ov         : OleVariant;iIndex     : Integer;
beginResult := nil;// 系统开发人员枚举pSysDevEnum := nil;// 枚举猫pEnumCat    := nil;// 绰号pMoniker    := nil;// 如果 共同创建实例() = 0if CocreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC, IID_ICreateDevEnum, pSysDevEnum) = S_OK thenbegin// 系统开发人员枚举.创建类枚举器(gid,枚举猫,0)if pSysDevEnum.CreateClassEnumerator(gid, pEnumCat, 0) = S_OK thenbeginiIndex := 0;while (pEnumCat.Next(1, pMoniker, @cFetched) = S_OK) and (cFetched > 0) and (pMoniker <> nil) dobeginbc := nil;mo := nil;pMoniker.BindToStorage(bc, mo, IID_IPropertyBag, pPropBag);er := nil;pPropBag.Read('FriendlyName', ov, er);if AnsiString(ov) = FriendlyName thenbeginif iIndex = instanceIndex thenbeginbc := nil;mo := nil;pMoniker.BindToObject(bc, mo, IID_IBaseFilter, Result);end;Inc(iIndex);end;pPropBag := nil;pMoniker := nil;end;end;end;pEnumCat    := nil;pSysDevEnum := nil;
end;function VideoMediaSubTypeToStr(mst: TGUID): AnsiString;
varI: Integer;
beginResult := '';for I  := 0 to 35 doif CompareMem(c_arrVideoFormatGUID[I], @mst, sizeof(TGUID)) thenbeginResult := c_arrVideoFormatName[I];break;end;
end;procedure FreeMediaType(mt: TAMMediaType);
beginif (mt.cbFormat <> 0) thenbeginCoTaskMemFree(mt.pbFormat);mt.cbFormat := 0;mt.pbFormat := nil;end;if (mt.pUnk <> nil) thenbeginmt.pUnk := nil;end;
end;procedure DeleteMediaType(pmt: PAMMediaType);
beginif pmt <> nil thenbeginFreeMediaType(pmt^);CoTaskMemFree(pmt);end;
end;// 获取输出引脚
function GetOutputPin(filter: IBaseFilter): IPin;
varpenum: IEnumPins;f    : Integer;d    : PIN_DIRECTION;
beginResult := nil;filter.EnumPins(penum);while (penum.Next(1, Result, @f) = S_OK) and (f > 0) dobeginif (Result.QueryDirection(d) = S_OK) and (d = PINDIR_OUTPUT) thenbegin{ 找到输出接口,返回 }Exit;end;end;Result := nil;
end;// Str到视频媒体子类型(格式)
function StrToVideoMediaSubType(ss: AnsiString): TGUID;
varI: Integer;
beginResult := c_arrVideoFormatGUID[0]^;for I  := 0 to 35 doif ss = c_arrVideoFormatName[I] thenbeginResult := c_arrVideoFormatGUID[I]^;break;end;
end;function CompareGUID(const g1, g2: TGUID): Boolean;
beginResult := CompareMem(@g1, @g2, sizeof(TGUID));
end;// 设置媒体类型(基本Filter,宽,高,格式)
function SetMediaType(filter: IBaseFilter; Width, Height: Integer; format: AnsiString): Boolean;
varpmt            : PAMMediaType;piCount, piSize: Integer;I              : Integer;pSCC           : PVideoStreamConfigCaps;streamConfig   : IAMStreamConfig;outPin         : IPin;formatID       : TGUID;selectedIndex  : Integer;ih             : PVIDEOINFOHEADER;bitRate        : dword;
beginResult := False;if (Width = 0) or (Height = 0) thenExit;// 获取输出引脚outPin := GetOutputPin(filter);// 查询界面(IID_IAM流配置,流配置)outPin.QueryInterface(IID_IAMStreamConfig, streamConfig);// 如果 已分配(流配置)if assigned(streamConfig) thenbegin// 选定索引 = -1selectedIndex := -1;// 比特率 = 0bitRate       := 0;// 格式ID = Str到视频媒体子类型(格式)formatID      := StrToVideoMediaSubType(format);// 配置流.获取功能数量(数量,大小)streamConfig.GetNumberOfCapabilities(piCount, piSize);// getmen(视频流配置上限,大小)getmem(pSCC, piSize);tryfor I := 0 to piCount - 1 dobegin// 配置流.获取流上限(选定索引,媒体类型,视频流配置上限)streamConfig.GetStreamCaps(I, pmt, pSCC);// 视频信息头ih := Pointer(pmt^.pbFormat);// 选择最大比特率的格式if (pSCC^.MinOutputSize.cx = Width) and (pSCC^.MinOutputSize.cy = Height) and (ih^.bmiHeader.biWidth = Width) and (ih^.bmiHeader.biheight = Height) and ((format = '') or (CompareGUID(formatID, pmt^.subtype))) and (ih^.dwBitRate > bitRate) // select format with maximum bitratethenbeginselectedIndex := I;bitRate       := ih^.dwBitRate;end;// 删除媒体类型(媒体类型)DeleteMediaType(pmt);end;if selectedIndex > -1 thenbeginstreamConfig.GetStreamCaps(selectedIndex, pmt, pSCC);try// 配置流.设置格式()streamConfig.SetFormat(pmt^);finallyDeleteMediaType(pmt);end;end;finally// 释放FreeMem(pSCC);end;end;Result := True;
end;// 枚举所有USB摄像头
{ 枚举所有视频输入设备 }
procedure EnumAllUSBCamera(strsList: TStrings);
varSysDevEnum: ICreateDevEnum;EnumCat   : IEnumMoniker;hr        : Integer;Moniker   : IMoniker;Fetched   : ULONG;PropBag   : IPropertyBag;strName   : OleVariant;strGuid   : OleVariant;III       : Integer;puInfo    : PVideoInputInfo;intIndex  : Integer;
begin// 共同创建实例{ 创建系统枚举器对象 }hr := CocreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC, IID_ICreateDevEnum, SysDevEnum);// 如果 hr <> 0if hr <> S_OK thenExit;// 系统开发人员枚举.创建类枚举器(CLSID视频输入设备类别,枚举猫,0){ 用指定的 Filter 目录类型创建一个枚举器,并获得 IEnumMoniker 接口; }hr := SysDevEnum.CreateClassEnumerator(CLSID_VideoInputDeviceCategory, EnumCat, 0);if hr <> S_OK thenExit;try{ 释放内存 }// 如果 数组的成员数量 > 0if strsList.Count > 0 thenbeginfor III := 0 to strsList.Count - 1 dobegin// 释放(视频格式信息(对象))FreeMem(PVideoFormatInfo(strsList.Objects[III]));end;end;// 数组释放strsList.Clear;{ 获取指定类型目录下所有设备标识 }while (EnumCat.Next(1, Moniker, @Fetched) = S_OK) dobeginMoniker.BindToStorage(nil, nil, IID_IPropertyBag, PropBag);PropBag.Read('CLSID', strGuid, nil);PropBag.Read('FriendlyName', strName, nil);New(puInfo);puInfo^.id      := TGUID(strGuid);puInfo^.strName := ShortString(strName);puInfo^.index   := 0;if strsList.IndexOf(strName) = -1 thenbeginstrsList.AddObject(strName, TObject(puInfo));endelsebegin{ 相同名称的 USBCamera 相机,<有可能有多个名称重复的相机> }intIndex      := GetMaxIndex(strsList, strName);puInfo^.index := intIndex + 1;strsList.AddObject(strName + format('(%d)', [puInfo^.index]), TObject(puInfo));end;PropBag := nil;Moniker := nil;end;finallyEnumCat    := nil;SysDevEnum := nil;end;
end;// 遍历出来所有支持的格式【各种分辨率】参数1:传进来的名字,参数2:选择名字的下标,参数3:枚举出来的格式放在那里
{ 枚举视频支持格式 }
function EnumVideoFormat(const strFriendlyName: String; const intIndex: Integer; strsList: TStrings): Boolean;
varSysDevEnum          : IBaseFilter;CaptureGraphBuilder2: ICaptureGraphBuilder2;iunk                : IUnknown;fStreamConfig       : IAMStreamConfig;piCount, piSize     : Integer;III                 : Integer;pmt                 : PAMMediaType;pSCC                : PVideoStreamConfigCaps;pvInfo              : PVideoFormatInfo;
beginResult := False;// Filter 实际上它不是物理摄像头,只是模拟摄像头设备可以采集图像{ 获取指定USB摄像头的 Filter }SysDevEnum := CreateFilter(CLSID_VideoInputDeviceCategory, AnsiString(strFriendlyName), intIndex);if SysDevEnum = nil thenExit;{ 释放内存 }if strsList.Count > 0 thenbeginfor III := 0 to strsList.Count - 1 dobeginFreeMem(PVideoFormatInfo(strsList.Objects[III]));end;end;strsList.Clear;{ 创建 ICaptureGraphBuilder2 接口 }if Failed(CocreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, CaptureGraphBuilder2)) thenExit;{ 获取 IID_IAMStreamConfig 接口 }if Failed(CaptureGraphBuilder2.FindInterface(nil, nil, SysDevEnum, IID_IAMStreamConfig, iunk)) thenExit;{ 获取 IAMStreamConfig 媒体类型接口 }if Failed(iunk.QueryInterface(IID_IAMStreamConfig, fStreamConfig)) thenExit;if Failed(fStreamConfig.GetNumberOfCapabilities(piCount, piSize)) thenExit;if piCount <= 0 thenExit;// pSCC 视频流配置上线{ 枚举支持的视频格式 }pSCC := AllocMem(piSize);tryfor III := 0 to piCount - 1 dobeginif fStreamConfig.GetStreamCaps(III, pmt, pSCC) = S_OK thenbegintryNew(pvInfo); { 注意释放内存 }pvInfo^.Frame   := PVIDEOINFOHEADER(pmt^.pbFormat)^.AvgTimePerFrame;pvInfo^.id      := pmt^.formattype;pvInfo^.iWidth  := pSCC^.MaxOutputSize.cx;pvInfo^.iHeight := pSCC^.MaxOutputSize.cy;pvInfo^.iMod    := pmt^.subtype;pvInfo^.format  := VideoMediaSubTypeToStr(pmt^.subtype);strsList.AddObject(format('类型:%s  分辨率:%4d×%4d', [pvInfo^.format, pvInfo^.iWidth, pvInfo^.iHeight]), TObject(pvInfo));finallyDeleteMediaType(pmt);end;end;end;finallyFreeMem(pSCC);end;SysDevEnum           := nil;CaptureGraphBuilder2 := nil;fStreamConfig        := nil;Result := True;
end;/// <summary>
/// 普通影片
/// </summary>
/// <param name="FIGraphBuilder">FI图形生成器</param>
/// <param name="FICaptureGraphBuilder2">FI捕获图生成器</param>
/// <param name="FSysDevEnum">FSys开发枚举</param>
/// <param name="FIVideoWindow">FI视频窗口</param>
/// <param name="FIMediaControl">FI媒体控制</param>
/// <param name="FISampleGrabber">FI样品采集器</param>
/// <param name="pv">P视频输入信息</param>
/// <param name="pf">P视频格式信息</param>
/// <param name="pnl">搭载视频的面板【panel面板控件】</param>
/// <param name="strSaveFileName">保存文件路径名</param>
/// <param name="bRecord">是否开始录像</param>
/// <param name="bSnapBmp">是否开启截图功能</param>
/// <returns>布尔类型</returns>
function CommonVideo(var FIGraphBuilder: IGraphBuilder;               // FI图形生成器var FICaptureGraphBuilder2: ICaptureGraphBuilder2;                  // FI捕获图生成器var FSysDevEnum: IBaseFilter;                                       // FSys开发枚举var FIVideoWindow: IVideoWindow;                                    // FI视频窗口var FIMediaControl: IMediaControl;                                  // FI媒体控制var FISampleGrabber: ISampleGrabber;                                // FI样品采集器pv: PVideoInputInfo; pf: PVideoFormatInfo;                          // pv:P视频输入信息、pf:P视频格式信息pnl: TPanel;                                                        // 搭载视频的面板【panel面板控件】const strSaveFileName: string = ''; const bRecord: Boolean = False; // 录像 【strSaveFileName:保存文件路径名、bRecord:是否开始录像】const bSnapBmp: Boolean = False                                     // 截图 【bSnapBmp:是否开启截图功能】): Boolean;
varSampleGrabberFilter: IBaseFilter;mt                 : TAMMediaType;multiplexer        : IBaseFilter;Writer             : IFileSinkFilter;
beginResult := False;// 创建 图形生成器 接口{ 创建 IGraphBuilder 接口 }if Failed(CocreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC, IID_IGraphBuilder, FIGraphBuilder)) thenExit;// 创建 捕获图生成器 接口{ 创建 ICaptureGraphBuilder2 接口 }if Failed(CocreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, FICaptureGraphBuilder2)) thenExit;// SetFiltergraph:设置滤镜{ 调用 ICaptureGraphBuilder2 的 SetFilterGraph 方法将 FilterGraph 加入到 Builder 中 }if Failed(FICaptureGraphBuilder2.SetFiltergraph(FIGraphBuilder)) thenExit;// 调用本单元的 CreateFilter 创建 Filter{ 获取指定USB摄像头的 Filter }FSysDevEnum := CreateFilter(CLSID_VideoInputDeviceCategory, AnsiString(pv^.strName), pv^.index);if FSysDevEnum = nil thenExit;// 调用本单元 SetMediaType 【设置指定 Filter 的媒体格式类型】{ 设置指定 Filter 的媒体格式类型 }if not SetMediaType(FSysDevEnum, pf^.iWidth, pf^.iHeight, pf^.format) thenExit;{ 将视频捕捉 Filter 添加到 Filter 图中 }if Failed(FIGraphBuilder.AddFilter(FSysDevEnum, 'VideoCapture')) thenExit;{ 如果需要截图功能 }if bSnapBmp thenbegin// 共同创建实例(,,,,样品采集器Filter)CocreateInstance(CLSID_SampleGrabber, nil, CLSCTX_INPROC, IID_IBaseFilter, SampleGrabberFilter);// FI图形生成器.添加 Filter(样品采集器Filter,‘样品采集器’)FIGraphBuilder.AddFilter(SampleGrabberFilter, 'SampleGrabber');// 样品采集器Filter.查询接口()SampleGrabberFilter.QueryInterface(IID_ISampleGrabber, FISampleGrabber);zeromemory(@mt, sizeof(AM_MEDIA_TYPE));mt.majortype := MEDIATYPE_Video;mt.subtype   := MEDIASUBTYPE_RGB24;     // 24位,位图格式输出FISampleGrabber.SetMediaType(@mt);      //// 样品采集器.设置缓冲液样本()FISampleGrabber.SetBufferSamples(True); // 允许从 Buffer 中获取数据{ 渲染预览视频PIN }if Failed(FICaptureGraphBuilder2.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, FSysDevEnum, SampleGrabberFilter, nil)) thenExit;endelsebegin{ 渲染预览视频PIN }if Failed(FICaptureGraphBuilder2.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, FSysDevEnum, nil, nil)) thenExit;end;{ 如果是视频录制 }if bRecord thenbegin// SetOutputFileName:设置输出文件名{ 视频录制文件保持路径 }if Failed(FICaptureGraphBuilder2.SetOutputFileName(MEDIASUBTYPE_Avi, PWideChar(strSaveFileName), multiplexer, Writer)) thenExit;// RenderStream:渲染流if Failed(FICaptureGraphBuilder2.RenderStream(@PIN_CATEGORY_CAPTURE, @MEDIATYPE_Video, FSysDevEnum, nil, multiplexer)) thenExit;end;{ 设置视频预览窗口 }if Failed(FIGraphBuilder.QueryInterface(IID_IVideoWindow, FIVideoWindow)) thenExit;{ 设置视频播放的WINDOWS窗口 }if Failed(FIVideoWindow.put_Owner(pnl.Handle)) thenExit;if Failed(FIVideoWindow.put_windowstyle(WS_CHILD or WS_Clipsiblings)) thenExit;{ 设置视频尺寸 }if Failed(FIVideoWindow.SetWindowposition(0, 0, pnl.Width, pnl.Height)) thenExit;{ 得到IMediaControl接口,用于控制流播放 }if Failed(FIGraphBuilder.QueryInterface(IID_IMediaControl, FIMediaControl)) thenExit;Result := True;
end;{ 视频预览 }
function USBVideoPreview(var FIGraphBuilder: IGraphBuilder; var FICaptureGraphBuilder2: ICaptureGraphBuilder2; var FSysDevEnum: IBaseFilter; var FIVideoWindow: IVideoWindow; var FIMediaControl: IMediaControl; var FISampleGrabber: ISampleGrabber; pv: PVideoInputInfo; pf: PVideoFormatInfo; pnl: TPanel; const bSnapBmp: Boolean = True): Boolean;
beginResult := CommonVideo(FIGraphBuilder, FICaptureGraphBuilder2, FSysDevEnum, FIVideoWindow, FIMediaControl, FISampleGrabber, pv, pf, pnl, '', False, bSnapBmp);
end;{ 视频录制 }
function USBVideoRecord(var FIGraphBuilder: IGraphBuilder; var FICaptureGraphBuilder2: ICaptureGraphBuilder2; var FSysDevEnum: IBaseFilter; var FIVideoWindow: IVideoWindow; var FIMediaControl: IMediaControl; var FISampleGrabber: ISampleGrabber; pv: PVideoInputInfo; pf: PVideoFormatInfo; pnl: TPanel; const strSaveFileName: String): Boolean;
beginResult := CommonVideo(FIGraphBuilder, FICaptureGraphBuilder2, FSysDevEnum, FIVideoWindow, FIMediaControl, FISampleGrabber, pv, pf, pnl, strSaveFileName, True, True);
end;end.

一点点笔记,以便以后翻阅。

Delphi USB摄像头相关推荐

  1. Delphi 控制摄像头操作

    DELPHI控制摄像头操作可以使用TVideoCap控件,或直接使用MS的AVICAP32.DLL就可轻松的实现对摄像头编程. 首先常量定义和函数定义: implementation const WM ...

  2. Delphi7 下基于SDL2+FFMPEG 实现USB摄像头播放及拍照

    目录 简述: 准备工作 获取视频设备类表 FFMPEG视频解码 视频播放 拍照 Demo下载 简述: delphi7 下进行USB摄像头开发网上的办法一般两种1.基于AVICAP32的windowsA ...

  3. FFmpeg实现获取USB摄像头视频流测试代码

    通过USB摄像头(注:windows7/10下使用内置摄像头,linux下接普通的usb摄像头(Logitech))获取视频流用到的模块包括avformat和avdevice.头文件仅include ...

  4. NVIDIA TX2 使用 USB 摄像头

    用了一个很冷门的 USB 摄像头,在 Windows 下会自动安装驱动,本来以为在 Ubuntu 下得手动安,试了 easycam 和 gspca 都失败(太老了).没想到貌似根本不需要安装,TX2 ...

  5. [转载]树莓派新版系统上使用mjpg-streamer获取USB摄像头和树莓派专用摄像头RaspiCamera图像...

    树莓派新版系统上使用mjpg-streamer获取USB摄像头和树莓派专用摄像头RaspiCamera图像 网上有很多关于mjpg-stream移植到树莓派的文章,大部分还是使用的sourceforg ...

  6. 2.7 usb摄像头之usb摄像头描述符打印

    学习目标:参考lsusb源码,打印USB摄像头的设备描述符.配置描述符.接口联合描述符.端点描述符: 一.lsusb命令和源码 使用命令lsusb可以看看设备的id,并执行 # lsusb -v -d ...

  7. NanoPi NEO Air使用十五:使用V4L2驱动USB摄像头

    USB摄像头初识   Linux UVC driver(uvc) 该驱动适用于符合USB视频类(USB Video Class)规范的摄像头设备,它包括V4L2内核设备驱动和用户空间工具补丁.大多数大 ...

  8. (原创)基于ZedBoard的Webcam设计(二):USB摄像头图片采集+QT显示

    在(原创基于ZedBoard的Webcam设计(一):Zedboard上的USB摄像头(V4L2接口)的图片采集中,我们完成了ZedBoard上USB摄像头的单幅图片采集,采集到的图片是存储在文件系统 ...

  9. 31全志r58平台Android4.4.2下打开USB摄像头

    31全志r58平台Android4.4.2下打开USB摄像头 2018/10/26 16:00 版本:V1.0 开发板:SC5806 1.系统编译:(略) 2.需要修改的文件: W:\r58_andr ...

最新文章

  1. 开源教程 「nlp-tutorial」!用百行代码搞定各类NLP模型
  2. 自动驾驶中常用的四类机器学习算法
  3. 解剖SQLSERVER 第十篇 OrcaMDF Studio 发布+ 特性重温(译)
  4. 4分钟极速甩脂训练!抛开借口!繁忙族必备!
  5. cocos2dx[3.2](18)——屏幕截图ScreenShot
  6. 【Python】青少年蓝桥杯_每日一题_10.11_小球反弹
  7. HDU 2001 计算两点间的距离
  8. 50、Power Query-Text.Contains的学习
  9. mac下日期、时间戳互转
  10. c++ 枚举与字符串 比较
  11. 获得picker选项的当前年月值_如果你用OPPO手机!千万记得开启开发者选项,手机性能大幅度提升...
  12. 什么软件测试显示器响应时间准,自己动手测试液晶显示器响应时间
  13. 熊猫直播宣布正式关站 至今已运行1286天
  14. 读书笔记之文件和注册表操作
  15. restfulframework详解
  16. Kaggle竞赛:Quora Insincere Questions Classification 总结与心得感想
  17. IE8/9下,text-indent对css描绘三角形的影响
  18. python中easygui()库的使用
  19. 计算机视觉及其工业中的应用,计算机视觉技术在工业领域中的应用
  20. nicegram安卓_Nicegram测试版

热门文章

  1. 国内申请NewBing账号【不排队】
  2. C语言实习字母金字塔
  3. Android开发:BaseExpandableListAdapter的使用
  4. 怎么用wps抽签_怎么用WPS做活动抽签用的PPT?有模板可以给我更好!
  5. 快乐英语新概念英语 绿色
  6. 计算机服务 无法保存,无法保存打印机设置0x000006d9?详细教您怎么办
  7. 快递助手 V1.2.2.0
  8. 新手从零开始学习微信小程序开发01
  9. 跨域css加载,css跨域加载字体
  10. wm8960驱动调试问题集合