📄 baseclass.pas
字号:
// fail). After calling this, you need to free any queued data
// and then call downstream.
function BeginFlush: HRESULT; override; stdcall;
// default handling for EndFlush - call at end of your implementation
// - before calling this, ensure that there is no queued data and no thread
// pushing any more without a further receive, then call downstream,
// then call this method to clear the m_bFlushing flag and re-enable
// receives
function EndFlush: HRESULT; override; stdcall;
// Release the pin's allocator.
function BreakConnect: HRESULT; override;
// helper method to check the read-only flag
property IsReadOnly: boolean read FReadOnly;
// helper method to see if we are flushing
property IsFlushing: boolean read FFlushing;
// Override this for checking whether it's OK to process samples
// Also call this from EndOfStream.
function CheckStreaming: HRESULT; virtual;
// Pass a Quality notification on to the appropriate sink
function PassNotify(const q: TQuality): HRESULT;
//================================================================================
// IQualityControl methods (from CBasePin)
//================================================================================
function Notify(pSelf: IBaseFilter; q: TQuality): HRESULT; override; stdcall;
// no need to override:
// STDMETHODIMP SetSink(IQualityControl * piqc);
// switch the pin to inactive state - may already be inactive
function Inactive: HRESULT; override;
// Return sample properties pointer
function SampleProps: PAMSample2Properties;
end;
// milenko start (added TBCDynamicOutputPin conversion)
TBLOCK_STATE = (NOT_BLOCKED, PENDING, BLOCKED);
TBCDynamicOutputPin = class(TBCBaseOutputPin, IPinFlowControl)
public
constructor Create(ObjectName: WideString; Filter: TBCBaseFilter;
Lock: TBCCritSec; out hr: HRESULT; Name: WideString);
destructor Destroy; override;
// IUnknown Methods
function NonDelegatingQueryInterface(const IID: TGUID; out Obj): HResult; override;
// IPin Methods
function Disconnect: HRESULT; override; stdcall;
// IPinFlowControl Methods
function Block(dwBlockFlags: DWORD; hEvent: THandle): HResult; stdcall;
// Set graph config info
procedure SetConfigInfo(GraphConfig: IGraphConfig; StopEvent: THandle);
{$IFDEF DEBUG}
function Deliver(Sample: IMediaSample): HRESULT; override;
function DeliverEndOfStream: HRESULT; override;
function DeliverNewSegment(Start, Stop: TReferenceTime; Rate: double): HRESULT; override;
{$ENDIF} // DEBUG
function DeliverBeginFlush: HRESULT; override;
function DeliverEndFlush: HRESULT; override;
function Active: HRESULT; override;
function Inactive: HRESULT; override;
function CompleteConnect(ReceivePin: IPin): HRESULT; override;
function StartUsingOutputPin: HRESULT; virtual;
procedure StopUsingOutputPin; virtual;
function StreamingThreadUsingOutputPin: Boolean; virtual;
function ChangeOutputFormat(const pmt: PAMMediaType; tSegmentStart, tSegmentStop:
TreferenceTime; dSegmentRate: Double): HRESULT;
function ChangeMediaType(const pmt: PAMMEdiaType): HRESULT;
function DynamicReconnect(const pmt: PAMMediaType): HRESULT;
protected
// This lock should be held when the following class members are
// being used: m_hNotifyCallerPinBlockedEvent, m_BlockState,
// m_dwBlockCallerThreadID and m_dwNumOutstandingOutputPinUsers.
FBlockStateLock: TBCCritSec;
// This event should be signaled when the output pin is
// not blocked. This is a manual reset event. For more
// information on events, see the documentation for
// CreateEvent() in the Windows SDK.
FUnblockOutputPinEvent: THandle;
// This event will be signaled when block operation succeedes or
// when the user cancels the block operation. The block operation
// can be canceled by calling IPinFlowControl2::Block( 0, NULL )
// while the block operation is pending.
FNotifyCallerPinBlockedEvent: THandle;
// The state of the current block operation.
FBlockState: TBLOCK_STATE;
// The ID of the thread which last called IPinFlowControl::Block().
// For more information on thread IDs, see the documentation for
// GetCurrentThreadID() in the Windows SDK.
FBlockCallerThreadID: DWORD;
// The number of times StartUsingOutputPin() has been sucessfully
// called and a corresponding call to StopUsingOutputPin() has not
// been made. When this variable is greater than 0, the streaming
// thread is calling IPin::NewSegment(), IPin::EndOfStream(),
// IMemInputPin::Receive() or IMemInputPin::ReceiveMultiple(). The
// streaming thread could also be calling: DynamicReconnect(),
// ChangeMediaType() or ChangeOutputFormat(). The output pin cannot
// be blocked while the output pin is being used.
FNumOutstandingOutputPinUsers: DWORD;
// This event should be set when the IMediaFilter::Stop() is called.
// This is a manual reset event. It is also set when the output pin
// delivers a flush to the connected input pin.
FStopEvent: THandle;
FGraphConfig: IGraphConfig;
// TRUE if the output pin's allocator's samples are read only.
// Otherwise FALSE. For more information, see the documentation
// for IMemInputPin::NotifyAllocator().
FPinUsesReadOnlyAllocator: Boolean;
function SynchronousBlockOutputPin: HRESULT;
function AsynchronousBlockOutputPin(NotifyCallerPinBlockedEvent: THandle): HRESULT;
function UnblockOutputPin: HRESULT;
procedure BlockOutputPin;
procedure ResetBlockState;
class function WaitEvent(Event: THandle): HRESULT;
private
function Initialize: HRESULT;
function ChangeMediaTypeHelper(const pmt: PAMMediaType): HRESULT;
{$IFDEF DEBUG}
procedure AssertValid;
{$ENDIF} // DEBUG
end;
// milenko end
TBCTransformOutputPin = class;
TBCTransformInputPin = class;
TBCTransformFilter = class(TBCBaseFilter)
protected
FEOSDelivered : boolean; // have we sent EndOfStream
FSampleSkipped : boolean; // Did we just skip a frame
FQualityChanged: boolean; // Have we degraded?
// critical section protecting filter state.
FcsFilter: TBCCritSec;
// critical section stopping state changes (ie Stop) while we're
// processing a sample.
//
// This critical section is held when processing
// events that occur on the receive thread - Receive() and EndOfStream().
//
// If you want to hold both m_csReceive and m_csFilter then grab
// m_csFilter FIRST - like CTransformFilter::Stop() does.
FcsReceive: TBCCritSec;
// these hold our input and output pins
FInput : TBCTransformInputPin;
FOutput: TBCTransformOutputPin;
public
// map getpin/getpincount for base enum of pins to owner
// override this to return more specialised pin objects
function GetPinCount: integer; override;
function GetPin(n: integer): TBCBasePin; override;
function FindPin(Id: PWideChar; out ppPin: IPin): HRESULT; override; stdcall;
// override state changes to allow derived transform filter
// to control streaming start/stop
function Stop: HRESULT; override; stdcall;
function Pause: HRESULT; override; stdcall;
constructor Create(ObjectName: string; unk: IUnKnown; const clsid: TGUID);
constructor CreateFromFactory(Factory: TBCClassFactory; const Controller: IUnknown); override;
destructor destroy; override;
// =================================================================
// ----- override these bits ---------------------------------------
// =================================================================
// These must be supplied in a derived class
function Transform(msIn, msout: IMediaSample): HRESULT; virtual;
// check if you can support mtIn
function CheckInputType(mtIn: PAMMediaType): HRESULT; virtual; abstract;
// check if you can support the transform from this input to this output
function CheckTransform(mtIn, mtOut: PAMMediaType): HRESULT; virtual; abstract;
// this goes in the factory template table to create new instances
// static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *);
// call the SetProperties function with appropriate arguments
function DecideBufferSize(Allocator: IMemAllocator; prop: PAllocatorProperties): HRESULT; virtual; abstract;
// override to suggest OUTPUT pin media types
function GetMediaType(Position: integer; out MediaType: PAMMediaType): HRESULT; virtual; abstract;
// =================================================================
// ----- Optional Override Methods -----------------------
// =================================================================
// you can also override these if you want to know about streaming
function StartStreaming: HRESULT; virtual;
function StopStreaming: HRESULT; virtual;
// override if you can do anything constructive with quality notifications
function AlterQuality(const q: TQuality): HRESULT; virtual;
// override this to know when the media type is actually set
function SetMediaType(direction: TPinDirection; pmt: PAMMediaType): HRESULT; virtual;
// chance to grab extra interfaces on connection
function CheckConnect(dir: TPinDirection; Pin: IPin): HRESULT; virtual;
function BreakConnect(dir: TPinDirection): HRESULT; virtual;
function CompleteConnect(direction: TPinDirection; ReceivePin: IPin): HRESULT; virtual;
// chance to customize the transform process
function Receive(Sample: IMediaSample): HRESULT; virtual;
// Standard setup for output sample
function InitializeOutputSample(Sample: IMediaSample; out OutSample: IMediaSample): HRESULT; virtual;
// if you override Receive, you may need to override these three too
function EndOfStream: HRESULT; virtual;
function BeginFlush: HRESULT; virtual;
function EndFlush: HRESULT; virtual;
function NewSegment(Start, Stop: TReferenceTime; Rate: double): HRESULT; virtual;
property Input: TBCTransformInputPin read FInput write FInput;
property Output: TBCTransformOutputPin read FOutPut write FOutput;
end;
TBCTransformInputPin = class(TBCBaseInputPin)
private
FTransformFilter: TBCTransformFilter;
public
constructor Create(ObjectName: string; TransformFilter: TBCTransformFilter;
out hr: HRESULT; Name: WideString);
destructor destroy; override;
function QueryId(out id: PWideChar): HRESULT; override; stdcall;
// Grab and release extra interfaces if required
function CheckConnect(Pin: IPin): HRESULT; override;
function BreakConnect: HRESULT; override;
function CompleteConnect(ReceivePin: IPin): HRESULT; override;
// check that we can support this output type
function CheckMediaType(mtIn: PAMMediaType): HRESULT; override;
// set the connection media type
function SetMediaType(mt: PAMMediaType): HRESULT; override;
// --- IMemInputPin -----
// here's the next block of data from the stream.
// AddRef it yourself if you need to hold it beyond the end
// of this call.
function Receive(pSample: IMediaSample): HRESULT; override; stdcall;
// provide EndOfStream that passes straight downstream
// (there is no queued data)
function EndOfStream: HRESULT; override; stdcall;
// passes it to CTransformFilter::BeginFlush
function BeginFlush: HRESULT; override; stdcall;
// passes it to CTransformFilter::EndFlush
function EndFlush: HRESULT; override; stdcall;
function NewSegment(Start, Stop: TReferenceTime; Rate: double): HRESULT; override; stdcall;
// Check if it's OK to process samples
function CheckStreaming: HRESULT; override;
end;
TBCTransformOutputPin = class(TBCBaseOutputPin)
protected
FTransformFilter: TBCTransformFilter;
// implement IMediaPosition by passing upstream
FPosition: IUnknown;
public
constructor Create(ObjectName: string; TransformFilter: TBCTransformFilter;
out hr: HRESULT; Name: WideString);
destructor destroy; override;
// override to expose IMediaPosition
function NonDelegatingQueryInterface(const IID: TGUID; out Obj): HResult; override;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -