⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 upushsource.pas

📁 delphi源码
💻 PAS
📖 第 1 页 / 共 4 页
字号:
//------------------------------------------------------------------------------
// File:              UPushSource.pas
// Original file(s):  Setup.cpp, PushSource.h,
//                    PushSourceBitmap.cpp, PushSourceBitmapSet.cpp,
//                    PushSourceDesktop.cpp, PushSource.h,
//                    DibHelper.cpp, DibHelper.h, PushGuids.h
// Converted to Delphi by Nevhasymyy Andriy (E-Mail: a.n@email.com)
// Thanks to Henri Gourvest (hgourvest@progdigy.com)
//
// Desc: DirectShow sample code - In-memory push mode source filter
//
// Portions created by Microsoft are
// Copyright (c) 1992-2002 Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------

{
  @abstract(In-memory push mode source filter Delphi conversion)
  @author(Andriy Nevhasymyy: a.n@email.com)
  @created(Jun 28, 2003)
  @lastmod(Aug 04, 2003)
}
unit UPushSource;

interface
uses
  BaseClass, DirectShow9, DSUtil,
  Windows, ActiveX, SysUtils;

const
  //
  // GUID definitions for PushSource filter set
  //
  CLSID_PushSourceBitmap: TGUID = '{E446D455-7C13-492A-9C96-38F948687E8A}';
  CLSID_PushSourceBitmapSet: TGUID = '{D5070569-3C5F-4988-A77C-4DF44E850C43}';
  CLSID_PushSourceDesktop: TGUID = '{570757C1-D2D8-42D1-BA0C-24E1BED3F62F}';

  // Setup information
  sudPinTypes: TRegPinTypes =
  (
    // video stream connection
    clsMajorType: @MEDIATYPE_Video;
    // all available
    clsMinorType: @MEDIASUBTYPE_NULL
    );

  // pins info
  sudOutputPinBitmap: array[0..0] of TRegFilterPins =
  (
    (
    strName: 'Output'; // Pins string name
    bRendered: FALSE; // Is it rendered
    bOutput: TRUE; // Is it an output
    bZero: FALSE; // Are we allowed none
    bMany: FALSE; // And allowed many
    oFilter: nil; // Connects to filter
    strConnectsToPin: nil; // Connects to pin
    nMediaTypes: 1; // Number of types
    lpMediaType: @sudPinTypes // Pin information
    )
    );
  sudOutputPinBitmapSet: array[0..0] of TRegFilterPins =
  (
    (
    strName: 'Output'; // Pins string name
    bRendered: FALSE; // Is it rendered
    bOutput: TRUE; // Is it an output
    bZero: FALSE; // Are we allowed none
    bMany: FALSE; // And allowed many
    oFilter: nil; // Connects to filter
    strConnectsToPin: nil; // Connects to pin
    nMediaTypes: 1; // Number of types
    lpMediaType: @sudPinTypes // Pin information
    )
    );

  sudOutputPinDesktop: array[0..0] of TRegFilterPins =
  (
    (
    strName: 'Output'; // Pins string name
    bRendered: FALSE; // Is it rendered
    bOutput: TRUE; // Is it an output
    bZero: FALSE; // Are we allowed none
    bMany: FALSE; // And allowed many
    oFilter: nil; // Connects to filter
    strConnectsToPin: nil; // Connects to pin
    nMediaTypes: 1; // Number of types
    lpMediaType: @sudPinTypes // Pin information
    )
    );

  UNITS = 10000000;
  FPS_30 = UNITS div 30;
  FPS_20 = UNITS div 20;
  FPS_10 = UNITS div 10;
  FPS_5 = UNITS div 5;
  FPS_4 = UNITS div 4;
  FPS_3 = UNITS div 3;
  FPS_2 = UNITS div 2;
  FPS_1 = UNITS div 1;

  DefaultFrameLength: TReferenceTime = FPS_10;

  // Filter name strings
  PushBitmapName: WideString = '_ PushSource Bitmap Filter';
  PushBitmapSetName: WideString = '_ PushSource BitmapSet Filter';
  PushDesktopName: WideString = '_ PushSource Desktop Filter';

  // default bitmap file name
  BITMAP_NAME: string = 'sample.bmp';

  // Number of bitmap files to load in the CPushPinBitmapSet class
  Num_Files = 5;

