UAsyncFlt.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:10k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. //------------------------------------------------------------------------------
  2. // File: UAsyncFlt.pas
  3. // Original files: AsyncFlt.h, AsyncFlt.c
  4. //
  5. // Desc: AsyncFilter implementation
  6. //
  7. // Portions created by Microsoft are
  8. // Copyright (c) 2000-2002  Microsoft Corporation.  All rights reserved.
  9. //------------------------------------------------------------------------------
  10. unit UAsyncFlt;
  11. interface
  12. uses
  13.   BaseClass, DirectShow9, Windows, SysUtils, MMSystem, Math, ActiveX,
  14.   UAsyncRdr, UAsyncIo, DSUtil;
  15. const
  16.   // Setup data for filter registration
  17.   sudPinTypes : TRegPinTypes =
  18.   (
  19.   clsMajorType: @MEDIATYPE_Stream;
  20.   clsMinorType: @MEDIASUBTYPE_NULL
  21.   );
  22.   // pins info
  23.   sudpPins : array[0..0] of TRegFilterPins =
  24.   (
  25.    (
  26.     strName: 'Output';         // Pins string name
  27.     bRendered: False;          // Is it rendered
  28.     bOutput: True;             // Is it an output
  29.     bZero: False;              // Are we allowed none
  30.     bMany: False;              // And allowed many
  31.     oFilter: @GUID_NULL;       // Connects to filter
  32.     strConnectsToPin: 'Input'; // Connects to pin
  33.     nMediaTypes: 1;            // Number of types
  34.     lpMediaType: @sudPinTypes  // Pin information
  35.    )
  36.   );
  37. type
  38.   //  NOTE:  This filter does NOT support AVI format
  39.   //
  40.   //  Define an internal filter that wraps the base CBaseReader stuff
  41.   //
  42.   TBCMemStream = class(TBCAsyncStream)
  43.   public
  44.     constructor Create;
  45.     destructor Destroy; override;
  46.     //  Initialization
  47.     procedure Init(AData: PByte; ALength: LONGLONG; AKBPerSec: DWord = INFINITE);
  48.     function SetPointer(APos: LONGLONG): HResult; override;
  49.     function Read(ABuffer: PByte; ABytesToRead: DWord;
  50.       AAlign: Boolean; out ABytesRead: DWord): HResult; override;
  51.     function Size(out ASizeAvailable: LONGLONG): LONGLONG; override;
  52.     function Alignment: DWord; override;
  53.     procedure Lock; override;
  54.     procedure UnLock; override;
  55.   private
  56.     FCSLock: TBCCritSec;
  57.     FData: PByte;
  58.     FLength: LONGLONG;
  59.     FPosition: LONGLONG;
  60.     FKBPerSec: DWord;
  61.     FTimeStart: DWord;
  62.   end;
  63.   TBCAsyncFilter = class(TBCAsyncReader, IFileSourceFilter)
  64.   public
  65.     // construction / destruction
  66.     constructor Create(ObjName: string; Unk: IUnKnown; out hr : HRESULT);
  67.     constructor CreateFromFactory(Factory: TBCClassFactory;
  68.       const Controller: IUnknown); override;
  69.     destructor Destroy; override;
  70.     function NonDelegatingQueryInterface(const IID: TGUID;
  71.       out Obj): HResult; override;
  72.     //  IFileSourceFilter methods
  73.     //  Load a (new) file
  74.     function Load(AFileName: PWideChar; const Amt: PAMMediaType): HResult; stdcall;
  75.     // Modeled on IPersistFile::Load
  76.     // Caller needs to CoTaskMemFree or equivalent.
  77.     function GetCurFile(out AFileName: PWideChar; Amt: PAMMediaType): HResult;
  78.       stdcall;
  79.   private
  80.     FFileName: PWideChar;
  81.     FSize: LONGLONG;
  82.     FData: PByte;
  83.     FStream: TBCMemStream;
  84.     function ReadTheFile(AFileName: PChar): Boolean;
  85.   end;
  86. implementation
  87. // --- TBCMemStream ---
  88. constructor TBCMemStream.Create;
  89. begin
  90.   Inherited;
  91.   FCSLock := TBCCritSec.Create;
  92.   FPosition := 0;
  93. end;
  94. destructor TBCMemStream.Destroy;
  95. begin
  96.   if Assigned(FCSLock) then
  97.     FreeAndNil(FCSLock);
  98.   Inherited Destroy;
  99. end;
  100. procedure TBCMemStream.Init(AData: PByte; ALength: LONGLONG;
  101.   AKBPerSec: DWord = INFINITE);
  102. begin
  103.   FData := AData;
  104.   FLength := ALength;
  105.   FKBPerSec := AKBPerSec;
  106.   FTimeStart := timeGetTime;
  107. end;
  108. function TBCMemStream.SetPointer(APos: LONGLONG): HResult;
  109. begin
  110.   if (APos < 0) or (APos > FLength) then
  111.     Result := S_FALSE
  112.   else
  113.     begin
  114.       FPosition := APos;
  115.       Result := S_OK;
  116.     end;
  117. end;
  118. function TBCMemStream.Read(ABuffer: PByte; ABytesToRead: DWord;
  119.   AAlign: Boolean; out ABytesRead: DWord): HResult;
  120. var
  121.   _ReadLength, _Time, _TimeToArrive: DWord;
  122.   _Data: PByte;
  123. begin
  124.   Result := E_FAIL;
  125.   FCSLock.Lock;
  126.   try
  127.     //  Wait until the bytes are here!
  128.     _Time := timeGetTime;
  129.     if (FPosition + ABytesToRead > FLength) then
  130.         _ReadLength := FLength - FPosition
  131.     else
  132.       _ReadLength := ABytesToRead;
  133.     _TimeToArrive := (FPosition + _ReadLength) div FKBPerSec;
  134.     if (_Time - FTimeStart < _TimeToArrive) then
  135.       Sleep(_TimeToArrive - _Time + FTimeStart);
  136.     _Data := FData;
  137.     Inc(_Data, FPosition);
  138.     CopyMemory(ABuffer, _Data, _ReadLength);
  139.     Inc(FPosition, _ReadLength);
  140.     ABytesRead := _ReadLength;
  141.     Result := S_OK;
  142.   finally
  143.     FCSLock.UnLock;
  144.   end;
  145. end;
  146. function TBCMemStream.Size(out ASizeAvailable: LONGLONG): LONGLONG;
  147. var
  148.   _CurrentAvailable: LONGLONG;
  149. begin
  150.   _CurrentAvailable := UInt32x32To64(timeGetTime - FTimeStart, FKBPerSec);
  151.   ASizeAvailable := min(FLength, _CurrentAvailable);
  152.   Result := FLength;
  153. end;
  154. function TBCMemStream.Alignment: DWord;
  155. begin
  156.   Result := 1;
  157. end;
  158. procedure TBCMemStream.Lock;
  159. begin
  160.   FCSLock.Lock;
  161. end;
  162. procedure TBCMemStream.UnLock;
  163. begin
  164.   FCSLock.UnLock;
  165. end;
  166. // --- TBCAsyncFilter ---
  167. constructor TBCAsyncFilter.Create(ObjName: string; Unk: IUnKnown; out hr : HRESULT);
  168. begin
  169.   try
  170.     FStream := TBCMemStream.Create;
  171.     Inherited Create(ObjName, Unk, FStream, hr);
  172.     FFileName := '';
  173.     FData := nil;
  174.     hr := NOERROR;
  175.   except
  176.     hr := E_OUTOFMEMORY;
  177.   end;
  178. end;
  179. constructor TBCAsyncFilter.CreateFromFactory(Factory: TBCClassFactory;
  180.   const Controller: IUnknown);
  181. var
  182.   hr: HRESULT;
  183. begin
  184.   Create(Factory.Name, Controller, hr);
  185. end;
  186. destructor TBCAsyncFilter.Destroy;
  187. begin
  188.   if Assigned(FData) then
  189.     FreeMem(FData);
  190.   FFileName := '';
  191.   Inherited Destroy;
  192. end;
  193. function TBCAsyncFilter.NonDelegatingQueryInterface(const IID: TGUID;
  194.   out Obj): HResult;
  195. begin
  196.   if IsEqualGUID(IID, IID_IFileSourceFilter) then
  197.     if GetInterface(IID_IFileSourceFilter, Obj) then
  198.       Result := S_OK
  199.     else
  200.       Result := E_FAIL
  201.   else
  202.     Result := Inherited NonDelegatingQueryInterface(IID, Obj);
  203. end;
  204. function TBCAsyncFilter.Load(AFileName: PWideChar;
  205.   const Amt: PAMMediaType): HResult;
  206. var
  207.   cch: Integer;
  208.   {$IFNDEF UNICODE}
  209.   _FileName: PChar;
  210.   {$ELSE}
  211.   _FileName: array[0..MAX_PATH - 1] of Char;
  212.   {$ENDIF}
  213.   _mt: TAMMediaType;
  214. begin
  215.   if (AFileName = nil) then
  216.   begin
  217.     Result := E_POINTER;
  218.     Exit;
  219.   end;
  220.   // lstrlenW is one of the few Unicode functions that works on win95
  221.   cch := lstrlenW(AFileName) + 1;
  222.   {$IFNDEF UNICODE}
  223.   try
  224.     _FileName := nil;
  225.     GetMem(_FileName, cch * 2);
  226.   except
  227.     Result := E_OUTOFMEMORY;
  228.     Exit;
  229.   end;
  230.   WideCharToMultiByte(GetACP, 0, AFileName, -1,
  231.     _FileName, cch, nil, nil);
  232.   {$ELSE}
  233.   ZeroMemory(@_FileName[0], MAX_PATH, 0);
  234.   lstrcpy(_FileName, AFileName);
  235.   {$ENDIF}
  236.   FCSFilter.Lock;
  237.   try
  238.     //  Check the file type
  239.     if (Amt = nil) then
  240.     begin
  241.       ZeroMemory(@_mt, SizeOf(TAMMediaType));
  242.       _mt.majortype := MEDIATYPE_Stream;
  243. {$IFDEF AVI}
  244.       _mt.subtype := MEDIASUBTYPE_AVI;
  245. {$ELSE}
  246.       _mt.subtype := MEDIASUBTYPE_NULL;
  247. {$ENDIF}
  248.     end
  249.       else
  250.         CopyMemory(@_mt, Amt, SizeOf(TAMMediaType));
  251.     if Not ReadTheFile(_FileName) then
  252.     begin
  253.       {$IFNDEF UNICODE}
  254.         FreeMem(_FileName);
  255.       {$ENDIF}
  256.       Result := E_FAIL;
  257.       Exit;
  258.     end;
  259.     FStream.Init(FData, FSize);
  260.     try
  261.       GetMem(FFileName, SizeOf(WideChar) * cch);
  262.     except
  263.       Result := E_OUTOFMEMORY;
  264.       Exit;
  265.     end;
  266.     CopyMemory(FFileName, AFileName, cch * SizeOf(WideChar));
  267.     // this is not a simple assignment... pointers and format
  268.     // block (if any) are intelligently copied
  269.     CopyMemory(@Fmt, @_mt, SizeOf(TAMMediaType));
  270.     Fmt.bTemporalCompression := True;
  271.     Fmt.lSampleSize := 1;
  272.     Result := S_OK;
  273.   finally
  274.     FCSFilter.UnLock;
  275.   end;
  276. end;
  277. function TBCAsyncFilter.GetCurFile(out AFileName: PWideChar;
  278.   Amt: PAMMediaType): HResult;
  279. var
  280.   n: DWord;
  281. begin
  282.   AFileName := nil;
  283.   if Assigned(FFileName) then
  284.   begin
  285.     n := SizeOf(WideChar) * (1 + lstrlenW(FFileName));
  286.     AFileName := CoTaskMemAlloc(n);
  287.     if Assigned(AFileName) then
  288.       CopyMemory(AFileName, FFileName, n);
  289.   end;
  290.   if Assigned(Amt) then
  291.     CopyMemory(Amt, @Fmt, SizeOf(TAMMediaType));
  292.   Result := NOERROR;
  293. end;
  294. function TBCAsyncFilter.ReadTheFile(AFileName: PChar): Boolean;
  295. var
  296.   _BytesRead: DWord;
  297.   _File: THandle;
  298.   _Size: ULARGE_INTEGER;
  299.   _Mem: PByte;
  300. begin
  301.   // Open the requested file
  302.   _File := CreateFile(AFileName, GENERIC_READ, FILE_SHARE_READ,
  303.     nil, OPEN_EXISTING, 0, 0);
  304.   if (_File = INVALID_HANDLE_VALUE) then
  305.   begin
  306.     {$IFDEF DEBUG}
  307.     DbgLog(Format('Could not open %s', [AFileName]));
  308.     {$ENDIF}
  309.     Result := False;
  310.     Exit;
  311.   end;
  312.   // Determine the file size
  313.   _Size.LowPart := GetFileSize(_File, @_Size.HighPart);
  314.   try
  315.     _Mem := nil;
  316.     GetMem(_Mem, _Size.LowPart);
  317.   except
  318.     CloseHandle(_File);
  319.     Result := False;
  320.     Exit;
  321.   end;
  322.   // Read the data from the file
  323.   if (Not ReadFile(_File, _Mem^, _Size.LowPart, _BytesRead, nil)) or
  324.     (_BytesRead <> _Size.LowPart) then
  325.   begin
  326.     {$IFDEF DEBUG}
  327.     DbgLog(Format('Could not read %s', [AFileName]));
  328.     {$ENDIF}
  329.     FreeMem(_Mem);
  330.     CloseHandle(_File);
  331.     Result := False;
  332.     Exit;
  333.   end;
  334.   // Save a pointer to the data that was read from the file
  335.   FData := _Mem;
  336.   FSize := _Size.QuadPart;
  337.   // Close the file
  338.   CloseHandle(_File);
  339.   Result := True;
  340. end;
  341. initialization
  342.   // provide an entry in the CFactoryTemplate array
  343.   TBCClassFactory.CreateFilter(TBCAsyncFilter,
  344.     StringToOleStr('_ Sample File Source (Async.)'),
  345.     CLSID_AsyncSample, CLSID_LegacyAmFilterCategory, MERIT_UNLIKELY,
  346.     1, @sudpPins);
  347. end.