Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenoutput_pin.cpp
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy 00004 * FILE: dll/directx/ksproxy/output_pin.cpp 00005 * PURPOSE: OutputPin of Proxy Filter 00006 * 00007 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) 00008 */ 00009 #include "precomp.h" 00010 00011 class COutputPin : public IPin, 00012 public IKsObject, 00013 public IKsPropertySet, 00014 public IStreamBuilder, 00015 public IKsPinFactory, 00016 public ISpecifyPropertyPages, 00017 public IKsPinEx, 00018 public IKsPinPipe, 00019 public IKsControl, 00020 public IKsAggregateControl, 00021 public IQualityControl, 00022 public IMediaSeeking, 00023 public IAMBufferNegotiation, 00024 public IAMStreamConfig, 00025 public IMemAllocatorNotifyCallbackTemp 00026 00027 { 00028 public: 00029 typedef std::vector<IUnknown *>ProxyPluginVector; 00030 00031 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 00032 00033 STDMETHODIMP_(ULONG) AddRef() 00034 { 00035 InterlockedIncrement(&m_Ref); 00036 return m_Ref; 00037 } 00038 STDMETHODIMP_(ULONG) Release() 00039 { 00040 InterlockedDecrement(&m_Ref); 00041 if (!m_Ref) 00042 { 00043 //delete this; 00044 return 0; 00045 } 00046 return m_Ref; 00047 } 00048 00049 //IKsPin 00050 HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList); 00051 HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList); 00052 HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium); 00053 HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium); 00054 HRESULT STDMETHODCALLTYPE KsPropagateAcquire(); 00055 HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags); 00056 HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment); 00057 IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation); 00058 HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator); 00059 HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator(); 00060 LONG STDMETHODCALLTYPE KsIncrementPendingIoCount(); 00061 LONG STDMETHODCALLTYPE KsDecrementPendingIoCount(); 00062 HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta); 00063 // IKsPinEx 00064 VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr); 00065 00066 //IKsPinPipe 00067 HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option); 00068 HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option); 00069 IPin* STDMETHODCALLTYPE KsGetConnectedPin(); 00070 IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation); 00071 HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator); 00072 ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag(); 00073 HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag); 00074 GUID STDMETHODCALLTYPE KsGetPinBusCache(); 00075 HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus); 00076 PWCHAR STDMETHODCALLTYPE KsGetPinName(); 00077 PWCHAR STDMETHODCALLTYPE KsGetFilterName(); 00078 00079 //IPin methods 00080 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); 00081 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); 00082 HRESULT STDMETHODCALLTYPE Disconnect(); 00083 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin); 00084 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt); 00085 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo); 00086 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); 00087 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id); 00088 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt); 00089 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum); 00090 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin); 00091 HRESULT STDMETHODCALLTYPE EndOfStream(); 00092 HRESULT STDMETHODCALLTYPE BeginFlush(); 00093 HRESULT STDMETHODCALLTYPE EndFlush(); 00094 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); 00095 00096 // ISpecifyPropertyPages 00097 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages); 00098 00099 //IKsObject methods 00100 HANDLE STDMETHODCALLTYPE KsGetObjectHandle(); 00101 00102 //IKsPropertySet 00103 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData); 00104 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned); 00105 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport); 00106 00107 //IKsControl 00108 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned); 00109 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned); 00110 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned); 00111 00112 //IStreamBuilder 00113 HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph); 00114 HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph); 00115 00116 //IKsPinFactory 00117 HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory); 00118 00119 //IKsAggregateControl 00120 HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass); 00121 HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass); 00122 00123 //IQualityControl 00124 HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q); 00125 HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc); 00126 00127 //IMediaSeeking 00128 HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities); 00129 HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities); 00130 HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat); 00131 HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat); 00132 HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat); 00133 HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat); 00134 HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat); 00135 HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration); 00136 HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop); 00137 HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent); 00138 HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat); 00139 HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags); 00140 HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop); 00141 HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest); 00142 HRESULT STDMETHODCALLTYPE SetRate(double dRate); 00143 HRESULT STDMETHODCALLTYPE GetRate(double *pdRate); 00144 HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll); 00145 00146 //IAMBufferNegotiation 00147 HRESULT STDMETHODCALLTYPE SuggestAllocatorProperties(const ALLOCATOR_PROPERTIES *pprop); 00148 HRESULT STDMETHODCALLTYPE GetAllocatorProperties(ALLOCATOR_PROPERTIES *pprop); 00149 00150 //IAMStreamConfig 00151 HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt); 00152 HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt); 00153 HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize); 00154 HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **ppmt, BYTE *pSCC); 00155 00156 //IMemAllocatorNotifyCallbackTemp 00157 HRESULT STDMETHODCALLTYPE NotifyRelease(); 00158 00159 //--------------------------------------------------------------- 00160 COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication); 00161 virtual ~COutputPin(); 00162 HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt); 00163 HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt); 00164 HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt); 00165 HRESULT WINAPI IoProcessRoutine(); 00166 HRESULT WINAPI InitializeIOThread(); 00167 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids); 00168 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids); 00169 00170 friend DWORD WINAPI COutputPin_IoThreadStartup(LPVOID lpParameter); 00171 friend HRESULT STDMETHODCALLTYPE COutputPin_SetState(IPin * Pin, KSSTATE State); 00172 00173 protected: 00174 LONG m_Ref; 00175 IBaseFilter * m_ParentFilter; 00176 LPCWSTR m_PinName; 00177 HANDLE m_hPin; 00178 ULONG m_PinId; 00179 IPin * m_Pin; 00180 IKsAllocatorEx * m_KsAllocatorEx; 00181 ULONG m_PipeAllocatorFlag; 00182 BOOL m_bPinBusCacheInitialized; 00183 GUID m_PinBusCache; 00184 LPWSTR m_FilterName; 00185 FRAMING_PROP m_FramingProp[4]; 00186 PKSALLOCATOR_FRAMING_EX m_FramingEx[4]; 00187 00188 IMemAllocator * m_MemAllocator; 00189 IMemInputPin * m_MemInputPin; 00190 LONG m_IoCount; 00191 KSPIN_COMMUNICATION m_Communication; 00192 KSPIN_INTERFACE m_Interface; 00193 KSPIN_MEDIUM m_Medium; 00194 AM_MEDIA_TYPE m_MediaFormat; 00195 ALLOCATOR_PROPERTIES m_Properties; 00196 IKsInterfaceHandler * m_InterfaceHandler; 00197 00198 HANDLE m_hStartEvent; 00199 HANDLE m_hBufferAvailable; 00200 HANDLE m_hStopEvent; 00201 BOOL m_StopInProgress; 00202 BOOL m_IoThreadStarted; 00203 00204 KSSTATE m_State; 00205 CRITICAL_SECTION m_Lock; 00206 00207 ProxyPluginVector m_Plugins; 00208 }; 00209 00210 COutputPin::~COutputPin() 00211 { 00212 } 00213 00214 COutputPin::COutputPin( 00215 IBaseFilter * ParentFilter, 00216 LPCWSTR PinName, 00217 ULONG PinId, 00218 KSPIN_COMMUNICATION Communication) : m_Ref(0), 00219 m_ParentFilter(ParentFilter), 00220 m_PinName(PinName), 00221 m_hPin(INVALID_HANDLE_VALUE), 00222 m_PinId(PinId), 00223 m_Pin(0), 00224 m_KsAllocatorEx(0), 00225 m_PipeAllocatorFlag(0), 00226 m_bPinBusCacheInitialized(0), 00227 m_FilterName(0), 00228 m_MemAllocator(0), 00229 m_MemInputPin(0), 00230 m_IoCount(0), 00231 m_Communication(Communication), 00232 m_InterfaceHandler(0), 00233 m_hStartEvent(0), 00234 m_hBufferAvailable(0), 00235 m_hStopEvent(0), 00236 m_StopInProgress(0), 00237 m_IoThreadStarted(0), 00238 m_State(KSSTATE_STOP), 00239 m_Plugins() 00240 { 00241 HRESULT hr; 00242 IKsObject * KsObjectParent; 00243 00244 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 00245 assert(hr == S_OK); 00246 00247 ZeroMemory(m_FramingProp, sizeof(m_FramingProp)); 00248 ZeroMemory(m_FramingEx, sizeof(m_FramingEx)); 00249 ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE)); 00250 00251 hr = KsGetMediaType(0, &m_MediaFormat, KsObjectParent->KsGetObjectHandle(), m_PinId); 00252 00253 #ifdef KSPROXY_TRACE 00254 WCHAR Buffer[100]; 00255 swprintf(Buffer, L"COutputPin::COutputPin Format %p pbFormat %lu\n", &m_MediaFormat, m_MediaFormat.cbFormat); 00256 OutputDebugStringW(Buffer); 00257 #endif 00258 00259 assert(hr == S_OK); 00260 00261 InitializeCriticalSection(&m_Lock); 00262 00263 KsObjectParent->Release(); 00264 }; 00265 00266 HRESULT 00267 STDMETHODCALLTYPE 00268 COutputPin::QueryInterface( 00269 IN REFIID refiid, 00270 OUT PVOID* Output) 00271 { 00272 *Output = NULL; 00273 if (IsEqualGUID(refiid, IID_IUnknown) || 00274 IsEqualGUID(refiid, IID_IPin)) 00275 { 00276 #ifdef KSPROXY_TRACE 00277 OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n"); 00278 #endif 00279 *Output = PVOID(this); 00280 reinterpret_cast<IUnknown*>(*Output)->AddRef(); 00281 return NOERROR; 00282 } 00283 else if (IsEqualGUID(refiid, IID_IKsObject)) 00284 { 00285 if (m_hPin == INVALID_HANDLE_VALUE) 00286 { 00287 HRESULT hr = CreatePin(&m_MediaFormat); 00288 if (FAILED(hr)) 00289 return hr; 00290 } 00291 #ifdef KSPROXY_TRACE 00292 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n"); 00293 #endif 00294 *Output = (IKsObject*)(this); 00295 reinterpret_cast<IKsObject*>(*Output)->AddRef(); 00296 return NOERROR; 00297 } 00298 else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx)) 00299 { 00300 *Output = (IKsPinEx*)(this); 00301 reinterpret_cast<IKsPinEx*>(*Output)->AddRef(); 00302 return NOERROR; 00303 } 00304 else if (IsEqualGUID(refiid, IID_IKsPinPipe)) 00305 { 00306 *Output = (IKsPinPipe*)(this); 00307 reinterpret_cast<IKsPinPipe*>(*Output)->AddRef(); 00308 return NOERROR; 00309 } 00310 else if (IsEqualGUID(refiid, IID_IKsAggregateControl)) 00311 { 00312 *Output = (IKsAggregateControl*)(this); 00313 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef(); 00314 return NOERROR; 00315 } 00316 else if (IsEqualGUID(refiid, IID_IQualityControl)) 00317 { 00318 *Output = (IQualityControl*)(this); 00319 reinterpret_cast<IQualityControl*>(*Output)->AddRef(); 00320 return NOERROR; 00321 } 00322 else if (IsEqualGUID(refiid, IID_IKsPropertySet)) 00323 { 00324 if (m_hPin == INVALID_HANDLE_VALUE) 00325 { 00326 HRESULT hr = CreatePin(&m_MediaFormat); 00327 if (FAILED(hr)) 00328 return hr; 00329 } 00330 #ifdef KSPROXY_TRACE 00331 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n"); 00332 #endif 00333 *Output = (IKsPropertySet*)(this); 00334 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef(); 00335 return NOERROR; 00336 } 00337 else if (IsEqualGUID(refiid, IID_IKsControl)) 00338 { 00339 #ifdef KSPROXY_TRACE 00340 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n"); 00341 #endif 00342 *Output = (IKsControl*)(this); 00343 reinterpret_cast<IKsControl*>(*Output)->AddRef(); 00344 return NOERROR; 00345 } 00346 #if 0 00347 else if (IsEqualGUID(refiid, IID_IStreamBuilder)) 00348 { 00349 *Output = (IStreamBuilder*)(this); 00350 reinterpret_cast<IStreamBuilder*>(*Output)->AddRef(); 00351 return NOERROR; 00352 } 00353 #endif 00354 else if (IsEqualGUID(refiid, IID_IKsPinFactory)) 00355 { 00356 #ifdef KSPROXY_TRACE 00357 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n"); 00358 #endif 00359 *Output = (IKsPinFactory*)(this); 00360 reinterpret_cast<IKsPinFactory*>(*Output)->AddRef(); 00361 return NOERROR; 00362 } 00363 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) 00364 { 00365 #ifdef KSPROXY_TRACE 00366 OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n"); 00367 #endif 00368 *Output = (ISpecifyPropertyPages*)(this); 00369 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef(); 00370 return NOERROR; 00371 } 00372 else if (IsEqualGUID(refiid, IID_IMediaSeeking)) 00373 { 00374 *Output = (IMediaSeeking*)(this); 00375 reinterpret_cast<IMediaSeeking*>(*Output)->AddRef(); 00376 return NOERROR; 00377 } 00378 else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation)) 00379 { 00380 *Output = (IAMBufferNegotiation*)(this); 00381 reinterpret_cast<IAMBufferNegotiation*>(*Output)->AddRef(); 00382 return NOERROR; 00383 } 00384 else if (IsEqualGUID(refiid, IID_IAMStreamConfig)) 00385 { 00386 *Output = (IAMStreamConfig*)(this); 00387 reinterpret_cast<IAMStreamConfig*>(*Output)->AddRef(); 00388 return NOERROR; 00389 } 00390 else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp)) 00391 { 00392 *Output = (IMemAllocatorNotifyCallbackTemp*)(this); 00393 reinterpret_cast<IMemAllocatorNotifyCallbackTemp*>(*Output)->AddRef(); 00394 return NOERROR; 00395 } 00396 00397 #ifdef KSPROXY_TRACE 00398 WCHAR Buffer[MAX_PATH]; 00399 LPOLESTR lpstr; 00400 StringFromCLSID(refiid, &lpstr); 00401 swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s PinId %u PinName %s\n", lpstr, m_PinId, m_PinName); 00402 OutputDebugStringW(Buffer); 00403 CoTaskMemFree(lpstr); 00404 #endif 00405 00406 return E_NOINTERFACE; 00407 } 00408 00409 //------------------------------------------------------------------- 00410 // IAMBufferNegotiation interface 00411 // 00412 HRESULT 00413 STDMETHODCALLTYPE 00414 COutputPin::SuggestAllocatorProperties( 00415 const ALLOCATOR_PROPERTIES *pprop) 00416 { 00417 #ifdef KSPROXY_TRACE 00418 OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties\n"); 00419 #endif 00420 00421 if (m_Pin) 00422 { 00423 // pin is already connected 00424 return VFW_E_ALREADY_CONNECTED; 00425 } 00426 00427 CopyMemory(&m_Properties, pprop, sizeof(ALLOCATOR_PROPERTIES)); 00428 return NOERROR; 00429 } 00430 00431 HRESULT 00432 STDMETHODCALLTYPE 00433 COutputPin::GetAllocatorProperties( 00434 ALLOCATOR_PROPERTIES *pprop) 00435 { 00436 #ifdef KSPROXY_TRACE 00437 OutputDebugStringW(L"COutputPin::GetAllocatorProperties\n"); 00438 #endif 00439 00440 if (!m_Pin) 00441 { 00442 // you should call this method AFTER you connected 00443 return E_UNEXPECTED; 00444 } 00445 00446 if (!m_KsAllocatorEx) 00447 { 00448 // something went wrong while creating the allocator 00449 return E_FAIL; 00450 } 00451 00452 CopyMemory(pprop, &m_Properties, sizeof(ALLOCATOR_PROPERTIES)); 00453 return NOERROR; 00454 } 00455 00456 //------------------------------------------------------------------- 00457 // IAMStreamConfig interface 00458 // 00459 HRESULT 00460 STDMETHODCALLTYPE 00461 COutputPin::SetFormat( 00462 AM_MEDIA_TYPE *pmt) 00463 { 00464 #ifdef KSPROXY_TRACE 00465 OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n"); 00466 #endif 00467 return E_NOTIMPL; 00468 } 00469 00470 HRESULT 00471 STDMETHODCALLTYPE 00472 COutputPin::GetFormat(AM_MEDIA_TYPE **ppmt) 00473 { 00474 #ifdef KSPROXY_TRACE 00475 OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n"); 00476 #endif 00477 return E_NOTIMPL; 00478 } 00479 00480 HRESULT 00481 STDMETHODCALLTYPE 00482 COutputPin::GetNumberOfCapabilities( 00483 int *piCount, 00484 int *piSize) 00485 { 00486 #ifdef KSPROXY_TRACE 00487 OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n"); 00488 #endif 00489 return E_NOTIMPL; 00490 } 00491 00492 HRESULT 00493 STDMETHODCALLTYPE 00494 COutputPin::GetStreamCaps( 00495 int iIndex, 00496 AM_MEDIA_TYPE **ppmt, 00497 BYTE *pSCC) 00498 { 00499 #ifdef KSPROXY_TRACE 00500 OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n"); 00501 #endif 00502 return E_NOTIMPL; 00503 } 00504 00505 //------------------------------------------------------------------- 00506 // IMemAllocatorNotifyCallbackTemp interface 00507 // 00508 HRESULT 00509 STDMETHODCALLTYPE 00510 COutputPin::NotifyRelease() 00511 { 00512 #ifdef KSPROXY_TRACE 00513 OutputDebugStringW(L"COutputPin::NotifyRelease\n"); 00514 #endif 00515 00516 // notify thread of new available sample 00517 SetEvent(m_hBufferAvailable); 00518 00519 return NOERROR; 00520 } 00521 00522 //------------------------------------------------------------------- 00523 // IMediaSeeking interface 00524 // 00525 HRESULT 00526 STDMETHODCALLTYPE 00527 COutputPin::GetCapabilities( 00528 DWORD *pCapabilities) 00529 { 00530 IMediaSeeking * FilterMediaSeeking; 00531 HRESULT hr; 00532 00533 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00534 if (FAILED(hr)) 00535 return hr; 00536 00537 hr = FilterMediaSeeking->GetCapabilities(pCapabilities); 00538 00539 FilterMediaSeeking->Release(); 00540 return hr; 00541 } 00542 00543 HRESULT 00544 STDMETHODCALLTYPE 00545 COutputPin::CheckCapabilities( 00546 DWORD *pCapabilities) 00547 { 00548 IMediaSeeking * FilterMediaSeeking; 00549 HRESULT hr; 00550 00551 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00552 if (FAILED(hr)) 00553 return hr; 00554 00555 hr = FilterMediaSeeking->CheckCapabilities(pCapabilities); 00556 00557 FilterMediaSeeking->Release(); 00558 return hr; 00559 } 00560 00561 HRESULT 00562 STDMETHODCALLTYPE 00563 COutputPin::IsFormatSupported( 00564 const GUID *pFormat) 00565 { 00566 IMediaSeeking * FilterMediaSeeking; 00567 HRESULT hr; 00568 00569 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00570 if (FAILED(hr)) 00571 return hr; 00572 00573 hr = FilterMediaSeeking->IsFormatSupported(pFormat); 00574 00575 FilterMediaSeeking->Release(); 00576 return hr; 00577 } 00578 00579 HRESULT 00580 STDMETHODCALLTYPE 00581 COutputPin::QueryPreferredFormat( 00582 GUID *pFormat) 00583 { 00584 IMediaSeeking * FilterMediaSeeking; 00585 HRESULT hr; 00586 00587 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00588 if (FAILED(hr)) 00589 return hr; 00590 00591 hr = FilterMediaSeeking->QueryPreferredFormat(pFormat); 00592 00593 FilterMediaSeeking->Release(); 00594 return hr; 00595 } 00596 00597 HRESULT 00598 STDMETHODCALLTYPE 00599 COutputPin::GetTimeFormat( 00600 GUID *pFormat) 00601 { 00602 IMediaSeeking * FilterMediaSeeking; 00603 HRESULT hr; 00604 00605 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00606 if (FAILED(hr)) 00607 return hr; 00608 00609 hr = FilterMediaSeeking->GetTimeFormat(pFormat); 00610 00611 FilterMediaSeeking->Release(); 00612 return hr; 00613 } 00614 00615 HRESULT 00616 STDMETHODCALLTYPE 00617 COutputPin::IsUsingTimeFormat( 00618 const GUID *pFormat) 00619 { 00620 IMediaSeeking * FilterMediaSeeking; 00621 HRESULT hr; 00622 00623 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00624 if (FAILED(hr)) 00625 return hr; 00626 00627 hr = FilterMediaSeeking->IsUsingTimeFormat(pFormat); 00628 00629 FilterMediaSeeking->Release(); 00630 return hr; 00631 } 00632 00633 HRESULT 00634 STDMETHODCALLTYPE 00635 COutputPin::SetTimeFormat( 00636 const GUID *pFormat) 00637 { 00638 IMediaSeeking * FilterMediaSeeking; 00639 HRESULT hr; 00640 00641 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00642 if (FAILED(hr)) 00643 return hr; 00644 00645 hr = FilterMediaSeeking->SetTimeFormat(pFormat); 00646 00647 FilterMediaSeeking->Release(); 00648 return hr; 00649 } 00650 00651 HRESULT 00652 STDMETHODCALLTYPE 00653 COutputPin::GetDuration( 00654 LONGLONG *pDuration) 00655 { 00656 IMediaSeeking * FilterMediaSeeking; 00657 HRESULT hr; 00658 00659 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00660 if (FAILED(hr)) 00661 return hr; 00662 00663 hr = FilterMediaSeeking->GetDuration(pDuration); 00664 00665 FilterMediaSeeking->Release(); 00666 return hr; 00667 } 00668 00669 HRESULT 00670 STDMETHODCALLTYPE 00671 COutputPin::GetStopPosition( 00672 LONGLONG *pStop) 00673 { 00674 IMediaSeeking * FilterMediaSeeking; 00675 HRESULT hr; 00676 00677 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00678 if (FAILED(hr)) 00679 return hr; 00680 00681 hr = FilterMediaSeeking->GetStopPosition(pStop); 00682 00683 FilterMediaSeeking->Release(); 00684 return hr; 00685 } 00686 00687 00688 HRESULT 00689 STDMETHODCALLTYPE 00690 COutputPin::GetCurrentPosition( 00691 LONGLONG *pCurrent) 00692 { 00693 IMediaSeeking * FilterMediaSeeking; 00694 HRESULT hr; 00695 00696 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00697 if (FAILED(hr)) 00698 return hr; 00699 00700 hr = FilterMediaSeeking->GetCurrentPosition(pCurrent); 00701 00702 FilterMediaSeeking->Release(); 00703 return hr; 00704 } 00705 00706 HRESULT 00707 STDMETHODCALLTYPE 00708 COutputPin::ConvertTimeFormat( 00709 LONGLONG *pTarget, 00710 const GUID *pTargetFormat, 00711 LONGLONG Source, 00712 const GUID *pSourceFormat) 00713 { 00714 IMediaSeeking * FilterMediaSeeking; 00715 HRESULT hr; 00716 00717 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00718 if (FAILED(hr)) 00719 return hr; 00720 00721 hr = FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat); 00722 00723 FilterMediaSeeking->Release(); 00724 return hr; 00725 } 00726 00727 HRESULT 00728 STDMETHODCALLTYPE 00729 COutputPin::SetPositions( 00730 LONGLONG *pCurrent, 00731 DWORD dwCurrentFlags, 00732 LONGLONG *pStop, 00733 DWORD dwStopFlags) 00734 { 00735 IMediaSeeking * FilterMediaSeeking; 00736 HRESULT hr; 00737 00738 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00739 if (FAILED(hr)) 00740 return hr; 00741 00742 hr = FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags); 00743 00744 FilterMediaSeeking->Release(); 00745 return hr; 00746 } 00747 00748 HRESULT 00749 STDMETHODCALLTYPE 00750 COutputPin::GetPositions( 00751 LONGLONG *pCurrent, 00752 LONGLONG *pStop) 00753 { 00754 IMediaSeeking * FilterMediaSeeking; 00755 HRESULT hr; 00756 00757 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00758 if (FAILED(hr)) 00759 return hr; 00760 00761 hr = FilterMediaSeeking->GetPositions(pCurrent, pStop); 00762 00763 FilterMediaSeeking->Release(); 00764 return hr; 00765 } 00766 00767 HRESULT 00768 STDMETHODCALLTYPE 00769 COutputPin::GetAvailable( 00770 LONGLONG *pEarliest, 00771 LONGLONG *pLatest) 00772 { 00773 IMediaSeeking * FilterMediaSeeking; 00774 HRESULT hr; 00775 00776 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00777 if (FAILED(hr)) 00778 return hr; 00779 00780 hr = FilterMediaSeeking->GetAvailable(pEarliest, pLatest); 00781 00782 FilterMediaSeeking->Release(); 00783 return hr; 00784 } 00785 00786 HRESULT 00787 STDMETHODCALLTYPE 00788 COutputPin::SetRate( 00789 double dRate) 00790 { 00791 IMediaSeeking * FilterMediaSeeking; 00792 HRESULT hr; 00793 00794 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00795 if (FAILED(hr)) 00796 return hr; 00797 00798 hr = FilterMediaSeeking->SetRate(dRate); 00799 00800 FilterMediaSeeking->Release(); 00801 return hr; 00802 } 00803 00804 HRESULT 00805 STDMETHODCALLTYPE 00806 COutputPin::GetRate( 00807 double *pdRate) 00808 { 00809 IMediaSeeking * FilterMediaSeeking; 00810 HRESULT hr; 00811 00812 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00813 if (FAILED(hr)) 00814 return hr; 00815 00816 hr = FilterMediaSeeking->GetRate(pdRate); 00817 00818 FilterMediaSeeking->Release(); 00819 return hr; 00820 } 00821 00822 HRESULT 00823 STDMETHODCALLTYPE 00824 COutputPin::GetPreroll( 00825 LONGLONG *pllPreroll) 00826 { 00827 IMediaSeeking * FilterMediaSeeking; 00828 HRESULT hr; 00829 00830 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 00831 if (FAILED(hr)) 00832 return hr; 00833 00834 hr = FilterMediaSeeking->GetPreroll(pllPreroll); 00835 00836 FilterMediaSeeking->Release(); 00837 return hr; 00838 } 00839 00840 //------------------------------------------------------------------- 00841 // IQualityControl interface 00842 // 00843 HRESULT 00844 STDMETHODCALLTYPE 00845 COutputPin::Notify( 00846 IBaseFilter *pSelf, 00847 Quality q) 00848 { 00849 #ifdef KSPROXY_TRACE 00850 OutputDebugStringW(L"COutputPin::Notify NotImplemented\n"); 00851 #endif 00852 return E_NOTIMPL; 00853 } 00854 00855 HRESULT 00856 STDMETHODCALLTYPE 00857 COutputPin::SetSink( 00858 IQualityControl *piqc) 00859 { 00860 #ifdef KSPROXY_TRACE 00861 OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n"); 00862 #endif 00863 return E_NOTIMPL; 00864 } 00865 00866 00867 //------------------------------------------------------------------- 00868 // IKsAggregateControl interface 00869 // 00870 HRESULT 00871 STDMETHODCALLTYPE 00872 COutputPin::KsAddAggregate( 00873 IN REFGUID AggregateClass) 00874 { 00875 #ifdef KSPROXY_TRACE 00876 OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n"); 00877 #endif 00878 return E_NOTIMPL; 00879 } 00880 00881 HRESULT 00882 STDMETHODCALLTYPE 00883 COutputPin::KsRemoveAggregate( 00884 REFGUID AggregateClass) 00885 { 00886 #ifdef KSPROXY_TRACE 00887 OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n"); 00888 #endif 00889 return E_NOTIMPL; 00890 } 00891 00892 00893 //------------------------------------------------------------------- 00894 // IKsPin 00895 // 00896 00897 HRESULT 00898 STDMETHODCALLTYPE 00899 COutputPin::KsQueryMediums( 00900 PKSMULTIPLE_ITEM* MediumList) 00901 { 00902 HRESULT hr; 00903 HANDLE hFilter; 00904 IKsObject * KsObjectParent; 00905 00906 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 00907 if (FAILED(hr)) 00908 return E_NOINTERFACE; 00909 00910 hFilter = KsObjectParent->KsGetObjectHandle(); 00911 00912 if (hFilter) 00913 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList); 00914 else 00915 hr = E_HANDLE; 00916 00917 KsObjectParent->Release(); 00918 00919 return hr; 00920 } 00921 00922 HRESULT 00923 STDMETHODCALLTYPE 00924 COutputPin::KsQueryInterfaces( 00925 PKSMULTIPLE_ITEM* InterfaceList) 00926 { 00927 HRESULT hr; 00928 HANDLE hFilter; 00929 IKsObject * KsObjectParent; 00930 00931 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 00932 if (FAILED(hr)) 00933 return hr; 00934 00935 hFilter = KsObjectParent->KsGetObjectHandle(); 00936 00937 if (hFilter) 00938 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList); 00939 else 00940 hr = E_HANDLE; 00941 00942 KsObjectParent->Release(); 00943 00944 return hr; 00945 } 00946 00947 HRESULT 00948 STDMETHODCALLTYPE 00949 COutputPin::KsCreateSinkPinHandle( 00950 KSPIN_INTERFACE& Interface, 00951 KSPIN_MEDIUM& Medium) 00952 { 00953 #ifdef KSPROXY_TRACE 00954 OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n"); 00955 #endif 00956 return E_NOTIMPL; 00957 } 00958 00959 HRESULT 00960 STDMETHODCALLTYPE 00961 COutputPin::KsGetCurrentCommunication( 00962 KSPIN_COMMUNICATION *Communication, 00963 KSPIN_INTERFACE *Interface, 00964 KSPIN_MEDIUM *Medium) 00965 { 00966 if (Communication) 00967 { 00968 *Communication = m_Communication; 00969 } 00970 00971 if (Interface) 00972 { 00973 if (!m_hPin) 00974 return VFW_E_NOT_CONNECTED; 00975 00976 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE)); 00977 } 00978 00979 if (Medium) 00980 { 00981 if (!m_hPin) 00982 return VFW_E_NOT_CONNECTED; 00983 00984 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM)); 00985 } 00986 return NOERROR; 00987 } 00988 00989 HRESULT 00990 STDMETHODCALLTYPE 00991 COutputPin::KsPropagateAcquire() 00992 { 00993 KSPROPERTY Property; 00994 KSSTATE State; 00995 ULONG BytesReturned; 00996 HRESULT hr; 00997 00998 #ifdef KSPROXY_TRACE 00999 OutputDebugStringW(L"COutputPin::KsPropagateAcquire\n"); 01000 #endif 01001 01002 assert(m_hPin != INVALID_HANDLE_VALUE); 01003 01004 Property.Set = KSPROPSETID_Connection; 01005 Property.Id = KSPROPERTY_CONNECTION_STATE; 01006 Property.Flags = KSPROPERTY_TYPE_SET; 01007 01008 State = KSSTATE_ACQUIRE; 01009 01010 hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned); 01011 if (SUCCEEDED(hr)) 01012 { 01013 m_State = State; 01014 } 01015 01016 //TODO 01017 //propagate to connected pin on the pipe 01018 01019 return hr; 01020 } 01021 01022 HRESULT 01023 STDMETHODCALLTYPE 01024 COutputPin::KsDeliver( 01025 IMediaSample* Sample, 01026 ULONG Flags) 01027 { 01028 return E_FAIL; 01029 } 01030 01031 HRESULT 01032 STDMETHODCALLTYPE 01033 COutputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment) 01034 { 01035 return NOERROR; 01036 } 01037 01038 IMemAllocator * 01039 STDMETHODCALLTYPE 01040 COutputPin::KsPeekAllocator(KSPEEKOPERATION Operation) 01041 { 01042 if (Operation == KsPeekOperation_AddRef) 01043 { 01044 // add reference on allocator 01045 m_MemAllocator->AddRef(); 01046 } 01047 01048 return m_MemAllocator; 01049 } 01050 01051 HRESULT 01052 STDMETHODCALLTYPE 01053 COutputPin::KsReceiveAllocator(IMemAllocator *MemAllocator) 01054 { 01055 if (MemAllocator) 01056 { 01057 MemAllocator->AddRef(); 01058 } 01059 01060 if (m_MemAllocator) 01061 { 01062 m_MemAllocator->Release(); 01063 } 01064 01065 m_MemAllocator = MemAllocator; 01066 return NOERROR; 01067 } 01068 01069 HRESULT 01070 STDMETHODCALLTYPE 01071 COutputPin::KsRenegotiateAllocator() 01072 { 01073 return E_FAIL; 01074 } 01075 01076 LONG 01077 STDMETHODCALLTYPE 01078 COutputPin::KsIncrementPendingIoCount() 01079 { 01080 return InterlockedIncrement((volatile LONG*)&m_IoCount); 01081 } 01082 01083 LONG 01084 STDMETHODCALLTYPE 01085 COutputPin::KsDecrementPendingIoCount() 01086 { 01087 return InterlockedDecrement((volatile LONG*)&m_IoCount); 01088 } 01089 01090 HRESULT 01091 STDMETHODCALLTYPE 01092 COutputPin::KsQualityNotify( 01093 ULONG Proportion, 01094 REFERENCE_TIME TimeDelta) 01095 { 01096 #ifdef KSPROXY_TRACE 01097 OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n"); 01098 #endif 01099 return E_NOTIMPL; 01100 } 01101 01102 //------------------------------------------------------------------- 01103 // IKsPinEx 01104 // 01105 01106 VOID 01107 STDMETHODCALLTYPE 01108 COutputPin::KsNotifyError( 01109 IMediaSample* Sample, 01110 HRESULT hr) 01111 { 01112 #ifdef KSPROXY_TRACE 01113 OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n"); 01114 #endif 01115 } 01116 01117 01118 //------------------------------------------------------------------- 01119 // IKsPinPipe 01120 // 01121 01122 HRESULT 01123 STDMETHODCALLTYPE 01124 COutputPin::KsGetPinFramingCache( 01125 PKSALLOCATOR_FRAMING_EX *FramingEx, 01126 PFRAMING_PROP FramingProp, 01127 FRAMING_CACHE_OPS Option) 01128 { 01129 if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast) 01130 { 01131 // invalid argument 01132 return E_INVALIDARG; 01133 } 01134 01135 // get framing properties 01136 *FramingProp = m_FramingProp[Option]; 01137 *FramingEx = m_FramingEx[Option]; 01138 01139 return NOERROR; 01140 } 01141 01142 HRESULT 01143 STDMETHODCALLTYPE 01144 COutputPin::KsSetPinFramingCache( 01145 PKSALLOCATOR_FRAMING_EX FramingEx, 01146 PFRAMING_PROP FramingProp, 01147 FRAMING_CACHE_OPS Option) 01148 { 01149 ULONG Index; 01150 ULONG RefCount = 0; 01151 01152 if (m_FramingEx[Option]) 01153 { 01154 for(Index = 1; Index < 4; Index++) 01155 { 01156 if (m_FramingEx[Index] == m_FramingEx[Option]) 01157 RefCount++; 01158 } 01159 01160 if (RefCount == 1) 01161 { 01162 // existing framing is only used once 01163 CoTaskMemFree(m_FramingEx[Option]); 01164 } 01165 } 01166 01167 // store framing 01168 m_FramingEx[Option] = FramingEx; 01169 m_FramingProp[Option] = *FramingProp; 01170 01171 return S_OK; 01172 } 01173 01174 IPin* 01175 STDMETHODCALLTYPE 01176 COutputPin::KsGetConnectedPin() 01177 { 01178 return m_Pin; 01179 } 01180 01181 IKsAllocatorEx* 01182 STDMETHODCALLTYPE 01183 COutputPin::KsGetPipe( 01184 KSPEEKOPERATION Operation) 01185 { 01186 if (Operation == KsPeekOperation_AddRef) 01187 { 01188 if (m_KsAllocatorEx) 01189 m_KsAllocatorEx->AddRef(); 01190 } 01191 return m_KsAllocatorEx; 01192 } 01193 01194 HRESULT 01195 STDMETHODCALLTYPE 01196 COutputPin::KsSetPipe( 01197 IKsAllocatorEx *KsAllocator) 01198 { 01199 if (KsAllocator) 01200 KsAllocator->AddRef(); 01201 01202 if (m_KsAllocatorEx) 01203 m_KsAllocatorEx->Release(); 01204 01205 m_KsAllocatorEx = KsAllocator; 01206 return NOERROR; 01207 } 01208 01209 ULONG 01210 STDMETHODCALLTYPE 01211 COutputPin::KsGetPipeAllocatorFlag() 01212 { 01213 return m_PipeAllocatorFlag; 01214 } 01215 01216 01217 HRESULT 01218 STDMETHODCALLTYPE 01219 COutputPin::KsSetPipeAllocatorFlag( 01220 ULONG Flag) 01221 { 01222 m_PipeAllocatorFlag = Flag; 01223 return NOERROR; 01224 } 01225 01226 GUID 01227 STDMETHODCALLTYPE 01228 COutputPin::KsGetPinBusCache() 01229 { 01230 if (!m_bPinBusCacheInitialized) 01231 { 01232 CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID)); 01233 m_bPinBusCacheInitialized = TRUE; 01234 } 01235 01236 return m_PinBusCache; 01237 } 01238 01239 HRESULT 01240 STDMETHODCALLTYPE 01241 COutputPin::KsSetPinBusCache( 01242 GUID Bus) 01243 { 01244 CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID)); 01245 return NOERROR; 01246 } 01247 01248 PWCHAR 01249 STDMETHODCALLTYPE 01250 COutputPin::KsGetPinName() 01251 { 01252 return (PWCHAR)m_PinName; 01253 } 01254 01255 01256 PWCHAR 01257 STDMETHODCALLTYPE 01258 COutputPin::KsGetFilterName() 01259 { 01260 return m_FilterName; 01261 } 01262 01263 //------------------------------------------------------------------- 01264 // ISpecifyPropertyPages 01265 // 01266 01267 HRESULT 01268 STDMETHODCALLTYPE 01269 COutputPin::GetPages(CAUUID *pPages) 01270 { 01271 #ifdef KSPROXY_TRACE 01272 OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n"); 01273 #endif 01274 01275 if (!pPages) 01276 return E_POINTER; 01277 01278 pPages->cElems = 0; 01279 pPages->pElems = NULL; 01280 01281 return S_OK; 01282 } 01283 01284 //------------------------------------------------------------------- 01285 // IKsPinFactory 01286 // 01287 01288 HRESULT 01289 STDMETHODCALLTYPE 01290 COutputPin::KsPinFactory( 01291 ULONG* PinFactory) 01292 { 01293 #ifdef KSPROXY_TRACE 01294 OutputDebugStringW(L"COutputPin::KsPinFactory\n"); 01295 #endif 01296 01297 *PinFactory = m_PinId; 01298 return S_OK; 01299 } 01300 01301 01302 //------------------------------------------------------------------- 01303 // IStreamBuilder 01304 // 01305 01306 HRESULT 01307 STDMETHODCALLTYPE 01308 COutputPin::Render( 01309 IPin *ppinOut, 01310 IGraphBuilder *pGraph) 01311 { 01312 #ifdef KSPROXY_TRACE 01313 OutputDebugStringW(L"COutputPin::Render\n"); 01314 #endif 01315 return S_OK; 01316 } 01317 01318 HRESULT 01319 STDMETHODCALLTYPE 01320 COutputPin::Backout( 01321 IPin *ppinOut, 01322 IGraphBuilder *pGraph) 01323 { 01324 #ifdef KSPROXY_TRACE 01325 OutputDebugStringW(L"COutputPin::Backout\n"); 01326 #endif 01327 01328 return S_OK; 01329 } 01330 //------------------------------------------------------------------- 01331 // IKsObject 01332 // 01333 HANDLE 01334 STDMETHODCALLTYPE 01335 COutputPin::KsGetObjectHandle() 01336 { 01337 #ifdef KSPROXY_TRACE 01338 OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n"); 01339 #endif 01340 01341 assert(m_hPin != INVALID_HANDLE_VALUE); 01342 return m_hPin; 01343 } 01344 01345 //------------------------------------------------------------------- 01346 // IKsControl 01347 // 01348 HRESULT 01349 STDMETHODCALLTYPE 01350 COutputPin::KsProperty( 01351 PKSPROPERTY Property, 01352 ULONG PropertyLength, 01353 LPVOID PropertyData, 01354 ULONG DataLength, 01355 ULONG* BytesReturned) 01356 { 01357 HRESULT hr; 01358 01359 assert(m_hPin != INVALID_HANDLE_VALUE); 01360 01361 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned); 01362 #ifdef KSPROXY_TRACE 01363 WCHAR Buffer[100]; 01364 LPOLESTR pstr; 01365 StringFromCLSID(Property->Set, &pstr); 01366 swprintf(Buffer, L"COutputPin::KsProperty Set %s Id %lu Flags %x hr %x\n", pstr, Property->Id, Property->Flags, hr); 01367 OutputDebugStringW(Buffer); 01368 #endif 01369 01370 return hr; 01371 } 01372 01373 HRESULT 01374 STDMETHODCALLTYPE 01375 COutputPin::KsMethod( 01376 PKSMETHOD Method, 01377 ULONG MethodLength, 01378 LPVOID MethodData, 01379 ULONG DataLength, 01380 ULONG* BytesReturned) 01381 { 01382 assert(m_hPin != INVALID_HANDLE_VALUE); 01383 #ifdef KSPROXY_TRACE 01384 OutputDebugStringW(L"COutputPin::KsMethod\n"); 01385 #endif 01386 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned); 01387 } 01388 01389 HRESULT 01390 STDMETHODCALLTYPE 01391 COutputPin::KsEvent( 01392 PKSEVENT Event, 01393 ULONG EventLength, 01394 LPVOID EventData, 01395 ULONG DataLength, 01396 ULONG* BytesReturned) 01397 { 01398 assert(m_hPin != INVALID_HANDLE_VALUE); 01399 01400 #ifdef KSPROXY_TRACE 01401 OutputDebugStringW(L"COutputPin::KsEvent\n"); 01402 #endif 01403 01404 if (EventLength) 01405 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned); 01406 else 01407 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned); 01408 } 01409 01410 01411 //------------------------------------------------------------------- 01412 // IKsPropertySet 01413 // 01414 HRESULT 01415 STDMETHODCALLTYPE 01416 COutputPin::Set( 01417 REFGUID guidPropSet, 01418 DWORD dwPropID, 01419 LPVOID pInstanceData, 01420 DWORD cbInstanceData, 01421 LPVOID pPropData, 01422 DWORD cbPropData) 01423 { 01424 ULONG BytesReturned; 01425 01426 if (cbInstanceData) 01427 { 01428 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); 01429 if (!Property) 01430 return E_OUTOFMEMORY; 01431 01432 Property->Set = guidPropSet; 01433 Property->Id = dwPropID; 01434 Property->Flags = KSPROPERTY_TYPE_SET; 01435 01436 CopyMemory((Property+1), pInstanceData, cbInstanceData); 01437 01438 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); 01439 CoTaskMemFree(Property); 01440 return hr; 01441 } 01442 else 01443 { 01444 KSPROPERTY Property; 01445 01446 Property.Set = guidPropSet; 01447 Property.Id = dwPropID; 01448 Property.Flags = KSPROPERTY_TYPE_SET; 01449 01450 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); 01451 return hr; 01452 } 01453 } 01454 01455 HRESULT 01456 STDMETHODCALLTYPE 01457 COutputPin::Get( 01458 REFGUID guidPropSet, 01459 DWORD dwPropID, 01460 LPVOID pInstanceData, 01461 DWORD cbInstanceData, 01462 LPVOID pPropData, 01463 DWORD cbPropData, 01464 DWORD *pcbReturned) 01465 { 01466 ULONG BytesReturned; 01467 01468 if (cbInstanceData) 01469 { 01470 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); 01471 if (!Property) 01472 return E_OUTOFMEMORY; 01473 01474 Property->Set = guidPropSet; 01475 Property->Id = dwPropID; 01476 Property->Flags = KSPROPERTY_TYPE_GET; 01477 01478 CopyMemory((Property+1), pInstanceData, cbInstanceData); 01479 01480 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); 01481 CoTaskMemFree(Property); 01482 return hr; 01483 } 01484 else 01485 { 01486 KSPROPERTY Property; 01487 01488 Property.Set = guidPropSet; 01489 Property.Id = dwPropID; 01490 Property.Flags = KSPROPERTY_TYPE_GET; 01491 01492 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); 01493 return hr; 01494 } 01495 } 01496 01497 HRESULT 01498 STDMETHODCALLTYPE 01499 COutputPin::QuerySupported( 01500 REFGUID guidPropSet, 01501 DWORD dwPropID, 01502 DWORD *pTypeSupport) 01503 { 01504 KSPROPERTY Property; 01505 ULONG BytesReturned; 01506 01507 #ifdef KSPROXY_TRACE 01508 OutputDebugStringW(L"COutputPin::QuerySupported\n"); 01509 #endif 01510 01511 Property.Set = guidPropSet; 01512 Property.Id = dwPropID; 01513 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; 01514 01515 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned); 01516 } 01517 01518 01519 //------------------------------------------------------------------- 01520 // IPin interface 01521 // 01522 HRESULT 01523 STDMETHODCALLTYPE 01524 COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) 01525 { 01526 HRESULT hr; 01527 ALLOCATOR_PROPERTIES Properties; 01528 IMemAllocatorCallbackTemp *pMemCallback; 01529 LPGUID pGuid; 01530 ULONG NumGuids = 0; 01531 01532 #ifdef KSPROXY_TRACE 01533 WCHAR Buffer[200]; 01534 OutputDebugStringW(L"COutputPin::Connect called\n"); 01535 #endif 01536 01537 if (pmt) 01538 { 01539 hr = pReceivePin->QueryAccept(pmt); 01540 if (FAILED(hr)) 01541 return hr; 01542 } 01543 else 01544 { 01545 // query accept 01546 hr = pReceivePin->QueryAccept(&m_MediaFormat); 01547 if (FAILED(hr)) 01548 return hr; 01549 01550 pmt = &m_MediaFormat; 01551 } 01552 01553 if (m_hPin == INVALID_HANDLE_VALUE) 01554 { 01555 hr = CreatePin(pmt); 01556 if (FAILED(hr)) 01557 { 01558 #ifdef KSPROXY_TRACE 01559 swprintf(Buffer, L"COutputPin::Connect CreatePin handle failed with %lx\n", hr); 01560 OutputDebugStringW(Buffer); 01561 #endif 01562 return hr; 01563 } 01564 } 01565 01566 01567 // query for IMemInput interface 01568 hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin); 01569 if (FAILED(hr)) 01570 { 01571 #ifdef KSPROXY_TRACE 01572 OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n"); 01573 #endif 01574 01575 return hr; 01576 } 01577 01578 // get input pin allocator properties 01579 ZeroMemory(&Properties, sizeof(ALLOCATOR_PROPERTIES)); 01580 m_MemInputPin->GetAllocatorRequirements(&Properties); 01581 01582 //FIXME determine allocator properties 01583 Properties.cBuffers = 32; 01584 Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size 01585 Properties.cbAlign = 4; 01586 01587 // get input pin allocator 01588 #if 0 01589 hr = m_MemInputPin->GetAllocator(&m_MemAllocator); 01590 if (SUCCEEDED(hr)) 01591 { 01592 // set allocator properties 01593 hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); 01594 if (FAILED(hr)) 01595 m_MemAllocator->Release(); 01596 } 01597 #endif 01598 01599 if (1) 01600 { 01601 hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator); 01602 if (FAILED(hr)) 01603 return hr; 01604 01605 // set allocator properties 01606 hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); 01607 if (FAILED(hr)) 01608 { 01609 #ifdef KSPROXY_TRACE 01610 swprintf(Buffer, L"COutputPin::Connect IMemAllocator::SetProperties failed with hr %lx\n", hr); 01611 OutputDebugStringW(Buffer); 01612 #endif 01613 m_MemAllocator->Release(); 01614 m_MemInputPin->Release(); 01615 return hr; 01616 } 01617 } 01618 01619 // commit property changes 01620 hr = m_MemAllocator->Commit(); 01621 if (FAILED(hr)) 01622 { 01623 #ifdef KSPROXY_TRACE 01624 swprintf(Buffer, L"COutputPin::Connect IMemAllocator::Commit failed with hr %lx\n", hr); 01625 OutputDebugStringW(Buffer); 01626 #endif 01627 m_MemAllocator->Release(); 01628 m_MemInputPin->Release(); 01629 return hr; 01630 } 01631 01632 // get callback interface 01633 hr = m_MemAllocator->QueryInterface(IID_IMemAllocatorCallbackTemp, (void**)&pMemCallback); 01634 if (FAILED(hr)) 01635 { 01636 #ifdef KSPROXY_TRACE 01637 swprintf(Buffer, L"COutputPin::Connect No IMemAllocatorCallbackTemp interface hr %lx\n", hr); 01638 OutputDebugStringW(Buffer); 01639 #endif 01640 m_MemAllocator->Release(); 01641 m_MemInputPin->Release(); 01642 return hr; 01643 } 01644 01645 // set notification routine 01646 hr = pMemCallback->SetNotify((IMemAllocatorNotifyCallbackTemp*)this); 01647 01648 // release IMemAllocatorNotifyCallbackTemp interface 01649 pMemCallback->Release(); 01650 01651 if (FAILED(hr)) 01652 { 01653 #ifdef KSPROXY_TRACE 01654 swprintf(Buffer, L"COutputPin::Connect IMemAllocatorNotifyCallbackTemp::SetNotify failed hr %lx\n", hr); 01655 OutputDebugStringW(Buffer); 01656 #endif 01657 m_MemAllocator->Release(); 01658 m_MemInputPin->Release(); 01659 return hr; 01660 } 01661 01662 // now set allocator 01663 hr = m_MemInputPin->NotifyAllocator(m_MemAllocator, TRUE); 01664 if (FAILED(hr)) 01665 { 01666 #ifdef KSPROXY_TRACE 01667 swprintf(Buffer, L"COutputPin::Connect IMemInputPin::NotifyAllocator failed with hr %lx\n", hr); 01668 OutputDebugStringW(Buffer); 01669 #endif 01670 m_MemAllocator->Release(); 01671 m_MemInputPin->Release(); 01672 return hr; 01673 } 01674 01675 01676 assert(m_hPin != INVALID_HANDLE_VALUE); 01677 01678 // get all supported sets 01679 if (m_Plugins.size() == 0) 01680 { 01681 if (GetSupportedSets(&pGuid, &NumGuids)) 01682 { 01683 // load all proxy plugins 01684 if (FAILED(LoadProxyPlugins(pGuid, NumGuids))); 01685 { 01686 #ifdef KSPROXY_TRACE 01687 OutputDebugStringW(L"COutputPin::Connect LoadProxyPlugins failed\n"); 01688 #endif 01689 } 01690 // free sets 01691 CoTaskMemFree(pGuid); 01692 } 01693 } 01694 01695 // receive connection; 01696 hr = pReceivePin->ReceiveConnection((IPin*)this, pmt); 01697 if (SUCCEEDED(hr)) 01698 { 01699 // increment reference count 01700 pReceivePin->AddRef(); 01701 m_Pin = pReceivePin; 01702 #ifdef KSPROXY_TRACE 01703 OutputDebugStringW(L"COutputPin::Connect success\n"); 01704 #endif 01705 } 01706 else 01707 { 01708 m_MemInputPin->Release(); 01709 m_MemAllocator->Release(); 01710 } 01711 01712 return hr; 01713 } 01714 01715 HRESULT 01716 STDMETHODCALLTYPE 01717 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) 01718 { 01719 return E_UNEXPECTED; 01720 } 01721 HRESULT 01722 STDMETHODCALLTYPE 01723 COutputPin::Disconnect( void) 01724 { 01725 #ifdef KSPROXY_TRACE 01726 OutputDebugStringW(L"COutputPin::Disconnect\n"); 01727 #endif 01728 01729 if (!m_Pin) 01730 { 01731 // pin was not connected 01732 return S_FALSE; 01733 } 01734 01735 //FIXME 01736 //check if filter is active 01737 01738 m_Pin->Release(); 01739 m_Pin = NULL; 01740 m_MemInputPin->Release(); 01741 m_MemAllocator->Release(); 01742 01743 CloseHandle(m_hPin); 01744 m_hPin = INVALID_HANDLE_VALUE; 01745 01746 #ifdef KSPROXY_TRACE 01747 OutputDebugStringW(L"COutputPin::Disconnect\n"); 01748 #endif 01749 return S_OK; 01750 } 01751 HRESULT 01752 STDMETHODCALLTYPE 01753 COutputPin::ConnectedTo(IPin **pPin) 01754 { 01755 #ifdef KSPROXY_TRACE 01756 OutputDebugStringW(L"COutputPin::ConnectedTo\n"); 01757 #endif 01758 01759 if (!pPin) 01760 return E_POINTER; 01761 01762 if (m_Pin) 01763 { 01764 // increment reference count 01765 m_Pin->AddRef(); 01766 *pPin = m_Pin; 01767 return S_OK; 01768 } 01769 01770 *pPin = NULL; 01771 return VFW_E_NOT_CONNECTED; 01772 } 01773 HRESULT 01774 STDMETHODCALLTYPE 01775 COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) 01776 { 01777 #ifdef KSPROXY_TRACE 01778 OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n"); 01779 #endif 01780 01781 return E_NOTIMPL; 01782 } 01783 HRESULT 01784 STDMETHODCALLTYPE 01785 COutputPin::QueryPinInfo(PIN_INFO *pInfo) 01786 { 01787 wcscpy(pInfo->achName, m_PinName); 01788 pInfo->dir = PINDIR_OUTPUT; 01789 pInfo->pFilter = m_ParentFilter; 01790 m_ParentFilter->AddRef(); 01791 01792 return S_OK; 01793 } 01794 HRESULT 01795 STDMETHODCALLTYPE 01796 COutputPin::QueryDirection(PIN_DIRECTION *pPinDir) 01797 { 01798 if (pPinDir) 01799 { 01800 *pPinDir = PINDIR_OUTPUT; 01801 return S_OK; 01802 } 01803 01804 return E_POINTER; 01805 } 01806 HRESULT 01807 STDMETHODCALLTYPE 01808 COutputPin::QueryId(LPWSTR *Id) 01809 { 01810 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR)); 01811 if (!*Id) 01812 return E_OUTOFMEMORY; 01813 01814 wcscpy(*Id, m_PinName); 01815 return S_OK; 01816 } 01817 HRESULT 01818 STDMETHODCALLTYPE 01819 COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt) 01820 { 01821 #ifdef KSPROXY_TRACE 01822 OutputDebugStringW(L"COutputPin::QueryAccept called\n"); 01823 #endif 01824 01825 return E_NOTIMPL; 01826 } 01827 HRESULT 01828 STDMETHODCALLTYPE 01829 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) 01830 { 01831 HRESULT hr; 01832 ULONG MediaTypeCount = 0, Index; 01833 AM_MEDIA_TYPE * MediaTypes; 01834 HANDLE hFilter; 01835 IKsObject * KsObjectParent; 01836 01837 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 01838 if (FAILED(hr)) 01839 return hr; 01840 01841 // get parent filter handle 01842 hFilter = KsObjectParent->KsGetObjectHandle(); 01843 01844 // release IKsObject 01845 KsObjectParent->Release(); 01846 01847 // query media type count 01848 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount); 01849 if (FAILED(hr) || !MediaTypeCount) 01850 { 01851 return hr; 01852 } 01853 01854 // allocate media types 01855 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount); 01856 if (!MediaTypes) 01857 { 01858 // not enough memory 01859 return E_OUTOFMEMORY; 01860 } 01861 01862 // zero media types 01863 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount); 01864 01865 for(Index = 0; Index < MediaTypeCount; Index++) 01866 { 01867 // get media type 01868 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId); 01869 if (FAILED(hr)) 01870 { 01871 // failed 01872 CoTaskMemFree(MediaTypes); 01873 return hr; 01874 } 01875 } 01876 01877 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum); 01878 } 01879 HRESULT 01880 STDMETHODCALLTYPE 01881 COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) 01882 { 01883 return E_NOTIMPL; 01884 } 01885 HRESULT 01886 STDMETHODCALLTYPE 01887 COutputPin::EndOfStream( void) 01888 { 01889 /* should be called only on input pins */ 01890 return E_UNEXPECTED; 01891 } 01892 HRESULT 01893 STDMETHODCALLTYPE 01894 COutputPin::BeginFlush( void) 01895 { 01896 /* should be called only on input pins */ 01897 return E_UNEXPECTED; 01898 } 01899 HRESULT 01900 STDMETHODCALLTYPE 01901 COutputPin::EndFlush( void) 01902 { 01903 /* should be called only on input pins */ 01904 return E_UNEXPECTED; 01905 } 01906 HRESULT 01907 STDMETHODCALLTYPE 01908 COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) 01909 { 01910 if (!m_Pin) 01911 { 01912 // we are not connected 01913 return VFW_E_NOT_CONNECTED; 01914 } 01915 01916 return m_Pin->NewSegment(tStart, tStop, dRate); 01917 } 01918 01919 //------------------------------------------------------------------- 01920 HRESULT 01921 STDMETHODCALLTYPE 01922 COutputPin::CheckFormat( 01923 const AM_MEDIA_TYPE *pmt) 01924 { 01925 PKSMULTIPLE_ITEM MultipleItem; 01926 PKSDATAFORMAT DataFormat; 01927 HRESULT hr; 01928 IKsObject * KsObjectParent; 01929 HANDLE hFilter; 01930 01931 if (!pmt) 01932 return E_POINTER; 01933 01934 // get IKsObject interface 01935 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 01936 if (FAILED(hr)) 01937 return hr; 01938 01939 // get parent filter handle 01940 hFilter = KsObjectParent->KsGetObjectHandle(); 01941 01942 // release IKsObject 01943 KsObjectParent->Release(); 01944 01945 if (!hFilter) 01946 return E_HANDLE; 01947 01948 01949 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem); 01950 if (FAILED(hr)) 01951 return S_FALSE; 01952 01953 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1); 01954 for(ULONG Index = 0; Index < MultipleItem->Count; Index++) 01955 { 01956 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) && 01957 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) && 01958 IsEqualGUID(pmt->formattype, DataFormat->Specifier)) 01959 { 01960 // format is supported 01961 CoTaskMemFree(MultipleItem); 01962 return S_OK; 01963 } 01964 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize); 01965 } 01966 //format is not supported 01967 CoTaskMemFree(MultipleItem); 01968 return S_FALSE; 01969 } 01970 01971 HRESULT 01972 STDMETHODCALLTYPE 01973 COutputPin::CreatePin( 01974 const AM_MEDIA_TYPE *pmt) 01975 { 01976 PKSMULTIPLE_ITEM MediumList; 01977 PKSMULTIPLE_ITEM InterfaceList; 01978 PKSPIN_MEDIUM Medium; 01979 PKSPIN_INTERFACE Interface; 01980 IKsInterfaceHandler * InterfaceHandler; 01981 HRESULT hr; 01982 01983 // query for pin medium 01984 hr = KsQueryMediums(&MediumList); 01985 if (FAILED(hr)) 01986 { 01987 #ifdef KSPROXY_TRACE 01988 WCHAR Buffer[100]; 01989 swprintf(Buffer, L"COutputPin::CreatePin KsQueryMediums failed %lx\n", hr); 01990 OutputDebugStringW(Buffer); 01991 #endif 01992 return hr; 01993 } 01994 01995 // query for pin interface 01996 hr = KsQueryInterfaces(&InterfaceList); 01997 if (FAILED(hr)) 01998 { 01999 // failed 02000 #ifdef KSPROXY_TRACE 02001 WCHAR Buffer[100]; 02002 swprintf(Buffer, L"COutputPin::CreatePin KsQueryInterfaces failed %lx\n", hr); 02003 OutputDebugStringW(Buffer); 02004 #endif 02005 02006 CoTaskMemFree(MediumList); 02007 return hr; 02008 } 02009 02010 if (MediumList->Count) 02011 { 02012 //use first available medium 02013 Medium = (PKSPIN_MEDIUM)(MediumList + 1); 02014 } 02015 else 02016 { 02017 // default to standard medium 02018 Medium = &StandardPinMedium; 02019 } 02020 02021 if (InterfaceList->Count) 02022 { 02023 //use first available interface 02024 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1); 02025 } 02026 else 02027 { 02028 // default to standard interface 02029 Interface = &StandardPinInterface; 02030 } 02031 02032 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE) 02033 { 02034 // now create pin 02035 hr = CreatePinHandle(Medium, Interface, pmt); 02036 if (FAILED(hr)) 02037 { 02038 #ifdef KSPROXY_TRACE 02039 WCHAR Buffer[100]; 02040 swprintf(Buffer, L"COutputPin::CreatePinHandle failed with %lx\n", hr); 02041 OutputDebugStringW(Buffer); 02042 #endif 02043 return hr; 02044 } 02045 02046 if (!m_InterfaceHandler) 02047 { 02048 // now load the IKsInterfaceHandler plugin 02049 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler); 02050 if (FAILED(hr)) 02051 { 02052 // failed to load interface handler plugin 02053 CoTaskMemFree(MediumList); 02054 CoTaskMemFree(InterfaceList); 02055 02056 #ifdef KSPROXY_TRACE 02057 WCHAR Buffer[100]; 02058 swprintf(Buffer, L"COutputPin::CreatePin failed to create interface handler %lx\n", hr); 02059 OutputDebugStringW(Buffer); 02060 #endif 02061 02062 return hr; 02063 } 02064 02065 // now set the pin 02066 hr = InterfaceHandler->KsSetPin((IKsPin*)this); 02067 if (FAILED(hr)) 02068 { 02069 // failed to initialize interface handler plugin 02070 #ifdef KSPROXY_TRACE 02071 WCHAR Buffer[100]; 02072 swprintf(Buffer, L"COutputPin::CreatePin failed to initialize interface handler %lx\n", hr); 02073 OutputDebugStringW(Buffer); 02074 #endif 02075 InterfaceHandler->Release(); 02076 CoTaskMemFree(MediumList); 02077 CoTaskMemFree(InterfaceList); 02078 return hr; 02079 } 02080 02081 // store interface handler 02082 m_InterfaceHandler = InterfaceHandler; 02083 } 02084 } 02085 else 02086 { 02087 #ifdef KSPROXY_TRACE 02088 WCHAR Buffer[100]; 02089 swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName); 02090 OutputDebugStringW(Buffer); 02091 #endif 02092 02093 hr = E_FAIL; 02094 } 02095 02096 // free medium / interface / dataformat 02097 CoTaskMemFree(MediumList); 02098 CoTaskMemFree(InterfaceList); 02099 02100 #ifdef KSPROXY_TRACE 02101 WCHAR Buffer[100]; 02102 swprintf(Buffer, L"COutputPin::CreatePin Result %lx\n", hr); 02103 OutputDebugStringW(Buffer); 02104 #endif 02105 02106 return hr; 02107 } 02108 02109 HRESULT 02110 STDMETHODCALLTYPE 02111 COutputPin::CreatePinHandle( 02112 PKSPIN_MEDIUM Medium, 02113 PKSPIN_INTERFACE Interface, 02114 const AM_MEDIA_TYPE *pmt) 02115 { 02116 PKSPIN_CONNECT PinConnect; 02117 PKSDATAFORMAT DataFormat; 02118 ULONG Length; 02119 HRESULT hr; 02120 HANDLE hFilter; 02121 IKsObject * KsObjectParent; 02122 02123 //KSALLOCATOR_FRAMING Framing; 02124 //KSPROPERTY Property; 02125 //ULONG BytesReturned; 02126 02127 OutputDebugStringW(L"COutputPin::CreatePinHandle\n"); 02128 02129 if (m_hPin != INVALID_HANDLE_VALUE) 02130 { 02131 // pin already exists 02132 //CloseHandle(m_hPin); 02133 //m_hPin = INVALID_HANDLE_VALUE; 02134 OutputDebugStringW(L"COutputPin::CreatePinHandle pin already exists\n"); 02135 return S_OK; 02136 } 02137 02138 02139 // calc format size 02140 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat; 02141 02142 // allocate pin connect 02143 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length); 02144 if (!PinConnect) 02145 { 02146 // failed 02147 OutputDebugStringW(L"COutputPin::CreatePinHandle out of memory\n"); 02148 return E_OUTOFMEMORY; 02149 } 02150 OutputDebugStringW(L"COutputPin::CreatePinHandle copy pinconnect\n"); 02151 // setup request 02152 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE)); 02153 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM)); 02154 PinConnect->PinId = m_PinId; 02155 PinConnect->PinToHandle = NULL; 02156 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; 02157 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL; 02158 02159 // get dataformat offset 02160 DataFormat = (PKSDATAFORMAT)(PinConnect + 1); 02161 OutputDebugStringW(L"COutputPin::CreatePinHandle copy format\n"); 02162 // copy data format 02163 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat; 02164 DataFormat->Flags = 0; 02165 DataFormat->SampleSize = pmt->lSampleSize; 02166 DataFormat->Reserved = 0; 02167 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID)); 02168 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID)); 02169 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID)); 02170 02171 if (pmt->cbFormat) 02172 { 02173 // copy extended format 02174 WCHAR Buffer[100]; 02175 swprintf(Buffer, L"COutputPin::CreatePinHandle copy format %p pbFormat %lu\n", pmt, pmt->cbFormat); 02176 OutputDebugStringW(Buffer); 02177 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat); 02178 } 02179 02180 // get IKsObject interface 02181 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 02182 if (FAILED(hr)) 02183 { 02184 OutputDebugStringW(L"COutputPin::CreatePinHandle no IID_IKsObject interface\n"); 02185 return hr; 02186 } 02187 02188 // get parent filter handle 02189 hFilter = KsObjectParent->KsGetObjectHandle(); 02190 02191 // release IKsObject 02192 KsObjectParent->Release(); 02193 02194 if (!hFilter) 02195 { 02196 OutputDebugStringW(L"COutputPin::CreatePinHandle no filter handle\n"); 02197 return E_HANDLE; 02198 } 02199 02200 OutputDebugStringW(L"COutputPin::CreatePinHandle before creating pin\n"); 02201 // create pin 02202 DWORD dwError = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin); 02203 02204 if (dwError == ERROR_SUCCESS) 02205 { 02206 OutputDebugStringW(L"COutputPin::CreatePinHandle created pin\n"); 02207 02208 // store current interface / medium 02209 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM)); 02210 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE)); 02211 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE)); 02212 02213 #ifdef KSPROXY_TRACE 02214 LPOLESTR pMajor, pSub, pFormat; 02215 StringFromIID(m_MediaFormat.majortype, &pMajor); 02216 StringFromIID(m_MediaFormat.subtype , &pSub); 02217 StringFromIID(m_MediaFormat.formattype, &pFormat); 02218 WCHAR Buffer[200]; 02219 swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat); 02220 CoTaskMemFree(pMajor); 02221 CoTaskMemFree(pSub); 02222 CoTaskMemFree(pFormat); 02223 OutputDebugStringW(Buffer); 02224 #endif 02225 02226 if (pmt->cbFormat) 02227 { 02228 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat); 02229 if (!m_MediaFormat.pbFormat) 02230 { 02231 CoTaskMemFree(PinConnect); 02232 m_MediaFormat.pbFormat = NULL; 02233 m_MediaFormat.cbFormat = 0; 02234 return E_OUTOFMEMORY; 02235 } 02236 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat); 02237 } 02238 #if 0 02239 Property.Set = KSPROPSETID_Connection; 02240 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; 02241 Property.Flags = KSPROPERTY_TYPE_GET; 02242 02243 ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING)); 02244 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); 02245 if (SUCCEEDED(hr)) 02246 { 02247 m_Properties.cbAlign = (Framing.FileAlignment + 1); 02248 m_Properties.cbBuffer = Framing.FrameSize; 02249 m_Properties.cbPrefix = 0; //FIXME 02250 m_Properties.cBuffers = Framing.Frames; 02251 } 02252 hr = S_OK; 02253 #endif 02254 02255 if (FAILED(InitializeIOThread())) 02256 { 02257 OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n"); 02258 } 02259 02260 //TODO 02261 // connect pin pipes 02262 02263 } 02264 else 02265 OutputDebugStringW(L"COutputPin::CreatePinHandle failed to create pin\n"); 02266 // free pin connect 02267 CoTaskMemFree(PinConnect); 02268 02269 return hr; 02270 } 02271 02272 HRESULT 02273 STDMETHODCALLTYPE 02274 COutputPin::GetSupportedSets( 02275 LPGUID * pOutGuid, 02276 PULONG NumGuids) 02277 { 02278 KSPROPERTY Property; 02279 LPGUID pGuid; 02280 ULONG NumProperty = 0; 02281 ULONG NumMethods = 0; 02282 ULONG NumEvents = 0; 02283 ULONG Length; 02284 ULONG BytesReturned; 02285 HRESULT hr; 02286 02287 Property.Set = GUID_NULL; 02288 Property.Id = 0; 02289 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; 02290 02291 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty); 02292 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods); 02293 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents); 02294 02295 Length = NumProperty + NumMethods + NumEvents; 02296 02297 assert(Length); 02298 02299 // allocate guid buffer 02300 pGuid = (LPGUID)CoTaskMemAlloc(Length); 02301 if (!pGuid) 02302 { 02303 // failed 02304 return E_OUTOFMEMORY; 02305 } 02306 02307 NumProperty /= sizeof(GUID); 02308 NumMethods /= sizeof(GUID); 02309 NumEvents /= sizeof(GUID); 02310 02311 // get all properties 02312 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned); 02313 if (FAILED(hr)) 02314 { 02315 CoTaskMemFree(pGuid); 02316 return E_FAIL; 02317 } 02318 Length -= BytesReturned; 02319 02320 // get all methods 02321 if (Length && NumMethods) 02322 { 02323 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned); 02324 if (FAILED(hr)) 02325 { 02326 CoTaskMemFree(pGuid); 02327 return E_FAIL; 02328 } 02329 Length -= BytesReturned; 02330 } 02331 02332 // get all events 02333 if (Length && NumEvents) 02334 { 02335 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned); 02336 if (FAILED(hr)) 02337 { 02338 CoTaskMemFree(pGuid); 02339 return E_FAIL; 02340 } 02341 Length -= BytesReturned; 02342 } 02343 02344 #ifdef KSPROXY_TRACE 02345 WCHAR Buffer[200]; 02346 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents); 02347 OutputDebugStringW(Buffer); 02348 #endif 02349 02350 *pOutGuid = pGuid; 02351 *NumGuids = NumProperty+NumEvents+NumMethods; 02352 return S_OK; 02353 } 02354 02355 HRESULT 02356 STDMETHODCALLTYPE 02357 COutputPin::LoadProxyPlugins( 02358 LPGUID pGuids, 02359 ULONG NumGuids) 02360 { 02361 ULONG Index; 02362 LPOLESTR pStr; 02363 HKEY hKey, hSubKey; 02364 HRESULT hr; 02365 IUnknown * pUnknown; 02366 02367 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS) 02368 { 02369 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n"); 02370 return E_FAIL; 02371 } 02372 02373 // enumerate all sets 02374 for(Index = 0; Index < NumGuids; Index++) 02375 { 02376 // convert to string 02377 hr = StringFromCLSID(pGuids[Index], &pStr); 02378 if (FAILED(hr)) 02379 return E_FAIL; 02380 02381 // now try open class key 02382 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) 02383 { 02384 // no plugin for that set exists 02385 CoTaskMemFree(pStr); 02386 continue; 02387 } 02388 02389 // try load plugin 02390 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown); 02391 if (SUCCEEDED(hr)) 02392 { 02393 // store plugin 02394 m_Plugins.push_back(pUnknown); 02395 } 02396 // close key 02397 RegCloseKey(hSubKey); 02398 } 02399 02400 // close media interfaces key 02401 RegCloseKey(hKey); 02402 return S_OK; 02403 } 02404 02405 02406 HRESULT 02407 WINAPI 02408 COutputPin::IoProcessRoutine() 02409 { 02410 IMediaSample *Sample; 02411 LONG SampleCount; 02412 HRESULT hr; 02413 PKSSTREAM_SEGMENT * StreamSegment; 02414 HANDLE hEvent; 02415 IMediaSample ** Samples; 02416 LONG NumHandles; 02417 DWORD dwStatus; 02418 02419 #ifdef KSPROXY_TRACE 02420 WCHAR Buffer[200]; 02421 #endif 02422 02423 NumHandles = m_Properties.cBuffers / 2; 02424 02425 if (!NumHandles) 02426 NumHandles = 8; 02427 02428 assert(NumHandles); 02429 02430 //allocate stream segment array 02431 StreamSegment = (PKSSTREAM_SEGMENT*)CoTaskMemAlloc(sizeof(PVOID) * NumHandles); 02432 if (!StreamSegment) 02433 { 02434 OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n"); 02435 return E_FAIL; 02436 } 02437 02438 // allocate handle array 02439 Samples = (IMediaSample**)CoTaskMemAlloc(sizeof(IMediaSample*) * NumHandles); 02440 if (!Samples) 02441 { 02442 OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n"); 02443 return E_FAIL; 02444 } 02445 02446 // zero handles array 02447 ZeroMemory(StreamSegment, sizeof(PVOID) * NumHandles); 02448 ZeroMemory(Samples, sizeof(IMediaSample*) * NumHandles); 02449 02450 // first wait for the start event to signal 02451 WaitForSingleObject(m_hStartEvent, INFINITE); 02452 02453 m_IoCount = 0; 02454 02455 assert(m_InterfaceHandler); 02456 do 02457 { 02458 if (m_StopInProgress) 02459 { 02460 // stop io thread 02461 break; 02462 } 02463 02464 assert(m_State == KSSTATE_RUN); 02465 assert(m_MemAllocator); 02466 02467 // get buffer 02468 hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT); 02469 02470 if (FAILED(hr)) 02471 { 02472 WaitForSingleObject(m_hBufferAvailable, INFINITE); 02473 // now retry again 02474 continue; 02475 } 02476 02477 // fill buffer 02478 SampleCount = 1; 02479 Samples[m_IoCount] = Sample; 02480 02481 Sample->SetTime(NULL, NULL); 02482 hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */ 02483 &Samples[m_IoCount], 02484 &SampleCount, 02485 KsIoOperation_Read, 02486 &StreamSegment[m_IoCount]); 02487 if (FAILED(hr) || !StreamSegment) 02488 { 02489 #ifdef KSPROXY_TRACE 02490 swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr); 02491 OutputDebugStringW(Buffer); 02492 #endif 02493 break; 02494 } 02495 02496 // interface handle should increment pending i/o count 02497 assert(m_IoCount >= 1); 02498 02499 swprintf(Buffer, L"COutputPin::IoProcessRoutine m_IoCount %lu NumHandles %lu\n", m_IoCount, NumHandles); 02500 OutputDebugStringW(Buffer); 02501 02502 if (m_IoCount != NumHandles) 02503 continue; 02504 02505 // get completion handle 02506 hEvent = StreamSegment[0]->CompletionEvent; 02507 02508 // wait for i/o completion 02509 dwStatus = WaitForSingleObject(hEvent, INFINITE); 02510 02511 swprintf(Buffer, L"COutputPin::IoProcessRoutine dwStatus %lx Error %lx NumHandles %lu\n", dwStatus, GetLastError(), NumHandles); 02512 OutputDebugStringW(Buffer); 02513 02514 // perform completion 02515 m_InterfaceHandler->KsCompleteIo(StreamSegment[0]); 02516 02517 // close completion event 02518 CloseHandle(hEvent); 02519 02520 if (SUCCEEDED(hr)) 02521 { 02522 assert(m_MemInputPin); 02523 02524 // now deliver the sample 02525 hr = m_MemInputPin->Receive(Samples[0]); 02526 02527 #ifdef KSPROXY_TRACE 02528 swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator); 02529 OutputDebugStringW(Buffer); 02530 #endif 02531 02532 if (FAILED(hr)) 02533 break; 02534 02535 Sample = NULL; 02536 } 02537 02538 //circular stream segment array 02539 RtlMoveMemory(StreamSegment, &StreamSegment[1], sizeof(PVOID) * (NumHandles - 1)); 02540 RtlMoveMemory(Samples, &Samples[1], sizeof(IMediaSample*) * (NumHandles - 1)); 02541 02542 }while(TRUE); 02543 02544 // signal end of i/o thread 02545 SetEvent(m_hStopEvent); 02546 02547 m_IoThreadStarted = false; 02548 02549 return NOERROR; 02550 } 02551 02552 DWORD 02553 WINAPI 02554 COutputPin_IoThreadStartup( 02555 LPVOID lpParameter) 02556 { 02557 COutputPin * Pin = (COutputPin*)lpParameter; 02558 assert(Pin); 02559 02560 return Pin->IoProcessRoutine(); 02561 } 02562 02563 02564 HRESULT 02565 WINAPI 02566 COutputPin::InitializeIOThread() 02567 { 02568 HANDLE hThread; 02569 02570 if (m_IoThreadStarted) 02571 return NOERROR; 02572 02573 if (!m_hStartEvent) 02574 m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 02575 02576 if (!m_hStartEvent) 02577 return E_OUTOFMEMORY; 02578 02579 if (!m_hStopEvent) 02580 m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 02581 02582 if (!m_hStopEvent) 02583 return E_OUTOFMEMORY; 02584 02585 if (!m_hBufferAvailable) 02586 m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL); 02587 02588 if (!m_hBufferAvailable) 02589 return E_OUTOFMEMORY; 02590 02591 m_StopInProgress = false; 02592 m_IoThreadStarted = true; 02593 02594 // now create the startup thread 02595 hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL); 02596 if (!hThread) 02597 return E_OUTOFMEMORY; 02598 02599 02600 // close thread handle 02601 CloseHandle(hThread); 02602 return NOERROR; 02603 } 02604 02605 HRESULT 02606 STDMETHODCALLTYPE 02607 COutputPin_SetState( 02608 IPin * Pin, 02609 KSSTATE State) 02610 { 02611 HRESULT hr = S_OK; 02612 KSPROPERTY Property; 02613 KSSTATE CurState; 02614 ULONG BytesReturned; 02615 COutputPin * pPin = (COutputPin*)Pin; 02616 02617 #ifdef KSPROXY_TRACE 02618 WCHAR Buffer[200]; 02619 #endif 02620 02621 Property.Set = KSPROPSETID_Connection; 02622 Property.Id = KSPROPERTY_CONNECTION_STATE; 02623 Property.Flags = KSPROPERTY_TYPE_SET; 02624 02625 EnterCriticalSection(&pPin->m_Lock); 02626 02627 if (pPin->m_State <= State) 02628 { 02629 if (pPin->m_State == KSSTATE_STOP) 02630 { 02631 hr = pPin->InitializeIOThread(); 02632 if (FAILED(hr)) 02633 { 02634 // failed to initialize I/O thread 02635 #ifdef KSPROXY_TRACE 02636 OutputDebugStringW(L"Failed to initialize I/O Thread\n"); 02637 #endif 02638 LeaveCriticalSection(&pPin->m_Lock); 02639 return hr; 02640 } 02641 CurState = KSSTATE_ACQUIRE; 02642 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 02643 02644 #ifdef KSPROXY_TRACE 02645 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_STOP KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); 02646 OutputDebugStringW(Buffer); 02647 #endif 02648 02649 if (FAILED(hr)) 02650 { 02651 LeaveCriticalSection(&pPin->m_Lock); 02652 return hr; 02653 } 02654 02655 pPin->m_State = CurState; 02656 02657 if (pPin->m_State == State) 02658 { 02659 LeaveCriticalSection(&pPin->m_Lock); 02660 return hr; 02661 } 02662 } 02663 if (pPin->m_State == KSSTATE_ACQUIRE) 02664 { 02665 CurState = KSSTATE_PAUSE; 02666 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 02667 02668 #ifdef KSPROXY_TRACE 02669 swprintf(Buffer, L"COutputPin_SetState Setting State CurState KSSTATE_ACQUIRE KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); 02670 OutputDebugStringW(Buffer); 02671 #endif 02672 02673 if (FAILED(hr)) 02674 { 02675 LeaveCriticalSection(&pPin->m_Lock); 02676 return hr; 02677 } 02678 02679 pPin->m_State = CurState; 02680 02681 if (pPin->m_State == State) 02682 { 02683 LeaveCriticalSection(&pPin->m_Lock); 02684 return hr; 02685 } 02686 } 02687 if (State == KSSTATE_RUN && pPin->m_State == KSSTATE_PAUSE) 02688 { 02689 CurState = KSSTATE_RUN; 02690 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 02691 02692 #ifdef KSPROXY_TRACE 02693 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr); 02694 OutputDebugStringW(Buffer); 02695 #endif 02696 02697 if (SUCCEEDED(hr)) 02698 { 02699 pPin->m_State = CurState; 02700 // signal start event 02701 SetEvent(pPin->m_hStartEvent); 02702 } 02703 } 02704 02705 LeaveCriticalSection(&pPin->m_Lock); 02706 return hr; 02707 } 02708 else 02709 { 02710 if (pPin->m_State == KSSTATE_RUN) 02711 { 02712 // setting pending stop flag 02713 pPin->m_StopInProgress = true; 02714 02715 // release any waiting threads 02716 SetEvent(pPin->m_hBufferAvailable); 02717 02718 // wait until i/o thread is done 02719 WaitForSingleObject(pPin->m_hStopEvent, INFINITE); 02720 02721 CurState = KSSTATE_PAUSE; 02722 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 02723 02724 #ifdef KSPROXY_TRACE 02725 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_RUN KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); 02726 OutputDebugStringW(Buffer); 02727 #endif 02728 02729 if (FAILED(hr)) 02730 { 02731 LeaveCriticalSection(&pPin->m_Lock); 02732 return hr; 02733 } 02734 02735 pPin->m_State = CurState; 02736 02737 if (FAILED(hr)) 02738 { 02739 LeaveCriticalSection(&pPin->m_Lock); 02740 return hr; 02741 } 02742 } 02743 if (pPin->m_State == KSSTATE_PAUSE) 02744 { 02745 CurState = KSSTATE_ACQUIRE; 02746 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 02747 02748 #ifdef KSPROXY_TRACE 02749 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); 02750 OutputDebugStringW(Buffer); 02751 #endif 02752 02753 if (FAILED(hr)) 02754 { 02755 LeaveCriticalSection(&pPin->m_Lock); 02756 return hr; 02757 } 02758 02759 pPin->m_State = CurState; 02760 02761 if (pPin->m_State == State) 02762 { 02763 LeaveCriticalSection(&pPin->m_Lock); 02764 return hr; 02765 } 02766 } 02767 02768 CloseHandle(pPin->m_hStopEvent); 02769 CloseHandle(pPin->m_hStartEvent); 02770 CloseHandle(pPin->m_hBufferAvailable); 02771 02772 /* close event handles */ 02773 pPin->m_hStopEvent = NULL; 02774 pPin->m_hStartEvent = NULL; 02775 pPin->m_hBufferAvailable = NULL; 02776 02777 CurState = KSSTATE_STOP; 02778 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 02779 02780 #ifdef KSPROXY_TRACE 02781 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_ACQUIRE KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr); 02782 OutputDebugStringW(Buffer); 02783 #endif 02784 02785 if (SUCCEEDED(hr)) 02786 { 02787 // store state 02788 pPin->m_State = CurState; 02789 } 02790 02791 // unset pending stop flag 02792 pPin->m_StopInProgress = false; 02793 02794 LeaveCriticalSection(&pPin->m_Lock); 02795 return hr; 02796 } 02797 } 02798 02799 HRESULT 02800 WINAPI 02801 COutputPin_Constructor( 02802 IBaseFilter * ParentFilter, 02803 LPCWSTR PinName, 02804 ULONG PinId, 02805 KSPIN_COMMUNICATION Communication, 02806 REFIID riid, 02807 LPVOID * ppv) 02808 { 02809 COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication); 02810 02811 if (!handler) 02812 return E_OUTOFMEMORY; 02813 02814 if (FAILED(handler->QueryInterface(riid, ppv))) 02815 { 02816 /* not supported */ 02817 delete handler; 02818 return E_NOINTERFACE; 02819 } 02820 02821 return S_OK; 02822 } Generated on Sun May 27 2012 04:21:52 for ReactOS by
1.7.6.1
|