I'm trying to get stream video from USB Web-camera in Delphi XE. Found a working example, but I can't figure out how to get all supported video formats (resolution, color depth, etc). This example works well with fixed Mediatype:
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;
How can I get all webcam supported video formats to combobox? If I need something to add, please, post in comment, thanks.
The code snippet provided is not quite relevant and presumably is just what you have at the moment. To enumerate video formats you typically obtain an output pin of interest first, which you don't do in your code snippet and rely on RenderStream
call to do dirty work for you.
Then, you obtain IAMStreamConfig
interface pointer from the pin and enumerate the media types (formats). Alternatively you can enumerate using IPin::EnumMediaTypes
, however IAMStreamConfig::GetStreamCaps
is the canonical way, esp. for webcams.
Bonus code 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;
...