网络摄像头支持的视频格式

Webcamera supported video formats

我正在尝试从 Delphi XE 中的 USB 网络摄像头获取流视频。找到了一个工作示例,但我不知道如何获得所有支持的视频格式(分辨率、颜色深度等)。此示例适用于固定媒体类型:

 var
  Form1: TForm1;
  IniFile: TIniFile;
  DeviceName: OleVariant;
  PropertyName: IPropertyBag;
  pDevEnum: ICreateDEvEnum;
  pEnum: IEnumMoniker;
  pMoniker: IMoniker;

  MArray1: array of IMoniker; 

  FGraphBuilder: IGraphBuilder;
  FCaptureGraphBuilder: ICaptureGraphBuilder2;
  FMux: IBaseFilter;
  FSink: IFileSinkFilter;
  FMediaControl: IMediaControl;
  FVideoWindow: IVideoWindow;
  FVideoCaptureFilter: IBaseFilter;
  FAudioCaptureFilter: IBaseFilter;
  FVideoRect: TRect;

  FBaseFilter: IBaseFilter;
  FSampleGrabber: ISampleGrabber;
  MediaType: AM_MEDIA_TYPE;


function TForm1.Initializ: HResult;
begin
  Result := CoCreateInstance(CLSID_SystemDeviceEnum, NIL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, pDevEnum);

  if Result <> S_OK then
    EXIT;

  Result := pDevEnum.CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
    pEnum, 0);

  if Result <> S_OK then
    EXIT;

  setlength(MArray1, 0);

  while (S_OK = pEnum.Next(1, pMoniker, Nil)) do
  begin
    setlength(MArray1, length(MArray1) + 1);
    MArray1[length(MArray1) - 1] := pMoniker;
    Result := pMoniker.BindToStorage(NIL, NIL, IPropertyBag, PropertyName);

    if FAILED(Result) then
      Continue;

    Result := PropertyName.Read('FriendlyName', DeviceName, NIL);

    if FAILED(Result) then
      Continue;

    ListBox1.Items.Add(DeviceName);
  end;

  if ListBox1.Count = 0 then
  begin
    ShowMessage('Webcam not found!');
    Result := E_FAIL;
    EXIT;
  end;
  ListBox1.ItemIndex := 0;

  Result := S_OK;
end;

function TForm1.CreateGraph: HResult;
var
  pConfigMux: IConfigAviMux;

begin
  FVideoCaptureFilter := NIL;
  FVideoWindow := NIL;
  FMediaControl := NIL;
  FSampleGrabber := NIL;
  FBaseFilter := NIL;
  FCaptureGraphBuilder := NIL;
  FGraphBuilder := NIL;

  Result := CoCreateInstance(CLSID_FilterGraph, NIL, CLSCTX_INPROC_SERVER,
    IID_IGraphBuilder, FGraphBuilder);
  if FAILED(Result) then
    EXIT;

  Result := CoCreateInstance(CLSID_SampleGrabber, NIL, CLSCTX_INPROC_SERVER,
    IID_IBaseFilter, FBaseFilter);
  if FAILED(Result) then
    EXIT;

  Result := CoCreateInstance(CLSID_CaptureGraphBuilder2, NIL,
    CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, FCaptureGraphBuilder);
  if FAILED(Result) then
    EXIT;

  Result := FGraphBuilder.AddFilter(FBaseFilter, 'GRABBER');
  if FAILED(Result) then
    EXIT;

  Result := FBaseFilter.QueryInterface(IID_ISampleGrabber, FSampleGrabber);
  if FAILED(Result) then
    EXIT;

  if FSampleGrabber <> NIL then
  begin

    ZeroMemory(@MediaType, sizeof(AM_MEDIA_TYPE));

    with MediaType do
    begin
      majortype := MEDIATYPE_Video;
      subtype := MEDIASUBTYPE_RGB24;
      formattype := FORMAT_VideoInfo;
    end;

    FSampleGrabber.SetMediaType(MediaType);

    FSampleGrabber.SetBufferSamples(TRUE);

    FSampleGrabber.SetOneShot(FALSE);
  end;

  Result := FCaptureGraphBuilder.SetFiltergraph(FGraphBuilder);
  if FAILED(Result) then
    EXIT;

  if ListBox1.ItemIndex >= 0 then
  begin
    MArray1[ListBox1.ItemIndex].BindToObject(NIL, NIL, IID_IBaseFilter,
      FVideoCaptureFilter);
    FGraphBuilder.AddFilter(FVideoCaptureFilter, 'VideoCaptureFilter');
  end;

  Result := FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, nil,
    FVideoCaptureFilter, FBaseFilter, nil);
  if FAILED(Result) then
    EXIT;

  Result := FGraphBuilder.QueryInterface(IID_IVideoWindow, FVideoWindow);
  if FAILED(Result) then
    EXIT;

  FVideoWindow.put_WindowStyle(WS_CHILD or WS_CLIPSIBLINGS);
  FVideoWindow.put_Owner(Panel1.Handle);
  FVideoRect := Panel1.ClientRect;
  FVideoWindow.SetWindowPosition(FVideoRect.Left, FVideoRect.Top,
  FVideoRect.Right - FVideoRect.Left, FVideoRect.Bottom - FVideoRect.Top);
  FVideoWindow.put_Visible(TRUE);

  Result := FGraphBuilder.QueryInterface(IID_IMediaControl, FMediaControl);
  if FAILED(Result) then
    EXIT;
  FMediaControl.Run();
end;

如何将所有网络摄像头支持的视频格式添加到组合框?如果我需要补充什么,请评论post,谢谢。

提供的代码片段不太相关,可能正是您目前所拥有的。要枚举视频格式,您通常首先获得感兴趣的输出引脚,您不会在您的代码片段中这样做,而是依靠 RenderStream 调用为您做脏活。

然后,您从引脚获取IAMStreamConfig接口指针并枚举媒体类型(格式)。或者,您可以使用 IPin::EnumMediaTypes 进行枚举,但是 IAMStreamConfig::GetStreamCaps 是规范的方式,尤其是。对于网络摄像头。

红利代码here:

// The TVideoSample class provides access to WebCams and similar Video-capture
//  devices via DirectShow.

...

// Fills "FormatArr" with list of all supported video formats (resolution, compression etc...)
FUNCTION TVideoSample.LoadListOfResolution: HResult;
...