type
  (**********************************************
   *
   *  Class declarations
   *
   **********************************************)

  TBCPushPinBitmap = class(TBCSourceStream)
  protected
    // To track where we are in the file
    FFramesWritten: Integer;
    // Do we need to clear the buffer?
    FZeroMemory: Boolean;
    // The time stamp for each sample
    FSampleTime: TRefTime;

    // Pointer to the bitmap header
    FBmi: PBitmapInfo;
    // Size of the bitmap header
    FBitmapInfo: DWord;

    // File opening variables
     // Handle returned from CreateFile
    FFileHandle: THandle;
    // Points to beginning of file buffer
    FFileBuffer: PByte;
    // Points to pixel bits
    FImage: PByte;

    // How many frames have been displayed
    FFrameNumber: Integer;
    // Duration of one frame
    FFrameLength: TReferenceTime;

    // Protects our internal state
    FSharedState: TBCCritSec;

  public
    constructor Create(out hr: HResult; Filter: TBCSource);
    destructor Destroy; override;

    // Override the version that offers exactly one media type
    function GetMediaType(MediaType: PAMMediaType): HResult; override;
    function DecideBufferSize(Allocator: IMemAllocator;
      Properties: PAllocatorProperties): HRESULT; override;
    function FillBuffer(Sample: IMediaSample): HResult; override;

    // Quality control
   // Not implemented because we aren't going in real time.
   // If the file-writing filter slows the graph down, we just do nothing, which means
   // wait until we're unblocked. No frames are ever dropped.
    // Quality control notifications sent to us
    function Notify(Filter: IBaseFilter; q: TQuality): HRESULT; override;
      stdcall;
  end;

  TBCPushPinBitmapSet = class(TBCSourceStream)
  protected
    // To track where we are in the file
    FFramesWritten: Integer;
    // Do we need to clear the buffer?
    FZeroMemory: Boolean;
    // The time stamp for each sample
    FSampleTime: TRefTime;

    // Array of bitmap headers pointers
    FBmi: array[0..Num_Files - 1] of PBitmapInfo;
    // Sizes of the bitmap headers
    FBitmapInfo: array[0..Num_Files - 1] of DWord;

    // File opening variables
     // Handles returned from CreateFile
    FFileHandle: array[0..Num_Files - 1] of THandle;
    // Points to beginning of files buffer
    FFileBuffer: array[0..Num_Files - 1] of PByte;
    // Points to pixel bits
    FImage: array[0..Num_Files - 1] of PByte;

    // number of files loaded
    FFilesLoaded: Boolean;

    // Which bitmap is being displayed
    FCurrentBitmap,
      // How many frames have been displayed
    FFrameNumber: Integer;
    // Duration of one frame
    FFrameLength: TReferenceTime;

    // Protects our internal state
    FSharedState: TBCCritSec;

  public
    constructor Create(out hr: HResult; Filter: TBCSource);
    destructor Destroy; override;

    // Override the version that offers exactly one media type
    function GetMediaType(MediaType: PAMMediaType): HResult; override;
    function DecideBufferSize(Allocator: IMemAllocator;
      Properties: PAllocatorProperties): HRESULT; override;
    function FillBuffer(Sample: IMediaSample): HResult; override;

    // Quality control
   // Not implemented because we aren't going in real time.
   // If the file-writing filter slows the graph down, we just do nothing, which means
   // wait until we're unblocked. No frames are ever dropped.
    // Quality control notifications sent to us
    function Notify(Filter: IBaseFilter; q: TQuality): HRESULT; override;
      stdcall;
  end;

  TBCPushPinDesktop = class(TBCSourceStream)
  protected
    // To track where we are in the file
    FFramesWritten: Integer;
    // Do we need to clear the buffer?
    FZeroMemory: Boolean;
    // The time stamp for each sample
    FSampleTime: TRefTime;

    // How many frames have been displayed
    FFrameNumber: Integer;
    // Duration of one frame
    FFrameLength: TReferenceTime;

    // Rect containing entire screen coordinates
    FScreenRect: TRect;

    // The current image height
    FImageHeight,
      // And current image width
    FImageWidth,
      // Time in msec between frames
    FRepeatTime,
      // Screen bit depth
    FCurrentBitDepth: Integer;

    FMediaType: TAMMediaType;

    // Protects our internal state
    FSharedState: TBCCritSec;

  public
    constructor Create(out hr: HResult; Filter: TBCSource);
    destructor Destroy; override;

    // Override the version that offers exactly one media type
    function GetMediaType(iPosition: Integer;
      out MediaType: PAMMediaType): HResult; override;
    // We will accept 8, 16, 24 or 32 bit video formats, in any
    // image size that gives room to bounce.
    // Returns E_INVALIDARG if the mediatype is not acceptable
    function CheckMediaType(MediaType: PAMMediaType): HResult; override;
    function DecideBufferSize(Allocator: IMemAllocator;
      Properties: PAllocatorProperties): HRESULT; override;
    function SetMediaType(MediaType: PAMMediaType): HRESULT; override;
    function FillBuffer(Sample: IMediaSample): HResult; override;

    // Quality control
   // Not implemented because we aren't going in real time.
   // If the file-writing filter slows the graph down, we just do nothing, which means
   // wait until we're unblocked. No frames are ever dropped.
    // Quality control notifications sent to us
    function Notify(Filter: IBaseFilter; q: TQuality): HRESULT; override;
      stdcall;
  end;

  // In-memory push mode source filter
  // Provides a static bitmap as the video output stream.
  TBCPushSourceBitmap = class(TBCSource)
  private
    FPin: TBCPushPinBitmap;

  public
    constructor Create(ObjName: string; Unk: IUnKnown; out hr: HRESULT);
    constructor CreateFromFactory(Factory: TBCClassFactory;
      const Controller: IUnknown); override;
    destructor Destroy; override;
  end;

  // In-memory push mode source filter
  // Provides a rotating set of bitmaps as the video output stream.
  TBCPushSourceBitmapset = class(TBCSource)
  private
    FPin: TBCPushPinBitmapSet;

  public
    constructor Create(ObjName: string; Unk: IUnKnown; out hr: HRESULT);
    constructor CreateFromFactory(Factory: TBCClassFactory;
      const Controller: IUnknown); override;
    destructor Destroy; override;
  end;

  // In-memory push mode source filter
  // Provides an image of the user's desktop as a continuously updating stream.
  TBCPushSourceDesktop = class(TBCSource)
  private
    FPin: TBCPushPinDesktop;

  public
    constructor Create(ObjName: string; Unk: IUnKnown; out hr: HRESULT);
    constructor CreateFromFactory(Factory: TBCClassFactory;
      const Controller: IUnknown); override;
    destructor Destroy; override;
  end;

