请熟悉DShow接口的朋友帮我看看下面的代码,其问题是图像有马赛克,而且在窗口关闭时出读地址错。
unit main;interfaceuses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, DSUtil, StdCtrls, DSPack, DirectShow9, Menus, ExtCtrls, ComCtrls,
 ExtDlgs, ActiveX;type
 TVideoForm = class(TForm)
   MainMenu1: TMainMenu;
   Devices: TMenuItem;
   SavePictureDialog1: TSavePictureDialog;
   Bitmap1: TMenuItem;
   Setup1: TMenuItem;
   Bitmap2: TMenuItem;
   Callback1: TMenuItem;
   VideoSize1: TMenuItem;
   N320X2401: TMenuItem;
   N640X4801: TMenuItem;
   N720X5761: TMenuItem;
   Debug1: TMenuItem;
   procedure FormCreate(Sender: TObject);
   procedure N720X5761Click(Sender: TObject);
   procedure FormResize(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private public
 end;var
 VideoForm: TVideoForm;
 //DirectShow 接口定义
 GraphBuilder   : IGraphBuilder;
 CaptureGraphBuilder : ICaptureGraphBuilder2; MediaControl   : IMediaControl;
 MediaSeeking   : IMediaSeeking;
 MediaPosition  : IMediaPosition;
 MediaEventEx   : IMediaEventEx; BasicAudio     : IBasicAudio;
 BasicVideo     : IBasicVideo;
 VideoWindow    : IVideoWindow; SampleGrabber  : ISampleGrabber;
 VideoFrameStep : IVideoFrameStep; CreateDevEnum  : ICreateDevEnum;
 EnumMoniker    : IEnumMoniker;
implementation{$R *.dfm}procedure TVideoForm.FormCreate(Sender: TObject);
var
 HR             : HResult;
 DebugMsg       : string;
 Moniker        : IMoniker;
 cFetched       : PLongInt;
 BaseFilter     : IBaseFilter;
begin
 Self.Width  := 640;
 Self.Height := 480;
 Self.Left := (Screen.Width - Self.Width) div 2;
 Self.Top  := (Screen.Height - Self.Height) div 2;
 //初始化接口...
 try
   HR := CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, GraphBuilder);
   if not Succeeded(HR) then Exit;
   DebugMsg := 'GraphBuilder Created!';   HR := CoCreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, CaptureGraphBuilder);
   if not Succeeded(HR) then Exit;
   DebugMsg := 'CaptureGraphBuilder Created!';   GraphBuilder.QueryInterface(IID_IMediaControl, MediaControl);
   GraphBuilder.QueryInterface(IID_IMediaEventEx, MediaEventEx);
   GraphBuilder.QueryInterface(IID_IVideoWindow,  VideoWindow);   MediaEventEx.SetNotifyWindow(Self.Handle, WM_GRAPHNOTIFY, 0);   CaptureGraphBuilder.SetFiltergraph(GraphBuilder);   //设备枚举
   HR := CoCreateInstance (CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, CreateDevEnum);
   if not Succeeded(HR) then Exit;
   CreateDevEnum.CreateClassEnumerator(CLSID_VideoInputDeviceCategory, EnumMoniker, 0);
   if EnumMoniker = nil then Exit;
   if EnumMoniker.Next(1, Moniker, cFetched) = S_OK then
     begin
       Moniker.BindToObject(nil, nil, IID_IBaseFilter, BaseFilter);
       Moniker := nil;
     end
   else Exit;   //将设备添加到graph
   HR := GraphBuilder.AddFilter(BaseFilter, 'Video Capture');
   if not Succeeded(HR) then Exit;
   //连接源...
   HR := CaptureGraphBuilder.RenderStream(nil, nil, BaseFilter, nil, nil);
   if not Succeeded(HR) then Exit;
   //视频窗口...
   HR := VideoWindow.put_Owner(Self.Handle);
   if not Succeeded(HR) then Exit;
   HR := VideoWindow.put_WindowStyle(WS_CHILD and WS_CLIPCHILDREN);
   if not Succeeded(HR) then Exit;
   VideoWindow.SetWindowPosition(0, 0, 640, 480);
   VideoWindow.put_Visible(True);
   //
   MediaControl.Run;
 finally
   Self.Caption := DebugMsg;
 end;
end;procedure TVideoForm.FormDestroy(Sender: TObject);
begin
 CaptureGraphBuilder := nil;
 GraphBuilder        := nil;
 MediaControl        := nil;
 MediaEventEx        := nil;
 VideoWindow         := nil;
 CreateDevEnum       := nil;
 EnumMoniker         := nil;
end;end.  

解决方案 »

  1.   

    指针错误:procedure TVideoForm.FormCreate(Sender: TObject);
    var
     HR             : HResult;
     DebugMsg       : string;
     Moniker        : IMoniker;
     cFetched       : LongInt;   <-----------  1
     BaseFilter     : IBaseFilter;...
       if EnumMoniker = nil then Exit;
       if EnumMoniker.Next(1, Moniker, @cFetched) = S_OK then   <------ 2
                                       ~~~~~~~~~
         begin
           Moniker.BindToObject(nil, nil, IID_IBaseFilter, BaseFilter);
           Moniker := nil;
         end
       else Exit;
    ...另外,你的“设备枚举”没有“枚举”的样,应该 While ... Do ...