1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy 4 * FILE: dll/directx/ksproxy/output_pin.cpp 5 * PURPOSE: OutputPin of Proxy Filter 6 * 7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) 8 */ 9 #include "precomp.h" 10 11 class COutputPin : public IPin, 12 public IKsObject, 13 public IKsPropertySet, 14 public IStreamBuilder, 15 public IKsPinFactory, 16 public ISpecifyPropertyPages, 17 public IKsPinEx, 18 public IKsPinPipe, 19 public IKsControl, 20 public IKsAggregateControl, 21 public IQualityControl, 22 public IMediaSeeking, 23 public IAMBufferNegotiation, 24 public IAMStreamConfig, 25 public IMemAllocatorNotifyCallbackTemp 26 27 { 28 public: 29 typedef std::vector<IUnknown *>ProxyPluginVector; 30 31 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 32 33 STDMETHODIMP_(ULONG) AddRef() 34 { 35 InterlockedIncrement(&m_Ref); 36 return m_Ref; 37 } 38 STDMETHODIMP_(ULONG) Release() 39 { 40 InterlockedDecrement(&m_Ref); 41 if (!m_Ref) 42 { 43 //delete this; 44 return 0; 45 } 46 return m_Ref; 47 } 48 49 //IKsPin 50 HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList); 51 HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList); 52 HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium); 53 HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium); 54 HRESULT STDMETHODCALLTYPE KsPropagateAcquire(); 55 HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags); 56 HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment); 57 IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation); 58 HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator); 59 HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator(); 60 LONG STDMETHODCALLTYPE KsIncrementPendingIoCount(); 61 LONG STDMETHODCALLTYPE KsDecrementPendingIoCount(); 62 HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta); 63 // IKsPinEx 64 VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr); 65 66 //IKsPinPipe 67 HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option); 68 HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option); 69 IPin* STDMETHODCALLTYPE KsGetConnectedPin(); 70 IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation); 71 HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator); 72 ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag(); 73 HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag); 74 GUID STDMETHODCALLTYPE KsGetPinBusCache(); 75 HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus); 76 PWCHAR STDMETHODCALLTYPE KsGetPinName(); 77 PWCHAR STDMETHODCALLTYPE KsGetFilterName(); 78 79 //IPin methods 80 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); 81 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); 82 HRESULT STDMETHODCALLTYPE Disconnect(); 83 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin); 84 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt); 85 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo); 86 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); 87 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id); 88 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt); 89 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum); 90 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin); 91 HRESULT STDMETHODCALLTYPE EndOfStream(); 92 HRESULT STDMETHODCALLTYPE BeginFlush(); 93 HRESULT STDMETHODCALLTYPE EndFlush(); 94 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); 95 96 // ISpecifyPropertyPages 97 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages); 98 99 //IKsObject methods 100 HANDLE STDMETHODCALLTYPE KsGetObjectHandle(); 101 102 //IKsPropertySet 103 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData); 104 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned); 105 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport); 106 107 //IKsControl 108 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned); 109 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned); 110 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned); 111 112 //IStreamBuilder 113 HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph); 114 HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph); 115 116 //IKsPinFactory 117 HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory); 118 119 //IKsAggregateControl 120 HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass); 121 HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass); 122 123 //IQualityControl 124 HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q); 125 HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc); 126 127 //IMediaSeeking 128 HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities); 129 HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities); 130 HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat); 131 HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat); 132 HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat); 133 HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat); 134 HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat); 135 HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration); 136 HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop); 137 HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent); 138 HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat); 139 HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags); 140 HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop); 141 HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest); 142 HRESULT STDMETHODCALLTYPE SetRate(double dRate); 143 HRESULT STDMETHODCALLTYPE GetRate(double *pdRate); 144 HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll); 145 146 //IAMBufferNegotiation 147 HRESULT STDMETHODCALLTYPE SuggestAllocatorProperties(const ALLOCATOR_PROPERTIES *pprop); 148 HRESULT STDMETHODCALLTYPE GetAllocatorProperties(ALLOCATOR_PROPERTIES *pprop); 149 150 //IAMStreamConfig 151 HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt); 152 HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt); 153 HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize); 154 HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **ppmt, BYTE *pSCC); 155 156 //IMemAllocatorNotifyCallbackTemp 157 HRESULT STDMETHODCALLTYPE NotifyRelease(); 158 159 //--------------------------------------------------------------- 160 COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication); 161 virtual ~COutputPin(); 162 HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt); 163 HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt); 164 HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt); 165 HRESULT WINAPI IoProcessRoutine(); 166 HRESULT WINAPI InitializeIOThread(); 167 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids); 168 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids); 169 170 friend DWORD WINAPI COutputPin_IoThreadStartup(LPVOID lpParameter); 171 friend HRESULT STDMETHODCALLTYPE COutputPin_SetState(IPin * Pin, KSSTATE State); 172 173 protected: 174 LONG m_Ref; 175 IBaseFilter * m_ParentFilter; 176 LPCWSTR m_PinName; 177 HANDLE m_hPin; 178 ULONG m_PinId; 179 IPin * m_Pin; 180 IKsAllocatorEx * m_KsAllocatorEx; 181 ULONG m_PipeAllocatorFlag; 182 BOOL m_bPinBusCacheInitialized; 183 GUID m_PinBusCache; 184 LPWSTR m_FilterName; 185 FRAMING_PROP m_FramingProp[4]; 186 PKSALLOCATOR_FRAMING_EX m_FramingEx[4]; 187 188 IMemAllocator * m_MemAllocator; 189 IMemInputPin * m_MemInputPin; 190 LONG m_IoCount; 191 KSPIN_COMMUNICATION m_Communication; 192 KSPIN_INTERFACE m_Interface; 193 KSPIN_MEDIUM m_Medium; 194 AM_MEDIA_TYPE m_MediaFormat; 195 ALLOCATOR_PROPERTIES m_Properties; 196 IKsInterfaceHandler * m_InterfaceHandler; 197 198 HANDLE m_hStartEvent; 199 HANDLE m_hBufferAvailable; 200 HANDLE m_hStopEvent; 201 BOOL m_StopInProgress; 202 BOOL m_IoThreadStarted; 203 204 KSSTATE m_State; 205 CRITICAL_SECTION m_Lock; 206 207 ProxyPluginVector m_Plugins; 208 }; 209 210 COutputPin::~COutputPin() 211 { 212 } 213 214 COutputPin::COutputPin( 215 IBaseFilter * ParentFilter, 216 LPCWSTR PinName, 217 ULONG PinId, 218 KSPIN_COMMUNICATION Communication) : m_Ref(0), 219 m_ParentFilter(ParentFilter), 220 m_PinName(PinName), 221 m_hPin(INVALID_HANDLE_VALUE), 222 m_PinId(PinId), 223 m_Pin(0), 224 m_KsAllocatorEx(0), 225 m_PipeAllocatorFlag(0), 226 m_bPinBusCacheInitialized(0), 227 m_FilterName(0), 228 m_MemAllocator(0), 229 m_MemInputPin(0), 230 m_IoCount(0), 231 m_Communication(Communication), 232 m_InterfaceHandler(0), 233 m_hStartEvent(0), 234 m_hBufferAvailable(0), 235 m_hStopEvent(0), 236 m_StopInProgress(0), 237 m_IoThreadStarted(0), 238 m_State(KSSTATE_STOP), 239 m_Plugins() 240 { 241 HRESULT hr; 242 IKsObject * KsObjectParent; 243 244 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 245 assert(hr == S_OK); 246 247 ZeroMemory(m_FramingProp, sizeof(m_FramingProp)); 248 ZeroMemory(m_FramingEx, sizeof(m_FramingEx)); 249 ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE)); 250 251 hr = KsGetMediaType(0, &m_MediaFormat, KsObjectParent->KsGetObjectHandle(), m_PinId); 252 253 #ifdef KSPROXY_TRACE 254 WCHAR Buffer[100]; 255 swprintf(Buffer, L"COutputPin::COutputPin Format %p pbFormat %lu\n", &m_MediaFormat, m_MediaFormat.cbFormat); 256 OutputDebugStringW(Buffer); 257 #endif 258 259 assert(hr == S_OK); 260 261 InitializeCriticalSection(&m_Lock); 262 263 KsObjectParent->Release(); 264 }; 265 266 HRESULT 267 STDMETHODCALLTYPE 268 COutputPin::QueryInterface( 269 IN REFIID refiid, 270 OUT PVOID* Output) 271 { 272 *Output = NULL; 273 if (IsEqualGUID(refiid, IID_IUnknown) || 274 IsEqualGUID(refiid, IID_IPin)) 275 { 276 #ifdef KSPROXY_TRACE 277 OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n"); 278 #endif 279 *Output = PVOID(this); 280 reinterpret_cast<IUnknown*>(*Output)->AddRef(); 281 return NOERROR; 282 } 283 else if (IsEqualGUID(refiid, IID_IKsObject)) 284 { 285 if (m_hPin == INVALID_HANDLE_VALUE) 286 { 287 HRESULT hr = CreatePin(&m_MediaFormat); 288 if (FAILED(hr)) 289 return hr; 290 } 291 #ifdef KSPROXY_TRACE 292 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n"); 293 #endif 294 *Output = (IKsObject*)(this); 295 reinterpret_cast<IKsObject*>(*Output)->AddRef(); 296 return NOERROR; 297 } 298 else if (IsEqualGUID(refiid, IID_IKsPin) || IsEqualGUID(refiid, IID_IKsPinEx)) 299 { 300 *Output = (IKsPinEx*)(this); 301 reinterpret_cast<IKsPinEx*>(*Output)->AddRef(); 302 return NOERROR; 303 } 304 else if (IsEqualGUID(refiid, IID_IKsPinPipe)) 305 { 306 *Output = (IKsPinPipe*)(this); 307 reinterpret_cast<IKsPinPipe*>(*Output)->AddRef(); 308 return NOERROR; 309 } 310 else if (IsEqualGUID(refiid, IID_IKsAggregateControl)) 311 { 312 *Output = (IKsAggregateControl*)(this); 313 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef(); 314 return NOERROR; 315 } 316 else if (IsEqualGUID(refiid, IID_IQualityControl)) 317 { 318 *Output = (IQualityControl*)(this); 319 reinterpret_cast<IQualityControl*>(*Output)->AddRef(); 320 return NOERROR; 321 } 322 else if (IsEqualGUID(refiid, IID_IKsPropertySet)) 323 { 324 if (m_hPin == INVALID_HANDLE_VALUE) 325 { 326 HRESULT hr = CreatePin(&m_MediaFormat); 327 if (FAILED(hr)) 328 return hr; 329 } 330 #ifdef KSPROXY_TRACE 331 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n"); 332 #endif 333 *Output = (IKsPropertySet*)(this); 334 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef(); 335 return NOERROR; 336 } 337 else if (IsEqualGUID(refiid, IID_IKsControl)) 338 { 339 #ifdef KSPROXY_TRACE 340 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n"); 341 #endif 342 *Output = (IKsControl*)(this); 343 reinterpret_cast<IKsControl*>(*Output)->AddRef(); 344 return NOERROR; 345 } 346 #if 0 347 else if (IsEqualGUID(refiid, IID_IStreamBuilder)) 348 { 349 *Output = (IStreamBuilder*)(this); 350 reinterpret_cast<IStreamBuilder*>(*Output)->AddRef(); 351 return NOERROR; 352 } 353 #endif 354 else if (IsEqualGUID(refiid, IID_IKsPinFactory)) 355 { 356 #ifdef KSPROXY_TRACE 357 OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n"); 358 #endif 359 *Output = (IKsPinFactory*)(this); 360 reinterpret_cast<IKsPinFactory*>(*Output)->AddRef(); 361 return NOERROR; 362 } 363 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) 364 { 365 #ifdef KSPROXY_TRACE 366 OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n"); 367 #endif 368 *Output = (ISpecifyPropertyPages*)(this); 369 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef(); 370 return NOERROR; 371 } 372 else if (IsEqualGUID(refiid, IID_IMediaSeeking)) 373 { 374 *Output = (IMediaSeeking*)(this); 375 reinterpret_cast<IMediaSeeking*>(*Output)->AddRef(); 376 return NOERROR; 377 } 378 else if (IsEqualGUID(refiid, IID_IAMBufferNegotiation)) 379 { 380 *Output = (IAMBufferNegotiation*)(this); 381 reinterpret_cast<IAMBufferNegotiation*>(*Output)->AddRef(); 382 return NOERROR; 383 } 384 else if (IsEqualGUID(refiid, IID_IAMStreamConfig)) 385 { 386 *Output = (IAMStreamConfig*)(this); 387 reinterpret_cast<IAMStreamConfig*>(*Output)->AddRef(); 388 return NOERROR; 389 } 390 else if (IsEqualGUID(refiid, IID_IMemAllocatorNotifyCallbackTemp)) 391 { 392 *Output = (IMemAllocatorNotifyCallbackTemp*)(this); 393 reinterpret_cast<IMemAllocatorNotifyCallbackTemp*>(*Output)->AddRef(); 394 return NOERROR; 395 } 396 397 #ifdef KSPROXY_TRACE 398 WCHAR Buffer[MAX_PATH]; 399 LPOLESTR lpstr; 400 StringFromCLSID(refiid, &lpstr); 401 swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s PinId %u PinName %s\n", lpstr, m_PinId, m_PinName); 402 OutputDebugStringW(Buffer); 403 CoTaskMemFree(lpstr); 404 #endif 405 406 return E_NOINTERFACE; 407 } 408 409 //------------------------------------------------------------------- 410 // IAMBufferNegotiation interface 411 // 412 HRESULT 413 STDMETHODCALLTYPE 414 COutputPin::SuggestAllocatorProperties( 415 const ALLOCATOR_PROPERTIES *pprop) 416 { 417 #ifdef KSPROXY_TRACE 418 OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties\n"); 419 #endif 420 421 if (m_Pin) 422 { 423 // pin is already connected 424 return VFW_E_ALREADY_CONNECTED; 425 } 426 427 CopyMemory(&m_Properties, pprop, sizeof(ALLOCATOR_PROPERTIES)); 428 return NOERROR; 429 } 430 431 HRESULT 432 STDMETHODCALLTYPE 433 COutputPin::GetAllocatorProperties( 434 ALLOCATOR_PROPERTIES *pprop) 435 { 436 #ifdef KSPROXY_TRACE 437 OutputDebugStringW(L"COutputPin::GetAllocatorProperties\n"); 438 #endif 439 440 if (!m_Pin) 441 { 442 // you should call this method AFTER you connected 443 return E_UNEXPECTED; 444 } 445 446 if (!m_KsAllocatorEx) 447 { 448 // something went wrong while creating the allocator 449 return E_FAIL; 450 } 451 452 CopyMemory(pprop, &m_Properties, sizeof(ALLOCATOR_PROPERTIES)); 453 return NOERROR; 454 } 455 456 //------------------------------------------------------------------- 457 // IAMStreamConfig interface 458 // 459 HRESULT 460 STDMETHODCALLTYPE 461 COutputPin::SetFormat( 462 AM_MEDIA_TYPE *pmt) 463 { 464 #ifdef KSPROXY_TRACE 465 OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n"); 466 #endif 467 return E_NOTIMPL; 468 } 469 470 HRESULT 471 STDMETHODCALLTYPE 472 COutputPin::GetFormat(AM_MEDIA_TYPE **ppmt) 473 { 474 #ifdef KSPROXY_TRACE 475 OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n"); 476 #endif 477 return E_NOTIMPL; 478 } 479 480 HRESULT 481 STDMETHODCALLTYPE 482 COutputPin::GetNumberOfCapabilities( 483 int *piCount, 484 int *piSize) 485 { 486 #ifdef KSPROXY_TRACE 487 OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n"); 488 #endif 489 return E_NOTIMPL; 490 } 491 492 HRESULT 493 STDMETHODCALLTYPE 494 COutputPin::GetStreamCaps( 495 int iIndex, 496 AM_MEDIA_TYPE **ppmt, 497 BYTE *pSCC) 498 { 499 #ifdef KSPROXY_TRACE 500 OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n"); 501 #endif 502 return E_NOTIMPL; 503 } 504 505 //------------------------------------------------------------------- 506 // IMemAllocatorNotifyCallbackTemp interface 507 // 508 HRESULT 509 STDMETHODCALLTYPE 510 COutputPin::NotifyRelease() 511 { 512 #ifdef KSPROXY_TRACE 513 OutputDebugStringW(L"COutputPin::NotifyRelease\n"); 514 #endif 515 516 // notify thread of new available sample 517 SetEvent(m_hBufferAvailable); 518 519 return NOERROR; 520 } 521 522 //------------------------------------------------------------------- 523 // IMediaSeeking interface 524 // 525 HRESULT 526 STDMETHODCALLTYPE 527 COutputPin::GetCapabilities( 528 DWORD *pCapabilities) 529 { 530 IMediaSeeking * FilterMediaSeeking; 531 HRESULT hr; 532 533 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 534 if (FAILED(hr)) 535 return hr; 536 537 hr = FilterMediaSeeking->GetCapabilities(pCapabilities); 538 539 FilterMediaSeeking->Release(); 540 return hr; 541 } 542 543 HRESULT 544 STDMETHODCALLTYPE 545 COutputPin::CheckCapabilities( 546 DWORD *pCapabilities) 547 { 548 IMediaSeeking * FilterMediaSeeking; 549 HRESULT hr; 550 551 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 552 if (FAILED(hr)) 553 return hr; 554 555 hr = FilterMediaSeeking->CheckCapabilities(pCapabilities); 556 557 FilterMediaSeeking->Release(); 558 return hr; 559 } 560 561 HRESULT 562 STDMETHODCALLTYPE 563 COutputPin::IsFormatSupported( 564 const GUID *pFormat) 565 { 566 IMediaSeeking * FilterMediaSeeking; 567 HRESULT hr; 568 569 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 570 if (FAILED(hr)) 571 return hr; 572 573 hr = FilterMediaSeeking->IsFormatSupported(pFormat); 574 575 FilterMediaSeeking->Release(); 576 return hr; 577 } 578 579 HRESULT 580 STDMETHODCALLTYPE 581 COutputPin::QueryPreferredFormat( 582 GUID *pFormat) 583 { 584 IMediaSeeking * FilterMediaSeeking; 585 HRESULT hr; 586 587 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 588 if (FAILED(hr)) 589 return hr; 590 591 hr = FilterMediaSeeking->QueryPreferredFormat(pFormat); 592 593 FilterMediaSeeking->Release(); 594 return hr; 595 } 596 597 HRESULT 598 STDMETHODCALLTYPE 599 COutputPin::GetTimeFormat( 600 GUID *pFormat) 601 { 602 IMediaSeeking * FilterMediaSeeking; 603 HRESULT hr; 604 605 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 606 if (FAILED(hr)) 607 return hr; 608 609 hr = FilterMediaSeeking->GetTimeFormat(pFormat); 610 611 FilterMediaSeeking->Release(); 612 return hr; 613 } 614 615 HRESULT 616 STDMETHODCALLTYPE 617 COutputPin::IsUsingTimeFormat( 618 const GUID *pFormat) 619 { 620 IMediaSeeking * FilterMediaSeeking; 621 HRESULT hr; 622 623 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 624 if (FAILED(hr)) 625 return hr; 626 627 hr = FilterMediaSeeking->IsUsingTimeFormat(pFormat); 628 629 FilterMediaSeeking->Release(); 630 return hr; 631 } 632 633 HRESULT 634 STDMETHODCALLTYPE 635 COutputPin::SetTimeFormat( 636 const GUID *pFormat) 637 { 638 IMediaSeeking * FilterMediaSeeking; 639 HRESULT hr; 640 641 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 642 if (FAILED(hr)) 643 return hr; 644 645 hr = FilterMediaSeeking->SetTimeFormat(pFormat); 646 647 FilterMediaSeeking->Release(); 648 return hr; 649 } 650 651 HRESULT 652 STDMETHODCALLTYPE 653 COutputPin::GetDuration( 654 LONGLONG *pDuration) 655 { 656 IMediaSeeking * FilterMediaSeeking; 657 HRESULT hr; 658 659 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 660 if (FAILED(hr)) 661 return hr; 662 663 hr = FilterMediaSeeking->GetDuration(pDuration); 664 665 FilterMediaSeeking->Release(); 666 return hr; 667 } 668 669 HRESULT 670 STDMETHODCALLTYPE 671 COutputPin::GetStopPosition( 672 LONGLONG *pStop) 673 { 674 IMediaSeeking * FilterMediaSeeking; 675 HRESULT hr; 676 677 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 678 if (FAILED(hr)) 679 return hr; 680 681 hr = FilterMediaSeeking->GetStopPosition(pStop); 682 683 FilterMediaSeeking->Release(); 684 return hr; 685 } 686 687 688 HRESULT 689 STDMETHODCALLTYPE 690 COutputPin::GetCurrentPosition( 691 LONGLONG *pCurrent) 692 { 693 IMediaSeeking * FilterMediaSeeking; 694 HRESULT hr; 695 696 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 697 if (FAILED(hr)) 698 return hr; 699 700 hr = FilterMediaSeeking->GetCurrentPosition(pCurrent); 701 702 FilterMediaSeeking->Release(); 703 return hr; 704 } 705 706 HRESULT 707 STDMETHODCALLTYPE 708 COutputPin::ConvertTimeFormat( 709 LONGLONG *pTarget, 710 const GUID *pTargetFormat, 711 LONGLONG Source, 712 const GUID *pSourceFormat) 713 { 714 IMediaSeeking * FilterMediaSeeking; 715 HRESULT hr; 716 717 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 718 if (FAILED(hr)) 719 return hr; 720 721 hr = FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat); 722 723 FilterMediaSeeking->Release(); 724 return hr; 725 } 726 727 HRESULT 728 STDMETHODCALLTYPE 729 COutputPin::SetPositions( 730 LONGLONG *pCurrent, 731 DWORD dwCurrentFlags, 732 LONGLONG *pStop, 733 DWORD dwStopFlags) 734 { 735 IMediaSeeking * FilterMediaSeeking; 736 HRESULT hr; 737 738 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 739 if (FAILED(hr)) 740 return hr; 741 742 hr = FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags); 743 744 FilterMediaSeeking->Release(); 745 return hr; 746 } 747 748 HRESULT 749 STDMETHODCALLTYPE 750 COutputPin::GetPositions( 751 LONGLONG *pCurrent, 752 LONGLONG *pStop) 753 { 754 IMediaSeeking * FilterMediaSeeking; 755 HRESULT hr; 756 757 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 758 if (FAILED(hr)) 759 return hr; 760 761 hr = FilterMediaSeeking->GetPositions(pCurrent, pStop); 762 763 FilterMediaSeeking->Release(); 764 return hr; 765 } 766 767 HRESULT 768 STDMETHODCALLTYPE 769 COutputPin::GetAvailable( 770 LONGLONG *pEarliest, 771 LONGLONG *pLatest) 772 { 773 IMediaSeeking * FilterMediaSeeking; 774 HRESULT hr; 775 776 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 777 if (FAILED(hr)) 778 return hr; 779 780 hr = FilterMediaSeeking->GetAvailable(pEarliest, pLatest); 781 782 FilterMediaSeeking->Release(); 783 return hr; 784 } 785 786 HRESULT 787 STDMETHODCALLTYPE 788 COutputPin::SetRate( 789 double dRate) 790 { 791 IMediaSeeking * FilterMediaSeeking; 792 HRESULT hr; 793 794 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 795 if (FAILED(hr)) 796 return hr; 797 798 hr = FilterMediaSeeking->SetRate(dRate); 799 800 FilterMediaSeeking->Release(); 801 return hr; 802 } 803 804 HRESULT 805 STDMETHODCALLTYPE 806 COutputPin::GetRate( 807 double *pdRate) 808 { 809 IMediaSeeking * FilterMediaSeeking; 810 HRESULT hr; 811 812 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 813 if (FAILED(hr)) 814 return hr; 815 816 hr = FilterMediaSeeking->GetRate(pdRate); 817 818 FilterMediaSeeking->Release(); 819 return hr; 820 } 821 822 HRESULT 823 STDMETHODCALLTYPE 824 COutputPin::GetPreroll( 825 LONGLONG *pllPreroll) 826 { 827 IMediaSeeking * FilterMediaSeeking; 828 HRESULT hr; 829 830 hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); 831 if (FAILED(hr)) 832 return hr; 833 834 hr = FilterMediaSeeking->GetPreroll(pllPreroll); 835 836 FilterMediaSeeking->Release(); 837 return hr; 838 } 839 840 //------------------------------------------------------------------- 841 // IQualityControl interface 842 // 843 HRESULT 844 STDMETHODCALLTYPE 845 COutputPin::Notify( 846 IBaseFilter *pSelf, 847 Quality q) 848 { 849 #ifdef KSPROXY_TRACE 850 OutputDebugStringW(L"COutputPin::Notify NotImplemented\n"); 851 #endif 852 return E_NOTIMPL; 853 } 854 855 HRESULT 856 STDMETHODCALLTYPE 857 COutputPin::SetSink( 858 IQualityControl *piqc) 859 { 860 #ifdef KSPROXY_TRACE 861 OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n"); 862 #endif 863 return E_NOTIMPL; 864 } 865 866 867 //------------------------------------------------------------------- 868 // IKsAggregateControl interface 869 // 870 HRESULT 871 STDMETHODCALLTYPE 872 COutputPin::KsAddAggregate( 873 IN REFGUID AggregateClass) 874 { 875 #ifdef KSPROXY_TRACE 876 OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n"); 877 #endif 878 return E_NOTIMPL; 879 } 880 881 HRESULT 882 STDMETHODCALLTYPE 883 COutputPin::KsRemoveAggregate( 884 REFGUID AggregateClass) 885 { 886 #ifdef KSPROXY_TRACE 887 OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n"); 888 #endif 889 return E_NOTIMPL; 890 } 891 892 893 //------------------------------------------------------------------- 894 // IKsPin 895 // 896 897 HRESULT 898 STDMETHODCALLTYPE 899 COutputPin::KsQueryMediums( 900 PKSMULTIPLE_ITEM* MediumList) 901 { 902 HRESULT hr; 903 HANDLE hFilter; 904 IKsObject * KsObjectParent; 905 906 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 907 if (FAILED(hr)) 908 return E_NOINTERFACE; 909 910 hFilter = KsObjectParent->KsGetObjectHandle(); 911 912 if (hFilter) 913 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList); 914 else 915 hr = E_HANDLE; 916 917 KsObjectParent->Release(); 918 919 return hr; 920 } 921 922 HRESULT 923 STDMETHODCALLTYPE 924 COutputPin::KsQueryInterfaces( 925 PKSMULTIPLE_ITEM* InterfaceList) 926 { 927 HRESULT hr; 928 HANDLE hFilter; 929 IKsObject * KsObjectParent; 930 931 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 932 if (FAILED(hr)) 933 return hr; 934 935 hFilter = KsObjectParent->KsGetObjectHandle(); 936 937 if (hFilter) 938 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList); 939 else 940 hr = E_HANDLE; 941 942 KsObjectParent->Release(); 943 944 return hr; 945 } 946 947 HRESULT 948 STDMETHODCALLTYPE 949 COutputPin::KsCreateSinkPinHandle( 950 KSPIN_INTERFACE& Interface, 951 KSPIN_MEDIUM& Medium) 952 { 953 #ifdef KSPROXY_TRACE 954 OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n"); 955 #endif 956 return E_NOTIMPL; 957 } 958 959 HRESULT 960 STDMETHODCALLTYPE 961 COutputPin::KsGetCurrentCommunication( 962 KSPIN_COMMUNICATION *Communication, 963 KSPIN_INTERFACE *Interface, 964 KSPIN_MEDIUM *Medium) 965 { 966 if (Communication) 967 { 968 *Communication = m_Communication; 969 } 970 971 if (Interface) 972 { 973 if (!m_hPin) 974 return VFW_E_NOT_CONNECTED; 975 976 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE)); 977 } 978 979 if (Medium) 980 { 981 if (!m_hPin) 982 return VFW_E_NOT_CONNECTED; 983 984 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM)); 985 } 986 return NOERROR; 987 } 988 989 HRESULT 990 STDMETHODCALLTYPE 991 COutputPin::KsPropagateAcquire() 992 { 993 KSPROPERTY Property; 994 KSSTATE State; 995 ULONG BytesReturned; 996 HRESULT hr; 997 998 #ifdef KSPROXY_TRACE 999 OutputDebugStringW(L"COutputPin::KsPropagateAcquire\n"); 1000 #endif 1001 1002 assert(m_hPin != INVALID_HANDLE_VALUE); 1003 1004 Property.Set = KSPROPSETID_Connection; 1005 Property.Id = KSPROPERTY_CONNECTION_STATE; 1006 Property.Flags = KSPROPERTY_TYPE_SET; 1007 1008 State = KSSTATE_ACQUIRE; 1009 1010 hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned); 1011 if (SUCCEEDED(hr)) 1012 { 1013 m_State = State; 1014 } 1015 1016 //TODO 1017 //propagate to connected pin on the pipe 1018 1019 return hr; 1020 } 1021 1022 HRESULT 1023 STDMETHODCALLTYPE 1024 COutputPin::KsDeliver( 1025 IMediaSample* Sample, 1026 ULONG Flags) 1027 { 1028 return E_FAIL; 1029 } 1030 1031 HRESULT 1032 STDMETHODCALLTYPE 1033 COutputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment) 1034 { 1035 return NOERROR; 1036 } 1037 1038 IMemAllocator * 1039 STDMETHODCALLTYPE 1040 COutputPin::KsPeekAllocator(KSPEEKOPERATION Operation) 1041 { 1042 if (Operation == KsPeekOperation_AddRef) 1043 { 1044 // add reference on allocator 1045 m_MemAllocator->AddRef(); 1046 } 1047 1048 return m_MemAllocator; 1049 } 1050 1051 HRESULT 1052 STDMETHODCALLTYPE 1053 COutputPin::KsReceiveAllocator(IMemAllocator *MemAllocator) 1054 { 1055 if (MemAllocator) 1056 { 1057 MemAllocator->AddRef(); 1058 } 1059 1060 if (m_MemAllocator) 1061 { 1062 m_MemAllocator->Release(); 1063 } 1064 1065 m_MemAllocator = MemAllocator; 1066 return NOERROR; 1067 } 1068 1069 HRESULT 1070 STDMETHODCALLTYPE 1071 COutputPin::KsRenegotiateAllocator() 1072 { 1073 return E_FAIL; 1074 } 1075 1076 LONG 1077 STDMETHODCALLTYPE 1078 COutputPin::KsIncrementPendingIoCount() 1079 { 1080 return InterlockedIncrement((volatile LONG*)&m_IoCount); 1081 } 1082 1083 LONG 1084 STDMETHODCALLTYPE 1085 COutputPin::KsDecrementPendingIoCount() 1086 { 1087 return InterlockedDecrement((volatile LONG*)&m_IoCount); 1088 } 1089 1090 HRESULT 1091 STDMETHODCALLTYPE 1092 COutputPin::KsQualityNotify( 1093 ULONG Proportion, 1094 REFERENCE_TIME TimeDelta) 1095 { 1096 #ifdef KSPROXY_TRACE 1097 OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n"); 1098 #endif 1099 return E_NOTIMPL; 1100 } 1101 1102 //------------------------------------------------------------------- 1103 // IKsPinEx 1104 // 1105 1106 VOID 1107 STDMETHODCALLTYPE 1108 COutputPin::KsNotifyError( 1109 IMediaSample* Sample, 1110 HRESULT hr) 1111 { 1112 #ifdef KSPROXY_TRACE 1113 OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n"); 1114 #endif 1115 } 1116 1117 1118 //------------------------------------------------------------------- 1119 // IKsPinPipe 1120 // 1121 1122 HRESULT 1123 STDMETHODCALLTYPE 1124 COutputPin::KsGetPinFramingCache( 1125 PKSALLOCATOR_FRAMING_EX *FramingEx, 1126 PFRAMING_PROP FramingProp, 1127 FRAMING_CACHE_OPS Option) 1128 { 1129 if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast) 1130 { 1131 // invalid argument 1132 return E_INVALIDARG; 1133 } 1134 1135 // get framing properties 1136 *FramingProp = m_FramingProp[Option]; 1137 *FramingEx = m_FramingEx[Option]; 1138 1139 return NOERROR; 1140 } 1141 1142 HRESULT 1143 STDMETHODCALLTYPE 1144 COutputPin::KsSetPinFramingCache( 1145 PKSALLOCATOR_FRAMING_EX FramingEx, 1146 PFRAMING_PROP FramingProp, 1147 FRAMING_CACHE_OPS Option) 1148 { 1149 ULONG Index; 1150 ULONG RefCount = 0; 1151 1152 if (m_FramingEx[Option]) 1153 { 1154 for(Index = 1; Index < 4; Index++) 1155 { 1156 if (m_FramingEx[Index] == m_FramingEx[Option]) 1157 RefCount++; 1158 } 1159 1160 if (RefCount == 1) 1161 { 1162 // existing framing is only used once 1163 CoTaskMemFree(m_FramingEx[Option]); 1164 } 1165 } 1166 1167 // store framing 1168 m_FramingEx[Option] = FramingEx; 1169 m_FramingProp[Option] = *FramingProp; 1170 1171 return S_OK; 1172 } 1173 1174 IPin* 1175 STDMETHODCALLTYPE 1176 COutputPin::KsGetConnectedPin() 1177 { 1178 return m_Pin; 1179 } 1180 1181 IKsAllocatorEx* 1182 STDMETHODCALLTYPE 1183 COutputPin::KsGetPipe( 1184 KSPEEKOPERATION Operation) 1185 { 1186 if (Operation == KsPeekOperation_AddRef) 1187 { 1188 if (m_KsAllocatorEx) 1189 m_KsAllocatorEx->AddRef(); 1190 } 1191 return m_KsAllocatorEx; 1192 } 1193 1194 HRESULT 1195 STDMETHODCALLTYPE 1196 COutputPin::KsSetPipe( 1197 IKsAllocatorEx *KsAllocator) 1198 { 1199 if (KsAllocator) 1200 KsAllocator->AddRef(); 1201 1202 if (m_KsAllocatorEx) 1203 m_KsAllocatorEx->Release(); 1204 1205 m_KsAllocatorEx = KsAllocator; 1206 return NOERROR; 1207 } 1208 1209 ULONG 1210 STDMETHODCALLTYPE 1211 COutputPin::KsGetPipeAllocatorFlag() 1212 { 1213 return m_PipeAllocatorFlag; 1214 } 1215 1216 1217 HRESULT 1218 STDMETHODCALLTYPE 1219 COutputPin::KsSetPipeAllocatorFlag( 1220 ULONG Flag) 1221 { 1222 m_PipeAllocatorFlag = Flag; 1223 return NOERROR; 1224 } 1225 1226 GUID 1227 STDMETHODCALLTYPE 1228 COutputPin::KsGetPinBusCache() 1229 { 1230 if (!m_bPinBusCacheInitialized) 1231 { 1232 CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID)); 1233 m_bPinBusCacheInitialized = TRUE; 1234 } 1235 1236 return m_PinBusCache; 1237 } 1238 1239 HRESULT 1240 STDMETHODCALLTYPE 1241 COutputPin::KsSetPinBusCache( 1242 GUID Bus) 1243 { 1244 CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID)); 1245 return NOERROR; 1246 } 1247 1248 PWCHAR 1249 STDMETHODCALLTYPE 1250 COutputPin::KsGetPinName() 1251 { 1252 return (PWCHAR)m_PinName; 1253 } 1254 1255 1256 PWCHAR 1257 STDMETHODCALLTYPE 1258 COutputPin::KsGetFilterName() 1259 { 1260 return m_FilterName; 1261 } 1262 1263 //------------------------------------------------------------------- 1264 // ISpecifyPropertyPages 1265 // 1266 1267 HRESULT 1268 STDMETHODCALLTYPE 1269 COutputPin::GetPages(CAUUID *pPages) 1270 { 1271 #ifdef KSPROXY_TRACE 1272 OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n"); 1273 #endif 1274 1275 if (!pPages) 1276 return E_POINTER; 1277 1278 pPages->cElems = 0; 1279 pPages->pElems = NULL; 1280 1281 return S_OK; 1282 } 1283 1284 //------------------------------------------------------------------- 1285 // IKsPinFactory 1286 // 1287 1288 HRESULT 1289 STDMETHODCALLTYPE 1290 COutputPin::KsPinFactory( 1291 ULONG* PinFactory) 1292 { 1293 #ifdef KSPROXY_TRACE 1294 OutputDebugStringW(L"COutputPin::KsPinFactory\n"); 1295 #endif 1296 1297 *PinFactory = m_PinId; 1298 return S_OK; 1299 } 1300 1301 1302 //------------------------------------------------------------------- 1303 // IStreamBuilder 1304 // 1305 1306 HRESULT 1307 STDMETHODCALLTYPE 1308 COutputPin::Render( 1309 IPin *ppinOut, 1310 IGraphBuilder *pGraph) 1311 { 1312 #ifdef KSPROXY_TRACE 1313 OutputDebugStringW(L"COutputPin::Render\n"); 1314 #endif 1315 return S_OK; 1316 } 1317 1318 HRESULT 1319 STDMETHODCALLTYPE 1320 COutputPin::Backout( 1321 IPin *ppinOut, 1322 IGraphBuilder *pGraph) 1323 { 1324 #ifdef KSPROXY_TRACE 1325 OutputDebugStringW(L"COutputPin::Backout\n"); 1326 #endif 1327 1328 return S_OK; 1329 } 1330 //------------------------------------------------------------------- 1331 // IKsObject 1332 // 1333 HANDLE 1334 STDMETHODCALLTYPE 1335 COutputPin::KsGetObjectHandle() 1336 { 1337 #ifdef KSPROXY_TRACE 1338 OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n"); 1339 #endif 1340 1341 assert(m_hPin != INVALID_HANDLE_VALUE); 1342 return m_hPin; 1343 } 1344 1345 //------------------------------------------------------------------- 1346 // IKsControl 1347 // 1348 HRESULT 1349 STDMETHODCALLTYPE 1350 COutputPin::KsProperty( 1351 PKSPROPERTY Property, 1352 ULONG PropertyLength, 1353 LPVOID PropertyData, 1354 ULONG DataLength, 1355 ULONG* BytesReturned) 1356 { 1357 HRESULT hr; 1358 1359 assert(m_hPin != INVALID_HANDLE_VALUE); 1360 1361 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned); 1362 #ifdef KSPROXY_TRACE 1363 WCHAR Buffer[100]; 1364 LPOLESTR pstr; 1365 StringFromCLSID(Property->Set, &pstr); 1366 swprintf(Buffer, L"COutputPin::KsProperty Set %s Id %lu Flags %x hr %x\n", pstr, Property->Id, Property->Flags, hr); 1367 OutputDebugStringW(Buffer); 1368 #endif 1369 1370 return hr; 1371 } 1372 1373 HRESULT 1374 STDMETHODCALLTYPE 1375 COutputPin::KsMethod( 1376 PKSMETHOD Method, 1377 ULONG MethodLength, 1378 LPVOID MethodData, 1379 ULONG DataLength, 1380 ULONG* BytesReturned) 1381 { 1382 assert(m_hPin != INVALID_HANDLE_VALUE); 1383 #ifdef KSPROXY_TRACE 1384 OutputDebugStringW(L"COutputPin::KsMethod\n"); 1385 #endif 1386 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned); 1387 } 1388 1389 HRESULT 1390 STDMETHODCALLTYPE 1391 COutputPin::KsEvent( 1392 PKSEVENT Event, 1393 ULONG EventLength, 1394 LPVOID EventData, 1395 ULONG DataLength, 1396 ULONG* BytesReturned) 1397 { 1398 assert(m_hPin != INVALID_HANDLE_VALUE); 1399 1400 #ifdef KSPROXY_TRACE 1401 OutputDebugStringW(L"COutputPin::KsEvent\n"); 1402 #endif 1403 1404 if (EventLength) 1405 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned); 1406 else 1407 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned); 1408 } 1409 1410 1411 //------------------------------------------------------------------- 1412 // IKsPropertySet 1413 // 1414 HRESULT 1415 STDMETHODCALLTYPE 1416 COutputPin::Set( 1417 REFGUID guidPropSet, 1418 DWORD dwPropID, 1419 LPVOID pInstanceData, 1420 DWORD cbInstanceData, 1421 LPVOID pPropData, 1422 DWORD cbPropData) 1423 { 1424 ULONG BytesReturned; 1425 1426 if (cbInstanceData) 1427 { 1428 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); 1429 if (!Property) 1430 return E_OUTOFMEMORY; 1431 1432 Property->Set = guidPropSet; 1433 Property->Id = dwPropID; 1434 Property->Flags = KSPROPERTY_TYPE_SET; 1435 1436 CopyMemory((Property+1), pInstanceData, cbInstanceData); 1437 1438 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); 1439 CoTaskMemFree(Property); 1440 return hr; 1441 } 1442 else 1443 { 1444 KSPROPERTY Property; 1445 1446 Property.Set = guidPropSet; 1447 Property.Id = dwPropID; 1448 Property.Flags = KSPROPERTY_TYPE_SET; 1449 1450 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); 1451 return hr; 1452 } 1453 } 1454 1455 HRESULT 1456 STDMETHODCALLTYPE 1457 COutputPin::Get( 1458 REFGUID guidPropSet, 1459 DWORD dwPropID, 1460 LPVOID pInstanceData, 1461 DWORD cbInstanceData, 1462 LPVOID pPropData, 1463 DWORD cbPropData, 1464 DWORD *pcbReturned) 1465 { 1466 ULONG BytesReturned; 1467 1468 if (cbInstanceData) 1469 { 1470 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); 1471 if (!Property) 1472 return E_OUTOFMEMORY; 1473 1474 Property->Set = guidPropSet; 1475 Property->Id = dwPropID; 1476 Property->Flags = KSPROPERTY_TYPE_GET; 1477 1478 CopyMemory((Property+1), pInstanceData, cbInstanceData); 1479 1480 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); 1481 CoTaskMemFree(Property); 1482 return hr; 1483 } 1484 else 1485 { 1486 KSPROPERTY Property; 1487 1488 Property.Set = guidPropSet; 1489 Property.Id = dwPropID; 1490 Property.Flags = KSPROPERTY_TYPE_GET; 1491 1492 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); 1493 return hr; 1494 } 1495 } 1496 1497 HRESULT 1498 STDMETHODCALLTYPE 1499 COutputPin::QuerySupported( 1500 REFGUID guidPropSet, 1501 DWORD dwPropID, 1502 DWORD *pTypeSupport) 1503 { 1504 KSPROPERTY Property; 1505 ULONG BytesReturned; 1506 1507 #ifdef KSPROXY_TRACE 1508 OutputDebugStringW(L"COutputPin::QuerySupported\n"); 1509 #endif 1510 1511 Property.Set = guidPropSet; 1512 Property.Id = dwPropID; 1513 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; 1514 1515 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned); 1516 } 1517 1518 1519 //------------------------------------------------------------------- 1520 // IPin interface 1521 // 1522 HRESULT 1523 STDMETHODCALLTYPE 1524 COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) 1525 { 1526 HRESULT hr; 1527 ALLOCATOR_PROPERTIES Properties; 1528 IMemAllocatorCallbackTemp *pMemCallback; 1529 LPGUID pGuid; 1530 ULONG NumGuids = 0; 1531 1532 #ifdef KSPROXY_TRACE 1533 WCHAR Buffer[200]; 1534 OutputDebugStringW(L"COutputPin::Connect called\n"); 1535 #endif 1536 1537 if (pmt) 1538 { 1539 hr = pReceivePin->QueryAccept(pmt); 1540 if (FAILED(hr)) 1541 return hr; 1542 } 1543 else 1544 { 1545 // query accept 1546 hr = pReceivePin->QueryAccept(&m_MediaFormat); 1547 if (FAILED(hr)) 1548 return hr; 1549 1550 pmt = &m_MediaFormat; 1551 } 1552 1553 if (m_hPin == INVALID_HANDLE_VALUE) 1554 { 1555 hr = CreatePin(pmt); 1556 if (FAILED(hr)) 1557 { 1558 #ifdef KSPROXY_TRACE 1559 swprintf(Buffer, L"COutputPin::Connect CreatePin handle failed with %lx\n", hr); 1560 OutputDebugStringW(Buffer); 1561 #endif 1562 return hr; 1563 } 1564 } 1565 1566 1567 // query for IMemInput interface 1568 hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin); 1569 if (FAILED(hr)) 1570 { 1571 #ifdef KSPROXY_TRACE 1572 OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n"); 1573 #endif 1574 1575 return hr; 1576 } 1577 1578 // get input pin allocator properties 1579 ZeroMemory(&Properties, sizeof(ALLOCATOR_PROPERTIES)); 1580 m_MemInputPin->GetAllocatorRequirements(&Properties); 1581 1582 //FIXME determine allocator properties 1583 Properties.cBuffers = 32; 1584 Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size 1585 Properties.cbAlign = 4; 1586 1587 // get input pin allocator 1588 #if 0 1589 hr = m_MemInputPin->GetAllocator(&m_MemAllocator); 1590 if (SUCCEEDED(hr)) 1591 { 1592 // set allocator properties 1593 hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); 1594 if (FAILED(hr)) 1595 m_MemAllocator->Release(); 1596 } 1597 #endif 1598 1599 if (1) 1600 { 1601 hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator); 1602 if (FAILED(hr)) 1603 return hr; 1604 1605 // set allocator properties 1606 hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); 1607 if (FAILED(hr)) 1608 { 1609 #ifdef KSPROXY_TRACE 1610 swprintf(Buffer, L"COutputPin::Connect IMemAllocator::SetProperties failed with hr %lx\n", hr); 1611 OutputDebugStringW(Buffer); 1612 #endif 1613 m_MemAllocator->Release(); 1614 m_MemInputPin->Release(); 1615 return hr; 1616 } 1617 } 1618 1619 // commit property changes 1620 hr = m_MemAllocator->Commit(); 1621 if (FAILED(hr)) 1622 { 1623 #ifdef KSPROXY_TRACE 1624 swprintf(Buffer, L"COutputPin::Connect IMemAllocator::Commit failed with hr %lx\n", hr); 1625 OutputDebugStringW(Buffer); 1626 #endif 1627 m_MemAllocator->Release(); 1628 m_MemInputPin->Release(); 1629 return hr; 1630 } 1631 1632 // get callback interface 1633 hr = m_MemAllocator->QueryInterface(IID_IMemAllocatorCallbackTemp, (void**)&pMemCallback); 1634 if (FAILED(hr)) 1635 { 1636 #ifdef KSPROXY_TRACE 1637 swprintf(Buffer, L"COutputPin::Connect No IMemAllocatorCallbackTemp interface hr %lx\n", hr); 1638 OutputDebugStringW(Buffer); 1639 #endif 1640 m_MemAllocator->Release(); 1641 m_MemInputPin->Release(); 1642 return hr; 1643 } 1644 1645 // set notification routine 1646 hr = pMemCallback->SetNotify((IMemAllocatorNotifyCallbackTemp*)this); 1647 1648 // release IMemAllocatorNotifyCallbackTemp interface 1649 pMemCallback->Release(); 1650 1651 if (FAILED(hr)) 1652 { 1653 #ifdef KSPROXY_TRACE 1654 swprintf(Buffer, L"COutputPin::Connect IMemAllocatorNotifyCallbackTemp::SetNotify failed hr %lx\n", hr); 1655 OutputDebugStringW(Buffer); 1656 #endif 1657 m_MemAllocator->Release(); 1658 m_MemInputPin->Release(); 1659 return hr; 1660 } 1661 1662 // now set allocator 1663 hr = m_MemInputPin->NotifyAllocator(m_MemAllocator, TRUE); 1664 if (FAILED(hr)) 1665 { 1666 #ifdef KSPROXY_TRACE 1667 swprintf(Buffer, L"COutputPin::Connect IMemInputPin::NotifyAllocator failed with hr %lx\n", hr); 1668 OutputDebugStringW(Buffer); 1669 #endif 1670 m_MemAllocator->Release(); 1671 m_MemInputPin->Release(); 1672 return hr; 1673 } 1674 1675 1676 assert(m_hPin != INVALID_HANDLE_VALUE); 1677 1678 // get all supported sets 1679 if (m_Plugins.empty()) 1680 { 1681 if (GetSupportedSets(&pGuid, &NumGuids)) 1682 { 1683 // load all proxy plugins 1684 if (FAILED(LoadProxyPlugins(pGuid, NumGuids))) 1685 { 1686 #ifdef KSPROXY_TRACE 1687 OutputDebugStringW(L"COutputPin::Connect LoadProxyPlugins failed\n"); 1688 #endif 1689 } 1690 // free sets 1691 CoTaskMemFree(pGuid); 1692 } 1693 } 1694 1695 // receive connection; 1696 hr = pReceivePin->ReceiveConnection((IPin*)this, pmt); 1697 if (SUCCEEDED(hr)) 1698 { 1699 // increment reference count 1700 pReceivePin->AddRef(); 1701 m_Pin = pReceivePin; 1702 #ifdef KSPROXY_TRACE 1703 OutputDebugStringW(L"COutputPin::Connect success\n"); 1704 #endif 1705 } 1706 else 1707 { 1708 m_MemInputPin->Release(); 1709 m_MemAllocator->Release(); 1710 } 1711 1712 return hr; 1713 } 1714 1715 HRESULT 1716 STDMETHODCALLTYPE 1717 COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) 1718 { 1719 return E_UNEXPECTED; 1720 } 1721 HRESULT 1722 STDMETHODCALLTYPE 1723 COutputPin::Disconnect( void) 1724 { 1725 #ifdef KSPROXY_TRACE 1726 OutputDebugStringW(L"COutputPin::Disconnect\n"); 1727 #endif 1728 1729 if (!m_Pin) 1730 { 1731 // pin was not connected 1732 return S_FALSE; 1733 } 1734 1735 //FIXME 1736 //check if filter is active 1737 1738 m_Pin->Release(); 1739 m_Pin = NULL; 1740 m_MemInputPin->Release(); 1741 m_MemAllocator->Release(); 1742 1743 CloseHandle(m_hPin); 1744 m_hPin = INVALID_HANDLE_VALUE; 1745 1746 #ifdef KSPROXY_TRACE 1747 OutputDebugStringW(L"COutputPin::Disconnect\n"); 1748 #endif 1749 return S_OK; 1750 } 1751 HRESULT 1752 STDMETHODCALLTYPE 1753 COutputPin::ConnectedTo(IPin **pPin) 1754 { 1755 #ifdef KSPROXY_TRACE 1756 OutputDebugStringW(L"COutputPin::ConnectedTo\n"); 1757 #endif 1758 1759 if (!pPin) 1760 return E_POINTER; 1761 1762 if (m_Pin) 1763 { 1764 // increment reference count 1765 m_Pin->AddRef(); 1766 *pPin = m_Pin; 1767 return S_OK; 1768 } 1769 1770 *pPin = NULL; 1771 return VFW_E_NOT_CONNECTED; 1772 } 1773 HRESULT 1774 STDMETHODCALLTYPE 1775 COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) 1776 { 1777 #ifdef KSPROXY_TRACE 1778 OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n"); 1779 #endif 1780 1781 return E_NOTIMPL; 1782 } 1783 HRESULT 1784 STDMETHODCALLTYPE 1785 COutputPin::QueryPinInfo(PIN_INFO *pInfo) 1786 { 1787 wcscpy(pInfo->achName, m_PinName); 1788 pInfo->dir = PINDIR_OUTPUT; 1789 pInfo->pFilter = m_ParentFilter; 1790 m_ParentFilter->AddRef(); 1791 1792 return S_OK; 1793 } 1794 HRESULT 1795 STDMETHODCALLTYPE 1796 COutputPin::QueryDirection(PIN_DIRECTION *pPinDir) 1797 { 1798 if (pPinDir) 1799 { 1800 *pPinDir = PINDIR_OUTPUT; 1801 return S_OK; 1802 } 1803 1804 return E_POINTER; 1805 } 1806 HRESULT 1807 STDMETHODCALLTYPE 1808 COutputPin::QueryId(LPWSTR *Id) 1809 { 1810 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR)); 1811 if (!*Id) 1812 return E_OUTOFMEMORY; 1813 1814 wcscpy(*Id, m_PinName); 1815 return S_OK; 1816 } 1817 HRESULT 1818 STDMETHODCALLTYPE 1819 COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt) 1820 { 1821 #ifdef KSPROXY_TRACE 1822 OutputDebugStringW(L"COutputPin::QueryAccept called\n"); 1823 #endif 1824 1825 return E_NOTIMPL; 1826 } 1827 HRESULT 1828 STDMETHODCALLTYPE 1829 COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) 1830 { 1831 HRESULT hr; 1832 ULONG MediaTypeCount = 0, Index; 1833 AM_MEDIA_TYPE * MediaTypes; 1834 HANDLE hFilter; 1835 IKsObject * KsObjectParent; 1836 1837 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 1838 if (FAILED(hr)) 1839 return hr; 1840 1841 // get parent filter handle 1842 hFilter = KsObjectParent->KsGetObjectHandle(); 1843 1844 // release IKsObject 1845 KsObjectParent->Release(); 1846 1847 // query media type count 1848 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount); 1849 if (FAILED(hr) || !MediaTypeCount) 1850 { 1851 return hr; 1852 } 1853 1854 // allocate media types 1855 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount); 1856 if (!MediaTypes) 1857 { 1858 // not enough memory 1859 return E_OUTOFMEMORY; 1860 } 1861 1862 // zero media types 1863 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount); 1864 1865 for(Index = 0; Index < MediaTypeCount; Index++) 1866 { 1867 // get media type 1868 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId); 1869 if (FAILED(hr)) 1870 { 1871 // failed 1872 CoTaskMemFree(MediaTypes); 1873 return hr; 1874 } 1875 } 1876 1877 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum); 1878 } 1879 HRESULT 1880 STDMETHODCALLTYPE 1881 COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) 1882 { 1883 return E_NOTIMPL; 1884 } 1885 HRESULT 1886 STDMETHODCALLTYPE 1887 COutputPin::EndOfStream( void) 1888 { 1889 /* should be called only on input pins */ 1890 return E_UNEXPECTED; 1891 } 1892 HRESULT 1893 STDMETHODCALLTYPE 1894 COutputPin::BeginFlush( void) 1895 { 1896 /* should be called only on input pins */ 1897 return E_UNEXPECTED; 1898 } 1899 HRESULT 1900 STDMETHODCALLTYPE 1901 COutputPin::EndFlush( void) 1902 { 1903 /* should be called only on input pins */ 1904 return E_UNEXPECTED; 1905 } 1906 HRESULT 1907 STDMETHODCALLTYPE 1908 COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) 1909 { 1910 if (!m_Pin) 1911 { 1912 // we are not connected 1913 return VFW_E_NOT_CONNECTED; 1914 } 1915 1916 return m_Pin->NewSegment(tStart, tStop, dRate); 1917 } 1918 1919 //------------------------------------------------------------------- 1920 HRESULT 1921 STDMETHODCALLTYPE 1922 COutputPin::CheckFormat( 1923 const AM_MEDIA_TYPE *pmt) 1924 { 1925 PKSMULTIPLE_ITEM MultipleItem; 1926 PKSDATAFORMAT DataFormat; 1927 HRESULT hr; 1928 IKsObject * KsObjectParent; 1929 HANDLE hFilter; 1930 1931 if (!pmt) 1932 return E_POINTER; 1933 1934 // get IKsObject interface 1935 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 1936 if (FAILED(hr)) 1937 return hr; 1938 1939 // get parent filter handle 1940 hFilter = KsObjectParent->KsGetObjectHandle(); 1941 1942 // release IKsObject 1943 KsObjectParent->Release(); 1944 1945 if (!hFilter) 1946 return E_HANDLE; 1947 1948 1949 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem); 1950 if (FAILED(hr)) 1951 return S_FALSE; 1952 1953 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1); 1954 for(ULONG Index = 0; Index < MultipleItem->Count; Index++) 1955 { 1956 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) && 1957 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) && 1958 IsEqualGUID(pmt->formattype, DataFormat->Specifier)) 1959 { 1960 // format is supported 1961 CoTaskMemFree(MultipleItem); 1962 return S_OK; 1963 } 1964 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize); 1965 } 1966 //format is not supported 1967 CoTaskMemFree(MultipleItem); 1968 return S_FALSE; 1969 } 1970 1971 HRESULT 1972 STDMETHODCALLTYPE 1973 COutputPin::CreatePin( 1974 const AM_MEDIA_TYPE *pmt) 1975 { 1976 PKSMULTIPLE_ITEM MediumList; 1977 PKSMULTIPLE_ITEM InterfaceList; 1978 PKSPIN_MEDIUM Medium; 1979 PKSPIN_INTERFACE Interface; 1980 IKsInterfaceHandler * InterfaceHandler; 1981 HRESULT hr; 1982 1983 // query for pin medium 1984 hr = KsQueryMediums(&MediumList); 1985 if (FAILED(hr)) 1986 { 1987 #ifdef KSPROXY_TRACE 1988 WCHAR Buffer[100]; 1989 swprintf(Buffer, L"COutputPin::CreatePin KsQueryMediums failed %lx\n", hr); 1990 OutputDebugStringW(Buffer); 1991 #endif 1992 return hr; 1993 } 1994 1995 // query for pin interface 1996 hr = KsQueryInterfaces(&InterfaceList); 1997 if (FAILED(hr)) 1998 { 1999 // failed 2000 #ifdef KSPROXY_TRACE 2001 WCHAR Buffer[100]; 2002 swprintf(Buffer, L"COutputPin::CreatePin KsQueryInterfaces failed %lx\n", hr); 2003 OutputDebugStringW(Buffer); 2004 #endif 2005 2006 CoTaskMemFree(MediumList); 2007 return hr; 2008 } 2009 2010 if (MediumList->Count) 2011 { 2012 //use first available medium 2013 Medium = (PKSPIN_MEDIUM)(MediumList + 1); 2014 } 2015 else 2016 { 2017 // default to standard medium 2018 Medium = &StandardPinMedium; 2019 } 2020 2021 if (InterfaceList->Count) 2022 { 2023 //use first available interface 2024 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1); 2025 } 2026 else 2027 { 2028 // default to standard interface 2029 Interface = &StandardPinInterface; 2030 } 2031 2032 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE) 2033 { 2034 // now create pin 2035 hr = CreatePinHandle(Medium, Interface, pmt); 2036 if (FAILED(hr)) 2037 { 2038 #ifdef KSPROXY_TRACE 2039 WCHAR Buffer[100]; 2040 swprintf(Buffer, L"COutputPin::CreatePinHandle failed with %lx\n", hr); 2041 OutputDebugStringW(Buffer); 2042 #endif 2043 return hr; 2044 } 2045 2046 if (!m_InterfaceHandler) 2047 { 2048 // now load the IKsInterfaceHandler plugin 2049 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler); 2050 if (FAILED(hr)) 2051 { 2052 // failed to load interface handler plugin 2053 CoTaskMemFree(MediumList); 2054 CoTaskMemFree(InterfaceList); 2055 2056 #ifdef KSPROXY_TRACE 2057 WCHAR Buffer[100]; 2058 swprintf(Buffer, L"COutputPin::CreatePin failed to create interface handler %lx\n", hr); 2059 OutputDebugStringW(Buffer); 2060 #endif 2061 2062 return hr; 2063 } 2064 2065 // now set the pin 2066 hr = InterfaceHandler->KsSetPin((IKsPin*)this); 2067 if (FAILED(hr)) 2068 { 2069 // failed to initialize interface handler plugin 2070 #ifdef KSPROXY_TRACE 2071 WCHAR Buffer[100]; 2072 swprintf(Buffer, L"COutputPin::CreatePin failed to initialize interface handler %lx\n", hr); 2073 OutputDebugStringW(Buffer); 2074 #endif 2075 InterfaceHandler->Release(); 2076 CoTaskMemFree(MediumList); 2077 CoTaskMemFree(InterfaceList); 2078 return hr; 2079 } 2080 2081 // store interface handler 2082 m_InterfaceHandler = InterfaceHandler; 2083 } 2084 } 2085 else 2086 { 2087 #ifdef KSPROXY_TRACE 2088 WCHAR Buffer[100]; 2089 swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName); 2090 OutputDebugStringW(Buffer); 2091 #endif 2092 2093 hr = E_FAIL; 2094 } 2095 2096 // free medium / interface / dataformat 2097 CoTaskMemFree(MediumList); 2098 CoTaskMemFree(InterfaceList); 2099 2100 #ifdef KSPROXY_TRACE 2101 WCHAR Buffer[100]; 2102 swprintf(Buffer, L"COutputPin::CreatePin Result %lx\n", hr); 2103 OutputDebugStringW(Buffer); 2104 #endif 2105 2106 return hr; 2107 } 2108 2109 HRESULT 2110 STDMETHODCALLTYPE 2111 COutputPin::CreatePinHandle( 2112 PKSPIN_MEDIUM Medium, 2113 PKSPIN_INTERFACE Interface, 2114 const AM_MEDIA_TYPE *pmt) 2115 { 2116 PKSPIN_CONNECT PinConnect; 2117 PKSDATAFORMAT DataFormat; 2118 ULONG Length; 2119 HRESULT hr; 2120 HANDLE hFilter; 2121 IKsObject * KsObjectParent; 2122 2123 //KSALLOCATOR_FRAMING Framing; 2124 //KSPROPERTY Property; 2125 //ULONG BytesReturned; 2126 2127 OutputDebugStringW(L"COutputPin::CreatePinHandle\n"); 2128 2129 if (m_hPin != INVALID_HANDLE_VALUE) 2130 { 2131 // pin already exists 2132 //CloseHandle(m_hPin); 2133 //m_hPin = INVALID_HANDLE_VALUE; 2134 OutputDebugStringW(L"COutputPin::CreatePinHandle pin already exists\n"); 2135 return S_OK; 2136 } 2137 2138 2139 // calc format size 2140 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat; 2141 2142 // allocate pin connect 2143 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length); 2144 if (!PinConnect) 2145 { 2146 // failed 2147 OutputDebugStringW(L"COutputPin::CreatePinHandle out of memory\n"); 2148 return E_OUTOFMEMORY; 2149 } 2150 OutputDebugStringW(L"COutputPin::CreatePinHandle copy pinconnect\n"); 2151 // setup request 2152 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE)); 2153 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM)); 2154 PinConnect->PinId = m_PinId; 2155 PinConnect->PinToHandle = NULL; 2156 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; 2157 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL; 2158 2159 // get dataformat offset 2160 DataFormat = (PKSDATAFORMAT)(PinConnect + 1); 2161 OutputDebugStringW(L"COutputPin::CreatePinHandle copy format\n"); 2162 // copy data format 2163 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat; 2164 DataFormat->Flags = 0; 2165 DataFormat->SampleSize = pmt->lSampleSize; 2166 DataFormat->Reserved = 0; 2167 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID)); 2168 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID)); 2169 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID)); 2170 2171 if (pmt->cbFormat) 2172 { 2173 // copy extended format 2174 WCHAR Buffer[100]; 2175 swprintf(Buffer, L"COutputPin::CreatePinHandle copy format %p pbFormat %lu\n", pmt, pmt->cbFormat); 2176 OutputDebugStringW(Buffer); 2177 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat); 2178 } 2179 2180 // get IKsObject interface 2181 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 2182 if (FAILED(hr)) 2183 { 2184 OutputDebugStringW(L"COutputPin::CreatePinHandle no IID_IKsObject interface\n"); 2185 return hr; 2186 } 2187 2188 // get parent filter handle 2189 hFilter = KsObjectParent->KsGetObjectHandle(); 2190 2191 // release IKsObject 2192 KsObjectParent->Release(); 2193 2194 if (!hFilter) 2195 { 2196 OutputDebugStringW(L"COutputPin::CreatePinHandle no filter handle\n"); 2197 return E_HANDLE; 2198 } 2199 2200 OutputDebugStringW(L"COutputPin::CreatePinHandle before creating pin\n"); 2201 // create pin 2202 DWORD dwError = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin); 2203 2204 if (dwError == ERROR_SUCCESS) 2205 { 2206 OutputDebugStringW(L"COutputPin::CreatePinHandle created pin\n"); 2207 2208 // store current interface / medium 2209 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM)); 2210 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE)); 2211 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE)); 2212 2213 #ifdef KSPROXY_TRACE 2214 LPOLESTR pMajor, pSub, pFormat; 2215 StringFromIID(m_MediaFormat.majortype, &pMajor); 2216 StringFromIID(m_MediaFormat.subtype , &pSub); 2217 StringFromIID(m_MediaFormat.formattype, &pFormat); 2218 WCHAR Buffer[200]; 2219 swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat); 2220 CoTaskMemFree(pMajor); 2221 CoTaskMemFree(pSub); 2222 CoTaskMemFree(pFormat); 2223 OutputDebugStringW(Buffer); 2224 #endif 2225 2226 if (pmt->cbFormat) 2227 { 2228 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat); 2229 if (!m_MediaFormat.pbFormat) 2230 { 2231 CoTaskMemFree(PinConnect); 2232 m_MediaFormat.pbFormat = NULL; 2233 m_MediaFormat.cbFormat = 0; 2234 return E_OUTOFMEMORY; 2235 } 2236 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat); 2237 } 2238 #if 0 2239 Property.Set = KSPROPSETID_Connection; 2240 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; 2241 Property.Flags = KSPROPERTY_TYPE_GET; 2242 2243 ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING)); 2244 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); 2245 if (SUCCEEDED(hr)) 2246 { 2247 m_Properties.cbAlign = (Framing.FileAlignment + 1); 2248 m_Properties.cbBuffer = Framing.FrameSize; 2249 m_Properties.cbPrefix = 0; //FIXME 2250 m_Properties.cBuffers = Framing.Frames; 2251 } 2252 hr = S_OK; 2253 #endif 2254 2255 if (FAILED(InitializeIOThread())) 2256 { 2257 OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n"); 2258 } 2259 2260 //TODO 2261 // connect pin pipes 2262 2263 } 2264 else 2265 OutputDebugStringW(L"COutputPin::CreatePinHandle failed to create pin\n"); 2266 // free pin connect 2267 CoTaskMemFree(PinConnect); 2268 2269 return hr; 2270 } 2271 2272 HRESULT 2273 STDMETHODCALLTYPE 2274 COutputPin::GetSupportedSets( 2275 LPGUID * pOutGuid, 2276 PULONG NumGuids) 2277 { 2278 KSPROPERTY Property; 2279 LPGUID pGuid; 2280 ULONG NumProperty = 0; 2281 ULONG NumMethods = 0; 2282 ULONG NumEvents = 0; 2283 ULONG Length; 2284 ULONG BytesReturned; 2285 HRESULT hr; 2286 2287 Property.Set = GUID_NULL; 2288 Property.Id = 0; 2289 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; 2290 2291 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty); 2292 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods); 2293 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents); 2294 2295 Length = NumProperty + NumMethods + NumEvents; 2296 2297 assert(Length); 2298 2299 // allocate guid buffer 2300 pGuid = (LPGUID)CoTaskMemAlloc(Length); 2301 if (!pGuid) 2302 { 2303 // failed 2304 return E_OUTOFMEMORY; 2305 } 2306 2307 NumProperty /= sizeof(GUID); 2308 NumMethods /= sizeof(GUID); 2309 NumEvents /= sizeof(GUID); 2310 2311 // get all properties 2312 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned); 2313 if (FAILED(hr)) 2314 { 2315 CoTaskMemFree(pGuid); 2316 return E_FAIL; 2317 } 2318 Length -= BytesReturned; 2319 2320 // get all methods 2321 if (Length && NumMethods) 2322 { 2323 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned); 2324 if (FAILED(hr)) 2325 { 2326 CoTaskMemFree(pGuid); 2327 return E_FAIL; 2328 } 2329 Length -= BytesReturned; 2330 } 2331 2332 // get all events 2333 if (Length && NumEvents) 2334 { 2335 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned); 2336 if (FAILED(hr)) 2337 { 2338 CoTaskMemFree(pGuid); 2339 return E_FAIL; 2340 } 2341 Length -= BytesReturned; 2342 } 2343 2344 #ifdef KSPROXY_TRACE 2345 WCHAR Buffer[200]; 2346 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents); 2347 OutputDebugStringW(Buffer); 2348 #endif 2349 2350 *pOutGuid = pGuid; 2351 *NumGuids = NumProperty+NumEvents+NumMethods; 2352 return S_OK; 2353 } 2354 2355 HRESULT 2356 STDMETHODCALLTYPE 2357 COutputPin::LoadProxyPlugins( 2358 LPGUID pGuids, 2359 ULONG NumGuids) 2360 { 2361 ULONG Index; 2362 LPOLESTR pStr; 2363 HKEY hKey, hSubKey; 2364 HRESULT hr; 2365 IUnknown * pUnknown; 2366 2367 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS) 2368 { 2369 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n"); 2370 return E_FAIL; 2371 } 2372 2373 // enumerate all sets 2374 for(Index = 0; Index < NumGuids; Index++) 2375 { 2376 // convert to string 2377 hr = StringFromCLSID(pGuids[Index], &pStr); 2378 if (FAILED(hr)) 2379 return E_FAIL; 2380 2381 // now try open class key 2382 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) 2383 { 2384 // no plugin for that set exists 2385 CoTaskMemFree(pStr); 2386 continue; 2387 } 2388 2389 // try load plugin 2390 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown); 2391 if (SUCCEEDED(hr)) 2392 { 2393 // store plugin 2394 m_Plugins.push_back(pUnknown); 2395 } 2396 // close key 2397 RegCloseKey(hSubKey); 2398 } 2399 2400 // close media interfaces key 2401 RegCloseKey(hKey); 2402 return S_OK; 2403 } 2404 2405 2406 HRESULT 2407 WINAPI 2408 COutputPin::IoProcessRoutine() 2409 { 2410 IMediaSample *Sample; 2411 LONG SampleCount; 2412 HRESULT hr; 2413 PKSSTREAM_SEGMENT * StreamSegment; 2414 HANDLE hEvent; 2415 IMediaSample ** Samples; 2416 LONG NumHandles; 2417 DWORD dwStatus; 2418 2419 #ifdef KSPROXY_TRACE 2420 WCHAR Buffer[200]; 2421 #endif 2422 2423 NumHandles = m_Properties.cBuffers / 2; 2424 2425 if (!NumHandles) 2426 NumHandles = 8; 2427 2428 assert(NumHandles); 2429 2430 //allocate stream segment array 2431 StreamSegment = (PKSSTREAM_SEGMENT*)CoTaskMemAlloc(sizeof(PVOID) * NumHandles); 2432 if (!StreamSegment) 2433 { 2434 OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n"); 2435 return E_FAIL; 2436 } 2437 2438 // allocate handle array 2439 Samples = (IMediaSample**)CoTaskMemAlloc(sizeof(IMediaSample*) * NumHandles); 2440 if (!Samples) 2441 { 2442 OutputDebugStringW(L"COutputPin::IoProcessRoutine out of memory\n"); 2443 return E_FAIL; 2444 } 2445 2446 // zero handles array 2447 ZeroMemory(StreamSegment, sizeof(PVOID) * NumHandles); 2448 ZeroMemory(Samples, sizeof(IMediaSample*) * NumHandles); 2449 2450 // first wait for the start event to signal 2451 WaitForSingleObject(m_hStartEvent, INFINITE); 2452 2453 m_IoCount = 0; 2454 2455 assert(m_InterfaceHandler); 2456 do 2457 { 2458 if (m_StopInProgress) 2459 { 2460 // stop io thread 2461 break; 2462 } 2463 2464 assert(m_State == KSSTATE_RUN); 2465 assert(m_MemAllocator); 2466 2467 // get buffer 2468 hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT); 2469 2470 if (FAILED(hr)) 2471 { 2472 WaitForSingleObject(m_hBufferAvailable, INFINITE); 2473 // now retry again 2474 continue; 2475 } 2476 2477 // fill buffer 2478 SampleCount = 1; 2479 Samples[m_IoCount] = Sample; 2480 2481 Sample->SetTime(NULL, NULL); 2482 hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */ 2483 &Samples[m_IoCount], 2484 &SampleCount, 2485 KsIoOperation_Read, 2486 &StreamSegment[m_IoCount]); 2487 if (FAILED(hr) || !StreamSegment) 2488 { 2489 #ifdef KSPROXY_TRACE 2490 swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr); 2491 OutputDebugStringW(Buffer); 2492 #endif 2493 break; 2494 } 2495 2496 // interface handle should increment pending i/o count 2497 assert(m_IoCount >= 1); 2498 2499 swprintf(Buffer, L"COutputPin::IoProcessRoutine m_IoCount %lu NumHandles %lu\n", m_IoCount, NumHandles); 2500 OutputDebugStringW(Buffer); 2501 2502 if (m_IoCount != NumHandles) 2503 continue; 2504 2505 // get completion handle 2506 hEvent = StreamSegment[0]->CompletionEvent; 2507 2508 // wait for i/o completion 2509 dwStatus = WaitForSingleObject(hEvent, INFINITE); 2510 2511 swprintf(Buffer, L"COutputPin::IoProcessRoutine dwStatus %lx Error %lx NumHandles %lu\n", dwStatus, GetLastError(), NumHandles); 2512 OutputDebugStringW(Buffer); 2513 2514 // perform completion 2515 m_InterfaceHandler->KsCompleteIo(StreamSegment[0]); 2516 2517 // close completion event 2518 CloseHandle(hEvent); 2519 2520 if (SUCCEEDED(hr)) 2521 { 2522 assert(m_MemInputPin); 2523 2524 // now deliver the sample 2525 hr = m_MemInputPin->Receive(Samples[0]); 2526 2527 #ifdef KSPROXY_TRACE 2528 swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator); 2529 OutputDebugStringW(Buffer); 2530 #endif 2531 2532 if (FAILED(hr)) 2533 break; 2534 2535 Sample = NULL; 2536 } 2537 2538 //circular stream segment array 2539 RtlMoveMemory(StreamSegment, &StreamSegment[1], sizeof(PVOID) * (NumHandles - 1)); 2540 RtlMoveMemory(Samples, &Samples[1], sizeof(IMediaSample*) * (NumHandles - 1)); 2541 2542 }while(TRUE); 2543 2544 // signal end of i/o thread 2545 SetEvent(m_hStopEvent); 2546 2547 m_IoThreadStarted = false; 2548 2549 return NOERROR; 2550 } 2551 2552 DWORD 2553 WINAPI 2554 COutputPin_IoThreadStartup( 2555 LPVOID lpParameter) 2556 { 2557 COutputPin * Pin = (COutputPin*)lpParameter; 2558 assert(Pin); 2559 2560 return Pin->IoProcessRoutine(); 2561 } 2562 2563 2564 HRESULT 2565 WINAPI 2566 COutputPin::InitializeIOThread() 2567 { 2568 HANDLE hThread; 2569 2570 if (m_IoThreadStarted) 2571 return NOERROR; 2572 2573 if (!m_hStartEvent) 2574 m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 2575 2576 if (!m_hStartEvent) 2577 return E_OUTOFMEMORY; 2578 2579 if (!m_hStopEvent) 2580 m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 2581 2582 if (!m_hStopEvent) 2583 return E_OUTOFMEMORY; 2584 2585 if (!m_hBufferAvailable) 2586 m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL); 2587 2588 if (!m_hBufferAvailable) 2589 return E_OUTOFMEMORY; 2590 2591 m_StopInProgress = false; 2592 m_IoThreadStarted = true; 2593 2594 // now create the startup thread 2595 hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL); 2596 if (!hThread) 2597 return E_OUTOFMEMORY; 2598 2599 2600 // close thread handle 2601 CloseHandle(hThread); 2602 return NOERROR; 2603 } 2604 2605 HRESULT 2606 STDMETHODCALLTYPE 2607 COutputPin_SetState( 2608 IPin * Pin, 2609 KSSTATE State) 2610 { 2611 HRESULT hr = S_OK; 2612 KSPROPERTY Property; 2613 KSSTATE CurState; 2614 ULONG BytesReturned; 2615 COutputPin * pPin = (COutputPin*)Pin; 2616 2617 #ifdef KSPROXY_TRACE 2618 WCHAR Buffer[200]; 2619 #endif 2620 2621 Property.Set = KSPROPSETID_Connection; 2622 Property.Id = KSPROPERTY_CONNECTION_STATE; 2623 Property.Flags = KSPROPERTY_TYPE_SET; 2624 2625 EnterCriticalSection(&pPin->m_Lock); 2626 2627 if (pPin->m_State <= State) 2628 { 2629 if (pPin->m_State == KSSTATE_STOP) 2630 { 2631 hr = pPin->InitializeIOThread(); 2632 if (FAILED(hr)) 2633 { 2634 // failed to initialize I/O thread 2635 #ifdef KSPROXY_TRACE 2636 OutputDebugStringW(L"Failed to initialize I/O Thread\n"); 2637 #endif 2638 LeaveCriticalSection(&pPin->m_Lock); 2639 return hr; 2640 } 2641 CurState = KSSTATE_ACQUIRE; 2642 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 2643 2644 #ifdef KSPROXY_TRACE 2645 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_STOP KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); 2646 OutputDebugStringW(Buffer); 2647 #endif 2648 2649 if (FAILED(hr)) 2650 { 2651 LeaveCriticalSection(&pPin->m_Lock); 2652 return hr; 2653 } 2654 2655 pPin->m_State = CurState; 2656 2657 if (pPin->m_State == State) 2658 { 2659 LeaveCriticalSection(&pPin->m_Lock); 2660 return hr; 2661 } 2662 } 2663 if (pPin->m_State == KSSTATE_ACQUIRE) 2664 { 2665 CurState = KSSTATE_PAUSE; 2666 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 2667 2668 #ifdef KSPROXY_TRACE 2669 swprintf(Buffer, L"COutputPin_SetState Setting State CurState KSSTATE_ACQUIRE KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); 2670 OutputDebugStringW(Buffer); 2671 #endif 2672 2673 if (FAILED(hr)) 2674 { 2675 LeaveCriticalSection(&pPin->m_Lock); 2676 return hr; 2677 } 2678 2679 pPin->m_State = CurState; 2680 2681 if (pPin->m_State == State) 2682 { 2683 LeaveCriticalSection(&pPin->m_Lock); 2684 return hr; 2685 } 2686 } 2687 if (State == KSSTATE_RUN && pPin->m_State == KSSTATE_PAUSE) 2688 { 2689 CurState = KSSTATE_RUN; 2690 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 2691 2692 #ifdef KSPROXY_TRACE 2693 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr); 2694 OutputDebugStringW(Buffer); 2695 #endif 2696 2697 if (SUCCEEDED(hr)) 2698 { 2699 pPin->m_State = CurState; 2700 // signal start event 2701 SetEvent(pPin->m_hStartEvent); 2702 } 2703 } 2704 2705 LeaveCriticalSection(&pPin->m_Lock); 2706 return hr; 2707 } 2708 else 2709 { 2710 if (pPin->m_State == KSSTATE_RUN) 2711 { 2712 // setting pending stop flag 2713 pPin->m_StopInProgress = true; 2714 2715 // release any waiting threads 2716 SetEvent(pPin->m_hBufferAvailable); 2717 2718 // wait until i/o thread is done 2719 WaitForSingleObject(pPin->m_hStopEvent, INFINITE); 2720 2721 CurState = KSSTATE_PAUSE; 2722 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 2723 2724 #ifdef KSPROXY_TRACE 2725 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_RUN KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); 2726 OutputDebugStringW(Buffer); 2727 #endif 2728 2729 if (FAILED(hr)) 2730 { 2731 LeaveCriticalSection(&pPin->m_Lock); 2732 return hr; 2733 } 2734 2735 pPin->m_State = CurState; 2736 2737 if (FAILED(hr)) 2738 { 2739 LeaveCriticalSection(&pPin->m_Lock); 2740 return hr; 2741 } 2742 } 2743 if (pPin->m_State == KSSTATE_PAUSE) 2744 { 2745 CurState = KSSTATE_ACQUIRE; 2746 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 2747 2748 #ifdef KSPROXY_TRACE 2749 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); 2750 OutputDebugStringW(Buffer); 2751 #endif 2752 2753 if (FAILED(hr)) 2754 { 2755 LeaveCriticalSection(&pPin->m_Lock); 2756 return hr; 2757 } 2758 2759 pPin->m_State = CurState; 2760 2761 if (pPin->m_State == State) 2762 { 2763 LeaveCriticalSection(&pPin->m_Lock); 2764 return hr; 2765 } 2766 } 2767 2768 CloseHandle(pPin->m_hStopEvent); 2769 CloseHandle(pPin->m_hStartEvent); 2770 CloseHandle(pPin->m_hBufferAvailable); 2771 2772 /* close event handles */ 2773 pPin->m_hStopEvent = NULL; 2774 pPin->m_hStartEvent = NULL; 2775 pPin->m_hBufferAvailable = NULL; 2776 2777 CurState = KSSTATE_STOP; 2778 hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); 2779 2780 #ifdef KSPROXY_TRACE 2781 swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_ACQUIRE KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr); 2782 OutputDebugStringW(Buffer); 2783 #endif 2784 2785 if (SUCCEEDED(hr)) 2786 { 2787 // store state 2788 pPin->m_State = CurState; 2789 } 2790 2791 // unset pending stop flag 2792 pPin->m_StopInProgress = false; 2793 2794 LeaveCriticalSection(&pPin->m_Lock); 2795 return hr; 2796 } 2797 } 2798 2799 HRESULT 2800 WINAPI 2801 COutputPin_Constructor( 2802 IBaseFilter * ParentFilter, 2803 LPCWSTR PinName, 2804 ULONG PinId, 2805 KSPIN_COMMUNICATION Communication, 2806 REFIID riid, 2807 LPVOID * ppv) 2808 { 2809 COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication); 2810 2811 if (!handler) 2812 return E_OUTOFMEMORY; 2813 2814 if (FAILED(handler->QueryInterface(riid, ppv))) 2815 { 2816 /* not supported */ 2817 delete handler; 2818 return E_NOINTERFACE; 2819 } 2820 2821 return S_OK; 2822 } 2823