implementation

// --- TBCPushPinBitmap ---------------

constructor TBCPushPinBitmap.Create(out hr: HResult; Filter: TBCSource);
var
  CurrentDir: array[0..MAX_PATH - 1] of Char;
  CurrentFileName, MediaFileName: AnsiString;
  MsgText: AnsiString;
  FileSize, BytesRead: DWord;
  FileHeaderSize: Integer;
  BmpFileHeader: PBITMAPFILEHEADER;
  pb: PByte;

begin
  inherited Create('_ Push Source Bitmap', hr, Filter, 'Out');

  FFramesWritten := 0;
  FZeroMemory := False;
  FBmi := nil;
  FBitmapInfo := 0;
  FFileHandle := INVALID_HANDLE_VALUE;
  FFileBuffer := nil;
  FImage := nil;
  FFrameNumber := 0;
  // Display 5 bitmap frames per second
  FFrameLength := FPS_5;
  FSharedState := TBCCritSec.Create;

  // The main point of this sample is to demonstrate how to take a DIB
  // in host memory and insert it into a video stream.
  // To keep this sample as simple as possible, we just read a single 24 bpp bitmap
  // from a file and copy it into every frame that we send downstream.

  // In the filter graph, we connect this filter to the AVI Mux, which creates
  // the AVI file with the video frames we pass to it. In this case,
  // the end result is a still image rendered as a video stream.

  // Your filter will hopefully do something more interesting here.
  // The main point is to set up a buffer containing the DIB pixel bits.
  // This must be done before you start running.

  // First look for the bitmap in the current directory
  GetCurrentDirectory(MAX_PATH - 1, CurrentDir);
  CurrentFileName := Format('%s\%s', [CurrentDir, Bitmap_Name]);

  FFileHandle := CreateFile(PChar(CurrentFileName), GENERIC_READ, 0, nil,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL, 0);

  if (FFileHandle = INVALID_HANDLE_VALUE) then
  begin
    // File was not in the application's current directory,
    // so look in the DirectX SDK media path instead.
    MediaFileName := Format('%s\%s'#0, [GetDXSDKMediaPath, Bitmap_Name]);

    FFileHandle := CreateFile(PChar(MediaFileName), GENERIC_READ, 0, nil,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL, 0);

    if (FFileHandle = INVALID_HANDLE_VALUE) then
    begin
      MsgText := Format('Could not open bitmap source file ' +
        'in the application directory:'#13#10 + '%s'#13#10 +
        'or in the DirectX SDK Media folder:'#13#10 + '%s'#13#10 +
        'Please copy this file either to the application''s folder'#13#10 +
        'or to the DirectX SDK Media folder, then recreate this filter'#13#10 +
        'Otherwise, you will not be able to render the output pin',
        [CurrentFileName, MediaFileName]);

      OutputDebugString(PChar(MsgText));
      MessageBox(0, PChar(MsgText), 'PushSource filter error',
        MB_ICONERROR or MB_OK);
      hr := HRESULTFROMWIN32(GetLastError);
      Exit;
    end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -