Delphi在directshow中更改网络摄像头的分辨率

时间:2014-01-21 22:20:11

标签: delphi delphi-7 directshow

我正在尝试将帧的分辨率更改为320x240,因为我的网络摄像头正在提供640x480的帧,并且我使用的编码器无法正常使用更高的分辨率,我这样做

procedure OnDevieStart()
begin
  FilterGraph.ClearGraph;
  FilterGraph.Active := False;
  Filter.BaseFilter.Moniker := SysDev.GetMoniker(TMenuItem(Sender).tag);
  FilterGraph.Active := true;
  SetVideoProperties(Filter as iBaseFilter);

  with FilterGraph as ICaptureGraphBuilder2 do
  try
    RenderStream(@PIN_CATEGORY_PREVIEW, nil, Filter as IBaseFilter, SampleGrabber as IBaseFilter, VideoWindow as IbaseFilter);
    FilterGraph.Play;
  except
    ShowMessage('Unable to use specified device!')
  end;
end;

function SetVideoProperties(pVideoCapture: IBaseFilter):Boolean;
var
  hr:HRESULT;
  pStreamConfig: IAMStreamConfig;
  pAM_Media: PAMMediaType;
  pvih: PVIDEOINFOHEADER;
  pICGP2: ICaptureGraphBuilder2;
begin

  pICGP2 := FilterGraph as ICaptureGraphBuilder2;
  hr := pICGP2.FindInterface(@PIN_CATEGORY_CAPTURE, nil, pVideoCapture,
                             IID_IAMStreamConfig, pStreamConfig);

  if (SUCCEEDED(hr)) then begin

    pStreamConfig.GetFormat(pAM_Media);
    pvih := pAM_Media.pbFormat ;
    pAM_Media.subtype := MEDIASUBTYPE_RGB24;
    pvih.bmiHeader.biWidth := 320;
    pvih.bmiHeader.biHeight := 240;
    pvih.AvgTimePerFrame := 10000000 div 15;
    pStreamConfig.SetFormat(pAM_Media^);
    DeleteMediaType(pAM_Media);
    pStreamConfig := nil;
  end;

end;

但是当通过样本采集器抓取帧时,分辨率保持不变

这种方法有什么问题吗?

更新

好的,我想我现在正在更新所有成员

function SetVideoProperties(pVideoCapture: IBaseFilter):Boolean;
var
  hr:HRESULT;
  pStreamConfig: IAMStreamConfig;
  pAM_Media: PAMMediaType;
  pvih: PVIDEOINFOHEADER;
  pICGP2: ICaptureGraphBuilder2;
begin

  pICGP2 := FilterGraph as ICaptureGraphBuilder2;
  hr := pICGP2.FindInterface(@PIN_CATEGORY_CAPTURE, nil, pVideoCapture,
                             IID_IAMStreamConfig, pStreamConfig);

  if (SUCCEEDED(hr)) then begin

    pStreamConfig.GetFormat(pAM_Media);

    pAM_Media.subtype := MEDIASUBTYPE_RGB24;
    pAM_Media.majortype := MEDIATYPE_Video;
    pAM_Media.bFixedSizeSamples := True;
    pAM_Media.bTemporalCompression := False;
    pAM_Media.lSampleSize := 230400;
    pAM_Media.formattype := FORMAT_VideoInfo;
    pAM_Media.pUnk := nil;
    pAM_Media.cbFormat := 88;

    pvih := pAM_Media.pbFormat;
    pvih.dwBitRate := 6912000;
    pvih.AvgTimePerFrame := 10000000 div 15;
    pvih.bmiHeader.biSize := 40;
    pvih.bmiHeader.biWidth := 320;
    pvih.bmiHeader.biHeight := 240;
    pvih.bmiHeader.biPlanes := 1;
    pvih.bmiHeader.biBitCount := 24;
    pvih.bmiHeader.biCompression := 0;
    pvih.bmiHeader.biSizeImage := 230400;
    pvih.bmiHeader.biXPelsPerMeter := 0;
    pvih.bmiHeader.biYPelsPerMeter := 0;
    pvih.bmiHeader.biClrUsed := 0;
    pvih.bmiHeader.biClrImportant := 0;

    hr := pStreamConfig.SetFormat(pAM_Media^);

    If Succeeded(hr) then ShowMessage('SUCCEED') else ShowMessage(IntToStr(hr));   
    DeleteMediaType(pAM_Media);
    pStreamConfig := nil;
  end;

end;

2 个答案:

答案 0 :(得分:0)

  1. 使用新分辨率初始化新媒体类型不正确/不完整:更新其他成员
  2. 您应该检查SetFormat结果以检测格式设置中的失败
  3. 代码本身似乎不完整,没有证据表明您完全改变格式并且源过滤器存在并添加到过滤器图中

答案 1 :(得分:0)

参见DSPack演示“...... \ dspack2.3.4 \ Demos \ D6-D7 \ videocap”

您需要枚举所有可用的网络摄像头格式,然后设置一个。

那里的代码: (按钮Start OnClick处理程序)

VideoMediaTypes, 
AudioMediaTypes: TEnumMediaType;

....... 

      // configure output Video media type
      if VideoSourceFilter.FilterGraph <> nil then
      begin
        PinList := TPinList.Create(VideoSourceFilter as IBaseFilter);
        if VideoFormats.ItemIndex <> -1 then
          with (PinList.First as IAMStreamConfig) do
            SetFormat(VideoMediaTypes.Items[VideoFormats.ItemIndex].AMMediaType^);
        PinList.Free;
      end;

下面

  SetFormat(VideoMediaTypes.Items[VideoFormats.ItemIndex].AMMediaType^);

VideoMediaTypes是用户选择来源时填充的可用格式列表。

VideoFormat是用于选择格式的GUI控件(ListBox)