Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy * FILE: dll/directx/ksproxy/output_pin.cpp * PURPOSE: OutputPin of Proxy Filter * * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) */#include "precomp.h"
class COutputPin : public IPin, public IKsObject, public IKsPropertySet, public IStreamBuilder, public IKsPinFactory, public ISpecifyPropertyPages, public IKsPinEx, public IKsPinPipe, public IKsControl, public IKsAggregateControl, public IQualityControl, public IMediaSeeking, public IAMBufferNegotiation, public IAMStreamConfig, public IMemAllocatorNotifyCallbackTemp
{public: typedef std::vector<IUnknown *>ProxyPluginVector;
STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef() { InterlockedIncrement(&m_Ref); return m_Ref; } STDMETHODIMP_(ULONG) Release() { InterlockedDecrement(&m_Ref); if (!m_Ref) { //delete this; return 0; } return m_Ref; }
//IKsPin HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList); HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList); HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium); HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium); HRESULT STDMETHODCALLTYPE KsPropagateAcquire(); HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags); HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment); IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation); HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator); HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator(); LONG STDMETHODCALLTYPE KsIncrementPendingIoCount(); LONG STDMETHODCALLTYPE KsDecrementPendingIoCount(); HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta); // IKsPinEx VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr);
//IKsPinPipe HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option); HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option); IPin* STDMETHODCALLTYPE KsGetConnectedPin(); IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation); HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator); ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag(); HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag); GUID STDMETHODCALLTYPE KsGetPinBusCache(); HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus); PWCHAR STDMETHODCALLTYPE KsGetPinName(); PWCHAR STDMETHODCALLTYPE KsGetFilterName();
//IPin methods HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE Disconnect(); HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin); HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo); HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id); HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum); HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin); HRESULT STDMETHODCALLTYPE EndOfStream(); HRESULT STDMETHODCALLTYPE BeginFlush(); HRESULT STDMETHODCALLTYPE EndFlush(); HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
// ISpecifyPropertyPages HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
//IKsObject methods HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
//IKsPropertySet HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData); HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned); HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
//IKsControl HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned); HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned); HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
//IStreamBuilder HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph); HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph);
//IKsPinFactory HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory);
//IKsAggregateControl HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass); HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass);
//IQualityControl HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q); HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc);
//IMediaSeeking HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities); HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities); HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat); HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat); HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat); HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat); HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat); HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration); HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop); HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent); HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat); HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags); HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop); HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest); HRESULT STDMETHODCALLTYPE SetRate(double dRate); HRESULT STDMETHODCALLTYPE GetRate(double *pdRate); HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll);
//IAMBufferNegotiation HRESULT STDMETHODCALLTYPE SuggestAllocatorProperties(const ALLOCATOR_PROPERTIES *pprop); HRESULT STDMETHODCALLTYPE GetAllocatorProperties(ALLOCATOR_PROPERTIES *pprop);
//IAMStreamConfig HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt); HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize); HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **ppmt, BYTE *pSCC);
//IMemAllocatorNotifyCallbackTemp HRESULT STDMETHODCALLTYPE NotifyRelease();
//--------------------------------------------------------------- COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication); virtual ~COutputPin(); HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt); HRESULT WINAPI IoProcessRoutine(); HRESULT WINAPI InitializeIOThread(); HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids); HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids);
friend DWORD WINAPI COutputPin_IoThreadStartup(LPVOID lpParameter); friend HRESULT STDMETHODCALLTYPE COutputPin_SetState(IPin * Pin, KSSTATE State);
protected: LONG m_Ref; IBaseFilter * m_ParentFilter; LPCWSTR m_PinName; HANDLE m_hPin; ULONG m_PinId; IPin * m_Pin; IKsAllocatorEx * m_KsAllocatorEx; ULONG m_PipeAllocatorFlag; BOOL m_bPinBusCacheInitialized; GUID m_PinBusCache; LPWSTR m_FilterName; FRAMING_PROP m_FramingProp[4]; PKSALLOCATOR_FRAMING_EX m_FramingEx[4];
IMemAllocator * m_MemAllocator; IMemInputPin * m_MemInputPin; LONG m_IoCount; KSPIN_COMMUNICATION m_Communication; KSPIN_INTERFACE m_Interface; KSPIN_MEDIUM m_Medium; AM_MEDIA_TYPE m_MediaFormat; ALLOCATOR_PROPERTIES m_Properties; IKsInterfaceHandler * m_InterfaceHandler;
HANDLE m_hStartEvent; HANDLE m_hBufferAvailable; HANDLE m_hStopEvent; BOOL m_StopInProgress; BOOL m_IoThreadStarted;
KSSTATE m_State; CRITICAL_SECTION m_Lock;
ProxyPluginVector m_Plugins;};
COutputPin::~COutputPin(){}
COutputPin::COutputPin( IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hPin(INVALID_HANDLE_VALUE), m_PinId(PinId), m_Pin(0), m_KsAllocatorEx(0), m_PipeAllocatorFlag(0), m_bPinBusCacheInitialized(0), m_FilterName(0), m_MemAllocator(0), m_MemInputPin(0), m_IoCount(0), m_Communication(Communication), m_InterfaceHandler(0), m_hStartEvent(0), m_hBufferAvailable(0), m_hStopEvent(0), m_StopInProgress(0), m_IoThreadStarted(0), m_State(KSSTATE_STOP), m_Plugins(){ HRESULT hr; IKsObject * KsObjectParent;
hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); assert(hr == S_OK);
ZeroMemory(m_FramingProp, sizeof(m_FramingProp)); ZeroMemory(m_FramingEx, sizeof(m_FramingEx)); ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE));
hr = KsGetMediaType(0, &m_MediaFormat, KsObjectParent->KsGetObjectHandle(), m_PinId);
#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::COutputPin Format %p pbFormat %lu\n", &m_MediaFormat, m_MediaFormat.cbFormat); OutputDebugStringW(Buffer);#endif
assert(hr == S_OK);
InitializeCriticalSection(&m_Lock);
KsObjectParent->Release();};
HRESULTSTDMETHODCALLTYPECOutputPin::QueryInterface( IN REFIID refiid, OUT PVOID* Output){ *Output = NULL; if (IsEqualGUID(refiid, IID_IUnknown) || IsEqualGUID(refiid, IID_IPin)) {#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n");#endif *Output = PVOID(this); reinterpret_cast<IUnknown*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsObject)) { if (m_hPin == INVALID_HANDLE_VALUE) { HRESULT hr = CreatePin(&m_MediaFormat); if (FAILED(hr)) return hr; }#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n");#endif *Output = (IKsObject*)(this); reinterpret_cast<IKsObject*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx)) { *Output = (IKsPinEx*)(this); reinterpret_cast<IKsPinEx*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsPinPipe)) { *Output = (IKsPinPipe*)(this); reinterpret_cast<IKsPinPipe*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsAggregateControl)) { *Output = (IKsAggregateControl*)(this); reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IQualityControl)) { *Output = (IQualityControl*)(this); reinterpret_cast<IQualityControl*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsPropertySet)) { if (m_hPin == INVALID_HANDLE_VALUE) { HRESULT hr = CreatePin(&m_MediaFormat); if (FAILED(hr)) return hr; }#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n");#endif *Output = (IKsPropertySet*)(this); reinterpret_cast<IKsPropertySet*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsControl)) {#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n");#endif *Output = (IKsControl*)(this); reinterpret_cast<IKsControl*>(*Output)->AddRef(); return NOERROR; }#if 0 else if (IsEqualGUID(refiid, IID_IStreamBuilder)) { *Output = (IStreamBuilder*)(this); reinterpret_cast<IStreamBuilder*>(*Output)->AddRef(); return NOERROR; }#endif else if (IsEqualGUID(refiid, IID_IKsPinFactory)) {#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n");#endif *Output = (IKsPinFactory*)(this); reinterpret_cast<IKsPinFactory*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) {#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n");#endif *Output = (ISpecifyPropertyPages*)(this); reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IMediaSeeking)) { *Output = (IMediaSeeking*)(this); reinterpret_cast<IMediaSeeking*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation)) { *Output = (IAMBufferNegotiation*)(this); reinterpret_cast<IAMBufferNegotiation*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IAMStreamConfig)) { *Output = (IAMStreamConfig*)(this); reinterpret_cast<IAMStreamConfig*>(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp)) { *Output = (IMemAllocatorNotifyCallbackTemp*)(this); reinterpret_cast<IMemAllocatorNotifyCallbackTemp*>(*Output)->AddRef(); return NOERROR; }
#ifdef KSPROXY_TRACE WCHAR Buffer[MAX_PATH]; LPOLESTR lpstr; StringFromCLSID(refiid, &lpstr); swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s PinId %u PinName %s\n", lpstr, m_PinId, m_PinName); OutputDebugStringW(Buffer); CoTaskMemFree(lpstr);#endif
return E_NOINTERFACE;}
//-------------------------------------------------------------------// IAMBufferNegotiation interface//HRESULTSTDMETHODCALLTYPECOutputPin::SuggestAllocatorProperties( const ALLOCATOR_PROPERTIES *pprop){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties\n");#endif
if (m_Pin) { // pin is already connected return VFW_E_ALREADY_CONNECTED; }
CopyMemory(&m_Properties, pprop, sizeof(ALLOCATOR_PROPERTIES)); return NOERROR;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetAllocatorProperties( ALLOCATOR_PROPERTIES *pprop){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetAllocatorProperties\n");#endif
if (!m_Pin) { // you should call this method AFTER you connected return E_UNEXPECTED; }
if (!m_KsAllocatorEx) { // something went wrong while creating the allocator return E_FAIL; }
CopyMemory(pprop, &m_Properties, sizeof(ALLOCATOR_PROPERTIES)); return NOERROR;}
//-------------------------------------------------------------------// IAMStreamConfig interface//HRESULTSTDMETHODCALLTYPECOutputPin::SetFormat( AM_MEDIA_TYPE *pmt){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n");#endif return E_NOTIMPL;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetFormat(AM_MEDIA_TYPE **ppmt){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n");#endif return E_NOTIMPL;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetNumberOfCapabilities( int *piCount, int *piSize){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n");#endif return E_NOTIMPL;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetStreamCaps( int iIndex, AM_MEDIA_TYPE **ppmt, BYTE *pSCC){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n");#endif return E_NOTIMPL;}
//-------------------------------------------------------------------// IMemAllocatorNotifyCallbackTemp interface//HRESULTSTDMETHODCALLTYPECOutputPin::NotifyRelease(){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::NotifyRelease\n");#endif
// notify thread of new available sample SetEvent(m_hBufferAvailable);
return NOERROR;}
//-------------------------------------------------------------------// IMediaSeeking interface//HRESULTSTDMETHODCALLTYPECOutputPin::GetCapabilities( DWORD *pCapabilities){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetCapabilities(pCapabilities);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::CheckCapabilities( DWORD *pCapabilities){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->CheckCapabilities(pCapabilities);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::IsFormatSupported( const GUID *pFormat){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->IsFormatSupported(pFormat);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::QueryPreferredFormat( GUID *pFormat){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->QueryPreferredFormat(pFormat);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetTimeFormat( GUID *pFormat){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetTimeFormat(pFormat);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::IsUsingTimeFormat( const GUID *pFormat){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->IsUsingTimeFormat(pFormat);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::SetTimeFormat( const GUID *pFormat){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->SetTimeFormat(pFormat);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetDuration( LONGLONG *pDuration){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetDuration(pDuration);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetStopPosition( LONGLONG *pStop){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetStopPosition(pStop);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetCurrentPosition( LONGLONG *pCurrent){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetCurrentPosition(pCurrent);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::ConvertTimeFormat( LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::SetPositions( LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetPositions( LONGLONG *pCurrent, LONGLONG *pStop){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetPositions(pCurrent, pStop);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetAvailable( LONGLONG *pEarliest, LONGLONG *pLatest){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetAvailable(pEarliest, pLatest);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::SetRate( double dRate){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->SetRate(dRate);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetRate( double *pdRate){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetRate(pdRate);
FilterMediaSeeking->Release(); return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetPreroll( LONGLONG *pllPreroll){ IMediaSeeking * FilterMediaSeeking; HRESULT hr;
hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); if (FAILED(hr)) return hr;
hr = FilterMediaSeeking->GetPreroll(pllPreroll);
FilterMediaSeeking->Release(); return hr;}
//-------------------------------------------------------------------// IQualityControl interface//HRESULTSTDMETHODCALLTYPECOutputPin::Notify( IBaseFilter *pSelf, Quality q){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Notify NotImplemented\n");#endif return E_NOTIMPL;}
HRESULTSTDMETHODCALLTYPECOutputPin::SetSink( IQualityControl *piqc){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n");#endif return E_NOTIMPL;}
//-------------------------------------------------------------------// IKsAggregateControl interface//HRESULTSTDMETHODCALLTYPECOutputPin::KsAddAggregate( IN REFGUID AggregateClass){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n");#endif return E_NOTIMPL;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsRemoveAggregate( REFGUID AggregateClass){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n");#endif return E_NOTIMPL;}
//-------------------------------------------------------------------// IKsPin//
HRESULTSTDMETHODCALLTYPECOutputPin::KsQueryMediums( PKSMULTIPLE_ITEM* MediumList){ HRESULT hr; HANDLE hFilter; IKsObject * KsObjectParent;
hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); if (FAILED(hr)) return E_NOINTERFACE;
hFilter = KsObjectParent->KsGetObjectHandle();
if (hFilter) hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList); else hr = E_HANDLE;
KsObjectParent->Release();
return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsQueryInterfaces( PKSMULTIPLE_ITEM* InterfaceList){ HRESULT hr; HANDLE hFilter; IKsObject * KsObjectParent;
hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); if (FAILED(hr)) return hr;
hFilter = KsObjectParent->KsGetObjectHandle();
if (hFilter) hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList); else hr = E_HANDLE;
KsObjectParent->Release();
return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsCreateSinkPinHandle( KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n");#endif return E_NOTIMPL;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsGetCurrentCommunication( KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium){ if (Communication) { *Communication = m_Communication; }
if (Interface) { if (!m_hPin) return VFW_E_NOT_CONNECTED;
CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE)); }
if (Medium) { if (!m_hPin) return VFW_E_NOT_CONNECTED;
CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM)); } return NOERROR;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsPropagateAcquire(){ KSPROPERTY Property; KSSTATE State; ULONG BytesReturned; HRESULT hr;
#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsPropagateAcquire\n");#endif
assert(m_hPin != INVALID_HANDLE_VALUE);
Property.Set = KSPROPSETID_Connection; Property.Id = KSPROPERTY_CONNECTION_STATE; Property.Flags = KSPROPERTY_TYPE_SET;
State = KSSTATE_ACQUIRE;
hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned); if (SUCCEEDED(hr)) { m_State = State; }
//TODO //propagate to connected pin on the pipe
return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsDeliver( IMediaSample* Sample, ULONG Flags){ return E_FAIL;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment){ return NOERROR;}
IMemAllocator *STDMETHODCALLTYPECOutputPin::KsPeekAllocator(KSPEEKOPERATION Operation){ if (Operation == KsPeekOperation_AddRef) { // add reference on allocator m_MemAllocator->AddRef(); }
return m_MemAllocator;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsReceiveAllocator(IMemAllocator *MemAllocator){ if (MemAllocator) { MemAllocator->AddRef(); }
if (m_MemAllocator) { m_MemAllocator->Release(); }
m_MemAllocator = MemAllocator; return NOERROR;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsRenegotiateAllocator(){ return E_FAIL;}
LONGSTDMETHODCALLTYPECOutputPin::KsIncrementPendingIoCount(){ return InterlockedIncrement((volatile LONG*)&m_IoCount);}
LONGSTDMETHODCALLTYPECOutputPin::KsDecrementPendingIoCount(){ return InterlockedDecrement((volatile LONG*)&m_IoCount);}
HRESULTSTDMETHODCALLTYPECOutputPin::KsQualityNotify( ULONG Proportion, REFERENCE_TIME TimeDelta){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n");#endif return E_NOTIMPL;}
//-------------------------------------------------------------------// IKsPinEx//
VOIDSTDMETHODCALLTYPECOutputPin::KsNotifyError( IMediaSample* Sample, HRESULT hr){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n");#endif}
//-------------------------------------------------------------------// IKsPinPipe//
HRESULTSTDMETHODCALLTYPECOutputPin::KsGetPinFramingCache( PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option){ if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast) { // invalid argument return E_INVALIDARG; }
// get framing properties *FramingProp = m_FramingProp[Option]; *FramingEx = m_FramingEx[Option];
return NOERROR;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsSetPinFramingCache( PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option){ ULONG Index; ULONG RefCount = 0;
if (m_FramingEx[Option]) { for(Index = 1; Index < 4; Index++) { if (m_FramingEx[Index] == m_FramingEx[Option]) RefCount++; }
if (RefCount == 1) { // existing framing is only used once CoTaskMemFree(m_FramingEx[Option]); } }
// store framing m_FramingEx[Option] = FramingEx; m_FramingProp[Option] = *FramingProp;
return S_OK;}
IPin*STDMETHODCALLTYPECOutputPin::KsGetConnectedPin(){ return m_Pin;}
IKsAllocatorEx*STDMETHODCALLTYPECOutputPin::KsGetPipe( KSPEEKOPERATION Operation){ if (Operation == KsPeekOperation_AddRef) { if (m_KsAllocatorEx) m_KsAllocatorEx->AddRef(); } return m_KsAllocatorEx;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsSetPipe( IKsAllocatorEx *KsAllocator){ if (KsAllocator) KsAllocator->AddRef();
if (m_KsAllocatorEx) m_KsAllocatorEx->Release();
m_KsAllocatorEx = KsAllocator; return NOERROR;}
ULONGSTDMETHODCALLTYPECOutputPin::KsGetPipeAllocatorFlag(){ return m_PipeAllocatorFlag;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsSetPipeAllocatorFlag( ULONG Flag){ m_PipeAllocatorFlag = Flag; return NOERROR;}
GUIDSTDMETHODCALLTYPECOutputPin::KsGetPinBusCache(){ if (!m_bPinBusCacheInitialized) { CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID)); m_bPinBusCacheInitialized = TRUE; }
return m_PinBusCache;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsSetPinBusCache( GUID Bus){ CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID)); return NOERROR;}
PWCHARSTDMETHODCALLTYPECOutputPin::KsGetPinName(){ return (PWCHAR)m_PinName;}
PWCHARSTDMETHODCALLTYPECOutputPin::KsGetFilterName(){ return m_FilterName;}
//-------------------------------------------------------------------// ISpecifyPropertyPages//
HRESULTSTDMETHODCALLTYPECOutputPin::GetPages(CAUUID *pPages){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n");#endif
if (!pPages) return E_POINTER;
pPages->cElems = 0; pPages->pElems = NULL;
return S_OK;}
//-------------------------------------------------------------------// IKsPinFactory//
HRESULTSTDMETHODCALLTYPECOutputPin::KsPinFactory( ULONG* PinFactory){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsPinFactory\n");#endif
*PinFactory = m_PinId; return S_OK;}
//-------------------------------------------------------------------// IStreamBuilder//
HRESULTSTDMETHODCALLTYPECOutputPin::Render( IPin *ppinOut, IGraphBuilder *pGraph){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Render\n");#endif return S_OK;}
HRESULTSTDMETHODCALLTYPECOutputPin::Backout( IPin *ppinOut, IGraphBuilder *pGraph){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Backout\n");#endif
return S_OK;}//-------------------------------------------------------------------// IKsObject//HANDLESTDMETHODCALLTYPECOutputPin::KsGetObjectHandle(){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n");#endif
assert(m_hPin != INVALID_HANDLE_VALUE); return m_hPin;}
//-------------------------------------------------------------------// IKsControl//HRESULTSTDMETHODCALLTYPECOutputPin::KsProperty( PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned){ HRESULT hr;
assert(m_hPin != INVALID_HANDLE_VALUE);
hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);#ifdef KSPROXY_TRACE WCHAR Buffer[100]; LPOLESTR pstr; StringFromCLSID(Property->Set, &pstr); swprintf(Buffer, L"COutputPin::KsProperty Set %s Id %lu Flags %x hr %x\n", pstr, Property->Id, Property->Flags, hr); OutputDebugStringW(Buffer);#endif
return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::KsMethod( PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned){ assert(m_hPin != INVALID_HANDLE_VALUE);#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsMethod\n");#endif return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);}
HRESULTSTDMETHODCALLTYPECOutputPin::KsEvent( PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned){ assert(m_hPin != INVALID_HANDLE_VALUE);
#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsEvent\n");#endif
if (EventLength) return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned); else return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);}
//-------------------------------------------------------------------// IKsPropertySet//HRESULTSTDMETHODCALLTYPECOutputPin::Set( REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData){ ULONG BytesReturned;
if (cbInstanceData) { PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); if (!Property) return E_OUTOFMEMORY;
Property->Set = guidPropSet; Property->Id = dwPropID; Property->Flags = KSPROPERTY_TYPE_SET;
CopyMemory((Property+1), pInstanceData, cbInstanceData);
HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); CoTaskMemFree(Property); return hr; } else { KSPROPERTY Property;
Property.Set = guidPropSet; Property.Id = dwPropID; Property.Flags = KSPROPERTY_TYPE_SET;
HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); return hr; }}
HRESULTSTDMETHODCALLTYPECOutputPin::Get( REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned){ ULONG BytesReturned;
if (cbInstanceData) { PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); if (!Property) return E_OUTOFMEMORY;
Property->Set = guidPropSet; Property->Id = dwPropID; Property->Flags = KSPROPERTY_TYPE_GET;
CopyMemory((Property+1), pInstanceData, cbInstanceData);
HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); CoTaskMemFree(Property); return hr; } else { KSPROPERTY Property;
Property.Set = guidPropSet; Property.Id = dwPropID; Property.Flags = KSPROPERTY_TYPE_GET;
HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); return hr; }}
HRESULTSTDMETHODCALLTYPECOutputPin::QuerySupported( REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport){ KSPROPERTY Property; ULONG BytesReturned;
#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QuerySupported\n");#endif
Property.Set = guidPropSet; Property.Id = dwPropID; Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);}
//-------------------------------------------------------------------// IPin interface//HRESULTSTDMETHODCALLTYPECOutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt){ HRESULT hr; ALLOCATOR_PROPERTIES Properties; IMemAllocatorCallbackTemp *pMemCallback; LPGUID pGuid; ULONG NumGuids = 0;
#ifdef KSPROXY_TRACE WCHAR Buffer[200]; OutputDebugStringW(L"COutputPin::Connect called\n");#endif
if (pmt) { hr = pReceivePin->QueryAccept(pmt); if (FAILED(hr)) return hr; } else { // query accept hr = pReceivePin->QueryAccept(&m_MediaFormat); if (FAILED(hr)) return hr;
pmt = &m_MediaFormat; }
if (m_hPin == INVALID_HANDLE_VALUE) { hr = CreatePin(pmt); if (FAILED(hr)) {#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin::Connect CreatePin handle failed with %lx\n", hr); OutputDebugStringW(Buffer);#endif return hr; } }
// query for IMemInput interface hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin); if (FAILED(hr)) {#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n");#endif
return hr; }
// get input pin allocator properties ZeroMemory(&Properties, sizeof(ALLOCATOR_PROPERTIES)); m_MemInputPin->GetAllocatorRequirements(&Properties);
//FIXME determine allocator properties Properties.cBuffers = 32; Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size Properties.cbAlign = 4;
// get input pin allocator#if 0 hr = m_MemInputPin->GetAllocator(&m_MemAllocator); if (SUCCEEDED(hr)) { // set allocator properties hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); if (FAILED(hr)) m_MemAllocator->Release(); }#endif
if (1) { hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator); if (FAILED(hr)) return hr;
// set allocator properties hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); if (FAILED(hr)) {#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin::Connect IMemAllocator::SetProperties failed with hr %lx\n", hr); OutputDebugStringW(Buffer);#endif m_MemAllocator->Release(); m_MemInputPin->Release(); return hr; } }
// commit property changes hr = m_MemAllocator->Commit(); if (FAILED(hr)) {#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin::Connect IMemAllocator::Commit failed with hr %lx\n", hr); OutputDebugStringW(Buffer);#endif m_MemAllocator->Release(); m_MemInputPin->Release(); return hr; }
// get callback interface hr = m_MemAllocator->QueryInterface(IID_IMemAllocatorCallbackTemp, (void**)&pMemCallback); if (FAILED(hr)) {#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin::Connect No IMemAllocatorCallbackTemp interface hr %lx\n", hr); OutputDebugStringW(Buffer);#endif m_MemAllocator->Release(); m_MemInputPin->Release(); return hr; }
// set notification routine hr = pMemCallback->SetNotify((IMemAllocatorNotifyCallbackTemp*)this);
// release IMemAllocatorNotifyCallbackTemp interface pMemCallback->Release();
if (FAILED(hr)) {#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin::Connect IMemAllocatorNotifyCallbackTemp::SetNotify failed hr %lx\n", hr); OutputDebugStringW(Buffer);#endif m_MemAllocator->Release(); m_MemInputPin->Release(); return hr; }
// now set allocator hr = m_MemInputPin->NotifyAllocator(m_MemAllocator, TRUE); if (FAILED(hr)) {#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin::Connect IMemInputPin::NotifyAllocator failed with hr %lx\n", hr); OutputDebugStringW(Buffer);#endif m_MemAllocator->Release(); m_MemInputPin->Release(); return hr; }
assert(m_hPin != INVALID_HANDLE_VALUE);
// get all supported sets if (m_Plugins.empty()) { if (GetSupportedSets(&pGuid, &NumGuids)) { // load all proxy plugins if (FAILED(LoadProxyPlugins(pGuid, NumGuids))) {#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Connect LoadProxyPlugins failed\n");#endif } // free sets CoTaskMemFree(pGuid); } }
// receive connection; hr = pReceivePin->ReceiveConnection((IPin*)this, pmt); if (SUCCEEDED(hr)) { // increment reference count pReceivePin->AddRef(); m_Pin = pReceivePin;#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Connect success\n");#endif } else { m_MemInputPin->Release(); m_MemAllocator->Release(); }
return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt){ return E_UNEXPECTED;}HRESULTSTDMETHODCALLTYPECOutputPin::Disconnect( void){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Disconnect\n");#endif
if (!m_Pin) { // pin was not connected return S_FALSE; }
//FIXME //check if filter is active
m_Pin->Release(); m_Pin = NULL; m_MemInputPin->Release(); m_MemAllocator->Release();
CloseHandle(m_hPin); m_hPin = INVALID_HANDLE_VALUE;
#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Disconnect\n");#endif return S_OK;}HRESULTSTDMETHODCALLTYPECOutputPin::ConnectedTo(IPin **pPin){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::ConnectedTo\n");#endif
if (!pPin) return E_POINTER;
if (m_Pin) { // increment reference count m_Pin->AddRef(); *pPin = m_Pin; return S_OK; }
*pPin = NULL; return VFW_E_NOT_CONNECTED;}HRESULTSTDMETHODCALLTYPECOutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n");#endif
return E_NOTIMPL;}HRESULTSTDMETHODCALLTYPECOutputPin::QueryPinInfo(PIN_INFO *pInfo){ wcscpy(pInfo->achName, m_PinName); pInfo->dir = PINDIR_OUTPUT; pInfo->pFilter = m_ParentFilter; m_ParentFilter->AddRef();
return S_OK;}HRESULTSTDMETHODCALLTYPECOutputPin::QueryDirection(PIN_DIRECTION *pPinDir){ if (pPinDir) { *pPinDir = PINDIR_OUTPUT; return S_OK; }
return E_POINTER;}HRESULTSTDMETHODCALLTYPECOutputPin::QueryId(LPWSTR *Id){ *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR)); if (!*Id) return E_OUTOFMEMORY;
wcscpy(*Id, m_PinName); return S_OK;}HRESULTSTDMETHODCALLTYPECOutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt){#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryAccept called\n");#endif
return E_NOTIMPL;}HRESULTSTDMETHODCALLTYPECOutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum){ HRESULT hr; ULONG MediaTypeCount = 0, Index; AM_MEDIA_TYPE * MediaTypes; HANDLE hFilter; IKsObject * KsObjectParent;
hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); if (FAILED(hr)) return hr;
// get parent filter handle hFilter = KsObjectParent->KsGetObjectHandle();
// release IKsObject KsObjectParent->Release();
// query media type count hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount); if (FAILED(hr) || !MediaTypeCount) { return hr; }
// allocate media types MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount); if (!MediaTypes) { // not enough memory return E_OUTOFMEMORY; }
// zero media types ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
for(Index = 0; Index < MediaTypeCount; Index++) { // get media type hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId); if (FAILED(hr)) { // failed CoTaskMemFree(MediaTypes); return hr; } }
return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);}HRESULTSTDMETHODCALLTYPECOutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin){ return E_NOTIMPL;}HRESULTSTDMETHODCALLTYPECOutputPin::EndOfStream( void){ /* should be called only on input pins */ return E_UNEXPECTED;}HRESULTSTDMETHODCALLTYPECOutputPin::BeginFlush( void){ /* should be called only on input pins */ return E_UNEXPECTED;}HRESULTSTDMETHODCALLTYPECOutputPin::EndFlush( void){ /* should be called only on input pins */ return E_UNEXPECTED;}HRESULTSTDMETHODCALLTYPECOutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate){ if (!m_Pin) { // we are not connected return VFW_E_NOT_CONNECTED; }
return m_Pin->NewSegment(tStart, tStop, dRate);}
//-------------------------------------------------------------------HRESULTSTDMETHODCALLTYPECOutputPin::CheckFormat( const AM_MEDIA_TYPE *pmt){ PKSMULTIPLE_ITEM MultipleItem; PKSDATAFORMAT DataFormat; HRESULT hr; IKsObject * KsObjectParent; HANDLE hFilter;
if (!pmt) return E_POINTER;
// get IKsObject interface hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); if (FAILED(hr)) return hr;
// get parent filter handle hFilter = KsObjectParent->KsGetObjectHandle();
// release IKsObject KsObjectParent->Release();
if (!hFilter) return E_HANDLE;
hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem); if (FAILED(hr)) return S_FALSE;
DataFormat = (PKSDATAFORMAT)(MultipleItem + 1); for(ULONG Index = 0; Index < MultipleItem->Count; Index++) { if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) && IsEqualGUID(pmt->subtype, DataFormat->SubFormat) && IsEqualGUID(pmt->formattype, DataFormat->Specifier)) { // format is supported CoTaskMemFree(MultipleItem); return S_OK; } DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize); } //format is not supported CoTaskMemFree(MultipleItem); return S_FALSE;}
HRESULTSTDMETHODCALLTYPECOutputPin::CreatePin( const AM_MEDIA_TYPE *pmt){ PKSMULTIPLE_ITEM MediumList; PKSMULTIPLE_ITEM InterfaceList; PKSPIN_MEDIUM Medium; PKSPIN_INTERFACE Interface; IKsInterfaceHandler * InterfaceHandler; HRESULT hr;
// query for pin medium hr = KsQueryMediums(&MediumList); if (FAILED(hr)) {#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePin KsQueryMediums failed %lx\n", hr); OutputDebugStringW(Buffer);#endif return hr; }
// query for pin interface hr = KsQueryInterfaces(&InterfaceList); if (FAILED(hr)) { // failed#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePin KsQueryInterfaces failed %lx\n", hr); OutputDebugStringW(Buffer);#endif
CoTaskMemFree(MediumList); return hr; }
if (MediumList->Count) { //use first available medium Medium = (PKSPIN_MEDIUM)(MediumList + 1); } else { // default to standard medium Medium = &StandardPinMedium; }
if (InterfaceList->Count) { //use first available interface Interface = (PKSPIN_INTERFACE)(InterfaceList + 1); } else { // default to standard interface Interface = &StandardPinInterface; }
if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE) { // now create pin hr = CreatePinHandle(Medium, Interface, pmt); if (FAILED(hr)) {#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePinHandle failed with %lx\n", hr); OutputDebugStringW(Buffer);#endif return hr; }
if (!m_InterfaceHandler) { // now load the IKsInterfaceHandler plugin hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler); if (FAILED(hr)) { // failed to load interface handler plugin CoTaskMemFree(MediumList); CoTaskMemFree(InterfaceList);
#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePin failed to create interface handler %lx\n", hr); OutputDebugStringW(Buffer);#endif
return hr; }
// now set the pin hr = InterfaceHandler->KsSetPin((IKsPin*)this); if (FAILED(hr)) { // failed to initialize interface handler plugin#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePin failed to initialize interface handler %lx\n", hr); OutputDebugStringW(Buffer);#endif InterfaceHandler->Release(); CoTaskMemFree(MediumList); CoTaskMemFree(InterfaceList); return hr; }
// store interface handler m_InterfaceHandler = InterfaceHandler; } } else {#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName); OutputDebugStringW(Buffer);#endif
hr = E_FAIL; }
// free medium / interface / dataformat CoTaskMemFree(MediumList); CoTaskMemFree(InterfaceList);
#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePin Result %lx\n", hr); OutputDebugStringW(Buffer);#endif
return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::CreatePinHandle( PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt){ PKSPIN_CONNECT PinConnect; PKSDATAFORMAT DataFormat; ULONG Length; HRESULT hr; HANDLE hFilter; IKsObject * KsObjectParent;
//KSALLOCATOR_FRAMING Framing; //KSPROPERTY Property; //ULONG BytesReturned;
OutputDebugStringW(L"COutputPin::CreatePinHandle\n");
if (m_hPin != INVALID_HANDLE_VALUE) { // pin already exists //CloseHandle(m_hPin); //m_hPin = INVALID_HANDLE_VALUE; OutputDebugStringW(L"COutputPin::CreatePinHandle pin already exists\n"); return S_OK; }
// calc format size Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
// allocate pin connect PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length); if (!PinConnect) { // failed OutputDebugStringW(L"COutputPin::CreatePinHandle out of memory\n"); return E_OUTOFMEMORY; } OutputDebugStringW(L"COutputPin::CreatePinHandle copy pinconnect\n"); // setup request CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE)); CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM)); PinConnect->PinId = m_PinId; PinConnect->PinToHandle = NULL; PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
// get dataformat offset DataFormat = (PKSDATAFORMAT)(PinConnect + 1); OutputDebugStringW(L"COutputPin::CreatePinHandle copy format\n"); // copy data format DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat; DataFormat->Flags = 0; DataFormat->SampleSize = pmt->lSampleSize; DataFormat->Reserved = 0; CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID)); CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID)); CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
if (pmt->cbFormat) { // copy extended format WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePinHandle copy format %p pbFormat %lu\n", pmt, pmt->cbFormat); OutputDebugStringW(Buffer); CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat); }
// get IKsObject interface hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); if (FAILED(hr)) { OutputDebugStringW(L"COutputPin::CreatePinHandle no IID_IKsObject interface\n"); return hr; }
// get parent filter handle hFilter = KsObjectParent->KsGetObjectHandle();
// release IKsObject KsObjectParent->Release();
if (!hFilter) { OutputDebugStringW(L"COutputPin::CreatePinHandle no filter handle\n"); return E_HANDLE; }
OutputDebugStringW(L"COutputPin::CreatePinHandle before creating pin\n"); // create pin DWORD dwError = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin);
if (dwError == ERROR_SUCCESS) { OutputDebugStringW(L"COutputPin::CreatePinHandle created pin\n");
// store current interface / medium CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM)); CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE)); CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE));
#ifdef KSPROXY_TRACE LPOLESTR pMajor, pSub, pFormat; StringFromIID(m_MediaFormat.majortype, &pMajor); StringFromIID(m_MediaFormat.subtype , &pSub); StringFromIID(m_MediaFormat.formattype, &pFormat); WCHAR Buffer[200]; swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat); CoTaskMemFree(pMajor); CoTaskMemFree(pSub); CoTaskMemFree(pFormat); OutputDebugStringW(Buffer);#endif
if (pmt->cbFormat) { m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat); if (!m_MediaFormat.pbFormat) { CoTaskMemFree(PinConnect); m_MediaFormat.pbFormat = NULL; m_MediaFormat.cbFormat = 0; return E_OUTOFMEMORY; } CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat); }#if 0 Property.Set = KSPROPSETID_Connection; Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; Property.Flags = KSPROPERTY_TYPE_GET;
ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING)); hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); if (SUCCEEDED(hr)) { m_Properties.cbAlign = (Framing.FileAlignment + 1); m_Properties.cbBuffer = Framing.FrameSize; m_Properties.cbPrefix = 0; //FIXME m_Properties.cBuffers = Framing.Frames; } hr = S_OK;#endif
if (FAILED(InitializeIOThread())) { OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n"); }
//TODO // connect pin pipes
} else OutputDebugStringW(L"COutputPin::CreatePinHandle failed to create pin\n"); // free pin connect CoTaskMemFree(PinConnect);
return hr;}
HRESULTSTDMETHODCALLTYPECOutputPin::GetSupportedSets( LPGUID * pOutGuid, PULONG NumGuids){ KSPROPERTY Property; LPGUID pGuid; ULONG NumProperty = 0; ULONG NumMethods = 0; ULONG NumEvents = 0; ULONG Length; ULONG BytesReturned; HRESULT hr;
Property.Set = GUID_NULL; Property.Id = 0; Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty); KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods); KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents);
Length = NumProperty + NumMethods + NumEvents;
assert(Length);
// allocate guid buffer pGuid = (LPGUID)CoTaskMemAlloc(Length); if (!pGuid) { // failed return E_OUTOFMEMORY; }
NumProperty /= sizeof(GUID); NumMethods /= sizeof(GUID); NumEvents /= sizeof(GUID);
// get all properties hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned); if (FAILED(hr)) { CoTaskMemFree(pGuid); return E_FAIL; } Length -= BytesReturned;
// get all methods if (Length && NumMethods) { hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned); if (FAILED(hr)) { CoTaskMemFree(pGuid); return E_FAIL; } Length -= BytesReturned; }
// get all events if (Length && NumEvents) { hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned); if (FAILED(hr)) { CoTaskMemFree(pGuid); return E_FAIL; } Length -= BytesReturned; }
#ifdef KSPROXY_TRACE WCHAR Buffer[200]; swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents); OutputDebugStringW(Buffer);#endif
*pOutGuid = pGuid; *NumGuids = NumProperty+NumEvents+NumMethods; return S_OK;}
HRESULTSTDMETHODCALLTYPECOutputPin::LoadProxyPlugins( LPGUID pGuids, ULONG NumGuids){ ULONG Index; LPOLESTR pStr; HKEY hKey, hSubKey; HRESULT hr; IUnknown * pUnknown;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS) { OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n"); return E_FAIL; }
// enumerate all sets for(Index = 0; Index < NumGuids; Index++) { // convert to string hr = StringFromCLSID(pGuids[Index], &pStr); if (FAILED(hr)) return E_FAIL;
// now try open class key if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) { // no plugin for that set exists CoTaskMemFree(pStr); continue; }
// try load plugin hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown); if (SUCCEEDED(hr)) { // store plugin m_Plugins.push_back(pUnknown); } // close key RegCloseKey(hSubKey); }
// close media interfaces key RegCloseKey(hKey); return S_OK;}
HRESULTWINAPICOutputPin::IoProcessRoutine(){ IMediaSample *Sample; LONG SampleCount; HRESULT hr; PKSSTREAM_SEGMENT * StreamSegment; HANDLE hEvent; IMediaSample ** Samples; LONG NumHandles; DWORD dwStatus;
#ifdef KSPROXY_TRACE WCHAR Buffer[200];#endif
NumHandles = m_Properties.cBuffers / 2;
if (!NumHandles) NumHandles = 8;
assert(NumHandles);
//allocate stream segment array StreamSegment = (PKSSTREAM_SEGMENT*)CoTaskMemAlloc(sizeof(PVOID) * NumHandles); if (!StreamSegment) { OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n"); return E_FAIL; }
// allocate handle array Samples = (IMediaSample**)CoTaskMemAlloc(sizeof(IMediaSample*) * NumHandles); if (!Samples) { OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n"); return E_FAIL; }
// zero handles array ZeroMemory(StreamSegment, sizeof(PVOID) * NumHandles); ZeroMemory(Samples, sizeof(IMediaSample*) * NumHandles);
// first wait for the start event to signal WaitForSingleObject(m_hStartEvent, INFINITE);
m_IoCount = 0;
assert(m_InterfaceHandler); do { if (m_StopInProgress) { // stop io thread break; }
assert(m_State == KSSTATE_RUN); assert(m_MemAllocator);
// get buffer hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT);
if (FAILED(hr)) { WaitForSingleObject(m_hBufferAvailable, INFINITE); // now retry again continue; }
// fill buffer SampleCount = 1; Samples[m_IoCount] = Sample;
Sample->SetTime(NULL, NULL); hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */ &Samples[m_IoCount], &SampleCount, KsIoOperation_Read, &StreamSegment[m_IoCount]); if (FAILED(hr) || !StreamSegment) {#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr); OutputDebugStringW(Buffer);#endif break; }
// interface handle should increment pending i/o count assert(m_IoCount >= 1);
swprintf(Buffer, L"COutputPin::IoProcessRoutine m_IoCount %lu NumHandles %lu\n", m_IoCount, NumHandles); OutputDebugStringW(Buffer);
if (m_IoCount != NumHandles) continue;
// get completion handle hEvent = StreamSegment[0]->CompletionEvent;
// wait for i/o completion dwStatus = WaitForSingleObject(hEvent, INFINITE);
swprintf(Buffer, L"COutputPin::IoProcessRoutine dwStatus %lx Error %lx NumHandles %lu\n", dwStatus, GetLastError(), NumHandles); OutputDebugStringW(Buffer);
// perform completion m_InterfaceHandler->KsCompleteIo(StreamSegment[0]);
// close completion event CloseHandle(hEvent);
if (SUCCEEDED(hr)) { assert(m_MemInputPin);
// now deliver the sample hr = m_MemInputPin->Receive(Samples[0]);
#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator); OutputDebugStringW(Buffer);#endif
if (FAILED(hr)) break;
Sample = NULL; }
//circular stream segment array RtlMoveMemory(StreamSegment, &StreamSegment[1], sizeof(PVOID) * (NumHandles - 1)); RtlMoveMemory(Samples, &Samples[1], sizeof(IMediaSample*) * (NumHandles - 1));
}while(TRUE);
// signal end of i/o thread SetEvent(m_hStopEvent);
m_IoThreadStarted = false;
return NOERROR;}
DWORDWINAPICOutputPin_IoThreadStartup( LPVOID lpParameter){ COutputPin * Pin = (COutputPin*)lpParameter; assert(Pin);
return Pin->IoProcessRoutine();}
HRESULTWINAPICOutputPin::InitializeIOThread(){ HANDLE hThread;
if (m_IoThreadStarted) return NOERROR;
if (!m_hStartEvent) m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!m_hStartEvent) return E_OUTOFMEMORY;
if (!m_hStopEvent) m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!m_hStopEvent) return E_OUTOFMEMORY;
if (!m_hBufferAvailable) m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!m_hBufferAvailable) return E_OUTOFMEMORY;
m_StopInProgress = false; m_IoThreadStarted = true;
// now create the startup thread hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL); if (!hThread) return E_OUTOFMEMORY;
// close thread handle CloseHandle(hThread); return NOERROR;}
HRESULTSTDMETHODCALLTYPECOutputPin_SetState( IPin * Pin, KSSTATE State){ HRESULT hr = S_OK; KSPROPERTY Property; KSSTATE CurState; ULONG BytesReturned; COutputPin * pPin = (COutputPin*)Pin;
#ifdef KSPROXY_TRACE WCHAR Buffer[200];#endif
Property.Set = KSPROPSETID_Connection; Property.Id = KSPROPERTY_CONNECTION_STATE; Property.Flags = KSPROPERTY_TYPE_SET;
EnterCriticalSection(&pPin->m_Lock);
if (pPin->m_State <= State) { if (pPin->m_State == KSSTATE_STOP) { hr = pPin->InitializeIOThread(); if (FAILED(hr)) { // failed to initialize I/O thread#ifdef KSPROXY_TRACE OutputDebugStringW(L"Failed to initialize I/O Thread\n");#endif LeaveCriticalSection(&pPin->m_Lock); return hr; } CurState = KSSTATE_ACQUIRE; hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_STOP KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); OutputDebugStringW(Buffer);#endif
if (FAILED(hr)) { LeaveCriticalSection(&pPin->m_Lock); return hr; }
pPin->m_State = CurState;
if (pPin->m_State == State) { LeaveCriticalSection(&pPin->m_Lock); return hr; } } if (pPin->m_State == KSSTATE_ACQUIRE) { CurState = KSSTATE_PAUSE; hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin_SetState Setting State CurState KSSTATE_ACQUIRE KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); OutputDebugStringW(Buffer);#endif
if (FAILED(hr)) { LeaveCriticalSection(&pPin->m_Lock); return hr; }
pPin->m_State = CurState;
if (pPin->m_State == State) { LeaveCriticalSection(&pPin->m_Lock); return hr; } } if (State == KSSTATE_RUN && pPin->m_State == KSSTATE_PAUSE) { CurState = KSSTATE_RUN; hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr); OutputDebugStringW(Buffer);#endif
if (SUCCEEDED(hr)) { pPin->m_State = CurState; // signal start event SetEvent(pPin->m_hStartEvent); } }
LeaveCriticalSection(&pPin->m_Lock); return hr; } else { if (pPin->m_State == KSSTATE_RUN) { // setting pending stop flag pPin->m_StopInProgress = true;
// release any waiting threads SetEvent(pPin->m_hBufferAvailable);
// wait until i/o thread is done WaitForSingleObject(pPin->m_hStopEvent, INFINITE);
CurState = KSSTATE_PAUSE; hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_RUN KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); OutputDebugStringW(Buffer);#endif
if (FAILED(hr)) { LeaveCriticalSection(&pPin->m_Lock); return hr; }
pPin->m_State = CurState;
if (FAILED(hr)) { LeaveCriticalSection(&pPin->m_Lock); return hr; } } if (pPin->m_State == KSSTATE_PAUSE) { CurState = KSSTATE_ACQUIRE; hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); OutputDebugStringW(Buffer);#endif
if (FAILED(hr)) { LeaveCriticalSection(&pPin->m_Lock); return hr; }
pPin->m_State = CurState;
if (pPin->m_State == State) { LeaveCriticalSection(&pPin->m_Lock); return hr; } }
CloseHandle(pPin->m_hStopEvent); CloseHandle(pPin->m_hStartEvent); CloseHandle(pPin->m_hBufferAvailable);
/* close event handles */ pPin->m_hStopEvent = NULL; pPin->m_hStartEvent = NULL; pPin->m_hBufferAvailable = NULL;
CurState = KSSTATE_STOP; hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned);
#ifdef KSPROXY_TRACE swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_ACQUIRE KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr); OutputDebugStringW(Buffer);#endif
if (SUCCEEDED(hr)) { // store state pPin->m_State = CurState; }
// unset pending stop flag pPin->m_StopInProgress = false;
LeaveCriticalSection(&pPin->m_Lock); return hr; }}
HRESULTWINAPICOutputPin_Constructor( IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication, REFIID riid, LPVOID * ppv){ COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication);
if (!handler) return E_OUTOFMEMORY;
if (FAILED(handler->QueryInterface(riid, ppv))) { /* not supported */ delete handler; return E_NOINTERFACE; }
return S_OK;}