关于Live Gamer Portable 2 Plus输出引脚帧率配置的API接口问题
问题:Live Gamer Portable 2 Plus输出引脚帧率配置异常
我正尝试为Live Gamer Portable 2 Plus的输出引脚配置更低帧率。通过GraphStudioNext可通过捕获引脚访问配置并修改帧率,但通过API调用捕获引脚的IAMStreamConfig接口时,仅能选择默认设置,无法实现GraphStudioNext中的帧率修改效果。是否有其他接口可获取GraphStudioNext中显示的输出引脚流配置?
以下是我修改帧率并保留其他参数后成功运行的默认Delphi例程片段:
if (Format.Width = MediaHeader.bmiHeader.biWidth) and (Format.Height = MediaHeader.bmiHeader.biHeight) and (Format.AvgTimePerFrame = MediaHeader.AvgTimePerFrame) and (Format.BitsPerPixel = MediaHeader.bmiHeader.biBitCount) then begin MediaHeader.AvgTimePerFrame := NewRate; CheckNull(AMStreamConfig, 'IAMStreamConfig'); CheckError(AMStreamConfig.SetFormat(MediaType)); Exit; end;
解答
你遇到的问题其实很常见——不少采集设备的输出引脚配置不会完全暴露在IAMStreamConfig接口里,GraphStudioNext之所以能看到更多选项,是因为它会同时查询多个DirectShow接口来获取完整的设备能力。下面给你几个可行的解决方案,按优先级排序:
1. 先尝试正确枚举IAMStreamConfig的所有支持格式
你当前的代码是直接修改现有格式的帧率,但有些设备要求必须从枚举的支持格式中选择并修改,而不是直接修改当前格式。试试先枚举所有可用格式,找到匹配的再修改帧率:
var NumCaps: Integer; CapsSize: Integer; MediaType: PAMMediaType; StreamCaps: PStreamConfigCaps; I: Integer; begin // 获取支持的格式数量和配置结构大小 CheckError(AMStreamConfig.GetNumberOfCapabilities(NumCaps, CapsSize)); GetMem(StreamCaps, CapsSize); try for I := 0 to NumCaps - 1 do begin GetMem(MediaType, SizeOf(TAMMediaType)); try // 获取第I个支持的格式 CheckError(AMStreamConfig.GetStreamCaps(I, MediaType^, StreamCaps^)); // 匹配当前的分辨率、位深参数 if (MediaType^.format^.bmiHeader.biWidth = Format.Width) and (MediaType^.format^.bmiHeader.biHeight = Format.Height) and (MediaType^.format^.bmiHeader.biBitCount = Format.BitsPerPixel) then begin // 修改帧率(AvgTimePerFrame单位是100ns,所以用10000000除以目标帧率) MediaType^.AvgTimePerFrame := 10000000 div NewRate; // 应用修改后的格式 CheckError(AMStreamConfig.SetFormat(MediaType^)); Break; end; finally FreeMem(MediaType); end; end; finally FreeMem(StreamCaps); end; end;
2. 尝试IAMVideoControl接口控制帧率
很多视频捕获设备会通过IAMVideoControl接口暴露帧率控制能力,这是DirectShow专门用于视频捕获控制的接口:
var VideoControl: IAMVideoControl; ControlCaps: TAMVideoControlCaps; begin // 查询捕获引脚是否支持IAMVideoControl if Succeeded(CapturePin.QueryInterface(IID_IAMVideoControl, VideoControl)) then begin // 获取设备的控制能力 if Succeeded(VideoControl.GetCaps(CapturePin, ControlCaps)) then begin // 检查是否支持帧率控制 if (ControlCaps.dwControlFlags and VideoControlFlag_FrameRate) <> 0 then begin // 设置新帧率对应的AvgTimePerFrame MediaHeader.AvgTimePerFrame := 10000000 div NewRate; // 启用帧率控制模式 CheckError(VideoControl.SetMode(CapturePin, VideoControlFlag_FrameRate)); end; end; end; end;
3. 底层方案:通过IKsPropertySet访问KS属性
如果上面两种方法都不行,那就要直接访问设备的KS(Kernel Streaming)属性了——GraphStudioNext就是通过读取这些底层属性来获取完整配置的。针对帧率的属性通常在PROPSETID_VIDCAP_CAPTURE集合下:
var KsPropSet: IKsPropertySet; FrameRate: DWORD; BytesReturned: DWORD; begin // 查询捕获引脚是否支持IKsPropertySet if Succeeded(CapturePin.QueryInterface(IID_IKsPropertySet, KsPropSet)) then begin // 先读取当前帧率(可选步骤) if Succeeded(KsPropSet.Get(PROPSETID_VIDCAP_CAPTURE, CAPTURE_PROP_FRAME_RATE, nil, 0, @FrameRate, SizeOf(FrameRate), BytesReturned)) then begin // 设置目标帧率 FrameRate := NewRate; CheckError(KsPropSet.Set(PROPSETID_VIDCAP_CAPTURE, CAPTURE_PROP_FRAME_RATE, nil, 0, @FrameRate, SizeOf(FrameRate))); end; end; end;
注意事项
- 不同设备的驱动实现差异很大,你需要逐个测试这些方法,找到适合Live Gamer Portable 2 Plus的方案;
AvgTimePerFrame的单位是100纳秒,所以计算时要用10000000 / 目标帧率来转换;- 调用接口前一定要检查返回值,避免空指针或不支持的操作导致崩溃。
内容的提问来源于stack exchange,提问作者Barry Andrews
相关产品推荐
相关产品推荐

