UAsyncFlt.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:10k
- //------------------------------------------------------------------------------
- // File: UAsyncFlt.pas
- // Original files: AsyncFlt.h, AsyncFlt.c
- //
- // Desc: AsyncFilter implementation
- //
- // Portions created by Microsoft are
- // Copyright (c) 2000-2002 Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
- unit UAsyncFlt;
- interface
- uses
- BaseClass, DirectShow9, Windows, SysUtils, MMSystem, Math, ActiveX,
- UAsyncRdr, UAsyncIo, DSUtil;
- const
- // Setup data for filter registration
- sudPinTypes : TRegPinTypes =
- (
- clsMajorType: @MEDIATYPE_Stream;
- clsMinorType: @MEDIASUBTYPE_NULL
- );
- // pins info
- sudpPins : 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: @GUID_NULL; // Connects to filter
- strConnectsToPin: 'Input'; // Connects to pin
- nMediaTypes: 1; // Number of types
- lpMediaType: @sudPinTypes // Pin information
- )
- );
- type
- // NOTE: This filter does NOT support AVI format
- //
- // Define an internal filter that wraps the base CBaseReader stuff
- //
- TBCMemStream = class(TBCAsyncStream)
- public
- constructor Create;
- destructor Destroy; override;
- // Initialization
- procedure Init(AData: PByte; ALength: LONGLONG; AKBPerSec: DWord = INFINITE);
- function SetPointer(APos: LONGLONG): HResult; override;
- function Read(ABuffer: PByte; ABytesToRead: DWord;
- AAlign: Boolean; out ABytesRead: DWord): HResult; override;
- function Size(out ASizeAvailable: LONGLONG): LONGLONG; override;
- function Alignment: DWord; override;
- procedure Lock; override;
- procedure UnLock; override;
- private
- FCSLock: TBCCritSec;
- FData: PByte;
- FLength: LONGLONG;
- FPosition: LONGLONG;
- FKBPerSec: DWord;
- FTimeStart: DWord;
- end;
- TBCAsyncFilter = class(TBCAsyncReader, IFileSourceFilter)
- public
- // construction / destruction
- constructor Create(ObjName: string; Unk: IUnKnown; out hr : HRESULT);
- constructor CreateFromFactory(Factory: TBCClassFactory;
- const Controller: IUnknown); override;
- destructor Destroy; override;
- function NonDelegatingQueryInterface(const IID: TGUID;
- out Obj): HResult; override;
- // IFileSourceFilter methods
- // Load a (new) file
- function Load(AFileName: PWideChar; const Amt: PAMMediaType): HResult; stdcall;
- // Modeled on IPersistFile::Load
- // Caller needs to CoTaskMemFree or equivalent.
- function GetCurFile(out AFileName: PWideChar; Amt: PAMMediaType): HResult;
- stdcall;
- private
- FFileName: PWideChar;
- FSize: LONGLONG;
- FData: PByte;
- FStream: TBCMemStream;
- function ReadTheFile(AFileName: PChar): Boolean;
- end;
- implementation
- // --- TBCMemStream ---
- constructor TBCMemStream.Create;
- begin
- Inherited;
- FCSLock := TBCCritSec.Create;
- FPosition := 0;
- end;
- destructor TBCMemStream.Destroy;
- begin
- if Assigned(FCSLock) then
- FreeAndNil(FCSLock);
- Inherited Destroy;
- end;
- procedure TBCMemStream.Init(AData: PByte; ALength: LONGLONG;
- AKBPerSec: DWord = INFINITE);
- begin
- FData := AData;
- FLength := ALength;
- FKBPerSec := AKBPerSec;
- FTimeStart := timeGetTime;
- end;
- function TBCMemStream.SetPointer(APos: LONGLONG): HResult;
- begin
- if (APos < 0) or (APos > FLength) then
- Result := S_FALSE
- else
- begin
- FPosition := APos;
- Result := S_OK;
- end;
- end;
- function TBCMemStream.Read(ABuffer: PByte; ABytesToRead: DWord;
- AAlign: Boolean; out ABytesRead: DWord): HResult;
- var
- _ReadLength, _Time, _TimeToArrive: DWord;
- _Data: PByte;
- begin
- Result := E_FAIL;
- FCSLock.Lock;
- try
- // Wait until the bytes are here!
- _Time := timeGetTime;
- if (FPosition + ABytesToRead > FLength) then
- _ReadLength := FLength - FPosition
- else
- _ReadLength := ABytesToRead;
- _TimeToArrive := (FPosition + _ReadLength) div FKBPerSec;
- if (_Time - FTimeStart < _TimeToArrive) then
- Sleep(_TimeToArrive - _Time + FTimeStart);
- _Data := FData;
- Inc(_Data, FPosition);
- CopyMemory(ABuffer, _Data, _ReadLength);
- Inc(FPosition, _ReadLength);
- ABytesRead := _ReadLength;
- Result := S_OK;
- finally
- FCSLock.UnLock;
- end;
- end;
- function TBCMemStream.Size(out ASizeAvailable: LONGLONG): LONGLONG;
- var
- _CurrentAvailable: LONGLONG;
- begin
- _CurrentAvailable := UInt32x32To64(timeGetTime - FTimeStart, FKBPerSec);
- ASizeAvailable := min(FLength, _CurrentAvailable);
- Result := FLength;
- end;
- function TBCMemStream.Alignment: DWord;
- begin
- Result := 1;
- end;
- procedure TBCMemStream.Lock;
- begin
- FCSLock.Lock;
- end;
- procedure TBCMemStream.UnLock;
- begin
- FCSLock.UnLock;
- end;
- // --- TBCAsyncFilter ---
- constructor TBCAsyncFilter.Create(ObjName: string; Unk: IUnKnown; out hr : HRESULT);
- begin
- try
- FStream := TBCMemStream.Create;
- Inherited Create(ObjName, Unk, FStream, hr);
- FFileName := '';
- FData := nil;
- hr := NOERROR;
- except
- hr := E_OUTOFMEMORY;
- end;
- end;
- constructor TBCAsyncFilter.CreateFromFactory(Factory: TBCClassFactory;
- const Controller: IUnknown);
- var
- hr: HRESULT;
- begin
- Create(Factory.Name, Controller, hr);
- end;
- destructor TBCAsyncFilter.Destroy;
- begin
- if Assigned(FData) then
- FreeMem(FData);
- FFileName := '';
- Inherited Destroy;
- end;
- function TBCAsyncFilter.NonDelegatingQueryInterface(const IID: TGUID;
- out Obj): HResult;
- begin
- if IsEqualGUID(IID, IID_IFileSourceFilter) then
- if GetInterface(IID_IFileSourceFilter, Obj) then
- Result := S_OK
- else
- Result := E_FAIL
- else
- Result := Inherited NonDelegatingQueryInterface(IID, Obj);
- end;
- function TBCAsyncFilter.Load(AFileName: PWideChar;
- const Amt: PAMMediaType): HResult;
- var
- cch: Integer;
- {$IFNDEF UNICODE}
- _FileName: PChar;
- {$ELSE}
- _FileName: array[0..MAX_PATH - 1] of Char;
- {$ENDIF}
- _mt: TAMMediaType;
- begin
- if (AFileName = nil) then
- begin
- Result := E_POINTER;
- Exit;
- end;
- // lstrlenW is one of the few Unicode functions that works on win95
- cch := lstrlenW(AFileName) + 1;
- {$IFNDEF UNICODE}
- try
- _FileName := nil;
- GetMem(_FileName, cch * 2);
- except
- Result := E_OUTOFMEMORY;
- Exit;
- end;
- WideCharToMultiByte(GetACP, 0, AFileName, -1,
- _FileName, cch, nil, nil);
- {$ELSE}
- ZeroMemory(@_FileName[0], MAX_PATH, 0);
- lstrcpy(_FileName, AFileName);
- {$ENDIF}
- FCSFilter.Lock;
- try
- // Check the file type
- if (Amt = nil) then
- begin
- ZeroMemory(@_mt, SizeOf(TAMMediaType));
- _mt.majortype := MEDIATYPE_Stream;
- {$IFDEF AVI}
- _mt.subtype := MEDIASUBTYPE_AVI;
- {$ELSE}
- _mt.subtype := MEDIASUBTYPE_NULL;
- {$ENDIF}
- end
- else
- CopyMemory(@_mt, Amt, SizeOf(TAMMediaType));
- if Not ReadTheFile(_FileName) then
- begin
- {$IFNDEF UNICODE}
- FreeMem(_FileName);
- {$ENDIF}
- Result := E_FAIL;
- Exit;
- end;
- FStream.Init(FData, FSize);
- try
- GetMem(FFileName, SizeOf(WideChar) * cch);
- except
- Result := E_OUTOFMEMORY;
- Exit;
- end;
- CopyMemory(FFileName, AFileName, cch * SizeOf(WideChar));
- // this is not a simple assignment... pointers and format
- // block (if any) are intelligently copied
- CopyMemory(@Fmt, @_mt, SizeOf(TAMMediaType));
- Fmt.bTemporalCompression := True;
- Fmt.lSampleSize := 1;
- Result := S_OK;
- finally
- FCSFilter.UnLock;
- end;
- end;
- function TBCAsyncFilter.GetCurFile(out AFileName: PWideChar;
- Amt: PAMMediaType): HResult;
- var
- n: DWord;
- begin
- AFileName := nil;
- if Assigned(FFileName) then
- begin
- n := SizeOf(WideChar) * (1 + lstrlenW(FFileName));
- AFileName := CoTaskMemAlloc(n);
- if Assigned(AFileName) then
- CopyMemory(AFileName, FFileName, n);
- end;
- if Assigned(Amt) then
- CopyMemory(Amt, @Fmt, SizeOf(TAMMediaType));
- Result := NOERROR;
- end;
- function TBCAsyncFilter.ReadTheFile(AFileName: PChar): Boolean;
- var
- _BytesRead: DWord;
- _File: THandle;
- _Size: ULARGE_INTEGER;
- _Mem: PByte;
- begin
- // Open the requested file
- _File := CreateFile(AFileName, GENERIC_READ, FILE_SHARE_READ,
- nil, OPEN_EXISTING, 0, 0);
- if (_File = INVALID_HANDLE_VALUE) then
- begin
- {$IFDEF DEBUG}
- DbgLog(Format('Could not open %s', [AFileName]));
- {$ENDIF}
- Result := False;
- Exit;
- end;
- // Determine the file size
- _Size.LowPart := GetFileSize(_File, @_Size.HighPart);
- try
- _Mem := nil;
- GetMem(_Mem, _Size.LowPart);
- except
- CloseHandle(_File);
- Result := False;
- Exit;
- end;
- // Read the data from the file
- if (Not ReadFile(_File, _Mem^, _Size.LowPart, _BytesRead, nil)) or
- (_BytesRead <> _Size.LowPart) then
- begin
- {$IFDEF DEBUG}
- DbgLog(Format('Could not read %s', [AFileName]));
- {$ENDIF}
- FreeMem(_Mem);
- CloseHandle(_File);
- Result := False;
- Exit;
- end;
- // Save a pointer to the data that was read from the file
- FData := _Mem;
- FSize := _Size.QuadPart;
- // Close the file
- CloseHandle(_File);
- Result := True;
- end;
- initialization
- // provide an entry in the CFactoryTemplate array
- TBCClassFactory.CreateFilter(TBCAsyncFilter,
- StringToOleStr('_ Sample File Source (Async.)'),
- CLSID_AsyncSample, CLSID_LegacyAmFilterCategory, MERIT_UNLIKELY,
- 1, @sudpPins);
- end.