4891 lines
162 KiB
Plaintext
4891 lines
162 KiB
Plaintext
(* ImageEn Build 7.0.0.06.2637 @ 7-4-17 14:58:42.679 *)
|
|
(*
|
|
Copyright (c) 1998-2017 by Carlotta Calandra. All rights reserved.
|
|
Copyright (c) 2011-2017 by Xequte Software.
|
|
|
|
This software comes without express or implied warranty.
|
|
In no case shall the author be liable for any damage or unwanted behavior of any
|
|
computer hardware and/or software.
|
|
|
|
Author grants you the right to include the component
|
|
in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE.
|
|
|
|
ImageEn, IEvolution and ImageEn ActiveX may not be included in any
|
|
commercial, shareware or freeware libraries or components.
|
|
|
|
www.ImageEn.com
|
|
*)
|
|
|
|
(*
|
|
File version 1019
|
|
*)
|
|
|
|
unit ieds;
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE DELPHI}
|
|
{$ENDIF}
|
|
|
|
{$R-}
|
|
{$Q-}
|
|
|
|
{$I ie.inc}
|
|
|
|
interface
|
|
|
|
{$IFDEF IEINCLUDEDIRECTSHOW}
|
|
|
|
uses
|
|
Windows, Classes, Sysutils, Graphics, iexBitmaps,
|
|
{$ifdef IEHASTYPES} Types, {$endif}
|
|
{$ifdef IEHASUITYPES} System.UITypes, {$endif}
|
|
hyiedefs, iewia, imageenproc, dialogs;
|
|
|
|
const
|
|
|
|
IEEC_ACTIVATE = $0013;
|
|
IEEC_BUFFERING_DATA = $0011;
|
|
IEEC_BUILT = $0300;
|
|
IEEC_CLOCK_CHANGED = $000D;
|
|
IEEC_CLOCK_UNSET = $0051;
|
|
IEEC_CODECAPI_EVENT = $0057;
|
|
IEEC_COMPLETE = $0001;
|
|
IEEC_DEVICE_LOST = $001F;
|
|
IEEC_DISPLAY_CHANGED = $0016;
|
|
IEEC_END_OF_SEGMENT = $001C;
|
|
IEEC_ERROR_STILLPLAYING = $0008;
|
|
IEEC_ERRORABORT = $0003;
|
|
IEEC_EXTDEVICE_MODE_CHANGE = $0031;
|
|
IEEC_FULLSCREEN_LOST = $0012;
|
|
IEEC_GRAPH_CHANGED = $0050;
|
|
IEEC_LENGTH_CHANGED = $001E;
|
|
IEEC_NEED_RESTART = $0014;
|
|
IEEC_NOTIFY_WINDOW = $0019;
|
|
IEEC_OLE_EVENT = $0018;
|
|
IEEC_OPENING_FILE = $0010;
|
|
IEEC_PALETTE_CHANGED = $0009;
|
|
IEEC_PAUSED = $000E;
|
|
IEEC_PREPROCESS_COMPLETE = $0056;
|
|
IEEC_QUALITY_CHANGE = $000B;
|
|
IEEC_REPAINT = $0005;
|
|
IEEC_SEGMENT_STARTED = $001D;
|
|
IEEC_SHUTTING_DOWN = $000C;
|
|
IEEC_SNDDEV_IN_ERROR = $0200;
|
|
IEEC_SNDDEV_OUT_ERROR = $0201;
|
|
IEEC_STARVATION = $0017;
|
|
IEEC_STATE_CHANGE = $0032;
|
|
IEEC_STEP_COMPLETE = $0024;
|
|
IEEC_STREAM_CONTROL_STARTED = $001B;
|
|
IEEC_STREAM_CONTROL_STOPPED = $001A;
|
|
IEEC_STREAM_ERROR_STILLPLAYING = $0007;
|
|
IEEC_STREAM_ERROR_STOPPED = $0006;
|
|
IEEC_TIMECODE_AVAILABLE = $0030;
|
|
IEEC_UNBUILT = $0301;
|
|
IEEC_USERABORT = $0002;
|
|
IEEC_VIDEO_SIZE_CHANGED = $000A;
|
|
IEEC_VMR_RENDERDEVICE_SET = $0053;
|
|
IEEC_VMR_SURFACE_FLIPPED = $0054;
|
|
IEEC_VMR_RECONNECTION_FAILED = $0055;
|
|
IEEC_WINDOW_DESTROYED = $0015;
|
|
IEEC_WMT_EVENT = $0252;
|
|
IEEC_WMT_INDEX_EVENT = $0251;
|
|
IEEC_USER = $8000;
|
|
|
|
// DVD events
|
|
IEEC_DVD_DOMAIN_CHANGE = ($0100 + $01);
|
|
IEEC_DVD_TITLE_CHANGE = ($0100 + $02);
|
|
IEEC_DVD_CHAPTER_START = ($0100 + $03);
|
|
IEEC_DVD_AUDIO_STREAM_CHANGE = ($0100 + $04);
|
|
IEEC_DVD_SUBPICTURE_STREAM_CHANGE = ($0100 + $05);
|
|
IEEC_DVD_ANGLE_CHANGE = ($0100 + $06);
|
|
IEEC_DVD_BUTTON_CHANGE = ($0100 + $07);
|
|
IEEC_DVD_VALID_UOPS_CHANGE = ($0100 + $08);
|
|
IEEC_DVD_STILL_ON = ($0100 + $09);
|
|
IEEC_DVD_STILL_OFF = ($0100 + $0a);
|
|
IEEC_DVD_CURRENT_TIME = ($0100 + $0b);
|
|
IEEC_DVD_ERROR = ($0100 + $0c);
|
|
IEEC_DVD_WARNING = ($0100 + $0d);
|
|
IEEC_DVD_CHAPTER_AUTOSTOP = ($0100 + $0e);
|
|
IEEC_DVD_NO_FP_PGC = ($0100 + $0f);
|
|
IEEC_DVD_PLAYBACK_RATE_CHANGE = ($0100 + $10);
|
|
IEEC_DVD_PARENTAL_LEVEL_CHANGE = ($0100 + $11);
|
|
IEEC_DVD_PLAYBACK_STOPPED = ($0100 + $12);
|
|
IEEC_DVD_ANGLES_AVAILABLE = ($0100 + $13);
|
|
IEEC_DVD_PLAYPERIOD_AUTOSTOP = ($0100 + $14);
|
|
IEEC_DVD_BUTTON_AUTO_ACTIVATED = ($0100 + $15);
|
|
IEEC_DVD_CMD_START = ($0100 + $16);
|
|
IEEC_DVD_CMD_END = ($0100 + $17);
|
|
IEEC_DVD_DISC_EJECTED = ($0100 + $18);
|
|
IEEC_DVD_DISC_INSERTED = ($0100 + $19);
|
|
IEEC_DVD_CURRENT_HMSF_TIME = ($0100 + $1a);
|
|
IEEC_DVD_KARAOKE_MODE = ($0100 + $1b);
|
|
IEEC_DVD_PROGRAM_CELL_CHANGE = ($0100 + $1c);
|
|
IEEC_DVD_TITLE_SET_CHANGE = ($0100 + $1d);
|
|
IEEC_DVD_PROGRAM_CHAIN_CHANGE = ($0100 + $1e);
|
|
IEEC_DVD_VOBU_Offset = ($0100 + $1f);
|
|
IEEC_DVD_VOBU_Timestamp = ($0100 + $20);
|
|
IEEC_DVD_GPRM_Change = ($0100 + $21);
|
|
IEEC_DVD_SPRM_Change = ($0100 + $22);
|
|
IEEC_DVD_BeginNavigationCommands = ($0100 + $23);
|
|
IEEC_DVD_NavigationCommand = ($0100 + $24);
|
|
|
|
|
|
|
|
type
|
|
|
|
{!!
|
|
<FS>TIETVStandard
|
|
|
|
<FM>Declaration<FC>
|
|
}
|
|
TIETVStandard = (ievsNONE, ievsNTSC_M, ievsNTSC_M_J, ievsNTSC_433, ievsPAL_B, ievsPAL_D, ievsPAL_H, ievsPAL_I, ievsPAL_M, ievsPAL_N, ievsPAL_60, ievsSECAM_B, ievsSECAM_D, ievsSECAM_G, ievsSECAM_H, ievsSECAM_K, ievsSECAM_K1, ievsSECAM_L, ievsSECAM_L1, ievsPAL_N_COMBO);
|
|
{!!}
|
|
|
|
{!!
|
|
<FS>TIETVStandards
|
|
|
|
<FM>Declaration<FC>
|
|
TIETVStandards = set of <A TIETVStandard>;
|
|
!!}
|
|
TIETVStandards = set of TIETVStandard;
|
|
|
|
{!!
|
|
<FS>TIEDVDMenu
|
|
|
|
<FM>Declaration<FC>
|
|
}
|
|
TIEDVDMenu = (iedmTITLE, iedmROOT, iedmSUBPICTURE, iedmAUDIO, iedmANGLE, iedmCHAPTER);
|
|
{!!}
|
|
|
|
IEREFERENCE_TIME = packed record
|
|
lo32: dword;
|
|
hi32: dword;
|
|
end;
|
|
PIEREFERENCE_TIME = ^IEREFERENCE_TIME;
|
|
|
|
IEAM_MEDIA_TYPE = record
|
|
majortype: TGUID;
|
|
subtype: TGUID;
|
|
bFixedSizeSamples: longbool;
|
|
bTemporalCompression: longbool;
|
|
lSampleSize: dword;
|
|
formattype: TGUID;
|
|
pUnk: IUnknown;
|
|
cbFormat: dword;
|
|
pbFormat: pbyte;
|
|
end;
|
|
|
|
PIEAM_MEDIA_TYPE = ^IEAM_MEDIA_TYPE;
|
|
|
|
|
|
|
|
|
|
IIEStorage = interface(IUnknown)
|
|
['{0000000B-0000-0000-C000-000000000046}']
|
|
function CreateStream(pwcsName: PWideChar; grfMode: Longint; reserved1: Longint; reserved2: Longint; out stm: IIEStream): HResult; stdcall;
|
|
function OpenStream(pwcsName: pwchar; reserved1: pointer; grfMode: dword; reserved2: dword; out ppstm: IIEStream): HResult; stdcall;
|
|
function CreateStorage: HResult; stdcall;
|
|
function OpenStorage: HResult; stdcall;
|
|
function CopyTo: HResult; stdcall;
|
|
function MoveElementTo: HResult; stdcall;
|
|
function Commit(grfCommitFlags: Longint): HResult; stdcall;
|
|
function Revert: HResult; stdcall;
|
|
function EnumElements(reserved1: DWORD; reserved2: pointer; reserved3: DWORD; out ppenum): HResult; stdcall;
|
|
function DestroyElement: HResult; stdcall;
|
|
function RenameElement: HResult; stdcall;
|
|
function SetElementTimes: HResult; stdcall;
|
|
function SetClass: HResult; stdcall;
|
|
function SetStateBits: HResult; stdcall;
|
|
function Stat: HResult; stdcall;
|
|
end;
|
|
|
|
IIEPersist = interface(IUnknown)
|
|
['{0000010C-0000-0000-C000-000000000046}']
|
|
function GetClassID (*(out classID: TCLSID)*): HResult; stdcall;
|
|
end;
|
|
|
|
IIEPersistStream = interface(IIEPersist)
|
|
['{00000109-0000-0000-C000-000000000046}']
|
|
function IsDirty: HResult; stdcall;
|
|
function Load(const stm: IIEStream): HResult; stdcall;
|
|
function Save(const stm: IIEStream; fClearDirty: BOOL): HResult; stdcall;
|
|
function GetSizeMax: HResult; stdcall;
|
|
end;
|
|
IID_IIEPersistStream = IIEPersistStream;
|
|
|
|
IIEEnumMoniker = interface(IUnknown)
|
|
['{00000102-0000-0000-C000-000000000046}']
|
|
function Next(celt: Longint; out elt; pceltFetched: pointer(*PLongint*)): HResult; stdcall;
|
|
function Skip (*(celt: Longint)*): HResult; stdcall;
|
|
function Reset: HResult; stdcall;
|
|
function Clone (*(out enm: IEnumMoniker)*): HResult; stdcall;
|
|
end;
|
|
|
|
IIEBindCtx = interface(IUnknown)
|
|
['{0000000E-0000-0000-C000-000000000046}']
|
|
function RegisterObjectBound (*(const unk: IUnknown)*): HResult; stdcall;
|
|
function RevokeObjectBound (*(const unk: IUnknown)*): HResult; stdcall;
|
|
function ReleaseBoundObjects: HResult; stdcall;
|
|
function SetBindOptions (*(const bindopts: TBindOpts)*): HResult; stdcall;
|
|
function GetBindOptions (*(var bindopts: TBindOpts)*): HResult; stdcall;
|
|
function GetRunningObjectTable (*(out rot: IRunningObjectTable)*): HResult; stdcall;
|
|
function RegisterObjectParam (*(pszKey: POleStr; const unk: IUnknown)*): HResult; stdcall;
|
|
function GetObjectParam (*(pszKey: POleStr; out unk: IUnknown)*): HResult; stdcall;
|
|
function EnumObjectParam (*(out Enum: IEnumString)*): HResult; stdcall;
|
|
function RevokeObjectParam (*(pszKey: POleStr)*): HResult; stdcall;
|
|
end;
|
|
|
|
IIEMoniker = interface(IIEPersistStream)
|
|
['{0000000F-0000-0000-C000-000000000046}']
|
|
function BindToObject(const bc: IIEBindCtx; const mkToLeft: IIEMoniker; const iidResult: TGUID; out vResult): HResult; stdcall;
|
|
function BindToStorage(const bc: IIEBindCtx; const mkToLeft: IIEMoniker; const iid: TGUID; out vObj): HResult; stdcall;
|
|
function Reduce (*(const bc: IBindCtx; dwReduceHowFar: Longint; mkToLeft: PIMoniker; out mkReduced: IMoniker)*): HResult; stdcall;
|
|
function ComposeWith (*(const mkRight: IMoniker; fOnlyIfNotGeneric: BOOL; out mkComposite: IMoniker)*): HResult; stdcall;
|
|
function Enum (*(fForward: BOOL; out enumMoniker: IEnumMoniker)*): HResult; stdcall;
|
|
function IsEqual (*(const mkOtherMoniker: IMoniker)*): HResult; stdcall;
|
|
function Hash (*(out dwHash: Longint)*): HResult; stdcall;
|
|
function IsRunning (*(const bc: IBindCtx; const mkToLeft: IMoniker; const mkNewlyRunning: IMoniker)*): HResult; stdcall;
|
|
function GetTimeOfLastChange (*(const bc: IBindCtx; const mkToLeft: IMoniker; out filetime: TFileTime)*): HResult; stdcall;
|
|
function Inverse (*(out mk: IMoniker)*): HResult; stdcall;
|
|
function CommonPrefixWith (*(const mkOther: IMoniker; out mkPrefix: IMoniker)*): HResult; stdcall;
|
|
function RelativePathTo (*(const mkOther: IMoniker; out mkRelPath: IMoniker)*): HResult; stdcall;
|
|
function GetDisplayName (*(const bc: IBindCtx; const mkToLeft: IMoniker; out pszDisplayName: POleStr)*): HResult; stdcall;
|
|
function ParseDisplayName (*(const bc: IBindCtx; const mkToLeft: IMoniker; pszDisplayName: POleStr; out chEaten: Longint; out mkOut: IMoniker)*): HResult; stdcall;
|
|
function IsSystemMoniker (*(out dwMksys: Longint)*): HResult; stdcall;
|
|
end;
|
|
|
|
IIECreateDevEnum = interface(IUnknown)
|
|
['{29840822-5B84-11D0-BD3B-00A0C911CE86}']
|
|
function CreateClassEnumerator(const clsidDeviceClass: TGUID; var ppEnumMoniker: IIEEnumMoniker; dwFlags: DWORD): HRESULT; stdcall;
|
|
end;
|
|
IID_IIECreateDevEnum = IIECreateDevEnum;
|
|
|
|
IIEErrorLog = interface
|
|
['{3127CA40-446E-11CE-8135-00AA004BB851}']
|
|
function AddError (*(pszPropName: POleStr; pExcepInfo: PExcepInfo)*): HResult; stdcall;
|
|
end;
|
|
|
|
TIECAGUID = record
|
|
cElems: Longint;
|
|
pElems: pointer;
|
|
end;
|
|
|
|
IIESpecifyPropertyPages = interface(IUnknown)
|
|
['{B196B28B-BAB4-101A-B69C-00AA00341D07}']
|
|
function GetPages(out pages: TIECAGUID): HResult; stdcall;
|
|
end;
|
|
IID_IIESpecifyPropertyPages = IIESpecifyPropertyPages;
|
|
|
|
IIEAMVideoCompression = interface(IUnknown)
|
|
['{C6E13343-30AC-11d0-A18C-00A0C9118956}']
|
|
function put_KeyFrameRate(KeyFrameRate: integer): HRESULT; stdcall;
|
|
function get_KeyFrameRate(var pKeyFrameRate: integer): HRESULT; stdcall;
|
|
function put_PFramesPerKeyFrame: HRESULT; stdcall;
|
|
function get_PFramesPerKeyFrame: HRESULT; stdcall;
|
|
function put_Quality(Quality: double): HRESULT; stdcall;
|
|
function get_Quality(var pQuality: double): HRESULT; stdcall;
|
|
function put_WindowSize: HRESULT; stdcall;
|
|
function get_WindowSize: HRESULT; stdcall;
|
|
function GetInfo: HRESULT; stdcall;
|
|
function OverrideKeyFrame: HRESULT; stdcall;
|
|
function OverrideFrameSize: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEAMVideoCompression = IIEAMVideoCompression;
|
|
|
|
IIEReferenceClock = interface(IUnknown)
|
|
['{56a86897-0ad4-11ce-b03a-0020af0ba770}']
|
|
function GetTime: HRESULT; stdcall;
|
|
function AdviseTime: HRESULT; stdcall;
|
|
function AdvisePeriodic: HRESULT; stdcall;
|
|
function Unadvise: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEReferenceClock = IIEReferenceClock;
|
|
|
|
IIEPropertyBag = interface
|
|
['{55272A00-42CB-11CE-8135-00AA004BB851}']
|
|
function Read(pszPropName: PWideChar; var pvar: OleVariant; const pErrorLog: IIEErrorLog): HResult; stdcall;
|
|
function Write (*(pszPropName: POleStr; const pvar: OleVariant)*): HResult; stdcall;
|
|
end;
|
|
IID_IIEPropertyBag = IIEPropertyBag;
|
|
|
|
IIEMediaFilter = interface(IIEPersist)
|
|
['{56a86899-0ad4-11ce-b03a-0020af0ba770}']
|
|
function Stop: HRESULT; stdcall;
|
|
function Pause: HRESULT; stdcall;
|
|
function Run: HRESULT; stdcall;
|
|
function GetState: HRESULT; stdcall;
|
|
function SetSyncSource(pClock: IIEReferenceClock): HRESULT; stdcall;
|
|
function GetSyncSource: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEMediaFilter = IIEMediaFilter;
|
|
|
|
PPIEAM_MEDIA_TYPE = ^PIEAM_MEDIA_TYPE;
|
|
|
|
IIEEnumMediaTypes = interface(IUnknown)
|
|
['{89c31040-846b-11ce-97d3-00aa0055595a}']
|
|
function Next(cMediaTypes: DWORD; ppMediaTypes: PPIEAM_MEDIA_TYPE; out pcFetched: DWORD): HRESULT; stdcall;
|
|
function Skip(): HRESULT; stdcall;
|
|
function Reset(): HRESULT; stdcall;
|
|
function Clone(): HRESULT; stdcall;
|
|
end;
|
|
|
|
{$ifdef IEHASCONSTENUM}
|
|
IEPIN_DIRECTION = (IEPINDIR_INPUT = 0, IEPINDIR_OUTPUT = 1);
|
|
{$else}
|
|
type IEPIN_DIRECTION = dword;
|
|
const IEPINDIR_INPUT = 0;
|
|
const IEPINDIR_OUTPUT = 1;
|
|
{$endif}
|
|
|
|
type
|
|
|
|
IIEPin = interface(IUnknown)
|
|
['{56a86891-0ad4-11ce-b03a-0020af0ba770}']
|
|
function Connect(pReceivePin: IIEPin; pmt: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function ReceiveConnection: HRESULT; stdcall;
|
|
function Disconnect: HRESULT; stdcall;
|
|
function ConnectedTo(var ppPin: IIEPin): HRESULT; stdcall;
|
|
function ConnectionMediaType(pmt: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function QueryPinInfo(pInfo: pointer): HRESULT; stdcall;
|
|
function QueryDirection(out PinDir: IEPIN_DIRECTION): HRESULT; stdcall;
|
|
function QueryId: HRESULT; stdcall;
|
|
function QueryAccept(pmt: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function EnumMediaTypes(out enum_: IIEEnumMediaTypes): HRESULT; stdcall;
|
|
function QueryInternalConnections: HRESULT; stdcall;
|
|
function EndOfStream: HRESULT; stdcall;
|
|
function BeginFlush: HRESULT; stdcall;
|
|
function EndFlush: HRESULT; stdcall;
|
|
function NewSegment: HRESULT; stdcall;
|
|
end;
|
|
|
|
IIEEnumPins = interface(IUnknown)
|
|
['{56a86892-0ad4-11ce-b03a-0020af0ba770}']
|
|
function Next(cPins: integer; var ppPins: IIEPin; var pcFetched: integer): HRESULT; stdcall;
|
|
function Skip: HRESULT; stdcall;
|
|
function Reset: HRESULT; stdcall;
|
|
function Clone: HRESULT; stdcall;
|
|
end;
|
|
|
|
IIEBaseFilter = interface(IIEMediaFilter)
|
|
['{56a86895-0ad4-11ce-b03a-0020af0ba770}']
|
|
function EnumPins(var ppEnum: IIEEnumPins): HRESULT; stdcall;
|
|
function FindPin(Id: PWideChar; out Pin: IIEPin): HRESULT; stdcall;
|
|
function QueryFilterInfo(pInfo: pointer): HRESULT; stdcall;
|
|
function JoinFilterGraph: HRESULT; stdcall;
|
|
function QueryVendorInfo: HRESULT; stdcall;
|
|
end;
|
|
IID_IEBaseFilter = IIEBaseFilter;
|
|
|
|
IIEFilterGraph = interface(IUnknown)
|
|
['{56a8689f-0ad4-11ce-b03a-0020af0ba770}']
|
|
function AddFilter(pFilter: IIEBaseFilter; pName: PWideChar): HRESULT; stdcall;
|
|
function RemoveFilter(pFilter: IIEBaseFilter): HRESULT; stdcall;
|
|
function EnumFilters: HRESULT; stdcall;
|
|
function FindFilterByName(pName: PWideChar; var ppFilter: IIEBaseFilter): HRESULT; stdcall;
|
|
function ConnectDirect(ppinOut: IIEPin; ppinIn: IIEPin; pmt: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function Reconnect(ppin: IIEPin): HRESULT; stdcall;
|
|
function Disconnect(ppin: IIEPin): HRESULT; stdcall;
|
|
function SetDefaultSyncSource: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEFilterGraph = IIEFilterGraph;
|
|
|
|
IIEAMAnalogVideoDecoder = interface(IUnknown)
|
|
['{C6E13350-30AC-11d0-A18C-00A0C9118956}']
|
|
function get_AvailableTVFormats( lAnalogVideoStandard: plongint): HRESULT; stdcall;
|
|
function put_TVFormat( lAnalogVideoStandard: longint): HRESULT; stdcall;
|
|
function get_TVFormat( plAnalogVideoStandard: plongint): HRESULT; stdcall;
|
|
function get_HorizontalLocked( plLocked: plongint): HRESULT; stdcall;
|
|
function put_VCRHorizontalLocking( lVCRHorizontalLocking: longint): HRESULT; stdcall;
|
|
function get_VCRHorizontalLocking( plVCRHorizontalLocking: plongint): HRESULT; stdcall;
|
|
function get_NumberOfLines( plNumberOfLines: plongint): HRESULT; stdcall;
|
|
function put_OutputEnable( lOutputEnable: longint): HRESULT; stdcall;
|
|
function get_OutputEnable( plOutputEnable: plongint): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEAMAnalogVideoDecoder = IIEAMAnalogVideoDecoder;
|
|
|
|
IIEAMClockSlave = interface(IUnknown)
|
|
['{9FD52741-176D-4b36-8F51-CA8F933223BE}']
|
|
function SetErrorTolerance(dwTolerance: DWORD): HRESULT; stdcall;
|
|
function GetErrorTolerance(pdwTolerance: PDWORD): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEAMClockSlave = IIEAMClockSlave;
|
|
|
|
const
|
|
IEMAX_FILTER_NAME = 128;
|
|
type
|
|
IEFILTER_INFO = record
|
|
achName: array[0..IEMAX_FILTER_NAME - 1] of WideChar;
|
|
pGraph: IIEFilterGraph;
|
|
end;
|
|
|
|
type
|
|
IEPIN_INFO = record
|
|
pFilter: IIEBaseFilter;
|
|
dir: integer;
|
|
achName: array[0..IEMAX_FILTER_NAME - 1] of WideChar;
|
|
end;
|
|
|
|
IIEGraphBuilder = interface(IIEFilterGraph)
|
|
['{56a868a9-0ad4-11ce-b03a-0020af0ba770}']
|
|
function Connect(ppinOut: IIEPin; ppinIn: IIEPin): HRESULT; stdcall;
|
|
function Render(ppinOut: IIEPin): HRESULT; stdcall;
|
|
function RenderFile: HRESULT; stdcall;
|
|
function AddSourceFilter(lpwstrFileName: PWideChar; lpwstrFilterName: PWideChar; var ppFilter: IIEBaseFilter): HRESULT; stdcall;
|
|
function SetLogFile: HRESULT; stdcall;
|
|
function Abort: HRESULT; stdcall;
|
|
function ShouldOperationContinue: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEGraphBuilder = IIEGraphBuilder;
|
|
|
|
IIEFilterGraph2 = interface(IIEGraphBuilder)
|
|
['{36b73882-c2c8-11cf-8b46-00805f6cef60}']
|
|
function AddSourceFilterForMoniker: HRESULT; stdcall;
|
|
function ReconnectEx(ppin: IIEPin; pmt: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function RenderEx(pPinOut: IIEPin; dwFlags: DWORD; pvContext: PDWORD): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEFilterGraph2 = IIEFilterGraph2;
|
|
|
|
IIEFileSinkFilter = interface(IUnknown)
|
|
['{a2104830-7c70-11cf-8bce-00aa00a3f1a6}']
|
|
function SetFileName: HRESULT; stdcall;
|
|
function GetCurFile: HRESULT; stdcall;
|
|
end;
|
|
|
|
IIEDMOWrapperFilter = interface(IUnknown)
|
|
['{52d6f586-9f0f-4824-8fc8-e32ca04930c2}']
|
|
function Init(const clsidDMO: TGUID; const catDMO: TGUID): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEDMOWrapperFilter = IIEDMOWrapperFilter;
|
|
|
|
IIEVideoWindow = interface(IDispatch)
|
|
['{56a868b4-0ad4-11ce-b03a-0020af0ba770}']
|
|
function put_Caption: HRESULT; stdcall;
|
|
function get_Caption: HRESULT; stdcall;
|
|
function put_WindowStyle: HRESULT; stdcall;
|
|
function get_WindowStyle: HRESULT; stdcall;
|
|
function put_WindowStyleEx: HRESULT; stdcall;
|
|
function get_WindowStyleEx: HRESULT; stdcall;
|
|
function put_AutoShow(AutoShow: integer ): HRESULT; stdcall;
|
|
function get_AutoShow: HRESULT; stdcall;
|
|
function put_WindowState: HRESULT; stdcall;
|
|
function get_WindowState: HRESULT; stdcall;
|
|
function put_BackgroundPalette: HRESULT; stdcall;
|
|
function get_BackgroundPalette: HRESULT; stdcall;
|
|
function put_Visible: HRESULT; stdcall;
|
|
function get_Visible: HRESULT; stdcall;
|
|
function put_Left: HRESULT; stdcall;
|
|
function get_Left: HRESULT; stdcall;
|
|
function put_Width: HRESULT; stdcall;
|
|
function get_Width: HRESULT; stdcall;
|
|
function put_Top: HRESULT; stdcall;
|
|
function get_Top: HRESULT; stdcall;
|
|
function put_Height: HRESULT; stdcall;
|
|
function get_Height: HRESULT; stdcall;
|
|
function put_Owner: HRESULT; stdcall;
|
|
function get_Owner: HRESULT; stdcall;
|
|
function put_MessageDrain: HRESULT; stdcall;
|
|
function get_MessageDrain: HRESULT; stdcall;
|
|
function get_BorderColor: HRESULT; stdcall;
|
|
function put_BorderColor: HRESULT; stdcall;
|
|
function get_FullScreenMode: HRESULT; stdcall;
|
|
function put_FullScreenMode: HRESULT; stdcall;
|
|
function SetWindowForeground: HRESULT; stdcall;
|
|
function NotifyOwnerMessage: HRESULT; stdcall;
|
|
function SetWindowPosition: HRESULT; stdcall;
|
|
function GetWindowPosition: HRESULT; stdcall;
|
|
function GetMinIdealImageSize: HRESULT; stdcall;
|
|
function GetMaxIdealImageSize: HRESULT; stdcall;
|
|
function GetRestorePosition: HRESULT; stdcall;
|
|
function HideCursor: HRESULT; stdcall;
|
|
function IsCursorHidden: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEVideoWindow=IIEVideoWindow;
|
|
|
|
IIECaptureGraphBuilder2 = interface(IUnknown)
|
|
['{93E5A4E0-2D50-11d2-ABFA-00A0C9C6E38D}']
|
|
function SetFiltergraph(pfg: IIEGraphBuilder): HRESULT; stdcall;
|
|
function GetFiltergraph: HRESULT; stdcall;
|
|
function SetOutputFileName(const pType: TGUID; lpwstrFile: PWideChar; var ppf: IIEBaseFilter; var pSink: IIEFileSinkFilter): HRESULT; stdcall;
|
|
function FindInterface(pCategory, pType: PGUID; pf: IIEBaseFilter; const riid: TGUID; var ppint: IUnknown): HRESULT; stdcall;
|
|
function RenderStream(pCategory: PGUID; pType: PGUID; pSource: IUnknown; pIntermediate: IIEBaseFilter; pSink: IIEBaseFilter): HRESULT; stdcall;
|
|
function ControlStream(pCategory: PGUID; pType: PGUID; pFilter: IIEBaseFilter; pstart: PIEREFERENCE_TIME; pstop: PIEREFERENCE_TIME; wStartCookie: word; wStopCookie: word): HRESULT; stdcall;
|
|
function AllocCapFile: HRESULT; stdcall;
|
|
function CopyCaptureFile: HRESULT; stdcall;
|
|
function FindPin(pSource: IUnknown; pindir: integer; pCategory: PGUID; pType: PGUID; fUnconnected: longbool; num: integer; var ppPin: IIEPin): HRESULT; stdcall;
|
|
end;
|
|
IID_IIECaptureGraphBuilder2 = IIECaptureGraphBuilder2;
|
|
|
|
{!!
|
|
<FS>TIEDirectShowState
|
|
|
|
<FM>Declaration<FC>
|
|
}
|
|
TIEDirectShowState = (gsStopped, gsPaused, gsRunning);
|
|
{!!}
|
|
|
|
IIEMediaControl = interface(IDispatch)
|
|
['{56a868b1-0ad4-11ce-b03a-0020af0ba770}']
|
|
function Run(): HRESULT; stdcall;
|
|
function Pause(): HRESULT; stdcall;
|
|
function Stop(): HRESULT; stdcall;
|
|
function GetState(msTimeout: dword; var pfs: longint): HRESULT; stdcall;
|
|
function RenderFile(): HRESULT; stdcall;
|
|
function AddSourceFilter(): HRESULT; stdcall;
|
|
function get_FilterCollection(): HRESULT; stdcall;
|
|
function get_RegFilterCollection(): HRESULT; stdcall;
|
|
function StopWhenReady(): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEMediaControl = IIEMediaControl;
|
|
|
|
IIEMediaSeeking = interface(IUnknown)
|
|
['{36b73880-c2c8-11cf-8b46-00805f6cef60}']
|
|
function GetCapabilities: HRESULT; stdcall;
|
|
function CheckCapabilities: HRESULT; stdcall;
|
|
function IsFormatSupported: HRESULT; stdcall;
|
|
function QueryPreferredFormat: HRESULT; stdcall;
|
|
function GetTimeFormat(pFormat: PGUID): HRESULT; stdcall;
|
|
function IsUsingTimeFormat: HRESULT; stdcall;
|
|
function SetTimeFormat(pFormat: PGUID): HRESULT; stdcall;
|
|
function GetDuration(pDuration: PIEREFERENCE_TIME): HRESULT; stdcall;
|
|
function GetStopPosition(var pstop: int64): HRESULT; stdcall;
|
|
function GetCurrentPosition(pCurrent: PIEREFERENCE_TIME): HRESULT; stdcall;
|
|
function ConvertTimeFormat(pTarget: PIEREFERENCE_TIME; pTargetFormat: PGUID; Source: PIEREFERENCE_TIME; pSourceFormat: PGUID): HRESULT; stdcall;
|
|
function SetPositions(pCurrent: PIEREFERENCE_TIME; dwCurrentFlags: dword; pStop: PIEREFERENCE_TIME; dwStopFlags: dword): HRESULT; stdcall;
|
|
function GetPositions(pCurrent: PIEREFERENCE_TIME; pStop: PIEREFERENCE_TIME): HRESULT; stdcall;
|
|
function GetAvailable(var pEarliest: int64; var pLatest: int64): HRESULT; stdcall;
|
|
function SetRate(dRate: double): HRESULT; stdcall;
|
|
function GetRate(dRate: pdouble): HRESULT; stdcall;
|
|
function GetPreroll: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEMediaSeeking = IIEMediaSeeking;
|
|
|
|
IIEMediaEvent = interface(IDispatch)
|
|
['{56a868b6-0ad4-11ce-b03a-0020af0ba770}']
|
|
function GetEventHandle: HRESULT; stdcall;
|
|
function GetEvent(var lEventCode: integer; var lParam1: integer; var lParam2: integer; msTimeout: integer): HRESULT; stdcall;
|
|
function WaitForCompletion(msTimeout: integer; var pEvCode: integer): HRESULT; stdcall;
|
|
function CancelDefaultHandling: HRESULT; stdcall;
|
|
function RestoreDefaultHandling: HRESULT; stdcall;
|
|
function FreeEventParams(lEventCode: integer; lParam1: integer; lParam2: integer): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEMediaEvent = IIEMediaEvent;
|
|
|
|
IIEMediaEventEx = interface(IIEMediaEvent)
|
|
['{56a868c0-0ad4-11ce-b03a-0020af0ba770}']
|
|
function SetNotifyWindow(hwnd: THandle; lMsg: integer; lInstanceData: pointer): HRESULT; stdcall;
|
|
function SetNotifyFlags: HRESULT; stdcall;
|
|
function GetNotifyFlags: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEMediaEventEx = IIEMediaEventEx;
|
|
|
|
IEVIDEOINFOHEADER = record
|
|
rcSource: TRect;
|
|
rcTarget: TRect;
|
|
dwBitRate: dword;
|
|
dwBitErrorRate: dword;
|
|
AvgTimePerFrame: IEREFERENCE_TIME;
|
|
bmiHeader: TBITMAPINFOHEADER;
|
|
end;
|
|
PIEVIDEOINFOHEADER = ^IEVIDEOINFOHEADER;
|
|
|
|
IIEMediaSample = interface(IUnknown)
|
|
['{56a8689a-0ad4-11ce-b03a-0020af0ba770}']
|
|
function GetPointer: HRESULT; stdcall;
|
|
function GetSize: integer; stdcall;
|
|
function GetTime: HRESULT; stdcall;
|
|
function SetTime: HRESULT; stdcall;
|
|
function IsSyncPoint: HRESULT; stdcall;
|
|
function SetSyncPoint: HRESULT; stdcall;
|
|
function IsPreroll: HRESULT; stdcall;
|
|
function SetPreroll: HRESULT; stdcall;
|
|
function GetActualDataLength: integer; stdcall;
|
|
function SetActualDataLength: HRESULT; stdcall;
|
|
function GetMediaType: HRESULT; stdcall;
|
|
function SetMediaType: HRESULT; stdcall;
|
|
function IsDiscontinuity: HRESULT; stdcall;
|
|
function SetDiscontinuity: HRESULT; stdcall;
|
|
function GetMediaTime: HRESULT; stdcall;
|
|
function SetMediaTime: HRESULT; stdcall;
|
|
end;
|
|
|
|
IIESampleGrabberCB = interface(IUnknown)
|
|
['{0579154A-2B53-4994-B0D0-E773148EFF85}']
|
|
function SampleCB(SampleTime: double; pSample: IIEMediaSample): HRESULT; stdcall;
|
|
function BufferCB(SampleTime: double; pBuffer: pbyte; BufferLen: integer): HRESULT; stdcall;
|
|
end;
|
|
|
|
IIESampleGrabber = interface(IUnknown)
|
|
['{6B652FFF-11FE-4fce-92AD-0266B5D7C78F}']
|
|
function SetOneShot: HRESULT; stdcall;
|
|
function SetMediaType(pType: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function GetConnectedMediaType(pType: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function SetBufferSamples(BufferThem: longbool): HRESULT; stdcall;
|
|
function GetCurrentBuffer(pBufferSize: pinteger; pBuffer: pointer): HRESULT; stdcall;
|
|
function GetCurrentSample: HRESULT; stdcall;
|
|
function SetCallback(pCallback: IIESampleGrabberCB; WhichMethodToCallback: integer): HRESULT; stdcall;
|
|
end;
|
|
IID_IIESampleGrabber = IIESampleGrabber;
|
|
|
|
{!!
|
|
<FS>TIETimeFormat
|
|
|
|
<FM>Declaration<FC>
|
|
}
|
|
TIETimeFormat = (tfNone, tfFrame, tfSample, tfField, tfByte, tfTime);
|
|
{!!}
|
|
|
|
TIESampleGrabberCB = class(TInterfacedObject, IIESampleGrabberCB)
|
|
private
|
|
fOwner: TObject; // a TIEDirectShow object
|
|
public
|
|
constructor Create(Owner: TObject);
|
|
destructor Destroy; override;
|
|
function SampleCB(SampleTime: double; pSample: IIEMediaSample): HRESULT; stdcall;
|
|
function BufferCB(SampleTime: double; pBuffer: pbyte; BufferLen: integer): HRESULT; stdcall;
|
|
end;
|
|
|
|
IIEAMStreamConfig = interface(IUnknown)
|
|
['{C6E13340-30AC-11d0-A18C-00A0C9118956}']
|
|
function SetFormat(pmt: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function GetFormat(var ppmt: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function GetNumberOfCapabilities(var piCount, piSize: Integer): HRESULT; stdcall;
|
|
function GetStreamCaps(iIndex: Integer; var ppmt: PIEAM_MEDIA_TYPE; pSCC: pointer): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEAMStreamConfig = IIEAMStreamConfig;
|
|
|
|
IIEAMCrossbar = interface(IUnknown)
|
|
['{C6E13380-30AC-11d0-A18C-00A0C9118956}']
|
|
function get_PinCounts(var OutputPinCount: integer; var InputPinCount: integer): HRESULT; stdcall;
|
|
function CanRoute(OutputPinIndex: integer; InputPinIndex: integer): HRESULT; stdcall;
|
|
function Route(OutputPinIndex: integer; InputPinIndex: integer): HRESULT; stdcall;
|
|
function get_IsRoutedTo(OutputPinIndex: integer; var InputPinIndex: integer): HRESULT; stdcall;
|
|
function get_CrossbarPinInfo(IsInputPin: longbool; PinIndex: integer; var PinIndexRelated: integer; var PhysicalType: integer): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEAMCrossBar = IIEAMCrossBar;
|
|
|
|
IIEAMTuner = interface(IUnknown)
|
|
['{211A8761-03AC-11d1-8D13-00AA00BD8339}']
|
|
function put_Channel(lChannel: integer; lVideoSubChannel: integer; lAudioSubChannel: integer): HRESULT; stdcall;
|
|
function get_Channel(var plChannel: integer; var plVideoSubChannel: integer; var plAudioSubChannel: integer): HRESULT; stdcall;
|
|
function ChannelMinMax: HRESULT; stdcall;
|
|
function put_CountryCode: HRESULT; stdcall;
|
|
function get_CountryCode: HRESULT; stdcall;
|
|
function put_TuningSpace(lTuningSpace: integer): HRESULT; stdcall;
|
|
function get_TuningSpace: HRESULT; stdcall;
|
|
function Logon: HRESULT; stdcall;
|
|
function Logout: HRESULT; stdcall;
|
|
function SignalPresent(var plSignalStrength: integer): HRESULT; stdcall;
|
|
function put_Mode: HRESULT; stdcall;
|
|
function get_Mode: HRESULT; stdcall;
|
|
function GetAvailableModes: HRESULT; stdcall;
|
|
function RegisterNotificationCallBack: HRESULT; stdcall;
|
|
function UnRegisterNotificationCallBack: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEAMTuner = IIEAMTuner;
|
|
|
|
IIEAMTVTuner = interface(IIEAMTuner)
|
|
['{211A8766-03AC-11d1-8D13-00AA00BD8339}']
|
|
function get_AvailableTVFormats: HRESULT; stdcall;
|
|
function get_TVFormat: HRESULT; stdcall;
|
|
function AutoTune(lChannel: integer; var plFoundSignal: integer): HRESULT; stdcall;
|
|
function StoreAutoTune: HRESULT; stdcall;
|
|
function get_NumInputConnections: HRESULT; stdcall;
|
|
function put_InputType: HRESULT; stdcall;
|
|
function get_InputType: HRESULT; stdcall;
|
|
function put_ConnectInput: HRESULT; stdcall;
|
|
function get_ConnectInput: HRESULT; stdcall;
|
|
function get_VideoFrequency: HRESULT; stdcall;
|
|
function get_AudioFrequency: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEAMTVTuner = IIEAMTVTuner;
|
|
|
|
IIEVideoFrameStep = interface(IUnknown)
|
|
['{e46a9787-2b71-444d-a4b5-1fab7b708d6a}']
|
|
function Step(dwFrames: DWORD; pStepObject: IUnknown): HRESULT; stdcall;
|
|
function CanStep(bMultiple: integer; pStepObject: IUnknown): HRESULT; stdcall;
|
|
function CancelStep: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEVideoFrameStep = IIEVideoFrameStep;
|
|
|
|
IIEMediaDet = interface(IUnknown)
|
|
['{65BD0710-24D2-4ff7-9324-ED2E5D3ABAFA}']
|
|
function get_Filter(var pVal: IUnknown): HRESULT; stdcall;
|
|
function put_Filter(newVal: IUnknown ): HRESULT; stdcall;
|
|
function get_OutputStreams(pVal: pinteger): HRESULT; stdcall;
|
|
function get_CurrentStream(pVal: pinteger): HRESULT; stdcall;
|
|
function put_CurrentStream(newVal: integer): HRESULT; stdcall;
|
|
function get_StreamType(pVal: PGUID): HRESULT; stdcall;
|
|
function get_StreamTypeB(var pVal: PWideChar): HRESULT; stdcall;
|
|
function get_StreamLength(pVal: pdouble): HRESULT; stdcall;
|
|
function get_Filename(var pVal: PWideChar): HRESULT; stdcall;
|
|
function put_Filename(newVal: PWideChar): HRESULT; stdcall;
|
|
function GetBitmapBits(
|
|
StreamTime: double;
|
|
pBufferSize: pinteger;
|
|
pBuffer: PAnsiChar;
|
|
Width: integer;
|
|
Height: integer): HRESULT; stdcall;
|
|
function WriteBitmapBits(
|
|
StreamTime: double;
|
|
Width: integer;
|
|
Height: integer;
|
|
Filename: PWideChar): HRESULT; stdcall;
|
|
function get_StreamMediaType(pVal: PIEAM_MEDIA_TYPE): HRESULT; stdcall;
|
|
function GetSampleGrabber(var ppVal: IIESampleGrabber): HRESULT; stdcall;
|
|
function get_FrameRate(pVal: pdouble): HRESULT; stdcall;
|
|
function EnterBitmapGrabMode(SeekTime: double): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEMediaDet = IIEMediaDet;
|
|
|
|
|
|
IIEMediaObject = interface(IUnknown)
|
|
['{d8ad0f58-5494-4102-97c5-ec798e59bcf4}']
|
|
function GetStreamCount: HRESULT; stdcall;
|
|
function GetInputStreamInfo: HRESULT; stdcall;
|
|
function GetOutputStreamInfo: HRESULT; stdcall;
|
|
function GetInputType: HRESULT; stdcall;
|
|
function GetOutputType: HRESULT; stdcall;
|
|
function SetInputType: HRESULT; stdcall;
|
|
function SetOutputType: HRESULT; stdcall;
|
|
function GetInputCurrentType: HRESULT; stdcall;
|
|
function GetOutputCurrentType: HRESULT; stdcall;
|
|
function GetInputSizeInfo: HRESULT; stdcall;
|
|
function GetOutputSizeInfo: HRESULT; stdcall;
|
|
function GetInputMaxLatency: HRESULT; stdcall;
|
|
function SetInputMaxLatency: HRESULT; stdcall;
|
|
function Flush: HRESULT; stdcall;
|
|
function Discontinuity: HRESULT; stdcall;
|
|
function AllocateStreamingResources: HRESULT; stdcall;
|
|
function FreeStreamingResources: HRESULT; stdcall;
|
|
function GetInputStatus: HRESULT; stdcall;
|
|
function ProcessInput: HRESULT; stdcall;
|
|
function ProcessOutput: HRESULT; stdcall;
|
|
function Lock: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEMediaObject = IIEMediaObject;
|
|
|
|
|
|
IIEVMRWindowlessControl = interface(IUnknown)
|
|
['{0eb1088c-4dcd-46f0-878f-39dae86a51b7}']
|
|
function GetNativeVideoSize(
|
|
lpWidth: pinteger;
|
|
lpHeight: pinteger;
|
|
lpARWidth: pinteger;
|
|
lpARHeight: pinteger): HRESULT; stdcall;
|
|
function GetMinIdealVideoSize(
|
|
lpWidth: pinteger;
|
|
lpHeight: pinteger): HRESULT; stdcall;
|
|
function GetMaxIdealVideoSize(
|
|
lpWidth: pinteger;
|
|
lpHeight: pinteger): HRESULT; stdcall;
|
|
function SetVideoPosition(
|
|
lpSRCRect: PRect;
|
|
lpDSTRect: PRect): HRESULT; stdcall;
|
|
function GetVideoPosition(
|
|
lpSRCRect: PRect;
|
|
lpDSTRect: PRect): HRESULT; stdcall;
|
|
function GetAspectRatioMode(
|
|
lpAspectRatioMode: PDWORD): HRESULT; stdcall;
|
|
function SetAspectRatioMode(
|
|
AspectRatioMode: DWORD): HRESULT; stdcall;
|
|
function SetVideoClippingWindow(
|
|
hwnd: THandle): HRESULT; stdcall;
|
|
function RepaintVideo(
|
|
hwnd: THandle;
|
|
hdc: THandle): HRESULT; stdcall;
|
|
function DisplayModeChanged(): HRESULT; stdcall;
|
|
function GetCurrentImage(
|
|
var lpDib: pbyte): HRESULT; stdcall;
|
|
function SetBorderColor(
|
|
Clr: DWORD): HRESULT; stdcall;
|
|
function GetBorderColor(
|
|
lpClr: PDWORD): HRESULT; stdcall;
|
|
function SetColorKey(
|
|
Clr: DWORD): HRESULT; stdcall;
|
|
function GetColorKey(
|
|
lpClr: PDWORD): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEVMRWindowlessControl = IIEVMRWindowlessControl;
|
|
|
|
IIEVMRFilterConfig = interface(IUnknown)
|
|
['{9e5530c5-7034-48b4-bb46-0b8a6efc8e36}']
|
|
function SetImageCompositor: HRESULT; stdcall;
|
|
function SetNumberOfStreams(
|
|
dwMaxStreams: DWORD): HRESULT; stdcall;
|
|
function GetNumberOfStreams(
|
|
pdwMaxStreams: PDWORD): HRESULT; stdcall;
|
|
function SetRenderingPrefs(
|
|
dwRenderFlags: DWORD): HRESULT; stdcall;
|
|
function GetRenderingPrefs(
|
|
pdwRenderFlags: PDWORD): HRESULT; stdcall;
|
|
function SetRenderingMode(
|
|
Mode: DWORD): HRESULT; stdcall;
|
|
function GetRenderingMode(
|
|
pMode: PDWORD): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEVMRFilterConfig = IIEVMRFilterConfig;
|
|
|
|
IEVMRFrequency = packed record
|
|
dwNumerator: DWORD;
|
|
dwDenominator: DWORD;
|
|
end;
|
|
|
|
IEVMRVideoDesc = packed record
|
|
dwSize: DWORD;
|
|
dwSampleWidth: DWORD;
|
|
dwSampleHeight: DWORD;
|
|
SingleFieldPerSample: longbool;
|
|
dwFourCC: DWORD;
|
|
InputSampleFreq: IEVMRFrequency;
|
|
OutputFrameFreq: IEVMRFrequency;
|
|
end;
|
|
PIEVMRVideoDesc = ^IEVMRVideoDesc;
|
|
|
|
IEVMRDeinterlaceCaps = packed record
|
|
dwSize: DWORD;
|
|
dwNumPreviousOutputFrames: DWORD;
|
|
dwNumForwardRefSamples: DWORD;
|
|
dwNumBackwardRefSamples: DWORD;
|
|
DeinterlaceTechnology: DWORD; //VMRDeinterlaceTech;
|
|
end;
|
|
PIEVMRDeinterlaceCaps = ^IEVMRDeinterlaceCaps;
|
|
|
|
IIEVMRDeinterlaceControl = interface(IUnknown)
|
|
['{bb057577-0db8-4e6a-87a7-1a8c9a505a0f}']
|
|
function GetNumberOfDeinterlaceModes(
|
|
lpVideoDescription: PIEVMRVideoDesc;
|
|
lpdwNumDeinterlaceModes: PDWORD;
|
|
lpDeinterlaceModes: PGUID): HRESULT; stdcall;
|
|
function GetDeinterlaceModeCaps(
|
|
lpDeinterlaceMode: PGUID;
|
|
lpVideoDescription: PIEVMRVideoDesc;
|
|
lpDeinterlaceCaps: PIEVMRDeinterlaceCaps): HRESULT; stdcall;
|
|
function GetDeinterlaceMode(
|
|
dwStreamID: DWORD;
|
|
lpDeinterlaceMode: PGUID): HRESULT; stdcall;
|
|
function SetDeinterlaceMode(
|
|
dwStreamID: DWORD;
|
|
lpDeinterlaceMode: PGUID): HRESULT; stdcall;
|
|
function GetDeinterlacePrefs(
|
|
lpdwDeinterlacePrefs: PDWORD): HRESULT; stdcall;
|
|
function SetDeinterlacePrefs(
|
|
dwDeinterlacePrefs: DWORD): HRESULT; stdcall;
|
|
function GetActualDeinterlaceMode(
|
|
dwStreamID: DWORD;
|
|
lpDeinterlaceMode: PGUID): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEVMRDeinterlaceControl = IIEVMRDeinterlaceControl;
|
|
|
|
IEDVD_HMSF_TIMECODE = record
|
|
bHours: BYTE;
|
|
bMinutes: BYTE;
|
|
bSeconds: BYTE;
|
|
bFrames: BYTE;
|
|
end;
|
|
|
|
IEDVD_PLAYBACK_LOCATION2 = record
|
|
TitleNum: ULONG;
|
|
ChapterNum: ULONG;
|
|
TimeCode: IEDVD_HMSF_TIMECODE;
|
|
TimeCodeFlags: ULONG;
|
|
end;
|
|
|
|
IEAM_DVD_RENDERSTATUS=packed record
|
|
hrVPEStatus: HRESULT ;
|
|
bDVDVolInvalid: longbool ;
|
|
bDVDVolUnknown: longbool ;
|
|
bNoLine21In: longbool ;
|
|
bNoLine21Out: longbool ;
|
|
iNumStreams: integer ;
|
|
iNumStreamsFailed: integer ;
|
|
dwFailedStreamsFlag: DWORD ;
|
|
end;
|
|
PIEAM_DVD_RENDERSTATUS=^IEAM_DVD_RENDERSTATUS;
|
|
|
|
IIEDvdGraphBuilder = interface(IUnknown)
|
|
['{FCC152B6-F372-11d0-8E00-00C04FD7C08B}']
|
|
function GetFiltergraph( var ppGB: IIEGraphBuilder ) : HRESULT; stdcall;
|
|
function GetDvdInterface( const riid: TGUID ; out ppint): HRESULT; stdcall;
|
|
function RenderDvdVideoVolume( lpcwszPathName: pwchar; dwFlags: DWORD ; pStatus: PIEAM_DVD_RENDERSTATUS ): HRESULT; stdcall;
|
|
end;
|
|
|
|
IIEDvdCmd = interface(IUnknown)
|
|
['{5a4a97e4-94ee-4a55-9751-74b5643aa27d}']
|
|
function WaitForStart: HRESULT; stdcall;
|
|
function WaitForEnd: HRESULT; stdcall;
|
|
end;
|
|
PIIEDvdCmd=^IIEDvdCmd;
|
|
|
|
|
|
IIEDvdControl2 = interface(IUnknown)
|
|
['{33BC7430-EEC0-11D2-8201-00A0C9D74842}']
|
|
function PlayTitle(uiTitle: ULONG ; dwFlags: DWORD ; ppCmd: PIIEDvdCmd ): HRESULT; stdcall;
|
|
function PlayChapterInTitle(ulTitle: ULONG; ulChapter: ULONG; dwFlags: DWORD; var ppCmd: IIEDvdCmd): HRESULT; stdcall;
|
|
function PlayAtTimeInTitle(uiTitle: ULONG; var pTime: IEDVD_HMSF_TIMECODE; dwFlags: DWORD; var ppCmd: IIEDvdCmd): HRESULT; stdcall;
|
|
function Stop: HRESULT; stdcall;
|
|
function ReturnFromSubmenu: HRESULT; stdcall;
|
|
function PlayAtTime: HRESULT; stdcall;
|
|
function PlayChapter(ulChapter: ULONG; dwFlags: DWORD ; ppCmd: PIIEDvdCmd): HRESULT; stdcall;
|
|
function PlayPrevChapter: HRESULT; stdcall;
|
|
function ReplayChapter: HRESULT; stdcall;
|
|
function PlayNextChapter( dwFlags: DWORD; ppCmd: PIIEDvdCmd): HRESULT; stdcall;
|
|
function PlayForwards(dwSpeed: double ; dwFlags: DWORD; var ppCmd: IIEDvdCmd): HRESULT; stdcall;
|
|
function PlayBackwards(dwSpeed: double ; dwFlags: DWORD; var ppCmd: IIEDvdCmd): HRESULT; stdcall;
|
|
function ShowMenu(MenuID: ULONG; dwFlags: DWORD; var ppCmd: IIEDvdCmd): HRESULT; stdcall;
|
|
function Resume(dwFlags: DWORD; var ppCmd: IIEDvdCmd): HRESULT; stdcall;
|
|
function SelectRelativeButton: HRESULT; stdcall;
|
|
function ActivateButton: HRESULT; stdcall;
|
|
function SelectButton: HRESULT; stdcall;
|
|
function SelectAndActivateButton: HRESULT; stdcall;
|
|
function StillOff: HRESULT; stdcall;
|
|
function Pause(bState: longbool): HRESULT; stdcall;
|
|
function SelectAudioStream: HRESULT; stdcall;
|
|
function SelectSubpictureStream: HRESULT; stdcall;
|
|
function SetSubpictureState: HRESULT; stdcall;
|
|
function SelectAngle: HRESULT; stdcall;
|
|
function SelectParentalLevel: HRESULT; stdcall;
|
|
function SelectParentalCountry: HRESULT; stdcall;
|
|
function SelectKaraokeAudioPresentationMode: HRESULT; stdcall;
|
|
function SelectVideoModePreference(SelectVideoModePreference: DWORD): HRESULT; stdcall;
|
|
function SetDVDDirectory(path: pwchar): HRESULT; stdcall;
|
|
function ActivateAtPosition: HRESULT; stdcall;
|
|
function SelectAtPosition(piont: TPoint): HRESULT; stdcall;
|
|
function PlayChaptersAutoStop: HRESULT; stdcall;
|
|
function AcceptParentalLevelChange: HRESULT; stdcall;
|
|
function SetOption(flag: integer; Enable: longbool): HRESULT; stdcall;
|
|
function SetState: HRESULT; stdcall;
|
|
function PlayPeriodInTitleAutoStop: HRESULT; stdcall;
|
|
function SetGPRM: HRESULT; stdcall;
|
|
function SelectDefaultMenuLanguage: HRESULT; stdcall;
|
|
function SelectDefaultAudioLanguage: HRESULT; stdcall;
|
|
function SelectDefaultSubpictureLanguage: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEDvdControl2=IIEDvdControl2;
|
|
|
|
|
|
IIEDvdControl=interface(IUnknown)
|
|
['{A70EFE61-E2A3-11d0-A9BE-00AA0061BE93}']
|
|
function TitlePlay(uiTitle: ULONG ): HRESULT; stdcall;
|
|
function ChapterPlay: HRESULT; stdcall;
|
|
function TimePlay: HRESULT; stdcall;
|
|
function StopForResume: HRESULT; stdcall;
|
|
function GoUp: HRESULT; stdcall;
|
|
function TimeSearch: HRESULT; stdcall;
|
|
function ChapterSearch: HRESULT; stdcall;
|
|
function PrevPGSearch: HRESULT; stdcall;
|
|
function TopPGSearch: HRESULT; stdcall;
|
|
function NextPGSearch: HRESULT; stdcall;
|
|
function ForwardScan: HRESULT; stdcall;
|
|
function BackwardScan: HRESULT; stdcall;
|
|
function MenuCall: HRESULT; stdcall;
|
|
function Resume: HRESULT; stdcall;
|
|
function UpperButtonSelect: HRESULT; stdcall;
|
|
function LowerButtonSelect: HRESULT; stdcall;
|
|
function LeftButtonSelect: HRESULT; stdcall;
|
|
function RightButtonSelect: HRESULT; stdcall;
|
|
function ButtonActivate: HRESULT; stdcall;
|
|
function ButtonSelectAndActivate: HRESULT; stdcall;
|
|
function StillOff: HRESULT; stdcall;
|
|
function PauseOn: HRESULT; stdcall;
|
|
function PauseOff: HRESULT; stdcall;
|
|
function MenuLanguageSelect: HRESULT; stdcall;
|
|
function AudioStreamChange: HRESULT; stdcall;
|
|
function SubpictureStreamChange: HRESULT; stdcall;
|
|
function AngleChange: HRESULT; stdcall;
|
|
function ParentalLevelSelect: HRESULT; stdcall;
|
|
function ParentalCountrySelect: HRESULT; stdcall;
|
|
function KaraokeAudioPresentationModeChange: HRESULT; stdcall;
|
|
function VideoModePreferrence: HRESULT; stdcall;
|
|
function SetRoot: HRESULT; stdcall;
|
|
function MouseActivate: HRESULT; stdcall;
|
|
function MouseSelect: HRESULT; stdcall;
|
|
function ChapterPlayAutoStop: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEDvdControl=IIEDvdControl;
|
|
|
|
IIEDvdInfo2=interface(IUnknown)
|
|
['{34151510-EEC0-11D2-8201-00A0C9D74842}']
|
|
function GetCurrentDomain: HRESULT; stdcall;
|
|
function GetCurrentLocation(var pLocation: IEDVD_PLAYBACK_LOCATION2): HRESULT; stdcall;
|
|
function GetTotalTitleTime(var pTotalTime: IEDVD_HMSF_TIMECODE; var pulTimeCodeFlags: ULONG): HRESULT; stdcall;
|
|
function GetCurrentButton: HRESULT; stdcall;
|
|
function GetCurrentAngle: HRESULT; stdcall;
|
|
function GetCurrentAudio: HRESULT; stdcall;
|
|
function GetCurrentSubpicture: HRESULT; stdcall;
|
|
function GetCurrentUOPS: HRESULT; stdcall;
|
|
function GetAllSPRMs: HRESULT; stdcall;
|
|
function GetAllGPRMs: HRESULT; stdcall;
|
|
function GetAudioLanguage: HRESULT; stdcall;
|
|
function GetSubpictureLanguage: HRESULT; stdcall;
|
|
function GetTitleAttributes: HRESULT; stdcall;
|
|
function GetVMGAttributes: HRESULT; stdcall;
|
|
function GetCurrentVideoAttributes: HRESULT; stdcall;
|
|
function GetAudioAttributes: HRESULT; stdcall;
|
|
function GetKaraokeAttributes: HRESULT; stdcall;
|
|
function GetSubpictureAttributes: HRESULT; stdcall;
|
|
function GetDVDVolumeInfo(var pulNumOfVolumes: ULONG; var pulVolume: ULONG; var pSide: ULONG; var pulNumOfTitles: ULONG): HRESULT; stdcall;
|
|
function GetDVDTextNumberOfLanguages: HRESULT; stdcall;
|
|
function GetDVDTextLanguageInfo: HRESULT; stdcall;
|
|
function GetDVDTextStringAsNative: HRESULT; stdcall;
|
|
function GetDVDTextStringAsUnicode: HRESULT; stdcall;
|
|
function GetPlayerParentalLevel: HRESULT; stdcall;
|
|
function GetNumberOfChapters(ulTitle: ULONG; var pulNumOfChapters: ULONG): HRESULT; stdcall;
|
|
function GetTitleParentalLevels: HRESULT; stdcall;
|
|
function GetDVDDirectory: HRESULT; stdcall;
|
|
function IsAudioStreamEnabled: HRESULT; stdcall;
|
|
function GetDiscID(pszwPath: pointer; var pullDiscID: int64): HRESULT; stdcall;
|
|
function GetState: HRESULT; stdcall;
|
|
function GetMenuLanguages: HRESULT; stdcall;
|
|
function GetButtonAtPosition: HRESULT; stdcall;
|
|
function GetCmdFromEvent: HRESULT; stdcall;
|
|
function GetDefaultMenuLanguage: HRESULT; stdcall;
|
|
function GetDefaultAudioLanguage: HRESULT; stdcall;
|
|
function GetDefaultSubpictureLanguage: HRESULT; stdcall;
|
|
function GetDecoderCaps: HRESULT; stdcall;
|
|
function GetButtonRect: HRESULT; stdcall;
|
|
function IsSubpictureStreamEnabled: HRESULT; stdcall;
|
|
end;
|
|
IID_IIEDvdInfo2=IIEDvdInfo2;
|
|
|
|
IIEVMRAspectRatioControl = interface(IUnknown)
|
|
['{ede80b5c-bad6-4623-b537-65586c9f8dfd}']
|
|
function GetAspectRatioMode(lpdwARMode: PDWORD): HRESULT; stdcall;
|
|
function SetAspectRatioMode(dwARMode: DWORD): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEVMRAspectRatioControl=IIEVMRAspectRatioControl;
|
|
|
|
IIEAMGraphStreams = interface(IUnknown)
|
|
['{632105FA-072E-11d3-8AF9-00C04FB6BD3D}']
|
|
function FindUpstreamInterface: HRESULT; stdcall;
|
|
function SyncUsingStreamOffset(bUseStreamOffset: longbool): HRESULT; stdcall;
|
|
function SetMaxGraphLatency(rtMaxGraphLatency: IEREFERENCE_TIME): HRESULT; stdcall;
|
|
end;
|
|
IID_IIEAMGraphStreams=IIEAMGraphStreams;
|
|
|
|
{!!
|
|
<FS>TIEPropertyPages
|
|
|
|
<FM>Declaration<FC>
|
|
}
|
|
TIEPropertyPages = (iepVideoInput, iepAudioInput, iepVideoCodec, iepAudioCodec, iepVideoInputSource, iepTuner);
|
|
{!!}
|
|
|
|
{!!
|
|
<FS>TIEPropertyPagesType
|
|
|
|
<FM>Declaration<FC>
|
|
}
|
|
TIEPropertyPagesType = (ietFilter, ietInput, ietOutput);
|
|
{!!}
|
|
|
|
{!!
|
|
<FS>TIEVideoFormat
|
|
|
|
<FM>Declaration<FC>
|
|
}
|
|
TIEVideoFormat = class
|
|
Format: AnsiString; // pixels format
|
|
BitRate: integer; // Approximate data rate of the video stream, in bits per second.
|
|
VideoStandard: AnsiString; // The analog video standard supported.
|
|
MinWidth: integer;
|
|
MinHeight: integer;
|
|
MaxWidth: integer;
|
|
MaxHeight: integer;
|
|
GranularityX: integer;
|
|
GranularityY: integer;
|
|
BitmapWidth: integer;
|
|
BitmapHeight: integer;
|
|
end;
|
|
{!!}
|
|
|
|
{!!
|
|
<FS>TIEReferenceClock
|
|
|
|
<FM>Declaration<FC>
|
|
TIEReferenceClock = (rcDefault, rcNone, rcSystemClock, rcVideoInput, rcVideoOutput, rcAudioInput, rcAudioOutput);
|
|
|
|
<FM>Description<FN>
|
|
<TABLE>
|
|
<R> <H>Value</H> <H>Description</H> </R>
|
|
<R> <C>rcDefault</C> <C>Default DirectShow setting</C> </R>
|
|
<R> <C>rcNone</C> <C>No synchronism used</C> </R>
|
|
<R> <C>rcSystemClock</C> <C>Use system clock</C> </R>
|
|
<R> <C>rcVideoInput</C> <C>Video input is the synch reference</C> </R>
|
|
<R> <C>rcVideoOutput</C> <C>Video output is the synch reference</C> </R>
|
|
<R> <C>rcAudioInput</C> <C>Audio input is the synch reference</C> </R>
|
|
<R> <C>rcAudioOutput</C> <C>Audio output is the sync reference</C> </R>
|
|
</TABLE>
|
|
!!}
|
|
TIEReferenceClock = (rcDefault, rcNone, rcSystemClock, rcVideoInput, rcVideoOutput, rcAudioInput, rcAudioOutput);
|
|
|
|
|
|
{!!
|
|
<FS>TIEDSCapturemode
|
|
|
|
<FM>Declaration<FC>
|
|
TIEDSCapturemode = (iedscCapture, iedscPreview);
|
|
|
|
<FM>Description<FN>
|
|
<TABLE>
|
|
<R> <H>Value</H> <H>Description</H> </R>
|
|
<R> <C>iedscCapture</C> <C>Use Capture pin of video capture device</C> </R>
|
|
<R> <C>iedscPreview</C> <C>Use preview pin of video capture device</C> </R>
|
|
</TABLE>
|
|
!!}
|
|
TIEDSCapturemode = (iedscCapture, iedscPreview);
|
|
|
|
|
|
{!!
|
|
<FS>TIEDSRunResult
|
|
|
|
<FM>Declaration<FC>
|
|
TIEDSRunResult = (iedsSuccess, iedsError, iedsBusy);
|
|
|
|
<FM>Description<FN>
|
|
<TABLE>
|
|
<R> <H>Value</H> <H>Description</H> </R>
|
|
<R> <C>iedsSuccess</C> <C>Run succeeded</C> </R>
|
|
<R> <C>iedsError</C> <C>Generic failure</C> </R>
|
|
<R> <C>iedsBusy</C> <C>Device was busy</C> </R>
|
|
</TABLE>
|
|
!!}
|
|
TIEDSRunResult = (iedsSuccess, iedsError, iedsBusy);
|
|
|
|
|
|
{!!
|
|
<FS>TIEDirectShow
|
|
|
|
<FM>Description<FN>
|
|
TIEDirectShow class allows control of some Direct Show features, such as video capture, audio capture, multimedia files capture as well video rendering, and multimedia file writing.
|
|
|
|
|
|
<IMG help_images\IEView_Capture.gif>
|
|
|
|
<FM>Methods and Properties<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.AudioCodecs></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.AudioInputs></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.BufferToTIEBitmap></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.CaptureMode></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.ClockErrorTolerance></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.Connect></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.Connected></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.ConvertTimeFormat></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.Disconnect></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.Duration></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.DVDActivateButton></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.DVDGetProperty></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.DVDInputPath></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.DVDPlayAdvanced></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.DVDPlayAt></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.DVDSelectAt></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.DVDShowMenu></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.EnableSampleGrabber></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.EndOfStream></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.FileInput></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.FileOutput></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.GetAverageTimePerFrame></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.GetCurrentVideoFormat></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.GetEventCode></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.GetSample></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.GetSupportedTVStandards></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.GetVideoRenderNativeSize></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.GetVideoRenderRect></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.NotifyWindow></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.Pause></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.Position></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.Rate></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.ReferenceClock></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.RenderAudio></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.RenderVideo></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.RepaintVideo></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.Run></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SaveGraph></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetAudioCodec></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetAudioInput></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetCurrentVideoFormat></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetNotifyWindow></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetTVStandard></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetVCRHorizontalLocking></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetVideoCodec></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetVideoInput></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.SetVideoRenderRect></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.ShowPropertyPages></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.State></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.Step></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.Stop></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.TimeFormat></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.TunerChannel></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEDirectShow.TunerFindSignal></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.VideoCodecQuality></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.VideoCodecs></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.VideoFormats></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.VideoFormatsCount></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.VideoInputs></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.VideoInputSource></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEDirectShow.VideoInputSources></C> </R>
|
|
</TABLE>
|
|
|
|
!!}
|
|
TIEDirectShow = class
|
|
private
|
|
fOLEInitialized: boolean;
|
|
// capture filters lists
|
|
fAudioInputs: TStringList;
|
|
fVideoInputs: TStringList;
|
|
// compression filters list
|
|
fVideoCodecs: TStringList;
|
|
fAudioCodecs: TStringList;
|
|
//
|
|
fVideoFormats: TList; // array of TIEVideoFormat classes
|
|
fVideoInputSources: TStringList; // crossbar inputs
|
|
// conversion filters
|
|
fCurColor: IIEBaseFilter;
|
|
// currently input filters
|
|
fCurAudioInput: IIEBaseFilter;
|
|
fCurVideoInput: IIEBaseFilter;
|
|
fCurFileInput: IIEBaseFilter; // this implies that fCurAudioInput=nil and fCurVideoIinput=nil
|
|
// file input
|
|
fFileInput: AnsiString;
|
|
// currently compression filters
|
|
fCurVideoCodec: IIEBaseFilter;
|
|
fCurAudioCodec: IIEBaseFilter;
|
|
fIAMVideoCompression: IIEAMVideoCompression;
|
|
// output file name
|
|
fFileOutput: AnsiString;
|
|
// currenly filter graph
|
|
fGraph: IIEGraphBuilder;
|
|
fBuilder: IIECaptureGraphBuilder2;
|
|
fControl: IIEMediaControl;
|
|
fMediaSeeking: IIEMediaSeeking;
|
|
fMediaEvent: IIEMediaEventEx;
|
|
fStreamConfig: IIEAMStreamConfig;
|
|
fCrossBarFilter: IIEBaseFilter; // Same as fcrossbar but viewed as IIEBaseFilter
|
|
fCrossBar: IIEAMCrossBar;
|
|
fTuner: IIEAMTvTuner;
|
|
fTunerFilter: IIEBaseFilter; // Same as fTuner but viewed as IIEBaseFilter
|
|
fVideoFrameStep: IIEVideoFrameStep;
|
|
fAnalogVideoDecoder: IIEAMAnalogVideoDecoder;
|
|
fClockSlave: IIEAMClockSlave;
|
|
// currenly sample grabber filter
|
|
fSampleGrabber: IIEBaseFilter;
|
|
fSampleGrabberFilter: IIESampleGrabber; // ISampleGrabber queried from fSampleGrabber filter
|
|
fEnableSampleGrabber: boolean;
|
|
fSampleGrabberCB: TIESampleGrabberCB; // sample grabber callback
|
|
// renderer
|
|
fNullRenderer: IIEBaseFilter;
|
|
// avi decompressor
|
|
fAVIDecompressor: IIEBaseFilter;
|
|
// MPEG2
|
|
fMPEG2Demultiplexer: IIEBaseFilter;
|
|
fMPEG2Decoder: IIEBaseFilter;
|
|
fColorConverterDMO: IIEBaseFilter;
|
|
// video render
|
|
fRenderVideo: boolean;
|
|
fVideoMixingRenderer: IIEBaseFilter;
|
|
fVMRFilterConfig: IIEVMRFilterConfig;
|
|
fVMRWindowlessControl: IIEVMRWindowlessControl;
|
|
fVMRSavedPin1, fVMRSavedPin2: IIEPin;
|
|
// notification window
|
|
fNotifyWindow: THandle;
|
|
fNewFrameMessage: integer;
|
|
fEventMessage: integer;
|
|
fAcceptNextFrame: boolean;
|
|
fEndOfStream: boolean;
|
|
// other
|
|
fRenderaudio: boolean;
|
|
fReferenceClock: TIEReferenceClock;
|
|
fClockErrorTolerance: integer;
|
|
fSystemClock: IIEReferenceClock;
|
|
fCaptureMode: TIEDSCaptureMode;
|
|
// DVD
|
|
fDVDInputPath: widestring;
|
|
fDVDControl2: IIEDvdControl2;
|
|
fDVDInfo2: IIEDvdInfo2;
|
|
// filter graph creation steps
|
|
function GetAudioInputs: TStringList;
|
|
function GetVideoInputs: TStringList;
|
|
function GetVideoCodecs: TStringList;
|
|
function GetAudioCodecs: TStringList;
|
|
//
|
|
procedure SetPosition(v: int64);
|
|
function GetPosition: int64;
|
|
function GetDuration: int64;
|
|
function GetGraphCreated: boolean;
|
|
procedure SetRate(value: double);
|
|
function GetRate: double;
|
|
procedure SetXTimeFormat(value: TIETimeFormat);
|
|
function GetXTimeFormat: TIETimeFormat;
|
|
procedure SetVideoCodecQuality(value: double);
|
|
function GetVideoCodecQuality: double;
|
|
function ShowFilterPropertyPages(filter: IIEBaseFilter; checkOnly: boolean): boolean;
|
|
function ShowPinPropertyPages(pin: IIEPin; checkOnly: boolean): boolean;
|
|
procedure FillVideoFormats();
|
|
procedure ClearVideoFormats;
|
|
function GetVideoFormats(i: integer): TIEVideoFormat;
|
|
function GetVideoFormatsCount: integer;
|
|
procedure FillVideoInputSources;
|
|
function GetInputSource: integer;
|
|
procedure SetInputSource(value: integer);
|
|
procedure SetVideoTunerChannel(value: integer);
|
|
function GetVideoTunerChannel: integer;
|
|
procedure DVDConnect;
|
|
procedure StdConnect;
|
|
procedure VMRDisconnectInPin;
|
|
procedure VMRReconnectInPin;
|
|
procedure ConnectCrossbarAudioDecoder;
|
|
procedure VMRCreate;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
property AudioInputs: TStringList read GetAudioInputs;
|
|
property VideoInputs: TStringList read GetVideoInputs;
|
|
property VideoCodecs: TStringList read GetVideoCodecs;
|
|
property AudioCodecs: TStringList read GetAudioCodecs;
|
|
procedure SetVideoInput(idx: integer; instanceIndex: integer = 0; width: integer = 0; height: integer = 0; format: AnsiString = ''; bitRate: integer = 0);
|
|
procedure SetAudioInput(idx: integer; instanceIndex: integer = 0);
|
|
procedure SetVideoCodec(idx: integer);
|
|
procedure SetAudioCodec(idx: integer);
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.FileInput
|
|
|
|
<FM>Declaration<FC>
|
|
property FileInput: AnsiString;
|
|
|
|
<FM>Description<FN>
|
|
If you don't want get video from a capture card, but just from a file, you must set FileInput property with a full path name and a multimedia file.
|
|
!!}
|
|
property FileInput: AnsiString read fFileInput write fFileInput;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.FileOutput
|
|
|
|
<FM>Declaration<FC>
|
|
property FileOutput: AnsiString;
|
|
|
|
<FM>Description<FN>
|
|
Specifies the full path of the output multimedia file.
|
|
!!}
|
|
property FileOutput: AnsiString read fFileOutput write fFileOutput;
|
|
|
|
procedure SaveGraph(filename: AnsiString); // save .grf files (readable with graphedit for debug)
|
|
procedure Connect;
|
|
procedure Disconnect;
|
|
property Connected: boolean read GetGraphCreated;
|
|
function Run(): TIEDSRunResult;
|
|
procedure Stop();
|
|
procedure Pause();
|
|
property Rate: double read GetRate write SetRate;
|
|
function State: TIEDirectShowState;
|
|
property Position: int64 read GetPosition write SetPosition;
|
|
property Duration: int64 read GetDuration;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.EndOfStream
|
|
|
|
<FM>Declaration<FC>
|
|
property EndOfStream: boolean;
|
|
|
|
<FM>Description<FN>
|
|
EndOfStream tests whether the file position is at the end of a file.
|
|
This field is updated only when parent of TIEDirectShow is IO.TImageEnView and OnDShowEvent is not handled.
|
|
!!}
|
|
property EndOfStream: boolean read fEndOfStream write fEndOfStream;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.EnableSampleGrabber
|
|
|
|
<FM>Declaration<FC>
|
|
property EnableSampleGrabber: boolean;
|
|
|
|
<FM>Description<FN>
|
|
If EnableSampleGrabber is True, then an event occurs whenever a new frame is available.
|
|
The event is <A TImageEnView.OnDShowNewFrame> (unless you use <A TIEDirectShow.SetNotifyWindow> and use TIEDirectShow as stand alone object).
|
|
!!}
|
|
property EnableSampleGrabber: boolean read fEnableSampleGrabber write fEnableSampleGrabber;
|
|
|
|
procedure GetSample(DestBitmap: TIEBitmap; resample: boolean = true);
|
|
property TimeFormat: TIETimeFormat read GetXTimeFormat write SetXTimeFormat;
|
|
procedure BufferToTIEBitmap(buffer: pbyte; len: integer; DestBitmap: TIEBitmap);
|
|
procedure SetNotifyWindow(WindowHandle: THandle; NewFrameMessage: integer; EventMessage: integer);
|
|
function GetEventCode(var Event: integer): boolean;
|
|
property VideoCodecQuality: double read GetVideoCodecQuality write SetVideoCodecQuality;
|
|
function ShowPropertyPages(proppages: TIEPropertyPages; proptype: TIEPropertyPagesType; checkOnly: boolean=false): boolean;
|
|
procedure SetCurrentVideoFormat(width, height: integer; format: AnsiString = '');
|
|
procedure GetCurrentVideoFormat(var width, height: integer; var format: AnsiString);
|
|
property VideoFormats[i: integer]: TIEVideoFormat read GetVideoFormats;
|
|
property VideoFormatsCount: integer read GetVideoFormatsCount;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.VideoInputSources
|
|
|
|
<FM>Declaration<FC>
|
|
property VideoInputSources: TStringList;
|
|
|
|
<FM>Description<FN>
|
|
Contains a list of video input sources available for the selected video input.
|
|
A video input source is a line input, like Video-Composite, Tuner, etc.
|
|
!!}
|
|
property VideoInputSources: TStringList read fVideoInputSources;
|
|
|
|
property VideoInputSource: integer read GetInputSource write SetInputSource;
|
|
property TunerChannel: integer read GetVideoTunerChannel write SetVideoTunerChannel;
|
|
function TunerFindSignal: boolean;
|
|
function GetSupportedTVStandards: TIETVStandards;
|
|
procedure SetTVStandard(Value: TIETVStandard);
|
|
procedure SetVCRHorizontalLocking(Value: boolean);
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.RenderAudio
|
|
|
|
<FM>Declaration<FC>
|
|
property RenderAudio: boolean
|
|
|
|
<FM>Description<FN>
|
|
If True renders the audio stream to the default audio renderer.
|
|
Sometimes audio is not synchronized with video. To get audio/video synchronized we should interact directly with hardware devices, but this will loss compatibility.
|
|
Anyway you could try to play with <A TIEDirectShow.ReferenceClock> and <A TIEDirectShow.ClockErrorTolerance> properties to get better synchronization.
|
|
!!}
|
|
property RenderAudio: boolean read fRenderAudio write fRenderAudio;
|
|
|
|
function Step(frames: integer): boolean;
|
|
function ConvertTimeFormat(source: int64; sourceFormat: TIETimeFormat; targetFormat: TIETimeFormat): int64;
|
|
function GetAverageTimePerFrame: int64;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.NotifyWindow
|
|
|
|
<FM>Declaration<FC>
|
|
property NotifyWindow: THandle;
|
|
|
|
<FM>Description<FN>
|
|
Returns current notification window handle.
|
|
!!}
|
|
property NotifyWindow: THandle read fNotifyWindow;
|
|
|
|
property AcceptNextFrame: boolean read fAcceptNextFrame write fAcceptNextFrame;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.ReferenceClock
|
|
|
|
<FM>Declaration<FC>
|
|
property ReferenceClock: <A TIEReferenceClock>;
|
|
|
|
<FM>Description<FN>
|
|
Specifies the source of reference clock.
|
|
You should change it when audio and video aren't synchronized.
|
|
When <A TIEDirectShow.RenderAudio> and <A TIEDirectShow.RenderVideo> are true, it is suggested to set ReferenceClock=rcAudioOutput.
|
|
!!}
|
|
property ReferenceClock: TIEReferenceClock read fReferenceclock write fReferenceClock;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.ClockErrorTolerance
|
|
|
|
<FM>Declaration<FC>
|
|
property ClockErrorTolerance: integer;
|
|
|
|
<FM>Description<FN>
|
|
Sets the maximum tolerance, in milliseconds, of the audio renderer. The value must be from 1 to 1000, inclusive.
|
|
!!}
|
|
property ClockErrorTolerance: integer read fClockErrorTolerance write fClockErrorTolerance;
|
|
|
|
// video renderer
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.RenderVideo
|
|
|
|
<FM>Declaration<FC>
|
|
property RenderVideo: boolean;
|
|
|
|
<FM>Description<FN>
|
|
When true the video input (from capture card, file or dvd) is displayed inside the component area.
|
|
|
|
<FM>Demos<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_DEMO> <C>Demos\VideoCapture\VMR_Capture\VMR_Capture.dpr </C> </R>
|
|
<R> <C_IMG_DEMO> <C>Demos\VideoCapture\VMR_Camera\VMR_Camera.dpr </C> </R>
|
|
<R> <C_IMG_DEMO> <C>Demos\Display\VMR_DVD\VMR_DVD.dpr </C> </R>
|
|
<R> <C_IMG_DEMO> <C>Demos\Display\VMR_Video\VMR_Video.dpr </C> </R>
|
|
</TABLE>
|
|
!!}
|
|
property RenderVideo: boolean read fRenderVideo write fRenderVideo;
|
|
|
|
procedure SetVideoRenderRect(SrcRect, DstRect: TRect);
|
|
procedure GetVideoRenderRect(var SrcRect: TRect; var DstRect: TRect);
|
|
procedure GetVideoRenderNativeSize(var Width: integer; var Height: integer);
|
|
procedure RepaintVideo(hwnd: THandle; hdc: THandle);
|
|
|
|
// DVD
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.DVDInputPath
|
|
|
|
<FM>Declaration<FC>
|
|
property DVDInputPath: WideString;
|
|
|
|
<FM>Description<FN>
|
|
Specifies the driver letter of DVD reader. You can set 'Default' to select default DVD reader.
|
|
You can also specify a path to VIDEO_TS directory, which contains video data. For example "C:\mydvd\VIDEO_TS".
|
|
In order to play DVD inside Delphi IDE please disable "Integrated Debugging".
|
|
|
|
<FM>Example<FC>
|
|
with ImageEnView1.IO.DShowParams do
|
|
begin
|
|
DVDInputPath := 'Default';
|
|
RenderVideo := true;
|
|
RenderAudio := true;
|
|
Connect;
|
|
// Set bitmap size
|
|
GetVideoRenderNativeSize(w, h);
|
|
ImageEnView1.Proc.ImageResize(w, h);
|
|
Run;
|
|
end;
|
|
|
|
<FM>Demo<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_DEMO> <C>Demos\Display\VMR_DVD\VMR_DVD.dpr </C> </R>
|
|
</TABLE>
|
|
!!}
|
|
property DVDInputPath: widestring read fDVDInputPath write fDVDInputPath;
|
|
|
|
procedure DVDSelectAt(x, y: integer);
|
|
procedure DVDActivateButton;
|
|
|
|
procedure DVDPlayAt(Title: integer; Chapter: integer); overload;
|
|
procedure DVDPlayAt(Title: integer; Hours, Minutes, Seconds, Frames: integer); overload;
|
|
function DVDGetProperty(Prop: AnsiString; SubProp: AnsiString=''): AnsiString;
|
|
procedure DVDPlayAdvanced(PlayForward: boolean; Speed: double);
|
|
procedure DVDShowMenu(Menu: TIEDVDMenu);
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.CaptureMode
|
|
|
|
<FM>Declaration<FC>
|
|
property CaptureMode: <A TIEDSCaptureMode>;
|
|
|
|
<FM>Description<FN>
|
|
Specifies the capture mode to use (preview or capture). Set this property before connect.
|
|
!!}
|
|
property CaptureMode: TIEDSCaptureMode read fCaptureMode write fCaptureMode;
|
|
|
|
end;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// TIEMediaReader
|
|
|
|
{!!
|
|
<FS>TIEMediaReader
|
|
|
|
<FM>Description<FN>
|
|
This class provides access to frames from a media file (wmv, mpeg...).
|
|
TIEMediaReader is a simple stand-alone class, with one single method to copy the wanted frame to a <A TIEBitmap> object.
|
|
Reading of frames could be slow.
|
|
|
|
Note: TIEMediaReader uses IMediaDet. Microsoft marks IMediaDet as Deprecated and may be removed from future releases of Windows
|
|
|
|
<FM>Example<FC>
|
|
var
|
|
media: TIEMediaReader;
|
|
|
|
media := TIEMediaReader.Create('video.wmv');
|
|
|
|
// get frame 0 and save to sample0.jpeg
|
|
media.GetSample( 0, ImageEnView1.IEBitmap );
|
|
ImageEnView1.IO.SaveToFile('sample0.jpeg');
|
|
|
|
// get frame 1 and save to sample1.jpeg
|
|
media.GetSample( 1, ImageEnView1.IEBitmap );
|
|
ImageEnView1.IO.SaveToFile('sample1.jpeg');
|
|
|
|
...etc...
|
|
|
|
media.free;
|
|
|
|
<FM>Methods and Properties<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEMediaReader.FrameCount></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEMediaReader.FrameHeight></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEMediaReader.FrameRate></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEMediaReader.FrameWidth></C> </R>
|
|
<R> <C_IMG_METHOD> <C><A TIEMediaReader.GetSample></C> </R>
|
|
<R> <C_IMG_PROPERTY> <C><A TIEMediaReader.Length></C> </R>
|
|
</TABLE>
|
|
!!}
|
|
TIEMediaReader = class
|
|
private
|
|
fFileName: AnsiString;
|
|
fMediaDet: IIEMediaDet;
|
|
fFrameRate: double; // frames per seconds
|
|
fLength: double; // stream length in seconds
|
|
fFrameCount: int64; // frame count
|
|
fFrameWidth, fFrameHeight: integer;
|
|
//fFrameBuffer: pointer;
|
|
public
|
|
constructor Create(const FileName: AnsiString);
|
|
destructor Destroy; override;
|
|
|
|
{!!
|
|
<FS>TIEMediaReader.FrameRate
|
|
|
|
<FM>Declaration<FC>
|
|
property FrameRate: double;
|
|
|
|
<FM>Description<FN>
|
|
Returns the frame rate.
|
|
!!}
|
|
property FrameRate: double read fFrameRate;
|
|
|
|
{!!
|
|
<FS>TIEMediaReader.Length
|
|
|
|
<FM>Declaration<FC>
|
|
property Length: double;
|
|
|
|
<FM>Description<FN>
|
|
Returns the video length;
|
|
!!}
|
|
property Length: double read fLength;
|
|
|
|
{!!
|
|
<FS>TIEMediaReader.FrameCount
|
|
|
|
<FM>Declaration<FC>
|
|
property FrameCount: int64;
|
|
|
|
<FM>Description<FN>
|
|
Returns the number of frames (samples).
|
|
!!}
|
|
property FrameCount: int64 read fFrameCount;
|
|
|
|
procedure GetSample(frame: int64; OutBitmap: TIEBitmap);
|
|
|
|
{!!
|
|
<FS>TIEMediaReader.FrameWidth
|
|
|
|
<FM>Declaration<FC>
|
|
property FrameWidth: integer;
|
|
|
|
<FM>Description<FN>
|
|
Returns the frame bitmap width.
|
|
!!}
|
|
property FrameWidth: integer read fFrameWidth;
|
|
|
|
{!!
|
|
<FS>TIEMediaReader.FrameHeight
|
|
|
|
<FM>Declaration<FC>
|
|
property FrameHeight: integer;
|
|
<FM>Description<FN>
|
|
Returns the frame bitmap height.
|
|
!!}
|
|
property FrameHeight: integer read fFrameHeight;
|
|
|
|
end;
|
|
|
|
// TIEMediaReader
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
iesettings, hyieutils;
|
|
|
|
|
|
const
|
|
ole32 = 'ole32.dll';
|
|
|
|
function CoCreateInstance(const clsid: TGUID; unkOuter: IUnknown; dwClsContext: Longint; const iid: TGUID; out pv): HResult; stdcall; external ole32 name 'CoCreateInstance';
|
|
function OleInitialize(pwReserved: Pointer): HResult; stdcall; external ole32 name 'OleInitialize';
|
|
procedure OleUninitialize; stdcall; external ole32 name 'OleUninitialize';
|
|
procedure CoTaskMemFree(pv: pointer); stdcall; external ole32 name 'CoTaskMemFree';
|
|
//procedure ReleaseStgMedium(pmedium: pointer); stdcall; external ole32 name 'ReleaseStgMedium';
|
|
function FreePropVariantArray(cVariants: ULONG; rgvars: pointer): HRESULT; stdcall; external ole32 name 'FreePropVariantArray';
|
|
procedure SysFreeString(pstr: pointer); stdcall; external 'oleaut32.dll' name 'SysFreeString';
|
|
function StgCreateDocfile(pwcsName: PWideChar; grfMode: dword; reserved: dword; var ppstgOpen: IIEStorage): HRESULT; stdcall; external ole32 name 'StgCreateDocfile';
|
|
function OleCreatePropertyFrame(hwndOwner: THandle; x, y: dword; lpszCaption: PAnsiChar; cObjects: dword; lplpUnk: pointer; cPages: dword; lpPageClsID: PGUID; lcid: PGUID; dwReserved: dword; lpvReserved: pointer): HRESULT; stdcall; external 'OleAut32.dll' name 'OleCreatePropertyFrame';
|
|
function IsEqualGUID(const guid1, guid2: TGUID): Boolean; stdcall; external ole32 name 'IsEqualGUID';
|
|
|
|
|
|
const
|
|
|
|
VFW_S_CANT_CUE = $40268;
|
|
|
|
|
|
IEGUIDNULL: TGUID = '{00000000-0000-0000-0000-000000000000}';
|
|
|
|
CLSID_SystemDeviceEnum: TGUID = '{62BE5D10-60EB-11d0-BD3B-00A0C911CE86}';
|
|
CLSID_FilterGraph: TGUID = '{e436ebb3-524f-11ce-9f53-0020af0ba770}';
|
|
CLSID_CaptureGraphBuilder2: TGUID = '{BF87B6E1-8C27-11d0-B3F0-00AA003761C5}';
|
|
CLSID_MediaDet: TGUID = '{65BD0711-24D2-4ff7-9324-ED2E5D3ABAFA}';
|
|
|
|
CLSID_VideoInputDeviceCategory: TGUID = '{860BB310-5D01-11d0-BD3B-00A0C911CE86}';
|
|
CLSID_LegacyAmFilterCategory: TGUID = '{083863F1-70DE-11d0-BD40-00A0C911CE86}';
|
|
CLSID_VideoCompressorCategory: TGUID = '{33D9A760-90C8-11d0-BD43-00A0C911CE86}';
|
|
CLSID_AudioCompressorCategory: TGUID = '{33D9A761-90C8-11d0-BD43-00A0C911CE86}';
|
|
CLSID_AudioInputDeviceCategory: TGUID = '{33D9A762-90C8-11d0-BD43-00A0C911CE86}';
|
|
CLSID_AudioRendererCategory: TGUID = '{E0F158E1-CB04-11d0-BD4E-00A0C911CE86}';
|
|
CLSID_MidiRendererCategory: TGUID = '{4EFE2452-168A-11d1-BC76-00C04FB9453B}';
|
|
CLSID_SampleGrabber: TGUID = '{C1F400A0-3F08-11d3-9F0B-006008039E37}';
|
|
CLSID_NullRenderer: TGUID = '{C1F400A4-3F08-11d3-9F0B-006008039E37}';
|
|
|
|
CLSID_AVIDec: TGUID = '{CF49D4E0-1115-11CE-B03A-0020AF0BA770}';
|
|
|
|
CLSID_MMSPLITTER: TGUID = '{3ae86b20-7be8-11d1-abe6-00a0c905f375}';
|
|
|
|
DMOCATEGORY_VIDEO_EFFECT: TGUID = '{d990ee14-776c-4723-be46-3da2f56f10b9}';
|
|
|
|
CLSID_DMOWrapperFilter: TGUID = '{94297043-bd82-4dfd-b0de-8177739c6d20}';
|
|
|
|
CLSID_MPEG2Demultiplexer: TGUID = '{afb6c280-2c41-11d3-8a60-0000f81e0e4a}';
|
|
|
|
CLSID_CMPEG2VidDecoderDS: TGUID = '{212690FB-83E5-4526-8FD7-74478B7939CD}';
|
|
|
|
CLSID_CColorConvertDMO: TGUID = '{98230571-0087-4204-b020-3282538e57d3}';
|
|
|
|
CLSID_DvdGraphBuilder: TGUID = '{FCC152B7-F372-11d0-8E00-00C04FD7C08B}';
|
|
|
|
CLSID_Color: TGUID = '{1643e180-90f5-11ce-97d5-00aa0055595a}';
|
|
|
|
CLSID_VideoMixingRenderer: TGUID = '{B87BEB7B-8D29-423f-AE4D-6582C10175AC}';
|
|
CLSID_VideoMixingRenderer9: TGUID = '{51b4abf3-748f-4e3b-a276-c828330e926a}';
|
|
|
|
CLSID_DVDNavigator: TGUID = '{9B8C4620-2C1A-11d0-8493-00A02438AD48}';
|
|
|
|
CLSID_DSoundRender: TGUID = '{79376820-07D0-11cf-A24D-0020AFD79767}';
|
|
|
|
CLSID_SystemClock: TGUID = '{e436ebb1-524f-11ce-9f53-0020af0ba770}';
|
|
|
|
MEDIASUBTYPE_Avi: TGUID = '{e436eb88-524f-11ce-9f53-0020af0ba770}';
|
|
MEDIASUBTYPE_Asf: TGUID = '{3DB80F90-9412-11d1-ADED-0000F8754B99}';
|
|
MEDIASUBTYPE_WAVE: TGUID = '{e436eb8b-524f-11ce-9f53-0020af0ba770}';
|
|
MEDIASUBTYPE_MPEG1Video: TGUID = '{e436eb86-524f-11ce-9f53-0020af0ba770}';
|
|
MEDIASUBTYPE_None: TGUID = '{e436eb8e-524f-11ce-9f53-0020af0ba770}';
|
|
|
|
|
|
PIN_CATEGORY_CAPTURE: TGUID = '{fb6c4281-0353-11d1-905f-0000c0cc16ba}';
|
|
PIN_CATEGORY_PREVIEW: TGUID = '{fb6c4282-0353-11d1-905f-0000c0cc16ba}';
|
|
|
|
MEDIATYPE_Video: TGUID = '{73646976-0000-0010-8000-00AA00389B71}';
|
|
MEDIATYPE_Audio: TGUID = '{73647561-0000-0010-8000-00AA00389B71}';
|
|
MEDIATYPE_Stream : TGUID = '{e436eb83-524f-11ce-9f53-0020af0ba770}';
|
|
FORMAT_VideoInfo: TGUID = '{05589f80-c356-11ce-bf01-00aa0055595a}';
|
|
|
|
CLSCTX_LOCAL_SERVER = 4;
|
|
CLSCTX_REMOTE_SERVER = $10;
|
|
CLSCTX_INPROC_HANDLER = 2;
|
|
CLSCTX_INPROC_SERVER = 1;
|
|
CLSCTX_INPROC = CLSCTX_INPROC_SERVER or CLSCTX_INPROC_HANDLER;
|
|
|
|
STGM_CREATE = $00001000;
|
|
STGM_TRANSACTED = $00010000;
|
|
STGM_READWRITE = $00000002;
|
|
STGM_SHARE_EXCLUSIVE = $00000010;
|
|
STGM_WRITE = $00000001;
|
|
STGC_DEFAULT = 0;
|
|
|
|
AM_SEEKING_NoPositioning = 0;
|
|
AM_SEEKING_AbsolutePositioning = $1;
|
|
AM_SEEKING_RelativePositioning = $2;
|
|
AM_SEEKING_IncrementalPositioning = $3;
|
|
AM_SEEKING_PositioningBitsMask = $3;
|
|
AM_SEEKING_SeekToKeyFrame = $4;
|
|
AM_SEEKING_ReturnTime = $8;
|
|
AM_SEEKING_Segment = $10;
|
|
AM_SEEKING_NoFlush = $20;
|
|
|
|
TIME_FORMAT_NONE: TGUID = '{00000000-0000-0000-0000-000000000000}';
|
|
TIME_FORMAT_FRAME: TGUID = '{7b785570-8c82-11cf-bc0c-00aa00ac74f6}';
|
|
TIME_FORMAT_BYTE: TGUID = '{7b785571-8c82-11cf-bc0c-00aa00ac74f6}';
|
|
TIME_FORMAT_SAMPLE: TGUID = '{7b785572-8c82-11cf-bc0c-00aa00ac74f6}';
|
|
TIME_FORMAT_FIELD: TGUID = '{7b785573-8c82-11cf-bc0c-00aa00ac74f6}';
|
|
TIME_FORMAT_MEDIA_TIME: TGUID = '{7b785574-8c82-11cf-bc0c-00aa00ac74f6}';
|
|
|
|
INFINITE = $FFFFFFFF;
|
|
|
|
MEDIASUBTYPE_CLPL: TGUID = (D1: $4C504C43; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_YUYV: TGUID = (D1: $56595559; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_IYUV: TGUID = (D1: $56555949; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_YVU9: TGUID = (D1: $39555659; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_Y411: TGUID = (D1: $31313459; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_Y41P: TGUID = (D1: $50313459; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_YUY2: TGUID = (D1: $32595559; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_YVYU: TGUID = (D1: $55595659; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_UYVY: TGUID = (D1: $59565955; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_Y211: TGUID = (D1: $31313259; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_YV12: TGUID = (D1: $32315659; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_CLJR: TGUID = (D1: $524A4C43; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_IF09: TGUID = (D1: $39304649; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_CPLA: TGUID = (D1: $414C5043; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_MJPG: TGUID = (D1: $47504A4D; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_TVMJ: TGUID = (D1: $4A4D5654; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_WAKE: TGUID = (D1: $454B4157; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_CFCC: TGUID = (D1: $43434643; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_IJPG: TGUID = (D1: $47504A49; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_Plum: TGUID = (D1: $6D756C50; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_DVCS: TGUID = (D1: $53435644; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_DVSD: TGUID = (D1: $44535644; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_MDVF: TGUID = (D1: $4656444D; D2: $0000; D3: $0010; D4: ($80, $00, $00, $AA, $00, $38, $9B, $71));
|
|
MEDIASUBTYPE_RGB1: TGUID = (D1: $E436EB78; D2: $524F; D3: $11CE; D4: ($9F, $53, $00, $20, $AF, $0B, $A7, $70));
|
|
MEDIASUBTYPE_RGB4: TGUID = (D1: $E436EB79; D2: $524F; D3: $11CE; D4: ($9F, $53, $00, $20, $AF, $0B, $A7, $70));
|
|
MEDIASUBTYPE_RGB8: TGUID = (D1: $E436EB7A; D2: $524F; D3: $11CE; D4: ($9F, $53, $00, $20, $AF, $0B, $A7, $70));
|
|
MEDIASUBTYPE_RGB565: TGUID = (D1: $E436EB7B; D2: $524F; D3: $11CE; D4: ($9F, $53, $00, $20, $AF, $0B, $A7, $70));
|
|
MEDIASUBTYPE_RGB555: TGUID = (D1: $E436EB7C; D2: $524F; D3: $11CE; D4: ($9F, $53, $00, $20, $AF, $0B, $A7, $70));
|
|
MEDIASUBTYPE_RGB24: TGUID = (D1: $E436EB7D; D2: $524F; D3: $11CE; D4: ($9F, $53, $00, $20, $AF, $0B, $A7, $70));
|
|
MEDIASUBTYPE_RGB32: TGUID = (D1: $E436EB7E; D2: $524F; D3: $11CE; D4: ($9F, $53, $00, $20, $AF, $0B, $A7, $70));
|
|
MEDIASUBTYPE_ARGB1555: TGUID = '{297C55AF-E209-4cb3-B757-C76D6B9C88A8}';
|
|
MEDIASUBTYPE_ARGB4444: TGUID = '{6E6415E6-5C24-425f-93CD-80102B3D1CCA}';
|
|
MEDIASUBTYPE_ARGB32: TGUID = (D1: $773C9AC0; D2: $3274; D3: $11D0; D4: ($B7, $24, $00, $AA, $00, $6C, $1A, $1));
|
|
MEDIASUBTYPE_AYUV: TGUID = '{56555941-0000-0010-8000-00AA00389B71}'; //'AYUV' == MEDIASUBTYPE_AYUV
|
|
MEDIASUBTYPE_AI44: TGUID = '{34344941-0000-0010-8000-00AA00389B71}'; //'AI44' == MEDIASUBTYPE_AI44
|
|
MEDIASUBTYPE_IA44: TGUID = '{34344149-0000-0010-8000-00AA00389B71}'; //'IA44' == MEDIASUBTYPE_IA44
|
|
|
|
LOOK_UPSTREAM_ONLY: TGUID='{AC798BE0-98E3-11d1-B3F1-00AA003761C5}';
|
|
|
|
|
|
PINDIR_INPUT = 0;
|
|
PINDIR_OUTPUT = 1;
|
|
|
|
PhysConn_Video_Tuner = 1;
|
|
PhysConn_Video_Composite = 2;
|
|
PhysConn_Video_SVideo = 3;
|
|
PhysConn_Video_RGB = 4;
|
|
PhysConn_Video_YRYBY = 5;
|
|
PhysConn_Video_SerialDigital = 6;
|
|
PhysConn_Video_ParallelDigital = 7;
|
|
PhysConn_Video_SCSI = 8;
|
|
PhysConn_Video_AUX = 9;
|
|
PhysConn_Video_1394 = 10;
|
|
PhysConn_Video_USB = 11;
|
|
PhysConn_Video_VideoDecoder = 12;
|
|
PhysConn_Video_VideoEncoder = 13;
|
|
PhysConn_Video_SCART = 14;
|
|
|
|
PhysConn_Audio_Tuner = 4096;
|
|
PhysConn_Audio_Line = 4097;
|
|
PhysConn_Audio_Mic = 4098;
|
|
PhysConn_Audio_AESDigital = 4099;
|
|
PhysConn_Audio_SPDIFDigital = 4100;
|
|
PhysConn_Audio_SCSI = 4101;
|
|
PhysConn_Audio_AUX = 4102;
|
|
PhysConn_Audio_1394 = 4103;
|
|
PhysConn_Audio_USB = 4104;
|
|
PhysConn_Audio_AudioDecoder = 4105;
|
|
|
|
AMTUNER_SUBCHAN_NO_TUNE = -2;
|
|
AMTUNER_SUBCHAN_DEFAULT = -1;
|
|
|
|
VMRMode_Windowed = $1;
|
|
VMRMode_Windowless = $2;
|
|
VMRMode_Renderless = $4;
|
|
VMRMode_Mask = $7;
|
|
|
|
// DVD_CMD_FLAGS
|
|
DVD_CMD_FLAG_None = $0;
|
|
DVD_CMD_FLAG_Flush = $1;
|
|
DVD_CMD_FLAG_SendEvents = $2;
|
|
DVD_CMD_FLAG_Block = $4;
|
|
DVD_CMD_FLAG_StartWhenRendered = $8;
|
|
DVD_CMD_FLAG_EndAfterRendered = $10;
|
|
|
|
|
|
const
|
|
cv: array[0..35] of PGUID = (@MEDIASUBTYPE_CLPL, @MEDIASUBTYPE_YUYV, @MEDIASUBTYPE_IYUV, @MEDIASUBTYPE_YVU9, @MEDIASUBTYPE_Y411,
|
|
@MEDIASUBTYPE_Y41P, @MEDIASUBTYPE_YUY2, @MEDIASUBTYPE_YVYU, @MEDIASUBTYPE_UYVY, @MEDIASUBTYPE_Y211,
|
|
@MEDIASUBTYPE_YV12, @MEDIASUBTYPE_CLJR, @MEDIASUBTYPE_IF09, @MEDIASUBTYPE_CPLA, @MEDIASUBTYPE_MJPG,
|
|
@MEDIASUBTYPE_TVMJ, @MEDIASUBTYPE_WAKE, @MEDIASUBTYPE_CFCC, @MEDIASUBTYPE_IJPG, @MEDIASUBTYPE_Plum,
|
|
@MEDIASUBTYPE_DVCS, @MEDIASUBTYPE_DVSD, @MEDIASUBTYPE_MDVF, @MEDIASUBTYPE_RGB1, @MEDIASUBTYPE_RGB4,
|
|
@MEDIASUBTYPE_RGB8, @MEDIASUBTYPE_RGB565, @MEDIASUBTYPE_RGB555, @MEDIASUBTYPE_RGB24, @MEDIASUBTYPE_RGB32,
|
|
@MEDIASUBTYPE_ARGB1555, @MEDIASUBTYPE_ARGB4444, @MEDIASUBTYPE_ARGB32, @MEDIASUBTYPE_AYUV, @MEDIASUBTYPE_AI44, @MEDIASUBTYPE_IA44);
|
|
cs: array[0..35] of AnsiString = ('CLPL', 'YUYV', 'IYUV', 'YVU9', 'Y411',
|
|
'Y41P', 'YUY2', 'YVYU', 'UYVY', 'Y211',
|
|
'YV12', 'CLJR', 'IF09', 'CPLA', 'MJPG',
|
|
'TVMJ', 'WAKE', 'CFCC', 'IJPG', 'Plum',
|
|
'DVCS', 'DVSD', 'MDVF', 'RGB1', 'RGB4',
|
|
'RGB8', 'RGB565', 'RGB555', 'RGB24', 'RGB32',
|
|
'ARGB1555', 'ARGB4444', 'ARGB32', 'AYUV', 'AI44', 'IA44');
|
|
AR_bitsPerPixel: array [0..35] of integer = (12, 16, 12, 9, 12,
|
|
12, 16, 16, 16, 8,
|
|
12, 8, 9, 0, 0,
|
|
0, 0, 0, 0, 0,
|
|
0, 0, 0, 1, 4,
|
|
8, 16, 16, 24, 32,
|
|
16, 16, 32, 16, 0, 0);
|
|
|
|
|
|
type
|
|
TVideo_Stream_Config_Caps = record
|
|
guid: TGUID;
|
|
VideoStandard: ULONG;
|
|
InputSize: TSize;
|
|
MinCroppingSize: TSize;
|
|
MaxCroppingSize: TSize;
|
|
CropGranularityX: Integer;
|
|
CropGranularityY: Integer;
|
|
CropAlignX: Integer;
|
|
CropAlignY: Integer;
|
|
MinOutputSize: TSize;
|
|
MaxOutputSize: TSize;
|
|
OutputGranularityX: Integer;
|
|
OutputGranularityY: Integer;
|
|
StretchTapsX: Integer;
|
|
StretchTapsY: Integer;
|
|
ShrinkTapsX: Integer;
|
|
ShrinkTapsY: Integer;
|
|
MinFrameIntervalLO: Integer;
|
|
MinFrameIntervalHI: Integer;
|
|
MaxFrameIntervalLO: Integer;
|
|
MaxFrameIntervalHI: Integer;
|
|
MinBitsPerSecond: Longint;
|
|
MaxBitsPerSecond: Longint;
|
|
end;
|
|
PVideo_Stream_Config_Caps = ^TVideo_Stream_Config_Caps;
|
|
|
|
procedure FreeMediaType(mt: IEAM_MEDIA_TYPE);
|
|
begin
|
|
if (mt.cbFormat <> 0) then
|
|
begin
|
|
CoTaskMemFree(mt.pbFormat);
|
|
mt.cbFormat := 0;
|
|
mt.pbFormat := nil;
|
|
end;
|
|
if (mt.pUnk <> nil) then
|
|
begin
|
|
mt.pUnk := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure DeleteMediaType(pmt: PIEAM_MEDIA_TYPE);
|
|
begin
|
|
if pmt <> nil then
|
|
begin
|
|
FreeMediaType(pmt^);
|
|
CoTaskMemFree(pmt);
|
|
end;
|
|
end;
|
|
|
|
constructor TIEDirectShow.Create;
|
|
begin
|
|
inherited Create;
|
|
fOLEInitialized := Succeeded(OleInitialize(nil));
|
|
fAudioInputs := TStringList.Create;
|
|
fVideoInputs := TStringList.Create;
|
|
fVideoCodecs := TStringList.Create;
|
|
fAudioCodecs := TStringList.Create;
|
|
fVideoFormats := TList.Create;
|
|
fVideoInputSources := TStringList.Create;
|
|
fCurAudioInput := nil;
|
|
fCurVideoInput := nil;
|
|
fCurVideoCodec := nil;
|
|
fCurAudioCodec := nil;
|
|
fGraph := nil;
|
|
fBuilder := nil;
|
|
fFileOutput := '';
|
|
fControl := nil;
|
|
fCurFileInput := nil;
|
|
fFileInput := '';
|
|
fCurColor := nil;
|
|
fMediaSeeking := nil;
|
|
fMediaEvent := nil;
|
|
fSampleGrabber := nil;
|
|
fSampleGrabberFilter := nil;
|
|
fEnableSampleGrabber := false;
|
|
fNullRenderer := nil;
|
|
fSampleGrabberCB := nil;
|
|
fNotifyWindow := 0;
|
|
fAcceptNextFrame := true;
|
|
fIAMVideoCompression := nil;
|
|
fStreamConfig := nil;
|
|
fCrossBar := nil;
|
|
fCrossBarFilter := nil;
|
|
fTuner := nil;
|
|
fTunerFilter := nil;
|
|
fAnalogVideoDecoder := nil;
|
|
fRenderAudio := false;
|
|
fVideoFrameStep := nil;
|
|
fDVDControl2 := nil;
|
|
fDVDInfo2 := nil;
|
|
fDVDInputPath := '';
|
|
fRenderVideo := false;
|
|
fVideoMixingRenderer := nil;
|
|
fVMRFilterConfig := nil;
|
|
fVMRWindowlessControl := nil;
|
|
fVMRSavedPin1 := nil;
|
|
fVMRSavedPin2 := nil;
|
|
fSystemClock := nil;
|
|
fAVIDecompressor := nil;
|
|
fMPEG2Demultiplexer := nil;
|
|
fMPEG2Decoder := nil;
|
|
fColorConverterDMO := nil;
|
|
fEndOfStream := false;
|
|
fReferenceClock := rcDefault;
|
|
fClockErrorTolerance := -1; // -1=default value
|
|
fCaptureMode := iedscCapture;
|
|
end;
|
|
|
|
destructor TIEDirectShow.Destroy;
|
|
begin
|
|
Disconnect;
|
|
fCurVideoInput := nil;
|
|
fCurAudioInput := nil;
|
|
fCurFileInput := nil;
|
|
fCurVideoCodec := nil;
|
|
fCurAudioCodec := nil;
|
|
|
|
ClearVideoFormats;
|
|
FreeAndNil(fVideoInputSources);
|
|
FreeAndNil(fVideoFormats);
|
|
FreeAndNil(fAudioInputs);
|
|
FreeAndNil(fVideoInputs);
|
|
FreeAndNil(fAudioCodecs);
|
|
FreeAndNil(fVideoCodecs);
|
|
if fOLEInitialized then
|
|
OleUninitialize;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure FillFilterList(clid: TGUID; list: TStringList);
|
|
var
|
|
pSysDevEnum: IIECreateDevEnum;
|
|
pEnumCat: IIEEnumMoniker;
|
|
pMoniker: IIEMoniker;
|
|
cFetched: ULONG;
|
|
pPropBag: IIEPropertyBag;
|
|
bc: IIEBindCtx;
|
|
mo: IIEMoniker;
|
|
er: IIEErrorLog;
|
|
ov: OleVariant;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
list.clear;
|
|
pSysDevEnum := nil;
|
|
CoCreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC, IID_IIECreateDevEnum, pSysDevEnum);
|
|
pEnumCat := nil;
|
|
if pSysDevEnum.CreateClassEnumerator(clid, pEnumCat, 0) = S_OK then
|
|
begin
|
|
pMoniker := nil;
|
|
while pEnumCat.Next(1, pMoniker, @cFetched) = S_OK do
|
|
begin
|
|
bc := nil;
|
|
mo := nil;
|
|
pMoniker.BindToStorage(bc, mo, IID_IIEPropertyBag, pPropBag);
|
|
er := nil;
|
|
pPropBag.Read('FriendlyName', ov, er);
|
|
list.Add(string(AnsiString(ov)));
|
|
pPropBag := nil;
|
|
pMoniker := nil;
|
|
end;
|
|
end;
|
|
pEnumCat := nil;
|
|
pSysDevEnum := nil;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
function CreateFilter(clid: TGUID; FriendlyName: AnsiString; instanceIndex: integer): IIEBaseFilter;
|
|
var
|
|
pSysDevEnum: IIECreateDevEnum;
|
|
pEnumCat: IIEEnumMoniker;
|
|
pMoniker: IIEMoniker;
|
|
cFetched: ULONG;
|
|
pPropBag: IIEPropertyBag;
|
|
bc: IIEBindCtx;
|
|
mo: IIEMoniker;
|
|
er: IIEErrorLog;
|
|
ov: OleVariant;
|
|
iindex: integer;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
result := nil;
|
|
pSysDevEnum := nil;
|
|
CoCreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC, IID_IIECreateDevEnum, pSysDevEnum);
|
|
pEnumCat := nil;
|
|
if pSysDevEnum.CreateClassEnumerator(clid, pEnumCat, 0) = S_OK then
|
|
begin
|
|
pMoniker := nil;
|
|
iindex := 0;
|
|
while (pEnumCat.Next(1, pMoniker, @cFetched) = S_OK) and (cFetched>0) and (pMoniker<>nil) do
|
|
begin
|
|
bc := nil;
|
|
mo := nil;
|
|
pMoniker.BindToStorage(bc, mo, IID_IIEPropertyBag, pPropBag);
|
|
er := nil;
|
|
pPropBag.Read('FriendlyName', ov, er);
|
|
if AnsiString(ov) = FriendlyName then
|
|
begin
|
|
if iindex = instanceIndex then
|
|
begin
|
|
bc := nil;
|
|
mo := nil;
|
|
pMoniker.BindToObject(bc, mo, IID_IEBaseFilter, result);
|
|
end;
|
|
inc(iindex);
|
|
end;
|
|
pPropBag := nil;
|
|
pMoniker := nil;
|
|
end;
|
|
end;
|
|
pEnumCat := nil;
|
|
pSysDevEnum := nil;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.AudioInputs
|
|
|
|
<FM>Declaration<FC>
|
|
property AudioInputs: TStringList;
|
|
|
|
<FM>Description<FN>
|
|
Contains a list of audio inputs available.
|
|
!!}
|
|
function TIEDirectShow.GetAudioInputs: TStringList;
|
|
begin
|
|
if fAudioInputs.Count = 0 then
|
|
FillFilterList(CLSID_AudioInputDeviceCategory, fAudioInputs);
|
|
result := fAudioInputs;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.VideoInputs
|
|
|
|
<FM>Declaration<FC>
|
|
property VideoInputs: TStringList;
|
|
|
|
<FM>Description<FN>
|
|
Contains a list of available video inputs (video capture inputs).
|
|
!!}
|
|
function TIEDirectShow.GetVideoInputs: TStringList;
|
|
begin
|
|
if fVideoInputs.Count = 0 then
|
|
FillFilterList(CLSID_VideoInputDeviceCategory, fVideoInputs);
|
|
result := fVideoInputs;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.VideoCodecs
|
|
|
|
<FM>Declaration<FC>
|
|
property VideoCodecs: TStringList;
|
|
|
|
<FM>Description<FN>
|
|
Contains a list of video compression codecs.
|
|
!!}
|
|
function TIEDirectShow.GetVideoCodecs: TStringList;
|
|
begin
|
|
if fVideoCodecs.Count = 0 then
|
|
FillFilterList(CLSID_VideoCompressorCategory, fVideoCodecs);
|
|
result := fVideoCodecs;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.AudioCodecs
|
|
|
|
<FM>Declaration<FC>
|
|
property AudioCodecs: TStringList;
|
|
|
|
<FM>Description<FN>
|
|
Contains a list of audio compression codecs available.
|
|
!!}
|
|
function TIEDirectShow.GetAudioCodecs: TStringList;
|
|
begin
|
|
if fAudioCodecs.Count = 0 then
|
|
FillFilterList(CLSID_AudioCompressorCategory, fAudioCodecs);
|
|
result := fAudioCodecs;
|
|
end;
|
|
|
|
|
|
|
|
function StrToVideoMediaSubType(ss: AnsiString): TGUID;
|
|
var
|
|
i: integer;
|
|
begin
|
|
result := cv[0]^;
|
|
for i := 0 to 35 do
|
|
if ss = cs[i] then
|
|
begin
|
|
result := cv[i]^;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
|
|
function GetOutputPin(filter: IIEBaseFilter): IIEPin;
|
|
var
|
|
penum: IIEEnumPins;
|
|
f: integer;
|
|
d: IEPIN_DIRECTION;
|
|
begin
|
|
result := nil;
|
|
filter.EnumPins(penum);
|
|
while (penum.Next(1, result, f)=S_OK) and (f > 0) do
|
|
begin
|
|
if (result.QueryDirection(d) = S_OK) and (d = IEPINDIR_OUTPUT) then
|
|
begin
|
|
// found first output pin
|
|
exit;
|
|
end;
|
|
end;
|
|
result := nil;
|
|
end;
|
|
|
|
|
|
// if bitrate=0 then SetMediaType selects the higher
|
|
procedure SetMediaType(filter: IIEBaseFilter; width, height: integer; format: AnsiString; bitrate: dword);
|
|
var
|
|
pmt: PIEAM_MEDIA_TYPE;
|
|
piCount, piSize: integer;
|
|
i: integer;
|
|
pSCC: PVideo_Stream_Config_Caps;
|
|
streamConfig: IIEAMStreamConfig;
|
|
outPin: IIEPin;
|
|
formatID: TGUID;
|
|
selectedIndex: integer;
|
|
ih: PIEVIDEOINFOHEADER;
|
|
bestBitrate: dword;
|
|
ihBitRate: dword;
|
|
ihBitmapWidth: integer;
|
|
ihBitmapHeight: integer;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if (width = 0) or (height = 0) then
|
|
exit;
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
outPin := GetOutputPin(filter);
|
|
outPin.QueryInterface(IID_IIEAMStreamConfig, streamConfig);
|
|
if assigned(streamConfig) then
|
|
begin
|
|
selectedIndex := -1;
|
|
bestBitrate := 0;
|
|
formatID := StrToVideoMediaSubType(format);
|
|
streamConfig.GetNumberOfCapabilities(piCount, piSize);
|
|
getmem(pSCC, piSize);
|
|
try
|
|
for i := 0 to piCount - 1 do
|
|
begin
|
|
streamConfig.GetStreamCaps(i, pmt, pSCC);
|
|
ih := pointer(pmt^.pbFormat);
|
|
if ih <> nil then
|
|
begin
|
|
ihBitRate := ih^.dwBitRate;
|
|
ihBitmapWidth := ih^.bmiHeader.biWidth;
|
|
ihBitmapHeight := ih^.bmiHeader.biHeight;
|
|
end
|
|
else
|
|
begin
|
|
ihBitRate := 0;
|
|
ihBitmapWidth := 0;
|
|
ihBitmapHeight := 0;
|
|
end;
|
|
if ((width >= pSCC^.MinOutputSize.cx) and (width <= pSCC^.MaxOutputSize.cx)) and
|
|
((height >= pSCC^.MinOutputSize.cy) and (height <= pSCC^.MaxOutputSize.cy)) and
|
|
((ihBitmapWidth = 0) or (ihBitmapWidth = width)) and
|
|
((ihBitmapHeight = 0) or (ihBitmapHeight = height)) and
|
|
((format = '') or (CompareGUID(formatID, pmt^.subtype))) and
|
|
((bitrate > 0) and (ihBitRate = bitrate)) or ((bitrate = 0) and (ihBitRate > bestBitrate))
|
|
then
|
|
begin
|
|
selectedIndex := i;
|
|
bestBitrate := ih^.dwBitRate;
|
|
end;
|
|
DeleteMediaType(pmt);
|
|
end;
|
|
if selectedIndex > -1 then
|
|
begin
|
|
streamConfig.GetStreamCaps(selectedIndex, pmt, pSCC);
|
|
try
|
|
streamConfig.SetFormat(pmt);
|
|
finally
|
|
DeleteMediaType(pmt);
|
|
end;
|
|
end;
|
|
finally
|
|
freemem(pSCC);
|
|
end;
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetVideoInput
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetVideoInput(idx: integer; instanceIndex: integer = 0; width: integer = 0; height: integer = 0; format: AnsiString = ''; bitRate: integer = 0);
|
|
|
|
<FM>Description<FN>
|
|
Allows selection of a video input. You can get an index from <A TIEDirectShow.VideoInputs> property.
|
|
|
|
<TABLE>
|
|
<R> <H>Parameter</H> <H>Description</H> </R>
|
|
<R> <C><FC>idx<FN></C> <C>Index of video input.</C> </R>
|
|
<R> <C><FC>InstanceIndex<FN></C> <C>specifies the video input on the same device.</C> </R>
|
|
<R> <C><FC>width<FN></C> <C>Width of video frame.</C> </R>
|
|
<R> <C><FC>height<FN></C> <C>Height of video frame.</C> </R>
|
|
<R> <C><FC>format<FN></C> <C>Video format (ie. 'YUY2',...).</C> </R>
|
|
<R> <C><FC>bitRate<FN></C> <C>Bit rate in bits per second (0 = use the highest available).</C> </R>
|
|
</TABLE>
|
|
|
|
<FM>Example<FC>
|
|
ImageEnView.IO.DShowParams.SetVideoInput(0, 0, 640, 480); // captures at 640x480
|
|
!!}
|
|
procedure TIEDirectShow.SetVideoInput(idx: integer; instanceIndex: integer; width: integer; height: integer; format: AnsiString; bitRate: integer);
|
|
begin
|
|
if idx<0 then
|
|
fCurVideoInput := nil
|
|
else
|
|
if idx < VideoInputs.Count then
|
|
begin
|
|
fCurVideoInput := CreateFilter(CLSID_VideoInputDeviceCategory, AnsiString(VideoInputs[idx]), instanceIndex);
|
|
SetMediaType(fCurVideoInput, width, height, format, bitRate);
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetAudioInput
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetAudioInput(idx: integer; instanceIndex: integer = 0);
|
|
|
|
<FM>Description<FN>
|
|
Allows selection of an audio input. You can get an index from AudioInputs property.
|
|
InstanceIndex specifies the audio input on the same device.
|
|
!!}
|
|
procedure TIEDirectShow.SetAudioInput(idx: integer; instanceIndex: integer);
|
|
begin
|
|
if idx<0 then
|
|
fCurAudioInput := nil
|
|
else
|
|
if idx < AudioInputs.Count then
|
|
fCurAudioInput := CreateFilter(CLSID_AudioInputDeviceCategory, AnsiString(AudioInputs[idx]), instanceIndex);
|
|
end;
|
|
|
|
// note about divx: it shows a window for compression feedback. To disable it set
|
|
// "HKEY_CURRENT_USER\Software\DivXNetworks\DivX4Windows\Disable Feedback" = 1
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetVideoCodec
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetVideoCodec(idx: integer);
|
|
|
|
<FM>Description<FN>
|
|
Specifies the video compression codec. You can get an index from <A TIEDirectShow.VideoCodecs> property.
|
|
!!}
|
|
procedure TIEDirectShow.SetVideoCodec(idx: integer);
|
|
begin
|
|
if idx<0 then
|
|
fCurVideoCodec := nil
|
|
else
|
|
if idx < VideoCodecs.Count then
|
|
fCurVideoCodec := CreateFilter(CLSID_VideoCompressorCategory, AnsiString(VideoCodecs[idx]), 0);
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetAudioCodec
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetAudioCodec(idx: integer);
|
|
|
|
<FM>Description<FN>
|
|
Specifies the audio compression codec. You can get an index from <A TIEDirectShow.AudioCodecs> property.
|
|
!!}
|
|
procedure TIEDirectShow.SetAudioCodec(idx: integer);
|
|
begin
|
|
if idx<0 then
|
|
fCurAudioCodec := nil
|
|
else
|
|
if idx < AudioCodecs.Count then
|
|
fCurAudioCodec := CreateFilter(CLSID_AudioCompressorCategory, AnsiString(AudioCodecs[idx]), 0);
|
|
end;
|
|
|
|
|
|
function VideoMediaSubTypeToStr(mst: TGUID): AnsiString;
|
|
var
|
|
i: integer;
|
|
begin
|
|
result := '';
|
|
for i := 0 to 35 do
|
|
if comparemem(cv[i], @mst, sizeof(TGuid)) then
|
|
begin
|
|
result := cs[i];
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
function VideoMediaSubTypeToBitsPerPixel(mst: TGUID): integer;
|
|
var
|
|
i: integer;
|
|
begin
|
|
result := 0;
|
|
for i := 0 to 35 do
|
|
if CompareMem(cv[i], @mst, sizeof(TGUID)) then
|
|
begin
|
|
result := AR_bitsPerPixel[i];
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
procedure TIEDirectShow.ClearVideoFormats;
|
|
var
|
|
i: integer;
|
|
begin
|
|
for i := 0 to fVideoFormats.Count - 1 do
|
|
TIEVideoFormat(fVideoFormats[i]).Free;
|
|
fVideoFormats.Clear;
|
|
end;
|
|
|
|
const
|
|
vs1: array[0..19] of integer = ($00000000, $00000001, $00000002, $00000004, $00000010, $00000020, $00000080, $00000100, $00000200, $00000400,
|
|
$00000800, $00001000, $00002000, $00004000, $00008000, $00010000, $00020000, $00040000, $00080000, $00100000);
|
|
vs2: array[0..19] of AnsiString = ('None', 'NTSC_M', 'NTSC_M_J', 'NTSC_433', 'PAL_B', 'PAL_D', 'PAL_H', 'PAL_I', 'PAL_M', 'PAL_N', 'PAL_60', 'SECAM_B',
|
|
'SECAM_D', 'SECAM_G', 'SECAM_H', 'SECAM_K', 'SECAM_K1', 'SECAM_L', 'SECAM_L1', 'PAL_N_COMBO');
|
|
vs3: array[0..19] of TIETVStandard = (ievsNONE, ievsNTSC_M, ievsNTSC_M_J, ievsNTSC_433, ievsPAL_B, ievsPAL_D, ievsPAL_H, ievsPAL_I, ievsPAL_M, ievsPAL_N,
|
|
ievsPAL_60, ievsSECAM_B, ievsSECAM_D, ievsSECAM_G, ievsSECAM_H, ievsSECAM_K, ievsSECAM_K1, ievsSECAM_L, ievsSECAM_L1, ievsPAL_N_COMBO);
|
|
|
|
|
|
function VideoStandard2Str(vs: integer): AnsiString;
|
|
var
|
|
i: integer;
|
|
begin
|
|
result := '';
|
|
for i := 0 to 19 do
|
|
if (vs and vs1[i]) <> 0 then
|
|
result := result + vs2[i] + ' ';
|
|
result := IETrim(result);
|
|
end;
|
|
|
|
function Str2VideoStandard(vs: AnsiString): integer;
|
|
var
|
|
i: integer;
|
|
begin
|
|
result := 0;
|
|
for i := 0 to 19 do
|
|
if IEPos(vs2[i], vs) > 0 then
|
|
result := result or vs1[i];
|
|
end;
|
|
|
|
procedure TIEDirectShow.FillVideoFormats;
|
|
var
|
|
piCount, piSize: integer;
|
|
i: integer;
|
|
pSCC: PVideo_Stream_Config_Caps;
|
|
pmt: PIEAM_MEDIA_TYPE;
|
|
ih: PIEVIDEOINFOHEADER;
|
|
vf: TIEVideoFormat;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
ClearVideoFormats;
|
|
if assigned(fStreamConfig) then
|
|
begin
|
|
fStreamConfig.GetNumberOfCapabilities(piCount, piSize);
|
|
getmem(pSCC, piSize);
|
|
try
|
|
for i := 0 to piCount - 1 do
|
|
begin
|
|
fStreamConfig.GetStreamCaps(i, pmt, pSCC);
|
|
try
|
|
if CompareMem(@pmt.formattype, @FORMAT_VideoInfo, sizeof(TGUID)) then
|
|
begin
|
|
ih := pointer(pmt^.pbFormat);
|
|
vf := TIEVideoFormat.Create;
|
|
fVideoFormats.Add(vf);
|
|
vf.Format := VideoMediaSubTypeToStr(pmt^.subtype);
|
|
if ih <> nil then
|
|
begin
|
|
vf.BitRate := ih^.dwBitRate;
|
|
vf.BitmapWidth := ih^.bmiHeader.biWidth;
|
|
vf.BitmapHeight := ih^.bmiHeader.biHeight;
|
|
end
|
|
else
|
|
begin
|
|
vf.BitRate := 0;
|
|
vf.BitmapWidth := 0;
|
|
vf.BitmapHeight := 0;
|
|
end;
|
|
vf.VideoStandard := VideoStandard2Str(pSCC^.VideoStandard);
|
|
vf.MinWidth := pSCC^.MinOutputSize.cx;
|
|
vf.MinHeight := pSCC^.MinOutputSize.cy;
|
|
vf.MaxWidth := pSCC^.MaxOutputSize.cx;
|
|
vf.MaxHeight := pSCC^.MaxOutputSize.cy;
|
|
vf.GranularityX := pSCC^.OutputGranularityX;
|
|
vf.GranularityY := pSCC^.OutputGranularityY;
|
|
end;
|
|
finally
|
|
DeleteMediaType(pmt);
|
|
end;
|
|
end;
|
|
finally
|
|
freemem(pSCC);
|
|
end;
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
// uses fCrossBar inputs
|
|
procedure TIEDirectShow.FillVideoInputSources;
|
|
var
|
|
pFilter: IIEBaseFilter;
|
|
pins: IIEEnumPins;
|
|
pP: IIEPin;
|
|
n: integer;
|
|
pInfo: IEPIN_INFO;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fVideoInputSources.Clear;
|
|
if assigned(fCrossBar) then
|
|
begin
|
|
pFilter := nil;
|
|
fCrossBar.QueryInterface(IID_IEBaseFilter, pFilter);
|
|
if assigned(pFilter) then
|
|
begin
|
|
pins := nil;
|
|
pFilter.EnumPins(pins);
|
|
while (pins.Next(1, pP, n) = S_OK) do
|
|
begin
|
|
pP.QueryPinInfo(@pInfo);
|
|
if pInfo.dir = PINDIR_INPUT then
|
|
fVideoInputSources.Add(WideCharToString(pInfo.achName));
|
|
pInfo.pFilter := nil;
|
|
pP := nil;
|
|
end;
|
|
pins := nil;
|
|
pFilter := nil;
|
|
end;
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
function TIEDirectShow.GetInputSource: integer;
|
|
var
|
|
i: integer;
|
|
OutputPinCount, InputPinCount: integer;
|
|
PinIndexRelated, PhysicalType: integer;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
result := 0;
|
|
if assigned(fCrossBar) then
|
|
begin
|
|
// identify the output pin (video decoder)
|
|
fCrossBar.get_PinCounts(OutputPinCount, InputPinCount);
|
|
for i := 0 to OutputPinCount - 1 do
|
|
begin
|
|
fCrossBar.get_CrossbarPinInfo(false, i, PinIndexRelated, PhysicalType);
|
|
if PhysicalType = PhysConn_Video_VideoDecoder then
|
|
begin
|
|
// found
|
|
fCrossBar.get_IsRoutedTo(i, result);
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.VideoInputSource
|
|
|
|
<FM>Declaration<FC>
|
|
property VideoInputSource: integer;
|
|
|
|
<FM>Description<FN>
|
|
Specifies the video input source. A video input source is a line input, like Video-Composite, Tuner, etc.
|
|
You can get an index from VideoInputSources property.
|
|
!!}
|
|
procedure TIEDirectShow.SetInputSource(value: integer);
|
|
var
|
|
i: integer;
|
|
OutputPinCount, InputPinCount: integer;
|
|
PinIndexRelated, PhysicalType: integer;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if assigned(fCrossBar) then
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
// identify the output pin (video decoder)
|
|
fCrossBar.get_PinCounts(OutputPinCount, InputPinCount);
|
|
for i := 0 to OutputPinCount - 1 do
|
|
begin
|
|
fCrossBar.get_CrossbarPinInfo(false, i, PinIndexRelated, PhysicalType);
|
|
if PhysicalType = PhysConn_Video_VideoDecoder then
|
|
begin
|
|
// found
|
|
fCrossBar.Route(i, value);
|
|
break;
|
|
end;
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.VideoFormats
|
|
|
|
<FM>Declaration<FC>
|
|
property VideoFormats[i: integer]: <A TIEVideoFormat>;
|
|
|
|
<FM>Description<FN>
|
|
VideoFormats contains a list of available video formats.
|
|
A video format specifies the frame width, height and other info.
|
|
!!}
|
|
function TIEDirectShow.GetVideoFormats(i: integer): TIEVideoFormat;
|
|
begin
|
|
result := TIEVideoFormat(fVideoFormats[i]);
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.VideoFormatsCount
|
|
|
|
<FM>Declaration<FC>
|
|
property VideoFormatsCount: integer;
|
|
|
|
<FM>Description<FN>
|
|
VideoFormatsCount specifies the <A TIEDirectShow.VideoFormats> list size.
|
|
!!}
|
|
function TIEDirectShow.GetVideoFormatsCount: integer;
|
|
begin
|
|
result := fVideoFormats.Count;
|
|
end;
|
|
|
|
procedure TIEDirectShow.ConnectCrossbarAudioDecoder;
|
|
var
|
|
cout, cin: integer;
|
|
i: integer;
|
|
lout, lin: integer;
|
|
PinIndexRelated, PhysicalType: integer;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if assigned(fCrossBar) then
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fCrossBar.get_PinCounts(cout, cin);
|
|
lout := -1;
|
|
lin := -1;
|
|
for i := 0 to cout-1 do
|
|
begin
|
|
fCrossBar.get_CrossbarPinInfo(false, i, PinIndexRelated, PhysicalType);
|
|
if PhysicalType=PhysConn_Audio_AudioDecoder then
|
|
lout := i;
|
|
end;
|
|
for i := 0 to cin-1 do
|
|
begin
|
|
fCrossBar.get_CrossbarPinInfo(true, i, PinIndexRelated, PhysicalType);
|
|
if PhysicalType=PhysConn_Audio_Tuner then
|
|
lin := i;
|
|
end;
|
|
if (lin>-1) and (lout>-1) then
|
|
fCrossBar.Route(lout, lin);
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TIEDirectShow.VMRCreate;
|
|
var
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
if assigned(fVideoMixingRenderer) then
|
|
begin
|
|
// removes previous one
|
|
fGraph.RemoveFilter(fVideoMixingRenderer);
|
|
end;
|
|
fVMRFilterConfig := nil;
|
|
fVideoMixingRenderer := nil;
|
|
CoCreateInstance(CLSID_VideoMixingRenderer, nil, CLSCTX_INPROC, IID_IEBaseFilter, fVideoMixingRenderer);
|
|
if fVideoMixingRenderer<>nil then
|
|
begin
|
|
fGraph.AddFilter(fVideoMixingRenderer, 'Video Mixing Renderer');
|
|
fVideoMixingRenderer.QueryInterface(IID_IIEVMRFilterConfig, fVMRFilterConfig);
|
|
fVMRFilterConfig.SetNumberOfStreams(1); // set mixer mode "on"
|
|
fVMRFilterConfig.SetRenderingMode(VMRMode_Windowless);
|
|
fVideoMixingRenderer.QueryInterface(IID_IIEVMRWindowlessControl, fVMRWindowlessControl);
|
|
fVMRWindowlessControl.SetVideoClippingWindow(fNotifyWindow);
|
|
fVMRWindowlessControl.SetAspectRatioMode(0);
|
|
InvalidateRect(fNotifyWindow, nil, false);
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
(*
|
|
procedure GetPin(filter: IIEBaseFilter; dir: IEPIN_DIRECTION; mediatype: TGUID; out pin: IIEPin);
|
|
var
|
|
enumPins: IIEEnumPins;
|
|
f: integer;
|
|
d: IEPIN_DIRECTION;
|
|
p: IIEPin;
|
|
pmt: PIEAM_MEDIA_TYPE;
|
|
enumMedias: IIEEnumMediaTypes;
|
|
dw: DWORD;
|
|
mediaTypeOK: boolean;
|
|
begin
|
|
pin := nil;
|
|
p := nil;
|
|
filter.EnumPins(enumPins);
|
|
while enumPins.Next(1, p, f) = S_OK do
|
|
begin
|
|
p.QueryDirection(d);
|
|
enumMedias := nil;
|
|
p.EnumMediaTypes(enumMedias);
|
|
if assigned(enumMedias) then
|
|
begin
|
|
mediaTypeOK := false;
|
|
while enumMedias.Next(1, @pmt, dw) = S_OK do
|
|
begin
|
|
if CompareGUID(pmt^.majortype, mediatype) then
|
|
begin
|
|
mediaTypeOK := true;
|
|
break;
|
|
end;
|
|
DeleteMediaType(pmt);
|
|
end;
|
|
enumMedias := nil;
|
|
end
|
|
else
|
|
begin
|
|
pmt := nil;
|
|
mediaTypeOK := true;
|
|
end;
|
|
if (d = dir) and mediaTypeOK then
|
|
begin
|
|
DeleteMediaType(pmt);
|
|
pin := p;
|
|
break;
|
|
end;
|
|
p := nil;
|
|
end;
|
|
enumPins := nil;
|
|
end;
|
|
*)
|
|
|
|
|
|
|
|
procedure TIEDirectShow.StdConnect;
|
|
var
|
|
ppf: IIEBaseFilter;
|
|
multiplex: IIEBaseFilter;
|
|
inter: IIEBaseFilter;
|
|
pSink: IIEFileSinkFilter;
|
|
extIn, extOut: AnsiString;
|
|
mt: IEAM_MEDIA_TYPE;
|
|
CurInput: IIEBaseFilter;
|
|
iunk: IUnknown;
|
|
mf: IIEMediaFilter;
|
|
rf: IIEReferenceClock;
|
|
colorConvertInt: IIEDMOWrapperFilter;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
|
|
extIn := '';
|
|
extOut := '';
|
|
CurInput := nil;
|
|
fGraph := nil;
|
|
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC, IID_IIEGraphBuilder, fGraph);
|
|
fBuilder := nil;
|
|
CoCreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC, IID_IIECaptureGraphBuilder2, fBuilder);
|
|
fBuilder.SetFiltergraph(fGraph);
|
|
|
|
// set source filters
|
|
if fCurVideoInput <> nil then
|
|
fGraph.AddFilter(fCurVideoInput, 'VideoCapture');
|
|
if fCurAudioInput <> nil then
|
|
fGraph.AddFilter(fCurAudioInput, 'AudioCapture');
|
|
if fFileInput <> '' then
|
|
begin
|
|
extIn := IEExtractFileExtA(fFileInput);
|
|
fCurFileInput := nil;
|
|
fGraph.AddSourceFilter(PWideChar(WideString(fFileInput)), 'FileFilter', fCurFileInput);
|
|
end;
|
|
|
|
// codecs
|
|
if fCurVideoCodec <> nil then
|
|
fGraph.AddFilter(fCurVideoCodec, 'VideoCodec');
|
|
if fCurAudioCodec <> nil then
|
|
fGraph.AddFilter(fCurAudioCodec, 'AudioCodec');
|
|
|
|
ppf := nil;
|
|
multiplex := nil;
|
|
|
|
// output file
|
|
if fFileOutput <> '' then
|
|
begin
|
|
pSink := nil;
|
|
extOut := IEExtractFileExtA(fFileOutput);
|
|
if extOut = '.avi' then
|
|
fBuilder.SetOutputFileName(MEDIASUBTYPE_Avi, PWideChar(WideString(fFileOutput)), multiplex, pSink)
|
|
else
|
|
if extOut = '.asf' then
|
|
fBuilder.SetOutputFileName(MEDIASUBTYPE_Asf, PWideChar(WideString(fFileOutput)), multiplex, pSink);
|
|
ppf := multiplex;
|
|
end;
|
|
|
|
// color conversion filter (needed only when it is not specified a video compression filter)
|
|
// commenting "not fRenderVideo" could disable deinterlacing, but allows VMR on some capture cards
|
|
if (fCurVideoCodec = nil) (*and (not fRenderVideo)*) then
|
|
begin
|
|
fCurColor := nil;
|
|
CoCreateInstance(CLSID_Color, nil, CLSCTX_INPROC, IID_IEBaseFilter, fCurColor);
|
|
fGraph.AddFilter(fCurColor, 'ColorConverter');
|
|
inter := fCurColor;
|
|
end
|
|
else
|
|
inter := fCurVideoCodec;
|
|
|
|
// sample grabber
|
|
if fEnableSampleGrabber and (fCurVideoCodec = nil) then
|
|
begin // grabbing and compression don't allowed
|
|
fSampleGrabber := nil;
|
|
CoCreateInstance(CLSID_SampleGrabber, nil, CLSCTX_INPROC, IID_IEBaseFilter, fSampleGrabber);
|
|
fGraph.AddFilter(fSampleGrabber, 'SampleGrabber');
|
|
fSampleGrabber.QueryInterface(IID_IIESampleGrabber, fSampleGrabberFilter);
|
|
fSampleGrabberFilter.SetBufferSamples(true);
|
|
zeromemory(@mt, sizeof(IEAM_MEDIA_TYPE));
|
|
mt.majortype := MEDIATYPE_Video;
|
|
mt.subtype := MEDIASUBTYPE_RGB24;
|
|
fSampleGrabberFilter.SetMediaType(@mt);
|
|
if fNotifyWindow <> 0 then
|
|
begin
|
|
fSampleGrabberCB := TIESampleGrabberCB.Create(self);
|
|
fSampleGrabberFilter.SetCallback(fSampleGrabberCB, 1); // call 1=BufferCB
|
|
end;
|
|
inter := fSampleGrabber;
|
|
end;
|
|
|
|
// video renderer
|
|
if fRenderVideo then
|
|
begin
|
|
VMRCreate;
|
|
ppf := fVideoMixingRenderer;
|
|
end;
|
|
|
|
// null renderer (avoid displaying the output)
|
|
if ppf = nil then
|
|
begin
|
|
fNullRenderer := nil;
|
|
CoCreateInstance(CLSID_NullRenderer, nil, CLSCTX_INPROC, IID_IEBaseFilter, fNullRenderer);
|
|
fGraph.AddFilter(fNullRenderer, 'NullRenderer');
|
|
ppf := fNullRenderer;
|
|
end;
|
|
|
|
fAVIDecompressor := nil;
|
|
CoCreateInstance(CLSID_AVIDec, nil, CLSCTX_INPROC, IID_IEBaseFilter, fAVIDecompressor);
|
|
if fAVIDecompressor <> nil then
|
|
fGraph.AddFilter(fAVIDecompressor, 'AVI Decompressor');
|
|
|
|
if fCurVideoInput <> nil then
|
|
begin
|
|
if (multiplex <> nil) and (multiplex <> ppf) then
|
|
begin
|
|
// video input -> capture to file & VMR preview
|
|
fBuilder.RenderStream(@PIN_CATEGORY_CAPTURE, @MEDIATYPE_Video, fCurVideoInput, inter, multiplex);
|
|
fBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, fCurVideoInput, nil, ppf);
|
|
end
|
|
else
|
|
begin
|
|
case fCaptureMode of
|
|
iedscCapture:
|
|
begin
|
|
fBuilder.RenderStream(@PIN_CATEGORY_CAPTURE, @MEDIATYPE_Video, fCurVideoInput, inter, ppf);
|
|
end;
|
|
iedscPreview:
|
|
begin
|
|
fBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, fCurVideoInput, inter, ppf);
|
|
end;
|
|
end;
|
|
end;
|
|
CurInput := fCurVideoInput;
|
|
end;
|
|
|
|
if fCurAudioInput <> nil then
|
|
begin
|
|
if multiplex <> nil then
|
|
fBuilder.RenderStream(@PIN_CATEGORY_CAPTURE, @MEDIATYPE_Audio, fCurAudioInput, fCurAudioCodec, multiplex)
|
|
else
|
|
fBuilder.RenderStream(@PIN_CATEGORY_CAPTURE, @MEDIATYPE_Audio, fCurAudioInput, fCurAudioCodec, ppf);
|
|
end;
|
|
|
|
if fCurFileInput <> nil then
|
|
begin
|
|
if (extIn = '.mov') or (extIn = '.mp4') then
|
|
begin
|
|
fBuilder.RenderStream(nil, nil, fCurFileInput, inter, ppf);
|
|
fBuilder.RenderStream(nil, @MEDIATYPE_Video, fCurFileInput, inter, ppf);
|
|
end
|
|
else
|
|
if (IEGlobalSettings().OpSys in [ieosUnknown, ieosWin7, ieosWin8, ieosWin10]) and ((extIn = '.mpeg') or (extIn = '.mpg')) then
|
|
begin
|
|
fMPEG2Demultiplexer := nil;
|
|
CoCreateInstance(CLSID_MPEG2Demultiplexer, nil, CLSCTX_INPROC, IID_IEBaseFilter, fMPEG2Demultiplexer);
|
|
if fMPEG2Demultiplexer <> nil then
|
|
fGraph.AddFilter(fMPEG2Demultiplexer, 'MPEG-2 Demultiplexer');
|
|
|
|
fMPEG2Decoder := nil;
|
|
CoCreateInstance(CLSID_CMPEG2VidDecoderDS, nil, CLSCTX_INPROC, IID_IEBaseFilter, fMPEG2Decoder);
|
|
if fMPEG2Decoder <> nil then
|
|
fGraph.AddFilter(fMPEG2Decoder, 'MPEG-2 Decoder');
|
|
|
|
fColorConverterDMO := nil;
|
|
CoCreateInstance(CLSID_DMOWrapperFilter, nil, CLSCTX_INPROC, IID_IEBaseFilter, fColorConverterDMO);
|
|
if fColorConverterDMO <> nil then
|
|
begin
|
|
colorConvertInt := nil;
|
|
fColorConverterDMO.QueryInterface(IID_IIEDMOWrapperFilter, colorConvertInt);
|
|
if colorConvertInt <> nil then
|
|
begin
|
|
colorConvertInt.Init(CLSID_CColorConvertDMO, DMOCATEGORY_VIDEO_EFFECT);
|
|
fGraph.AddFilter(fColorConverterDMO, 'Color Converter DMO');
|
|
end;
|
|
end;
|
|
|
|
fBuilder.RenderStream(nil, nil, fCurFileInput, nil, fMPEG2Demultiplexer);
|
|
fBuilder.RenderStream(nil, @MEDIATYPE_Video, fMPEG2Demultiplexer, nil, fMPEG2Decoder);
|
|
fBuilder.RenderStream(nil, nil, fMPEG2Decoder, nil, fColorConverterDMO);
|
|
fBuilder.RenderStream(nil, nil, fColorConverterDMO, nil, inter);
|
|
fBuilder.RenderStream(nil, nil, inter, nil, ppf);
|
|
end
|
|
else
|
|
begin
|
|
fBuilder.RenderStream(nil, nil, fCurFileInput, fAVIDecompressor, inter); // 3.0.0 b3
|
|
fBuilder.RenderStream(nil, nil, inter, nil, ppf); // 3.0.0 b3
|
|
fBuilder.RenderStream(nil, nil, fCurFileInput, inter, ppf);
|
|
fBuilder.RenderStream(nil, @MEDIATYPE_Video, fCurFileInput, inter, ppf); // with this works also for WMV
|
|
end;
|
|
|
|
if (ppf <> nil) and (fCurAudioCodec <> nil) then
|
|
fBuilder.RenderStream(nil, nil, fCurFileInput, fCurAudioCodec, ppf);
|
|
CurInput := fCurFileInput;
|
|
end;
|
|
|
|
if fRenderAudio then
|
|
fBuilder.RenderStream(nil, @MEDIATYPE_Audio, CurInput, nil, nil);
|
|
|
|
fControl := nil;
|
|
fGraph.QueryInterface(IID_IIEMediaControl, fControl);
|
|
fMediaSeeking := nil;
|
|
fGraph.QueryInterface(IID_IIEMediaSeeking, fMediaSeeking);
|
|
fMediaEvent := nil;
|
|
fGraph.QueryInterface(IID_IIEMediaEventEx, fMediaEvent);
|
|
//
|
|
if fNotifyWindow <> 0 then
|
|
begin
|
|
fMediaEvent.SetNotifyWindow(fNotifyWindow, fEventMessage, pointer(self));
|
|
end;
|
|
//
|
|
if fCurVideoCodec <> nil then
|
|
begin
|
|
fIAMVideoCompression := nil;
|
|
fCurVideoCodec.QueryInterface(IID_IIEAMVideoCompression, fIAMVideoCompression);
|
|
end;
|
|
// stream config
|
|
iunk := nil;
|
|
fBuilder.FindInterface(nil, nil, CurInput, IID_IIEAMStreamConfig, iunk);
|
|
fStreamConfig := nil;
|
|
if assigned(iunk) then
|
|
begin
|
|
iunk.QueryInterface(IID_IIEAMStreamConfig, fStreamConfig);
|
|
iunk := nil;
|
|
end;
|
|
// crossbar
|
|
iunk := nil;
|
|
fBuilder.FindInterface(nil, nil, CurInput, IID_IIEAMCrossBar, iunk);
|
|
fCrossBar := nil;
|
|
if assigned(iunk) then
|
|
begin
|
|
iunk.QueryInterface(IID_IIEAMCrossBar, fCrossBar);
|
|
iunk.QueryInterface(IID_IEBaseFilter, fCrossBarFilter);
|
|
iunk := nil;
|
|
end;
|
|
// tuner
|
|
iunk := nil;
|
|
fBuilder.FindInterface(nil, nil, CurInput, IID_IIEAMTvTuner, iunk);
|
|
fTuner := nil;
|
|
if assigned(iunk) then
|
|
begin
|
|
iunk.QueryInterface(IID_IIEAMTvTuner, fTuner);
|
|
iunk.QueryInterface(IID_IEBaseFilter, fTunerFilter);
|
|
iunk := nil;
|
|
ConnectCrossbarAudioDecoder;
|
|
end;
|
|
// video decoder
|
|
iunk := nil;
|
|
fBuilder.FindInterface(nil, nil, CurInput, IID_IIEAMAnalogVideoDecoder, iunk);
|
|
fAnalogVideoDecoder := nil;
|
|
if assigned(iunk) then
|
|
begin
|
|
iunk.QueryInterface(IID_IIEAMAnalogVideoDecoder, fAnalogVideoDecoder);
|
|
iunk := nil;
|
|
end;
|
|
// step handling
|
|
fVideoFrameStep := nil;
|
|
fGraph.QueryInterface(IID_IIEVideoFrameStep, fVideoFrameStep);
|
|
// reference clock
|
|
if fReferenceClock<>rcDefault then
|
|
begin
|
|
mf := nil;
|
|
fGraph.QueryInterface(IID_IIEMediaFilter, mf);
|
|
if assigned(mf) then
|
|
begin
|
|
rf := nil; // rcNone
|
|
case fReferenceClock of
|
|
rcSystemClock:
|
|
begin
|
|
CoCreateInstance(CLSID_SystemClock, nil, CLSCTX_INPROC, IID_IIEReferenceClock, fSystemClock);
|
|
rf := fSystemClock;
|
|
end;
|
|
rcVideoInput:
|
|
if assigned(fCurVideoInput) then
|
|
fCurVideoInput.QueryInterface(IID_IIEReferenceClock, rf);
|
|
rcVideoOutput:
|
|
if assigned(fVideoMixingRenderer) then
|
|
fVideoMixingRenderer.QueryInterface(IID_IIEReferenceClock, rf);
|
|
rcAudioInput:
|
|
if assigned(fCurAudioInput) then
|
|
fCurAudioInput.QueryInterface(IID_IIEReferenceClock, rf);
|
|
rcAudioOutput:
|
|
begin
|
|
ppf := nil;
|
|
fGraph.FindFilterByName('Audio Renderer', ppf);
|
|
if assigned(ppf) then
|
|
ppf.QueryInterface(IID_IIEReferenceClock, rf);
|
|
end;
|
|
end;
|
|
mf.SetSyncSource(rf);
|
|
mf := nil;
|
|
end;
|
|
end;
|
|
// Clock slave
|
|
iunk := nil;
|
|
fBuilder.FindInterface(nil, nil, CurInput, IID_IIEAMClockSlave, iunk);
|
|
fClockSlave := nil;
|
|
if assigned(iunk) then
|
|
begin
|
|
iunk.QueryInterface(IID_IIEAMClockSlave, fClockSlave);
|
|
iunk := nil;
|
|
if assigned(fClockSlave) and (fClockErrorTolerance>-1) then
|
|
fClockSlave.SetErrorTolerance(fClockErrorTolerance);
|
|
end;
|
|
|
|
//
|
|
FillVideoFormats;
|
|
FillVideoInputSources;
|
|
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
procedure TIEDirectShow.DVDConnect;
|
|
var
|
|
DVDNavigator: IIEBaseFilter;
|
|
penum: IIEEnumPins;
|
|
pin: IIEPin;
|
|
f: integer;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fGraph := nil;
|
|
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC, IID_IIEGraphBuilder, fGraph);
|
|
DVDNavigator := nil;
|
|
CoCreateInstance(CLSID_DVDNavigator, nil, CLSCTX_INPROC, IID_IEBaseFilter, DVDNavigator);
|
|
if assigned(DVDNavigator) then
|
|
begin
|
|
fGraph.AddFilter(DVDNavigator, 'DVD Navigator');
|
|
|
|
// add Video Mixing Renderer
|
|
fRenderVideo := true;
|
|
fVideoMixingRenderer := nil;
|
|
CoCreateInstance(CLSID_VideoMixingRenderer, nil, CLSCTX_INPROC, IID_IEBaseFilter, fVideoMixingRenderer);
|
|
if fVideoMixingRenderer<>nil then
|
|
begin
|
|
fGraph.AddFilter(fVideoMixingRenderer, 'Video Mixing Renderer');
|
|
fVMRFilterConfig := nil;
|
|
fVideoMixingRenderer.QueryInterface(IID_IIEVMRFilterConfig, fVMRFilterConfig);
|
|
fVMRFilterConfig.SetNumberOfStreams(1); // set mixer mode "on"
|
|
fVMRFilterConfig.SetRenderingMode(VMRMode_Windowless);
|
|
fVideoMixingRenderer.QueryInterface(IID_IIEVMRWindowlessControl, fVMRWindowlessControl);
|
|
fVMRWindowlessControl.SetVideoClippingWindow(fNotifyWindow);
|
|
fVMRWindowlessControl.SetAspectRatioMode(0);
|
|
InvalidateRect(fNotifyWindow, nil, false);
|
|
end;
|
|
|
|
// render all DVDNavigator pins
|
|
DVDNavigator.EnumPins(penum);
|
|
while penum.Next(1, pin, f) = S_OK do
|
|
begin
|
|
fGraph.Render(pin);
|
|
pin := nil;
|
|
end;
|
|
penum := nil;
|
|
|
|
fMediaEvent := nil;
|
|
fGraph.QueryInterface(IID_IIEMediaEventEx, fMediaEvent);
|
|
|
|
fControl := nil;
|
|
fGraph.QueryInterface(IID_IIEMediaControl, fControl);
|
|
|
|
fMediaSeeking := nil;
|
|
fGraph.QueryInterface(IID_IIEMediaSeeking, fMediaSeeking);
|
|
if fNotifyWindow <> 0 then
|
|
fMediaEvent.SetNotifyWindow(fNotifyWindow, fEventMessage, pointer(self));
|
|
|
|
fDVDControl2 := nil;
|
|
DVDNavigator.QueryInterface(IID_IIEDvdControl2, fDVDControl2);
|
|
if lowercase(fDVDInputPath) <> 'default' then
|
|
fDVDControl2.SetDVDDirectory( pwchar(WideString(fDVDInputPath)) );
|
|
|
|
fDVDInfo2 := nil;
|
|
DVDNavigator.QueryInterface(IID_IIEDvdInfo2, fDVDInfo2);
|
|
|
|
end;
|
|
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.DVDSelectAt
|
|
|
|
<FM>Declaration<FC>
|
|
procedure DVDSelectAt(x, y: integer);
|
|
|
|
<FM>Description<FN>
|
|
Select a button in DVD menu, at specified position. To actually press the button call <A TIEDirectShow.DVDActivateButton>.
|
|
In order to play DVD inside Delphi IDE please disable "Integrated Debugging".
|
|
|
|
<FM>Example<FC>
|
|
procedure TForm1.ImageEnView1MouseMove(Sender: TObject; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
ImageEnView1.IO.DShowParams.DVDSelectAt(x, y);
|
|
end;
|
|
|
|
<FM>Demo<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_DEMO> <C>Demos\Display\VMR_DVD\VMR_DVD.dpr </C> </R>
|
|
</TABLE>
|
|
!!}
|
|
procedure TIEDirectShow.DVDSelectAt(x, y: integer);
|
|
begin
|
|
if assigned(fDVDControl2) then
|
|
fDVDControl2.SelectAtPosition(Point(x, y));
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.DVDActivateButton
|
|
|
|
<FM>Declaration<FC>
|
|
procedure DVDActivateButton;
|
|
|
|
<FM>Description<FN>
|
|
Press a button in DVD menu. To select a position call <A TIEDirectShow.DVDSelectAt>.
|
|
In order to play DVD inside Delphi IDE please disable "Integrated Debugging".
|
|
|
|
<FM>Example<FC>
|
|
procedure TForm1.ImageEnView1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
ImageEnView1.IO.DShowParams.DVDActivateButton();
|
|
end;
|
|
|
|
<FM>Demo<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_DEMO> <C>Demos\Display\VMR_DVD\VMR_DVD.dpr </C> </R>
|
|
</TABLE>
|
|
!!}
|
|
procedure TIEDirectShow.DVDActivateButton;
|
|
begin
|
|
if assigned(fDVDControl2) then
|
|
fDVDControl2.ActivateButton;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.DVDPlayAt
|
|
|
|
<FM>Declaration<FC>
|
|
procedure DVDPlayAt(Title: integer; Chapter: integer);
|
|
procedure DVDPlayAt(Title: integer; Hours, Minutes, Seconds, Frames: integer);
|
|
|
|
<FM>Description<FN>
|
|
Starts playback from the beginning of the specified chapter of the specified title.
|
|
You can access the number of Chapters and Titles (and the current position) by calling <A TIEDirectShow.DVDGetProperty>.
|
|
|
|
The second overload allows you to specify the exact time inside the specified title.
|
|
|
|
<FM>Example<FC>
|
|
// playes chapter 1 in title 5
|
|
ImageEnView1.IO.DShowParams.DVDPlayAt(5, 1);
|
|
|
|
// playes title 1, after 10 minutes
|
|
ImageEnView1.IO.DShowParams.DVDPlayAt(1, 0, 10, 0, 0);
|
|
|
|
<FM>Demo<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_DEMO> <C>Demos\Display\VMR_DVD\VMR_DVD.dpr </C> </R>
|
|
</TABLE>
|
|
!!}
|
|
procedure TIEDirectShow.DVDPlayAt(Title: integer; Chapter: integer);
|
|
var
|
|
cmd: IIEDvdCmd;
|
|
begin
|
|
if assigned(fDVDControl2) then
|
|
begin
|
|
fDVDControl2.PlayChapterInTitle(Title, Chapter, 0, cmd);
|
|
end;
|
|
end;
|
|
|
|
procedure TIEDirectShow.DVDPlayAt(Title: integer; Hours, Minutes, Seconds, Frames: integer);
|
|
var
|
|
cmd: IIEDvdCmd;
|
|
pTime: IEDVD_HMSF_TIMECODE;
|
|
begin
|
|
if assigned(fDVDControl2) then
|
|
begin
|
|
pTime.bHours := Hours;
|
|
pTime.bMinutes := Minutes;
|
|
pTime.bSeconds := Seconds;
|
|
pTime.bFrames := Frames;
|
|
fDVDControl2.PlayAtTimeInTitle(Title, pTime, 0, cmd);
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.DVDShowMenu
|
|
|
|
<FM>Declaration<FC>
|
|
procedure DVDShowMenu(Menu: <A TIEDVDMenu>);
|
|
|
|
<FM>Description<FN>
|
|
Displays the specified menu, if available.
|
|
|
|
<FM>Example<FC>
|
|
ImageEnView1.IO.DShowParams.DVDShowMenu(iedmROOT);
|
|
|
|
<FM>Demo<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_DEMO> <C>Demos\Display\VMR_DVD\VMR_DVD.dpr </C> </R>
|
|
</TABLE>
|
|
!!}
|
|
procedure TIEDirectShow.DVDShowMenu(Menu: TIEDVDMenu);
|
|
var
|
|
cmd: IIEDvdCmd;
|
|
begin
|
|
if assigned(fDVDControl2) then
|
|
fDVDControl2.ShowMenu(dword(Menu)+2, 0, cmd);
|
|
end;
|
|
|
|
function pad2(v: AnsiString): AnsiString;
|
|
begin
|
|
if length(v)<2 then
|
|
result := '0'+v
|
|
else
|
|
result := v;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.DVDGetProperty
|
|
|
|
<FM>Declaration<FC>
|
|
function DVDGetProperty(Prop: AnsiString; SubProp: AnsiString): AnsiString;
|
|
|
|
<FM>Description<FN>
|
|
Read a property from current DVD. This method can return current DVD position and some other properties like number of titles and chapters.
|
|
|
|
<TABLE>
|
|
<R> <H>Value</H> <H>Description</H> </R>
|
|
<R> <C>NumOfVolumes</C> <C>Returns number of volumes</C> </R>
|
|
<R> <C>Volume</C> <C>Returns current used volume</C> </R>
|
|
<R> <C>Side</C> <C>Returns current side (1 or 2)</C> </R>
|
|
<R> <C>NumOfTitles</C> <C>Returns number of titles</C> </R>
|
|
<R> <C>DiscID</C> <C>Returns system-generated 64-bit "unique" identification number for the specified DVD</C> </R>
|
|
<R> <C>NumOfChapters</C> <C>Returns number of chapters of the specified title (specify title in SubProp parameter)</C> </R>
|
|
<R> <C>Title</C> <C>Returns current title</C> </R>
|
|
<R> <C>Chapter</C> <C>Returns current chapter</C> </R>
|
|
<R> <C>Time</C> <C>Returns current time using format like "HH:MM:SS:FF", where FF is frame in current second.</C> </R>
|
|
<R> <C>TotalTitleTime</C> <C>Retrieves the total playback time for the current title.</C> </R>
|
|
</TABLE>
|
|
|
|
|
|
<FM>Example<FC>
|
|
// gets number of titles
|
|
NumOfTitles := StrToIntDef(ImageEnView1.IO.DShowParams.DVDGetProperty('NumOfTitles'), 0);
|
|
// gets number of chapters in title '1'
|
|
NumOfChapters := StrToIntdef(ImageEnView1.IO.DShowParams.DVDGetProperty('NumOfChapters', '1'), 0);
|
|
|
|
<FM>Demo<FN>
|
|
<TABLE2>
|
|
<R> <C_IMG_DEMO> <C>Demos\Display\VMR_DVD\VMR_DVD.dpr </C> </R>
|
|
</TABLE>
|
|
!!}
|
|
function TIEDirectShow.DVDGetProperty(Prop: AnsiString; SubProp: AnsiString): AnsiString;
|
|
var
|
|
pulNumOfVolumes, pulVolume, pSide, pulNumOfTitles: ULONG;
|
|
pullDiscID: int64;
|
|
pulNumOfChapters: ULONG;
|
|
pLocation: IEDVD_PLAYBACK_LOCATION2;
|
|
pTotalTime: IEDVD_HMSF_TIMECODE;
|
|
pulTimeCodeFlags: ULONG;
|
|
begin
|
|
result := '';
|
|
Prop := IEUpperCase(Prop);
|
|
SubProp := IEUpperCase(SubProp);
|
|
if assigned(fDVDInfo2) then
|
|
begin
|
|
result := 'Invalid Property';
|
|
if Prop='NUMOFVOLUMES' then
|
|
begin
|
|
fDVDInfo2.GetDVDVolumeInfo(pulNumOfVolumes, pulVolume, pSide, pulNumOfTitles);
|
|
result := IEIntToStr(pulNumOfVolumes);
|
|
end
|
|
else
|
|
if Prop='VOLUME' then
|
|
begin
|
|
fDVDInfo2.GetDVDVolumeInfo(pulNumOfVolumes, pulVolume, pSide, pulNumOfTitles);
|
|
result := IEIntToStr(pulVolume);
|
|
end
|
|
else
|
|
if Prop='SIDE' then
|
|
begin
|
|
fDVDInfo2.GetDVDVolumeInfo(pulNumOfVolumes, pulVolume, pSide, pulNumOfTitles);
|
|
result := IEIntToStr(pSide);
|
|
end
|
|
else
|
|
if Prop='NUMOFTITLES' then
|
|
begin
|
|
fDVDInfo2.GetDVDVolumeInfo(pulNumOfVolumes, pulVolume, pSide, pulNumOfTitles);
|
|
result := IEIntToStr(pulNumOfTitles);
|
|
end
|
|
else
|
|
if Prop='DISCID' then
|
|
begin
|
|
fDVDInfo2.GetDiscID(nil, pullDiscID);
|
|
result := AnsiString(IEIntToHex(pullDiscID, 16));
|
|
end
|
|
else
|
|
if (Prop='NUMOFCHAPTERS') and (SubProp<>'') then
|
|
begin
|
|
fDVDInfo2.GetNumberOfChapters(IEStrToIntDef(SubProp, 1), pulNumOfChapters);
|
|
result := IEIntToStr(pulNumOfChapters);
|
|
end
|
|
else
|
|
if (Prop='TITLE') then
|
|
begin
|
|
fDVDInfo2.GetCurrentLocation(pLocation);
|
|
result := IEIntToStr(pLocation.TitleNum);
|
|
end
|
|
else
|
|
if (Prop='CHAPTER') then
|
|
begin
|
|
fDVDInfo2.GetCurrentLocation(pLocation);
|
|
result := IEIntToStr(pLocation.ChapterNum);
|
|
end
|
|
else
|
|
if (Prop='TIME') then
|
|
begin
|
|
fDVDInfo2.GetCurrentLocation(pLocation);
|
|
with pLocation.TimeCode do
|
|
result := pad2(IEIntToStr(bHours))+': '+pad2(IEIntToStr(bMinutes))+': '+pad2(IEIntToStr(bSeconds))+': '+pad2(IEIntToStr(bFrames));
|
|
end
|
|
else
|
|
if (Prop='TOTALTITLETIME') then
|
|
begin
|
|
fDVDInfo2.GetTotalTitleTime(pTotalTime, pulTimeCodeFlags);
|
|
with pTotalTime do
|
|
result := pad2(IEIntToStr(bHours))+': '+pad2(IEIntToStr(bMinutes))+': '+pad2(IEIntToStr(bSeconds))+': '+pad2(IEIntToStr(bFrames));
|
|
end
|
|
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.DVDPlayAdvanced
|
|
|
|
<FM>Declaration<FC>
|
|
procedure DVDPlayAdvanced(PlayForward: boolean; Speed: double);
|
|
|
|
<FM>Description<FN>
|
|
Change the speed and direction of playing.
|
|
Setting PlayForward=true the DVD plays forward at the specified speed from the current location.
|
|
Setting playForward=false the DVD plays backward at the specified speed from the current location.
|
|
Speed specifies the playback speed. This value is a multiplier, where 1.0 is the authored speed, so a value of 2.5 plays at two and one-half times the authored speed, while a value of 0.5 plays at half the authored speed. The actual speed of playback depends on the capabilities of the video decoder. Values below 0.00001 are converted to 0.00001.
|
|
!!}
|
|
procedure TIEDirectShow.DVDPlayAdvanced(PlayForward: boolean; Speed: double);
|
|
var
|
|
ppCmd: IIEDVDCmd;
|
|
begin
|
|
if assigned(fDVDControl2) then
|
|
begin
|
|
if PlayForward then
|
|
fDVDControl2.PlayForwards(Speed, 0, ppCmd)
|
|
else
|
|
fDVDControl2.PlayBackwards(Speed, 0, ppCmd);
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Connect
|
|
|
|
<FM>Declaration<FC>
|
|
procedure Connect;
|
|
|
|
<FM>Description<FN>
|
|
Connects to the specified video input or multimedia file. This makes a DirectShow graph which needs to be activated with <A TIEDirectShow.Run> in order to make it active.
|
|
Several methods and properties work only after Connect has been successfully called.
|
|
!!}
|
|
procedure TIEDirectShow.Connect();
|
|
begin
|
|
fAcceptNextFrame := true;
|
|
if fDVDInputPath<>'' then
|
|
DVDConnect
|
|
else
|
|
StdConnect;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.TunerChannel
|
|
|
|
<FM>Declaration<FC>
|
|
property TunerChannel: integer;
|
|
|
|
<FM>Description<FN>
|
|
Sets the channel when the video input source is a TV Tuner.
|
|
!!}
|
|
procedure TIEDirectShow.SetVideoTunerChannel(value: integer);
|
|
begin
|
|
if assigned(fTuner) then
|
|
fTuner.put_Channel(value, AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT);
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Step
|
|
|
|
<FM>Declaration<FC>
|
|
procedure Step(frames: integer);
|
|
|
|
<FM>Description<FN>
|
|
Go forward for <FC>frames<FN> steps.
|
|
!!}
|
|
function TIEDirectShow.Step(frames: integer): boolean;
|
|
var
|
|
so: IUnknown;
|
|
begin
|
|
result := false;
|
|
if assigned(fVideoFrameStep) then
|
|
begin
|
|
so := nil;
|
|
result := fVideoFrameStep.Step(frames, so)=S_OK;
|
|
end;
|
|
end;
|
|
|
|
function TIEDirectShow.GetVideoTunerChannel: integer;
|
|
var
|
|
lVideoSubChannel: integer;
|
|
lAudioSubChannel: integer;
|
|
begin
|
|
result := 0;
|
|
if assigned(fTuner) then
|
|
fTuner.get_Channel(result, lVideoSubChannel, lAudioSubChannel);
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.TunerFindSignal
|
|
|
|
<FM>Declaration<FC>
|
|
function TunerFindSignal: boolean;
|
|
|
|
<FM>Description<FN>
|
|
Returns True when a channel contains a TV signal.
|
|
!!}
|
|
function TIEDirectShow.TunerFindSignal: boolean;
|
|
var
|
|
lChannel, lpFoundSignal: integer;
|
|
begin
|
|
result := false;
|
|
if assigned(fTuner) then
|
|
begin
|
|
lChannel := GetVideoTunerChannel;
|
|
fTuner.AutoTune(lChannel, lpFoundSignal);
|
|
result := lpFoundSignal = 1;
|
|
end;
|
|
end;
|
|
|
|
function GetPinFilter(p: IIEPin): IIEBaseFilter;
|
|
var
|
|
pInfo: IEPIN_INFO;
|
|
begin
|
|
p.QueryPinInfo(@pInfo);
|
|
result := pInfo.pFilter;
|
|
end;
|
|
|
|
procedure TIEDirectShow.VMRDisconnectInPin;
|
|
var
|
|
penum: IIEEnumPins;
|
|
f: integer;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if assigned(fVideoMixingRenderer) then
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
// save connection
|
|
fVMRSavedPin1 := nil;
|
|
fVMRSavedPin2 := nil;
|
|
fVideoMixingRenderer.EnumPins(penum);
|
|
penum.Next(1, fVMRSavedPin1, f); // only one pin
|
|
fVMRSavedPin1.ConnectedTo(fVMRSavedPin2);
|
|
// disconect pins (isolate VMR renderer)
|
|
fGraph.Disconnect(fVMRSavedPin2);
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TIEDirectShow.VMRReconnectInPin;
|
|
var
|
|
g2: IIEFilterGraph2;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if assigned(fVideoMixingRenderer) and assigned(fVMRSavedPin1) and assigned(fVMRSavedPin2) then
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
// recreate video mixing renderer and reconnect pins
|
|
VMRCreate;
|
|
g2 := nil;
|
|
fGraph.QueryInterface(IID_IIEFilterGraph2, g2);
|
|
g2.RenderEx(fVMRSavedPin2, 1, nil);
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
(*
|
|
procedure DisconnectInputPin(filter: IIEBaseFilter; out prevOutputPin: IIEPin; out prevInputPin: IIEPin);
|
|
var
|
|
penum: IIEEnumPins;
|
|
f: integer;
|
|
d: IEPIN_DIRECTION;
|
|
begin
|
|
prevOutputPin := nil;
|
|
prevInputPin := nil;
|
|
filter.EnumPins(penum);
|
|
while true do
|
|
begin
|
|
penum.Next(1, prevInputPin, f);
|
|
if f=0 then
|
|
break;
|
|
prevInputPin.QueryDirection(d);
|
|
if d = IEPINDIR_INPUT then
|
|
begin
|
|
// found first input pin
|
|
prevInputPin.ConnectedTo(prevOutputPin);
|
|
if assigned(prevOutputPin) then
|
|
begin
|
|
// ok, this is connected, disconnect and exit
|
|
prevOutputPin.Disconnect();
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure ConnectPins(graph: IIEGraphBuilder; outputPin: IIEPin; inputPin: IIEPin);
|
|
begin
|
|
graph.ConnectDirect(outputPin, inputPin, nil);
|
|
end;
|
|
*)
|
|
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetCurrentVideoFormat
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetCurrentVideoFormat(width, height: integer; format: AnsiString = '');
|
|
|
|
<FM>Description<FN>
|
|
Allows you to set the video format. You can read supported formats with the <A TIEDirectShow.VideoFormats> property.
|
|
The format parameter is equivalent to VideoFormats.Format. Or you can simply pass an empty string.
|
|
|
|
Please, to set frame resolution on webcams use additional parameters of <A TIEDirectShow.SetVideoInput> instead of SetCurrentVideoFormat.
|
|
!!}
|
|
procedure TIEDirectShow.SetCurrentVideoFormat(width, height: integer; format: AnsiString);
|
|
var
|
|
pmt: PIEAM_MEDIA_TYPE;
|
|
ih: PIEVIDEOINFOHEADER;
|
|
bitsPerPixel: integer;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if assigned(fStreamConfig) then
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fStreamConfig.GetFormat(pmt);
|
|
ih := pointer(pmt^.pbFormat);
|
|
if (width<>0) and (height<>0) then
|
|
begin
|
|
ih^.bmiHeader.biWidth := width;
|
|
ih^.bmiHeader.biHeight := height;
|
|
end;
|
|
if format <> '' then
|
|
pmt^.subtype := StrToVideoMediaSubType(format);
|
|
|
|
VMRDisconnectInPin; // diconnect and reconnect VMR, otherwise it doesn't accept new resolution
|
|
|
|
bitsPerPixel := VideoMediaSubTypeToBitsPerPixel(pmt^.subtype);
|
|
pmt^.lSampleSize := ih^.bmiHeader.biWidth * ih^.bmiHeader.biHeight * bitsPerPixel div 8;
|
|
ih^.dwBitRate := 0;
|
|
ih^.AvgTimePerFrame.lo32 := 0;
|
|
ih^.AvgTimePerFrame.hi32 := 0;
|
|
ih^.bmiHeader.biSizeImage := 0;
|
|
|
|
fStreamConfig.SetFormat(pmt);
|
|
|
|
VMRReconnectInPin;
|
|
|
|
DeleteMediaType(pmt);
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.GetCurrentVideoFormat
|
|
|
|
<FM>Declaration<FC>
|
|
procedure GetCurrentVideoFormat(var width, height: integer; var format: AnsiString);
|
|
|
|
<FM>Description<FN>
|
|
Allows you to set read the video format. You can read supported formats with the <A TIEDirectShow.VideoFormats> property.
|
|
The format parameter is equivalent to VideoFormats.Format. Or you can simply pass an empty string.
|
|
!!}
|
|
procedure TIEDirectShow.GetCurrentVideoFormat(var width, height: integer; var format: AnsiString);
|
|
var
|
|
pmt: PIEAM_MEDIA_TYPE;
|
|
ih: PIEVIDEOINFOHEADER;
|
|
mt: IEAM_MEDIA_TYPE;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
if assigned(fStreamConfig) then
|
|
begin
|
|
fStreamConfig.GetFormat(pmt);
|
|
ih := pointer(pmt^.pbFormat);
|
|
width := ih^.bmiHeader.biWidth;
|
|
height := ih^.bmiHeader.biHeight;
|
|
format := VideoMediaSubTypeToStr(pmt^.subtype);
|
|
DeleteMediaType(pmt);
|
|
end
|
|
else
|
|
if assigned(fSampleGrabberFilter) then
|
|
begin
|
|
fSampleGrabberFilter.GetConnectedMediaType(@mt);
|
|
try
|
|
if not CompareMem(@mt.formattype, @FORMAT_VideoInfo, sizeof(TGUID)) then
|
|
exit;
|
|
ih := PIEVIDEOINFOHEADER(mt.pbFormat);
|
|
width := ih^.bmiHeader.biWidth;
|
|
height := ih^.bmiHeader.biHeight;
|
|
finally
|
|
CoTaskMemFree(mt.pbFormat);
|
|
end;
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.GetAverageTimePerFrame
|
|
|
|
<FM>Declaration<FC>
|
|
function GetAverageTimePerFrame: int64;
|
|
|
|
<FM>Description<FN>
|
|
Returns, when available, the number of milliseconds for each frame.
|
|
|
|
<FM>Example<FC>
|
|
function AverageTimePerFrameForFile(const Filename: string): int64;
|
|
var
|
|
dshow: TIEDirectShow;
|
|
begin
|
|
Result := -1;
|
|
dshow := TIEDirectShow.Create;
|
|
try
|
|
dshow.FileInput := AnsiString(FileName);
|
|
dshow.EnableSampleGrabber := true;
|
|
dshow.Connect;
|
|
dshow.Pause;
|
|
|
|
dshow.TimeFormat := tfTime;
|
|
if dshow.Duration = 0 then
|
|
exit;
|
|
Result := dshow.GetAverageTimePerFrame;
|
|
dshow.Disconnect;
|
|
finally
|
|
FreeAndNil(dshow);
|
|
end;
|
|
end;
|
|
!!}
|
|
function TIEDirectShow.GetAverageTimePerFrame: int64;
|
|
var
|
|
pmt: PIEAM_MEDIA_TYPE;
|
|
ih: PIEVIDEOINFOHEADER;
|
|
mt: IEAM_MEDIA_TYPE;
|
|
lt: TIETimeFormat;
|
|
p1, p2: int64;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
result := 0;
|
|
if assigned(fStreamConfig) then
|
|
begin
|
|
fStreamConfig.GetFormat(pmt);
|
|
ih := pointer(pmt^.pbFormat);
|
|
result := ih^.AvgTimePerFrame.lo32 + (ih^.AvgTimePerFrame.hi32 * $100000000);
|
|
DeleteMediaType(pmt);
|
|
end
|
|
else
|
|
if assigned(fSampleGrabberFilter) then
|
|
begin
|
|
fSampleGrabberFilter.GetConnectedMediaType(@mt);
|
|
try
|
|
if not CompareMem(@mt.formattype, @FORMAT_VideoInfo, sizeof(TGUID)) then
|
|
exit;
|
|
ih := PIEVIDEOINFOHEADER(mt.pbFormat);
|
|
result := ih^.AvgTimePerFrame.lo32 + (ih^.AvgTimePerFrame.hi32 * $100000000);
|
|
finally
|
|
CoTaskMemFree(mt.pbFormat);
|
|
end;
|
|
end;
|
|
|
|
if result = 0 then
|
|
begin
|
|
lt := TimeFormat;
|
|
TimeFormat := tfTime;
|
|
p1 := -1;
|
|
Run;
|
|
repeat
|
|
p2 := Position;
|
|
if (p1 = -1) and (p2 <> 0) then
|
|
p1 := p2;
|
|
if (p1 <> -1) and (p2 <> p1) then
|
|
break;
|
|
sleep(10);
|
|
until false; // repeat forever
|
|
Pause;
|
|
TimeFormat := lt;
|
|
result := (p2 - p1);
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Disconnect
|
|
|
|
<FM>Declaration<FC>
|
|
procedure Disconnect;
|
|
|
|
<FM>Description<FN>
|
|
Disconnects from the specified video input or multimedia file.
|
|
!!}
|
|
procedure TIEDirectShow.Disconnect;
|
|
var
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
if (fControl <> nil) and (State <> gsStopped) then
|
|
fControl.Stop();
|
|
|
|
fAnalogVideoDecoder := nil;
|
|
fClockSlave := nil;
|
|
fAVIDecompressor := nil;
|
|
fMPEG2Demultiplexer := nil;
|
|
fMPEG2Decoder := nil;
|
|
fColorConverterDMO := nil;
|
|
fDVDControl2 := nil;
|
|
fDVDInfo2 := nil;
|
|
fVideoMixingRenderer := nil;
|
|
fVMRFilterConfig := nil;
|
|
fVMRWindowlessControl := nil;
|
|
fVMRSavedPin1 := nil;
|
|
fVMRSavedPin2 := nil;
|
|
fVideoFrameStep := nil;
|
|
fTunerFilter := nil;
|
|
fTuner := nil;
|
|
fCrossBarFilter := nil;
|
|
fCrossBar := nil;
|
|
fStreamConfig := nil;
|
|
fIAMVideoCompression := nil;
|
|
fMediaEvent := nil;
|
|
fMediaSeeking := nil;
|
|
fControl := nil;
|
|
fNullRenderer := nil;
|
|
fSampleGrabberFilter := nil;
|
|
fSampleGrabber := nil;
|
|
fCurColor := nil;
|
|
fCurFileInput := nil;
|
|
fBuilder := nil;
|
|
fGraph := nil;
|
|
fSampleGrabberCB := nil; // fSampleGrabberCB automatically called
|
|
fSystemClock := nil;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Connected
|
|
|
|
<FM>Declaration<FC>
|
|
property Connected: boolean;
|
|
|
|
<FM>Description<FN>
|
|
Returns true when connected to the video input or multimedia file.
|
|
!!}
|
|
function TIEDirectShow.GetGraphCreated: boolean;
|
|
begin
|
|
result := fGraph <> nil;
|
|
end;
|
|
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Run
|
|
|
|
<FM>Declaration<FC>
|
|
procedure Run(): <A TIEDSRunResult>;
|
|
|
|
<FM>Description<FN>
|
|
After calling Connect you must run the graph. This starts video capture or file capture.
|
|
!!}
|
|
function TIEDirectShow.Run(): TIEDSRunResult;
|
|
var
|
|
hr: HRESULT;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
result := iedsError;
|
|
fEndOfStream := false;
|
|
if fControl <> nil then
|
|
begin
|
|
hr := fControl.Run();
|
|
if HResultCode(hr) = ERROR_NO_SYSTEM_RESOURCES then
|
|
result := iedsBusy
|
|
else if SUCCEEDED(hr) then
|
|
result := iedsSuccess;
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Stop
|
|
|
|
<FM>Declaration<FC>
|
|
procedure Stop();
|
|
|
|
<FM>Description<FN>
|
|
This is used to stop the graph's execution.
|
|
!!}
|
|
procedure TIEDirectShow.Stop();
|
|
var
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if fControl <> nil then
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fControl.StopWhenReady();
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Pause
|
|
|
|
<FM>Declaration<FC>
|
|
procedure Pause();
|
|
|
|
<FM>Description<FN>
|
|
This is used to pause the graph.
|
|
!!}
|
|
procedure TIEDirectShow.Pause();
|
|
var
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if fControl <> nil then
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fControl.Pause();
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.State
|
|
|
|
<FM>Declaration<FC>
|
|
function State: <A TIEDirectShowState>;
|
|
|
|
<FM>Description<FN>
|
|
State function returns the current state of the graph.
|
|
!!}
|
|
function TIEDirectShow.State: TIEDirectShowState;
|
|
var
|
|
pfs: longint;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if fControl <> nil then
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fControl.GetState(100, pfs);
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
result := TIEDirectShowState(pfs);
|
|
end
|
|
else
|
|
result := gsStopped;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Rate
|
|
|
|
<FM>Declaration<FC>
|
|
property Rate: double;
|
|
|
|
<FM>Description<FN>
|
|
Specifies the frame rate where Rate is:
|
|
1 = normal speed
|
|
2 = double speed
|
|
0.5 = half speed
|
|
Not all devices support this property. Important. The Rate does NOT set or get the number of frames per second (FPS).
|
|
To save a movie originally shot at 30 fps to.15 fps set the rate to 0.5.
|
|
|
|
The Rate can only be set if the if the file is running or is paused..
|
|
!!}
|
|
procedure TIEDirectShow.SetRate(value: double);
|
|
begin
|
|
if fMediaSeeking <> nil then
|
|
fMediaSeeking.SetRate(value);
|
|
end;
|
|
|
|
function TIEDirectShow.GetRate: double;
|
|
begin
|
|
if fMediaSeeking <> nil then
|
|
fMediaSeeking.GetRate(@result);
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.ConvertTimeFormat
|
|
|
|
<FM>Declaration<FC>
|
|
function ConvertTimeFormat(source: int64; sourceFormat: <A TIETimeFormat>; targetFormat: <A TIETimeFormat>): int64;
|
|
|
|
<FM>Description<FN>
|
|
Converts from a time format to another one.
|
|
!!}
|
|
function TIEDirectShow.ConvertTimeFormat(source: int64; sourceFormat: TIETimeFormat; targetFormat: TIETimeFormat): int64;
|
|
const
|
|
ar: array [tfNone..tfTime] of PGUID=(@TIME_FORMAT_NONE, @TIME_FORMAT_FRAME, @TIME_FORMAT_SAMPLE, @TIME_FORMAT_FIELD, @TIME_FORMAT_BYTE, @TIME_FORMAT_MEDIA_TIME);
|
|
var
|
|
rt1, rt2: IEREFERENCE_TIME;
|
|
begin
|
|
rt1.lo32 := source and $FFFFFFFF;
|
|
rt1.hi32 := (source shr 16) shr 16; //rf.hi32 := v shr 32; why this? To support Delphi 3...
|
|
if fMediaSeeking.ConvertTimeFormat(@rt2, ar[targetFormat], @rt1, ar[sourceFormat])=S_OK then
|
|
result := rt2.lo32 + (rt2.hi32 * $100000000)
|
|
else
|
|
result := 0;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.TimeFormat
|
|
|
|
<FM>Declaration<FC>
|
|
property TimeFormat: <A TIETimeFormat>;
|
|
|
|
<FM>Description<FN>
|
|
Specifies the time format for <A TIEDirectShow.Position> and <A TIEDirectShow.Duration> properties.
|
|
!!}
|
|
procedure TIEDirectShow.SetXTimeFormat(value: TIETimeFormat);
|
|
begin
|
|
if fMediaSeeking <> nil then
|
|
begin
|
|
case value of
|
|
tfNone: fMediaSeeking.SetTimeFormat(@TIME_FORMAT_NONE);
|
|
tfFrame: fMediaSeeking.SetTimeFormat(@TIME_FORMAT_FRAME);
|
|
tfSample: fMediaSeeking.SetTimeFormat(@TIME_FORMAT_SAMPLE);
|
|
tfField: fMediaSeeking.SetTimeFormat(@TIME_FORMAT_FIELD);
|
|
tfByte: fMediaSeeking.SetTimeFormat(@TIME_FORMAT_BYTE);
|
|
tfTime: fMediaSeeking.SetTimeFormat(@TIME_FORMAT_MEDIA_TIME);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TIEDirectShow.GetXTimeFormat: TIETimeFormat;
|
|
var
|
|
tf: TGUID;
|
|
begin
|
|
result := tfNone;
|
|
if fMediaSeeking <> nil then
|
|
begin
|
|
fMediaSeeking.GetTimeFormat(@tf);
|
|
if CompareMem(@TIME_FORMAT_NONE, @tf, sizeof(TGUID)) then
|
|
result := tfNone
|
|
else
|
|
if CompareMem(@TIME_FORMAT_FRAME, @tf, sizeof(TGUID)) then
|
|
result := tfFrame
|
|
else
|
|
if CompareMem(@TIME_FORMAT_SAMPLE, @tf, sizeof(TGUID)) then
|
|
result := tfSample
|
|
else
|
|
if CompareMem(@TIME_FORMAT_FIELD, @tf, sizeof(TGUID)) then
|
|
result := tfField
|
|
else
|
|
if CompareMem(@TIME_FORMAT_BYTE, @tf, sizeof(TGUID)) then
|
|
result := tfByte
|
|
else
|
|
if CompareMem(@TIME_FORMAT_MEDIA_TIME, @tf, sizeof(TGUID)) then
|
|
result := tfTime;
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SaveGraph
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SaveGraph(filename: AnsiString);
|
|
|
|
<FM>Description<FN>
|
|
This method is useful to debug the filter graph built using Connect.
|
|
The file must have 'grf' extension and can be read using GraphEdit utility (you can get this from the Microsoft DirectShow SDK).
|
|
!!}
|
|
procedure TIEDirectShow.SaveGraph(filename: AnsiString);
|
|
const
|
|
wszStreamName: PWideChar = 'ActiveMovieGraph';
|
|
var
|
|
pStorage: IIEStorage;
|
|
pStream: IIEStream;
|
|
pPersist: IIEPersistStream;
|
|
begin
|
|
pStorage := nil;
|
|
StgCreateDocfile(PWideChar(WideString(filename)), STGM_CREATE or STGM_TRANSACTED or STGM_READWRITE or STGM_SHARE_EXCLUSIVE, 0, pStorage);
|
|
|
|
pStorage.CreateStream(wszStreamName, STGM_WRITE or STGM_CREATE or STGM_SHARE_EXCLUSIVE, 0, 0, pStream);
|
|
pPersist := nil;
|
|
fGraph.QueryInterface(IID_IIEPersistStream, pPersist);
|
|
pPersist.Save(pStream, TRUE);
|
|
pStream := nil;
|
|
pPersist := nil;
|
|
pStorage.Commit(STGC_DEFAULT);
|
|
pStorage := nil;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Duration
|
|
|
|
<FM>Declaration<FC>
|
|
property Duration: int64;
|
|
|
|
<FM>Description<FN>
|
|
Returns the duration of the stream (multimedia file) in a format specified by <A TIEDirectShow.TimeFormat> property.
|
|
Duration measured in 100-nanosecond per unit (when time is selected).
|
|
!!}
|
|
function TIEDirectShow.GetDuration: int64;
|
|
var
|
|
rf: IEREFERENCE_TIME;
|
|
begin
|
|
if (fMediaSeeking <> nil) and (fMediaSeeking.GetDuration(@rf) = S_OK) then
|
|
result := rf.lo32 + (rf.hi32 * $100000000)
|
|
else
|
|
result := 0;
|
|
end;
|
|
|
|
procedure TIEDirectShow.SetPosition(v: int64);
|
|
const
|
|
DS_TIMEOUT = 10000; // 10s
|
|
var
|
|
rf: IEREFERENCE_TIME;
|
|
pfs: longint;
|
|
timestart: dword;
|
|
re: HRESULT;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
if fMediaSeeking <> nil then
|
|
begin
|
|
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
|
|
try
|
|
|
|
rf.lo32 := v and $FFFFFFFF;
|
|
rf.hi32 := (v shr 16) shr 16; //rf.hi32 := v shr 32; why this? TO support Delphi 3...
|
|
fMediaSeeking.SetPositions(@rf, AM_SEEKING_AbsolutePositioning, nil, AM_SEEKING_NoPositioning);
|
|
|
|
if fControl <> nil then
|
|
begin
|
|
timestart := GetTickCount;
|
|
while GetTickCount-timestart < DS_TIMEOUT do
|
|
begin
|
|
re := fControl.GetState(100, pfs);
|
|
if (re=S_OK) or (re=VFW_S_CANT_CUE) then
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.Position
|
|
|
|
<FM>Declaration<FC>
|
|
property Position: int64;
|
|
|
|
<FM>Description<FN>
|
|
Returns the stream (multimedia file) position in a format specified by <A TIEDirectShow.TimeFormat> property.
|
|
Position measured in 100-nanosecond per unit (when time is selected).
|
|
!!}
|
|
function TIEDirectShow.GetPosition: int64;
|
|
var
|
|
rf: IEREFERENCE_TIME;
|
|
begin
|
|
if (fMediaSeeking <> nil) and (fMediaSeeking.GetCurrentPosition(@rf) = S_OK) then
|
|
result := rf.lo32 + (rf.hi32 * $100000000)
|
|
else
|
|
result := 0;
|
|
end;
|
|
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.BufferToTIEBitmap
|
|
|
|
<FM>Declaration<FC>
|
|
procedure BufferToTIEBitmap(buffer: pbyte; len: integer; DestBitmap: <A TIEBitmap>);
|
|
|
|
<FM>Description<FN>
|
|
For internal use only. Used only if you use TIEDirectShow as stand alone object.
|
|
!!}
|
|
// if buffer=nil calls SampleGrabberFilter.GetCurrentBuffer to get it
|
|
procedure TIEDirectShow.BufferToTIEBitmap(buffer: pbyte; len: integer; DestBitmap: TIEBitmap);
|
|
|
|
procedure CopyRows;
|
|
var
|
|
i, rl: integer;
|
|
src: pbyte;
|
|
begin
|
|
if (Destbitmap.BitAlignment=32) and (DestBitmap.Origin=ieboBOTTOMLEFT) then
|
|
CopyMemory(DestBitmap.Scanline[DestBitmap.Height - 1], buffer, Destbitmap.RowLen * DestBitmap.Height)
|
|
else
|
|
begin
|
|
src := buffer;
|
|
rl := IEBitmapRowLen(DestBitmap.Width, 24, 32);
|
|
for i := DestBitmap.Height-1 downto 0 do
|
|
begin
|
|
CopyMemory(DestBitmap.Scanline[i], src, rl);
|
|
inc(src, rl);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
mt: IEAM_MEDIA_TYPE;
|
|
vf: PIEVIDEOINFOHEADER;
|
|
begin
|
|
if fSampleGrabberFilter <> nil then
|
|
begin
|
|
if Succeeded(fSampleGrabberFilter.GetConnectedMediaType(@mt)) then
|
|
try
|
|
if not IsEqualGUID(mt.formattype, FORMAT_VideoInfo) then
|
|
exit; // finally will be executed
|
|
|
|
vf := PIEVIDEOINFOHEADER(mt.pbFormat);
|
|
if DestBitmap.Location = ieFile then
|
|
DestBitmap.Location := ieMemory;
|
|
if (DestBitmap.PixelFormat <> ie24RGB) or (DestBitmap.Width <> vf^.bmiHeader.biWidth) or (DestBitmap.Height <> vf^.bmiHeader.biHeight) then
|
|
DestBitmap.Allocate(vf^.bmiHeader.biWidth, vf^.bmiHeader.biHeight, ie24RGB);
|
|
if buffer <> nil then
|
|
begin
|
|
// use buffer and len
|
|
CopyRows;
|
|
end
|
|
else
|
|
begin
|
|
// use GetCurrentBuffer to get the buffer
|
|
len := 0;
|
|
fSampleGrabberFilter.GetCurrentBuffer(@len, buffer); // get buffer size
|
|
if len <> 0 then
|
|
begin
|
|
if (len = DestBitmap.RowLen * DestBitmap.Height) and (DestBitmap.Origin = ieboBOTTOMLEFT) then
|
|
begin
|
|
// bitalignment matches
|
|
buffer := DestBitmap.ScanLine[DestBitmap.Height - 1];
|
|
fSampleGrabberFilter.GetCurrentBuffer(@len, buffer);
|
|
end
|
|
else
|
|
begin
|
|
getmem(buffer, len);
|
|
try
|
|
fSampleGrabberFilter.GetCurrentBuffer(@len, buffer);
|
|
CopyRows;
|
|
finally
|
|
freemem(buffer);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
FreeMediaType(mt);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.GetSample
|
|
|
|
<FM>Declaration<FC>
|
|
procedure GetSample(DestBitmap: <A TIEBitmap>; resample: boolean = true);
|
|
|
|
<FM>Description<FN>
|
|
Copies current sample to the specified bitmap.
|
|
You can call this method inside a <A TImageEnView.OnDShowNewFrame> event or anywhere you want (for example, on response to a TTimer event).
|
|
|
|
If <FC>resample<FN> is <FC>true<FN> and input is VMR then the image is resampled to the original bitmap size.
|
|
|
|
Default: True
|
|
!!}
|
|
procedure TIEDirectShow.GetSample(DestBitmap: TIEBitmap; resample: boolean);
|
|
var
|
|
dib: pbyte;
|
|
tempProc: TImageEnProc;
|
|
ow, oh: integer;
|
|
begin
|
|
if assigned(fVMRWindowlessControl) then
|
|
begin
|
|
// video mixing renderer
|
|
ow := DestBitmap.Width;
|
|
oh := DestBitmap.Height;
|
|
dib := nil;
|
|
fVMRWindowlessControl.GetCurrentImage(dib);
|
|
if assigned(dib) then
|
|
begin
|
|
try
|
|
_CopyDIB2BitmapEx(cardinal(dib), DestBitmap, nil, true);
|
|
finally
|
|
CoTaskMemFree(dib);
|
|
end;
|
|
if resample then
|
|
begin
|
|
tempProc := TImageEnProc.CreateFromBitmap(DestBitmap);
|
|
try
|
|
tempProc.Resample(ow, oh, rfNone);
|
|
finally
|
|
tempProc.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
if assigned(fSampleGrabberFilter) then
|
|
// use sample grabber filter
|
|
BufferToTIEBitmap(nil, 0, DestBitmap);
|
|
end;
|
|
|
|
constructor TIESampleGrabberCB.Create(Owner: TObject);
|
|
begin
|
|
inherited Create;
|
|
fOwner := Owner;
|
|
end;
|
|
|
|
destructor TIESampleGrabberCB.Destroy;
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
function TIESampleGrabberCB.SampleCB(SampleTime: double; pSample: IIEMediaSample): HRESULT;
|
|
begin
|
|
result := S_OK;
|
|
end;
|
|
|
|
function TIESampleGrabberCB.BufferCB(SampleTime: double; pBuffer: pbyte; BufferLen: integer): HRESULT;
|
|
var
|
|
ds: TIEDirectShow;
|
|
begin
|
|
try
|
|
ds := TIEDirectShow(fOwner);
|
|
if ds.AcceptNextFrame then // 3.0.2
|
|
PostMessage(ds.fNotifyWindow, ds.fNewFrameMessage, 0, LPARAM(pointer(ds)));
|
|
except
|
|
end;
|
|
result := S_OK;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetNotifyWindow
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetNotifyWindow(WindowHandle: THandle; NewFrameMessage: integer; EventMessage: integer);
|
|
|
|
<FM>Description<FN>
|
|
For internal use only. Used only if you use TIEDirectShow as stand alone object.
|
|
!!}
|
|
procedure TIEDirectShow.SetNotifyWindow(WindowHandle: THandle; NewFrameMessage: integer; EventMessage: integer);
|
|
begin
|
|
fNotifyWindow := WindowHandle;
|
|
fNewFrameMessage := NewFrameMessage;
|
|
fEventMessage := EventMessage;
|
|
if Connected and assigned(fMediaEvent) then
|
|
begin
|
|
fMediaEvent.SetNotifyWindow(fNotifyWindow, fEventMessage, pointer(self));
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.GetEventCode
|
|
|
|
<FM>Declaration<FC>
|
|
function GetEventCode(var Event: integer): boolean;
|
|
|
|
<FM>Description<FN>
|
|
Read current event obtained from DirectShow.
|
|
|
|
A <A TImageEnView.OnDShowEvent> occurs whenever there is an event available.
|
|
Common events are:
|
|
<FC>
|
|
IEEC_ACTIVATE = $0013;
|
|
IEEC_BUFFERING_DATA = $0011;
|
|
IEEC_BUILT = $0300;
|
|
IEEC_CLOCK_CHANGED = $000D;
|
|
IEEC_CLOCK_UNSET = $0051;
|
|
IEEC_CODECAPI_EVENT = $0057;
|
|
IEEC_COMPLETE = $0001;
|
|
IEEC_DEVICE_LOST = $001F;
|
|
IEEC_DISPLAY_CHANGED = $0016;
|
|
IEEC_END_OF_SEGMENT = $001C;
|
|
IEEC_ERROR_STILLPLAYING = $0008;
|
|
IEEC_ERRORABORT = $0003;
|
|
IEEC_EXTDEVICE_MODE_CHANGE = $0031;
|
|
IEEC_FULLSCREEN_LOST = $0012;
|
|
IEEC_GRAPH_CHANGED = $0050;
|
|
IEEC_LENGTH_CHANGED = $001E;
|
|
IEEC_NEED_RESTART = $0014;
|
|
IEEC_NOTIFY_WINDOW = $0019;
|
|
IEEC_OLE_EVENT = $0018;
|
|
IEEC_OPENING_FILE = $0010;
|
|
IEEC_PALETTE_CHANGED = $0009;
|
|
IEEC_PAUSED = $000E;
|
|
IEEC_PREPROCESS_COMPLETE = $0056;
|
|
IEEC_QUALITY_CHANGE = $000B;
|
|
IEEC_REPAINT = $0005;
|
|
IEEC_SEGMENT_STARTED = $001D;
|
|
IEEC_SHUTTING_DOWN = $000C;
|
|
IEEC_SNDDEV_IN_ERROR = $0200;
|
|
IEEC_SNDDEV_OUT_ERROR = $0201;
|
|
IEEC_STARVATION = $0017;
|
|
IEEC_STATE_CHANGE = $0032;
|
|
IEEC_STEP_COMPLETE = $0024;
|
|
IEEC_STREAM_CONTROL_STARTED = $001B;
|
|
IEEC_STREAM_CONTROL_STOPPED = $001A;
|
|
IEEC_STREAM_ERROR_STILLPLAYING = $0007;
|
|
IEEC_STREAM_ERROR_STOPPED = $0006;
|
|
IEEC_TIMECODE_AVAILABLE = $0030;
|
|
IEEC_UNBUILT = $0301;
|
|
IEEC_USERABORT = $0002;
|
|
IEEC_VIDEO_SIZE_CHANGED = $000A;
|
|
IEEC_VMR_RENDERDEVICE_SET = $0053;
|
|
IEEC_VMR_SURFACE_FLIPPED = $0054;
|
|
IEEC_VMR_RECONNECTION_FAILED = $0055;
|
|
IEEC_WINDOW_DESTROYED = $0015;
|
|
IEEC_WMT_EVENT = $0252;
|
|
IEEC_WMT_INDEX_EVENT = $0251;
|
|
IEEC_USER = $8000;
|
|
|
|
// DVD events
|
|
IEEC_DVD_DOMAIN_CHANGE = ($0100 + $01)
|
|
IEEC_DVD_TITLE_CHANGE = ($0100 + $02)
|
|
IEEC_DVD_CHAPTER_START = ($0100 + $03)
|
|
IEEC_DVD_AUDIO_STREAM_CHANGE = ($0100 + $04)
|
|
IEEC_DVD_SUBPICTURE_STREAM_CHANGE = ($0100 + $05)
|
|
IEEC_DVD_ANGLE_CHANGE = ($0100 + $06)
|
|
IEEC_DVD_BUTTON_CHANGE = ($0100 + $07)
|
|
IEEC_DVD_VALID_UOPS_CHANGE = ($0100 + $08)
|
|
IEEC_DVD_STILL_ON = ($0100 + $09)
|
|
IEEC_DVD_STILL_OFF = ($0100 + $0a)
|
|
IEEC_DVD_CURRENT_TIME = ($0100 + $0b)
|
|
IEEC_DVD_ERROR = ($0100 + $0c)
|
|
IEEC_DVD_WARNING = ($0100 + $0d)
|
|
IEEC_DVD_CHAPTER_AUTOSTOP = ($0100 + $0e)
|
|
IEEC_DVD_NO_FP_PGC = ($0100 + $0f)
|
|
IEEC_DVD_PLAYBACK_RATE_CHANGE = ($0100 + $10)
|
|
IEEC_DVD_PARENTAL_LEVEL_CHANGE = ($0100 + $11)
|
|
IEEC_DVD_PLAYBACK_STOPPED = ($0100 + $12)
|
|
IEEC_DVD_ANGLES_AVAILABLE = ($0100 + $13)
|
|
IEEC_DVD_PLAYPERIOD_AUTOSTOP = ($0100 + $14)
|
|
IEEC_DVD_BUTTON_AUTO_ACTIVATED = ($0100 + $15)
|
|
IEEC_DVD_CMD_START = ($0100 + $16)
|
|
IEEC_DVD_CMD_END = ($0100 + $17)
|
|
IEEC_DVD_DISC_EJECTED = ($0100 + $18)
|
|
IEEC_DVD_DISC_INSERTED = ($0100 + $19)
|
|
IEEC_DVD_CURRENT_HMSF_TIME = ($0100 + $1a)
|
|
IEEC_DVD_KARAOKE_MODE = ($0100 + $1b)
|
|
IEEC_DVD_PROGRAM_CELL_CHANGE = ($0100 + $1c)
|
|
IEEC_DVD_TITLE_SET_CHANGE = ($0100 + $1d)
|
|
IEEC_DVD_PROGRAM_CHAIN_CHANGE = ($0100 + $1e)
|
|
IEEC_DVD_VOBU_Offset = ($0100 + $1f)
|
|
IEEC_DVD_VOBU_Timestamp = ($0100 + $20)
|
|
IEEC_DVD_GPRM_Change = ($0100 + $21)
|
|
IEEC_DVD_SPRM_Change = ($0100 + $22)
|
|
IEEC_DVD_BeginNavigationCommands = ($0100 + $23)
|
|
IEEC_DVD_NavigationCommand = ($0100 + $24)
|
|
<FN>
|
|
!!}
|
|
function TIEDirectShow.GetEventCode(var Event: integer): boolean;
|
|
var
|
|
evParam1, evParam2: integer;
|
|
begin
|
|
if assigned(fMediaEvent) then
|
|
begin
|
|
result := fMediaEvent.GetEvent(Event, evParam1, evParam2, 0) = S_OK;
|
|
if result then
|
|
fMediaEvent.FreeEventParams(Event, evParam1, evParam2);
|
|
end
|
|
else
|
|
result := false;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.VideoCodecQuality
|
|
|
|
<FM>Declaration<FC>
|
|
property VideoCodecQuality: double;
|
|
|
|
<FM>Description<FN>
|
|
Specifies the video compression codec quality. Not all codecs support this property.
|
|
!!}
|
|
procedure TIEDirectShow.SetVideoCodecQuality(value: double);
|
|
begin
|
|
if assigned(fIAMVideoCompression) then
|
|
fIAMVideoCompression.put_Quality(value);
|
|
end;
|
|
|
|
function TIEDirectShow.GetVideoCodecQuality: double;
|
|
begin
|
|
result := 0;
|
|
if assigned(fIAMVideoCompression) then
|
|
fIAMVideoCompression.get_Quality(result);
|
|
end;
|
|
|
|
function TIEDirectShow.ShowFilterPropertyPages(filter: IIEBaseFilter; checkOnly: boolean): boolean;
|
|
var
|
|
pSpecify: IIESpecifyPropertyPages;
|
|
caGUID: TIECAGUID;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
result := false;
|
|
pSpecify := nil;
|
|
filter.QueryInterface(IID_IIESpecifyPropertyPages, pSpecify);
|
|
if pSpecify <> nil then
|
|
begin
|
|
pSpecify.GetPages(caGUID);
|
|
pSpecify := nil;
|
|
if checkOnly then
|
|
result := true
|
|
else
|
|
result := OleCreatePropertyFrame(fNotifyWindow, 0, 0, '', 1, pointer(@filter), caGUID.cElems, PGUID(caGUID.pElems), nil, 0, nil)=S_OK;
|
|
CoTaskMemFree(caGUID.pElems);
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
function TIEDirectShow.ShowPinPropertyPages(pin: IIEPin; checkOnly: boolean): boolean;
|
|
var
|
|
pSpecify: IIESpecifyPropertyPages;
|
|
caGUID: TIECAGUID;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
result := false;
|
|
pSpecify := nil;
|
|
pin.QueryInterface(IID_IIESpecifyPropertyPages, pSpecify);
|
|
if pSpecify <> nil then
|
|
begin
|
|
pSpecify.GetPages(caGUID);
|
|
pSpecify := nil;
|
|
if checkOnly then
|
|
result := true
|
|
else
|
|
result := OleCreatePropertyFrame(fNotifyWindow, 0, 0, '', 1, pointer(@pin), caGUID.cElems, PGUID(caGUID.pElems), nil, 0, nil)=S_OK;
|
|
CoTaskMemFree(caGUID.pElems);
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.ShowPropertyPages
|
|
|
|
<FM>Declaration<FC>
|
|
function ShowPropertyPages(proppages: <A TIEPropertyPages>; proptype: <A TIEPropertyPagesType>; checkOnly: boolean=false): boolean;
|
|
|
|
<FM>Description<FN>
|
|
Shows a dialog for the specified filter of the filter graph.
|
|
|
|
<FC>proppages<FN>: Specifies the filter
|
|
<FC>proptype<FN>: Whether the dialog is for input, output or common filter properties
|
|
<FC>checkOnly<FN>: If True, the dialog will not be displayed, only determines if it is available (i.e. check the return value to know whether the dialog is available)
|
|
|
|
Return False if it fails.
|
|
!!}
|
|
function TIEDirectShow.ShowPropertyPages(proppages: TIEPropertyPages; proptype: TIEPropertyPagesType; checkOnly: boolean): boolean;
|
|
var
|
|
f: IIEBaseFilter;
|
|
pin: IIEPin;
|
|
begin
|
|
result := false;
|
|
f := nil;
|
|
if not Connected then
|
|
Connect;
|
|
case proppages of
|
|
iepVideoInput:
|
|
if fCurVideoInput <> nil then
|
|
f := fCurVideoInput
|
|
else
|
|
if fCurFileInput <> nil then
|
|
f := fCurFileInput;
|
|
iepAudioInput:
|
|
if fCurAudioInput <> nil then
|
|
f := fCurAudioInput
|
|
else
|
|
if fCurFileInput <> nil then
|
|
f := fCurFileInput;
|
|
iepVideoCodec:
|
|
if fCurVideoCodec <> nil then
|
|
f := fCurVideoCodec;
|
|
iepAudioCodec:
|
|
if fCurAudioCodec <> nil then
|
|
f := fCurAudioCodec;
|
|
iepVideoInputSource:
|
|
if fCrossBarFilter <> nil then
|
|
f := fCrossBarFilter;
|
|
iepTuner:
|
|
if fTunerFilter <> nil then
|
|
f := fTunerFilter;
|
|
end;
|
|
if assigned(f) then
|
|
case proptype of
|
|
ietFilter:
|
|
result := ShowFilterPropertyPages(f, checkOnly);
|
|
ietInput:
|
|
begin
|
|
fBuilder.FindPin(f, PINDIR_INPUT, nil, nil, false, 0, pin);
|
|
if assigned(pin) then
|
|
result := ShowPinPropertyPages(pin, checkOnly);
|
|
end;
|
|
ietOutput:
|
|
begin
|
|
fBuilder.FindPin(f, PINDIR_OUTPUT, nil, nil, false, 0, pin);
|
|
if assigned(pin) then
|
|
result := ShowPinPropertyPages(pin, checkOnly);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.GetSupportedTVStandards
|
|
|
|
<FM>Declaration<FC>
|
|
function GetSupportedTVStandards: <A TIETVStandards>;
|
|
|
|
<FM>Description<FN>
|
|
Returns a set of supported tv standards (NTSC, Pal,...).
|
|
This function is useful to know supported standard before call <A TIEDirectShow.SetTVStandard>.
|
|
!!}
|
|
function TIEDirectShow.GetSupportedTVStandards: TIETVStandards;
|
|
var
|
|
r: longint;
|
|
i: integer;
|
|
begin
|
|
result := [];
|
|
if assigned(fAnalogVideoDecoder) then
|
|
begin
|
|
fAnalogVideoDecoder.get_AvailableTVFormats(@r);
|
|
for i := 0 to 19 do
|
|
if (vs1[i] or r)<>0 then
|
|
include(result, vs3[i]);
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetTVStandard
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetTVStandard(Value: <A TIETVStandard>);
|
|
|
|
<FM>Description<FN>
|
|
Sets the input tv standard. To know supported tv standards use <A TIEDirectShow.GetSupportedTVStandards>.
|
|
!!}
|
|
procedure TIEDirectShow.SetTVStandard(Value: TIETVStandard);
|
|
var
|
|
i: integer;
|
|
begin
|
|
if assigned(fAnalogVideoDecoder) then
|
|
for i := 0 to 19 do
|
|
if Value=vs3[i] then
|
|
begin
|
|
fAnalogVideoDecoder.put_TVFormat(vs1[i]);
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetVCRHorizontalLocking
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetVCRHorizontalLocking(Value: boolean);
|
|
|
|
<FM>Description<FN>
|
|
When false assumes input from broadcast source (better synchronization pulses), when true tells the decoder to relas its standards (typically used from a tape source).
|
|
!!}
|
|
procedure TIEDirectShow.SetVCRHorizontalLocking(Value: boolean);
|
|
begin
|
|
if assigned(fAnalogVideoDecoder) then
|
|
fAnalogVideoDecoder.put_VCRHorizontalLocking(longint(Value));
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.SetVideoRenderRect
|
|
|
|
<FM>Declaration<FC>
|
|
procedure SetVideoRenderRect(SrcRect, DstRect: TRect);
|
|
|
|
<FM>Description<FN>
|
|
Used internally by <A TImageEnView> in order to set source and destination rectangle when <A TIEDirectShow.RenderVideo> is true.
|
|
!!}
|
|
procedure TIEDirectShow.SetVideoRenderRect(SrcRect, DstRect: TRect);
|
|
begin
|
|
if assigned(fVMRWindowlessControl) then
|
|
fVMRWindowlessControl.SetVideoPosition(@SrcRect, @DstRect);
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.GetVideoRenderRect
|
|
|
|
<FM>Declaration<FC>
|
|
procedure GetVideoRenderRect(var SrcRect: TRect; var DstRect: TRect);
|
|
|
|
<FM>Description<FN>
|
|
Used internally by <A TImageEnView> in order to get source and destination rectangle when <A TIEDirectShow.RenderVideo> is true.
|
|
!!}
|
|
procedure TIEDirectShow.GetVideoRenderRect(var SrcRect: TRect; var DstRect: TRect);
|
|
begin
|
|
if assigned(fVMRWindowlessControl) then
|
|
fVMRWindowlessControl.GetVideoPosition(@SrcRect, @DstRect);
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.GetVideoRenderNativeSize
|
|
|
|
<FM>Declaration<FC>
|
|
procedure GetVideoRenderNativeSize(var Width: integer; var Height: integer);
|
|
|
|
<FM>Description<FN>
|
|
Returns the video frame size when <A TIEDirectShow.RenderVideo> is true.
|
|
You should set the background bitmap to the same size.
|
|
|
|
<FM>Example<FC>
|
|
TImageEnView.IO.DShowParams.GetVideoRenderNativeSize(w, h);
|
|
TImageEnView.Proc.ImageResize(w, h);
|
|
!!}
|
|
procedure TIEDirectShow.GetVideoRenderNativeSize(var Width: integer; var Height: integer);
|
|
begin
|
|
if assigned(fVMRWindowlessControl) then
|
|
fVMRWindowlessControl.GetNativeVideoSize(@Width, @Height, nil, nil);
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEDirectShow.RepaintVideo
|
|
|
|
<FM>Declaration<FC>
|
|
procedure RepaintVideo(hwnd: THandle; hdc: THandle);
|
|
|
|
<FM>Description<FN>
|
|
Used internally by <A TImageEnView> in order to repaint display when <A TIEDirectShow.RenderVideo> is true.
|
|
!!}
|
|
procedure TIEDirectShow.RepaintVideo(hwnd: THandle; hdc: THandle);
|
|
begin
|
|
if assigned(fVMRWindowlessControl) then
|
|
fVMRWindowlessControl.RepaintVideo(hwnd, hdc);
|
|
end;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
// TIEMediaReader
|
|
|
|
constructor TIEMediaReader.Create(const FileName: AnsiString);
|
|
var
|
|
i, sCount, c: integer;
|
|
st: PWideChar;
|
|
mt: PIEAM_MEDIA_TYPE;
|
|
ih: PIEVIDEOINFOHEADER;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
inherited Create;
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fFileName := FileName;
|
|
CoCreateInstance(CLSID_MediaDet, nil, CLSCTX_INPROC, IID_IIEMediaDet, fMediaDet);
|
|
if assigned(fMediaDet) then
|
|
begin
|
|
// set filename
|
|
fMediaDet.put_Filename(PWideChar(WideString(fFileName)));
|
|
|
|
// get streams count
|
|
sCount := 0;
|
|
fMediaDet.get_OutputStreams(@sCount);
|
|
// iterate streams to search video stream
|
|
c := 0;
|
|
for i := 0 to sCount-1 do
|
|
begin
|
|
fMediaDet.put_CurrentStream(i);
|
|
fMediaDet.get_StreamTypeB(st);
|
|
if IEUpperCase(IEConvertGUIDToString(@MEDIATYPE_Video)) = IEUpperCase(AnsiString(WideCharToString(st))) then
|
|
c := i;
|
|
SysFreeString(st);
|
|
end;
|
|
fMediaDet.put_CurrentStream(c);
|
|
// get frame rate (frames per second)
|
|
fMediaDet.get_FrameRate(@fFrameRate);
|
|
// get length (seconds) and frame count
|
|
fMediaDet.get_StreamLength(@fLength);
|
|
fFrameCount := trunc(fLength*fFrameRate);
|
|
// media type and frame buffer
|
|
getmem(mt, 1024);
|
|
try
|
|
fMediaDet.get_StreamMediaType(mt);
|
|
try
|
|
ih := pointer(mt^.pbFormat);
|
|
fFrameWidth := ih^.bmiHeader.biWidth;
|
|
fFrameHeight := ih^.bmiHeader.biHeight;
|
|
finally
|
|
FreeMediaType(mt^); // 3.0.4
|
|
end;
|
|
finally
|
|
freemem(mt);
|
|
end;
|
|
end;
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
destructor TIEMediaReader.Destroy;
|
|
begin
|
|
fMediaDet := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{!!
|
|
<FS>TIEMediaReader.GetSample
|
|
|
|
<FM>Declaration<FC>
|
|
procedure GetSample(frame: int64; OutBitmap: <A TIEBitmap>);
|
|
|
|
<FM>Description<FN>
|
|
Copies the sample indexed by <FC>frame<FN> to <FC>OutBitmap<FN>.
|
|
!!}
|
|
procedure TIEMediaReader.GetSample(frame: int64; OutBitmap: TIEBitmap);
|
|
var
|
|
bf: integer;
|
|
frameBuffer: array of byte;
|
|
fpExpDisabler: TIE8087ExceptionsDisabler;
|
|
begin
|
|
fpExpDisabler := TIE8087ExceptionsDisabler.Create();
|
|
try
|
|
fMediaDet.GetBitmapBits(frame / fFrameRate, @bf, nil, fFrameWidth, fFrameHeight);
|
|
SetLength(frameBuffer, bf);
|
|
fMediaDet.GetBitmapBits(frame / fFrameRate, nil, pointer(frameBuffer), fFrameWidth, fFrameHeight);
|
|
OutBitmap.CopyFromDIB(pointer(frameBuffer));
|
|
finally
|
|
fpExpDisabler.Free();
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
// TIEMediaReader
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
{$ELSE} // IEINCLUDEDIRECTSHOW
|
|
implementation
|
|
{$ENDIF}
|
|
|
|
end.
|
|
|