1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy 4 * FILE: dll/directx/ksproxy/input_pin.cpp 5 * PURPOSE: InputPin of Proxy Filter 6 * 7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) 8 */ 9 #include "precomp.h" 10 11 const GUID IID_IKsPinPipe = {0xe539cd90, 0xa8b4, 0x11d1, {0x81, 0x89, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}}; 12 const GUID IID_IKsPinEx = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}}; 13 14 KSPIN_INTERFACE StandardPinInterface = 15 { 16 {STATIC_KSINTERFACESETID_Standard}, 17 KSINTERFACE_STANDARD_STREAMING, 18 0 19 }; 20 21 KSPIN_MEDIUM StandardPinMedium = 22 { 23 {STATIC_KSMEDIUMSETID_Standard}, 24 KSMEDIUM_TYPE_ANYINSTANCE, 25 0 26 }; 27 28 class CInputPin : public IPin, 29 public IKsPropertySet, 30 public IKsControl, 31 public IKsObject, 32 public IKsPinEx, 33 public IMemInputPin, 34 public IKsPinPipe, 35 public IKsPinFactory, 36 public IStreamBuilder, 37 public IKsAggregateControl, 38 public IQualityControl, 39 public ISpecifyPropertyPages 40 { 41 public: 42 typedef std::vector<IUnknown *>ProxyPluginVector; 43 44 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 45 46 STDMETHODIMP_(ULONG) AddRef() 47 { 48 InterlockedIncrement(&m_Ref); 49 return m_Ref; 50 } 51 STDMETHODIMP_(ULONG) Release() 52 { 53 InterlockedDecrement(&m_Ref); 54 if (!m_Ref) 55 { 56 delete this; 57 return 0; 58 } 59 return m_Ref; 60 } 61 62 //IKsPinPipe 63 HRESULT STDMETHODCALLTYPE KsGetPinFramingCache(PKSALLOCATOR_FRAMING_EX *FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option); 64 HRESULT STDMETHODCALLTYPE KsSetPinFramingCache(PKSALLOCATOR_FRAMING_EX FramingEx, PFRAMING_PROP FramingProp, FRAMING_CACHE_OPS Option); 65 IPin* STDMETHODCALLTYPE KsGetConnectedPin(); 66 IKsAllocatorEx* STDMETHODCALLTYPE KsGetPipe(KSPEEKOPERATION Operation); 67 HRESULT STDMETHODCALLTYPE KsSetPipe(IKsAllocatorEx *KsAllocator); 68 ULONG STDMETHODCALLTYPE KsGetPipeAllocatorFlag(); 69 HRESULT STDMETHODCALLTYPE KsSetPipeAllocatorFlag(ULONG Flag); 70 GUID STDMETHODCALLTYPE KsGetPinBusCache(); 71 HRESULT STDMETHODCALLTYPE KsSetPinBusCache(GUID Bus); 72 PWCHAR STDMETHODCALLTYPE KsGetPinName(); 73 PWCHAR STDMETHODCALLTYPE KsGetFilterName(); 74 75 //IPin methods 76 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); 77 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); 78 HRESULT STDMETHODCALLTYPE Disconnect(); 79 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin); 80 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt); 81 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo); 82 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); 83 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id); 84 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt); 85 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum); 86 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin); 87 HRESULT STDMETHODCALLTYPE EndOfStream(); 88 HRESULT STDMETHODCALLTYPE BeginFlush(); 89 HRESULT STDMETHODCALLTYPE EndFlush(); 90 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); 91 92 // ISpecifyPropertyPages 93 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages); 94 95 //IKsObject methods 96 HANDLE STDMETHODCALLTYPE KsGetObjectHandle(); 97 98 //IKsPropertySet 99 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData); 100 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned); 101 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport); 102 103 //IKsControl 104 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned); 105 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned); 106 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned); 107 108 //IKsPin 109 HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList); 110 HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList); 111 HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium); 112 HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium); 113 HRESULT STDMETHODCALLTYPE KsPropagateAcquire(); 114 HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags); 115 HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment); 116 IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation); 117 HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator); 118 HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator(); 119 LONG STDMETHODCALLTYPE KsIncrementPendingIoCount(); 120 LONG STDMETHODCALLTYPE KsDecrementPendingIoCount(); 121 HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta); 122 // IKsPinEx 123 VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr); 124 125 //IMemInputPin 126 HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator); 127 HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly); 128 HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps); 129 HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample); 130 HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed); 131 HRESULT STDMETHODCALLTYPE ReceiveCanBlock( void); 132 133 //IKsPinFactory 134 HRESULT STDMETHODCALLTYPE KsPinFactory(ULONG* PinFactory); 135 136 //IStreamBuilder 137 HRESULT STDMETHODCALLTYPE Render(IPin *ppinOut, IGraphBuilder *pGraph); 138 HRESULT STDMETHODCALLTYPE Backout(IPin *ppinOut, IGraphBuilder *pGraph); 139 140 //IKsAggregateControl 141 HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass); 142 HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass); 143 144 //IQualityControl 145 HRESULT STDMETHODCALLTYPE Notify(IBaseFilter *pSelf, Quality q); 146 HRESULT STDMETHODCALLTYPE SetSink(IQualityControl *piqc); 147 148 //--------------------------------------------------------------- 149 HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt); 150 HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt); 151 HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt); 152 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids); 153 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids); 154 CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication); 155 virtual ~CInputPin(){}; 156 157 protected: 158 LONG m_Ref; 159 IBaseFilter * m_ParentFilter; 160 LPCWSTR m_PinName; 161 HANDLE m_hPin; 162 ULONG m_PinId; 163 IMemAllocator * m_MemAllocator; 164 LONG m_IoCount; 165 KSPIN_COMMUNICATION m_Communication; 166 KSPIN_INTERFACE m_Interface; 167 KSPIN_MEDIUM m_Medium; 168 AM_MEDIA_TYPE m_MediaFormat; 169 IPin * m_Pin; 170 BOOL m_ReadOnly; 171 IKsInterfaceHandler * m_InterfaceHandler; 172 IKsAllocatorEx * m_KsAllocatorEx; 173 ULONG m_PipeAllocatorFlag; 174 BOOL m_bPinBusCacheInitialized; 175 GUID m_PinBusCache; 176 LPWSTR m_FilterName; 177 FRAMING_PROP m_FramingProp[4]; 178 PKSALLOCATOR_FRAMING_EX m_FramingEx[4]; 179 ProxyPluginVector m_Plugins; 180 }; 181 182 CInputPin::CInputPin( 183 IBaseFilter * ParentFilter, 184 LPCWSTR PinName, 185 ULONG PinId, 186 KSPIN_COMMUNICATION Communication) : m_Ref(0), 187 m_ParentFilter(ParentFilter), 188 m_PinName(PinName), 189 m_hPin(INVALID_HANDLE_VALUE), 190 m_PinId(PinId), 191 m_MemAllocator(0), 192 m_IoCount(0), 193 m_Communication(Communication), 194 m_Pin(0), 195 m_ReadOnly(0), 196 m_InterfaceHandler(0), 197 m_KsAllocatorEx(0), 198 m_PipeAllocatorFlag(0), 199 m_bPinBusCacheInitialized(0), 200 m_FilterName(0), 201 m_Plugins() 202 { 203 ZeroMemory(m_FramingProp, sizeof(m_FramingProp)); 204 ZeroMemory(m_FramingEx, sizeof(m_FramingEx)); 205 206 HRESULT hr; 207 IKsObject * KsObjectParent; 208 HANDLE hFilter; 209 210 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 211 assert(hr == S_OK); 212 213 hFilter = KsObjectParent->KsGetObjectHandle(); 214 assert(hFilter); 215 216 KsObjectParent->Release(); 217 218 219 ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE)); 220 hr = KsGetMediaType(0, &m_MediaFormat, hFilter, m_PinId); 221 assert(hr == S_OK); 222 } 223 224 HRESULT 225 STDMETHODCALLTYPE 226 CInputPin::QueryInterface( 227 IN REFIID refiid, 228 OUT PVOID* Output) 229 { 230 WCHAR Buffer[100]; 231 232 *Output = NULL; 233 234 if (IsEqualGUID(refiid, IID_IUnknown) || 235 IsEqualGUID(refiid, IID_IPin)) 236 { 237 *Output = PVOID(this); 238 reinterpret_cast<IUnknown*>(*Output)->AddRef(); 239 return NOERROR; 240 } 241 else if (IsEqualGUID(refiid, IID_IMemInputPin)) 242 { 243 if (m_hPin == INVALID_HANDLE_VALUE) 244 { 245 HRESULT hr = CreatePin(&m_MediaFormat); 246 if (FAILED(hr)) 247 return hr; 248 } 249 250 *Output = (IMemInputPin*)(this); 251 reinterpret_cast<IMemInputPin*>(*Output)->AddRef(); 252 return NOERROR; 253 } 254 else if (IsEqualGUID(refiid, IID_IKsObject)) 255 { 256 *Output = (IKsObject*)(this); 257 reinterpret_cast<IKsObject*>(*Output)->AddRef(); 258 return NOERROR; 259 } 260 else if (IsEqualGUID(refiid, IID_IKsPropertySet)) 261 { 262 if (m_hPin == INVALID_HANDLE_VALUE) 263 { 264 HRESULT hr = CreatePin(&m_MediaFormat); 265 if (FAILED(hr)) 266 return hr; 267 } 268 269 *Output = (IKsPropertySet*)(this); 270 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef(); 271 return NOERROR; 272 } 273 else if (IsEqualGUID(refiid, IID_IKsControl)) 274 { 275 *Output = (IKsControl*)(this); 276 reinterpret_cast<IKsControl*>(*Output)->AddRef(); 277 return NOERROR; 278 } 279 else if (IsEqualGUID(refiid, IID_IKsPin) || 280 IsEqualGUID(refiid, IID_IKsPinEx)) 281 { 282 *Output = (IKsPinEx*)(this); 283 reinterpret_cast<IKsPinEx*>(*Output)->AddRef(); 284 return NOERROR; 285 } 286 else if (IsEqualGUID(refiid, IID_IKsPinPipe)) 287 { 288 *Output = (IKsPinPipe*)(this); 289 reinterpret_cast<IKsPinPipe*>(*Output)->AddRef(); 290 return NOERROR; 291 } 292 else if (IsEqualGUID(refiid, IID_IKsPinFactory)) 293 { 294 *Output = (IKsPinFactory*)(this); 295 reinterpret_cast<IKsPinFactory*>(*Output)->AddRef(); 296 return NOERROR; 297 } 298 #if 0 299 else if (IsEqualGUID(refiid, IID_IStreamBuilder)) 300 { 301 *Output = (IStreamBuilder*)(this); 302 reinterpret_cast<IStreamBuilder*>(*Output)->AddRef(); 303 return NOERROR; 304 } 305 #endif 306 else if (IsEqualGUID(refiid, IID_IKsAggregateControl)) 307 { 308 *Output = (IKsAggregateControl*)(this); 309 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef(); 310 return NOERROR; 311 } 312 else if (IsEqualGUID(refiid, IID_IQualityControl)) 313 { 314 *Output = (IQualityControl*)(this); 315 reinterpret_cast<IQualityControl*>(*Output)->AddRef(); 316 return NOERROR; 317 } 318 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) 319 { 320 *Output = (ISpecifyPropertyPages*)(this); 321 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef(); 322 return NOERROR; 323 } 324 325 LPOLESTR lpstr; 326 StringFromCLSID(refiid, &lpstr); 327 swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr); 328 OutputDebugStringW(Buffer); 329 CoTaskMemFree(lpstr); 330 331 return E_NOINTERFACE; 332 } 333 //------------------------------------------------------------------- 334 // IQualityControl interface 335 // 336 HRESULT 337 STDMETHODCALLTYPE 338 CInputPin::Notify( 339 IBaseFilter *pSelf, 340 Quality q) 341 { 342 #ifdef KSPROXY_TRACE 343 OutputDebugStringW(L"CInputPin::Notify NotImplemented\n"); 344 #endif 345 346 return E_NOTIMPL; 347 } 348 349 HRESULT 350 STDMETHODCALLTYPE 351 CInputPin::SetSink( 352 IQualityControl *piqc) 353 { 354 #ifdef KSPROXY_TRACE 355 OutputDebugStringW(L"CInputPin::SetSink NotImplemented\n"); 356 #endif 357 358 return E_NOTIMPL; 359 } 360 361 362 //------------------------------------------------------------------- 363 // IKsAggregateControl interface 364 // 365 HRESULT 366 STDMETHODCALLTYPE 367 CInputPin::KsAddAggregate( 368 IN REFGUID AggregateClass) 369 { 370 #ifdef KSPROXY_TRACE 371 OutputDebugStringW(L"CInputPin::KsAddAggregate NotImplemented\n"); 372 #endif 373 374 return E_NOTIMPL; 375 } 376 377 HRESULT 378 STDMETHODCALLTYPE 379 CInputPin::KsRemoveAggregate( 380 REFGUID AggregateClass) 381 { 382 #ifdef KSPROXY_TRACE 383 OutputDebugStringW(L"CInputPin::KsRemoveAggregate NotImplemented\n"); 384 #endif 385 386 return E_NOTIMPL; 387 } 388 389 //------------------------------------------------------------------- 390 // IStreamBuilder 391 // 392 393 HRESULT 394 STDMETHODCALLTYPE 395 CInputPin::Render( 396 IPin *ppinOut, 397 IGraphBuilder *pGraph) 398 { 399 OutputDebugStringW(L"CInputPin::Render\n"); 400 return S_OK; 401 } 402 403 HRESULT 404 STDMETHODCALLTYPE 405 CInputPin::Backout( 406 IPin *ppinOut, 407 IGraphBuilder *pGraph) 408 { 409 #ifdef KSPROXY_TRACE 410 OutputDebugStringW(L"CInputPin::Backout\n"); 411 #endif 412 413 return S_OK; 414 } 415 416 //------------------------------------------------------------------- 417 // IKsPinFactory 418 // 419 420 HRESULT 421 STDMETHODCALLTYPE 422 CInputPin::KsPinFactory( 423 ULONG* PinFactory) 424 { 425 #ifdef KSPROXY_TRACE 426 OutputDebugStringW(L"CInputPin::KsPinFactory\n"); 427 #endif 428 429 *PinFactory = m_PinId; 430 return S_OK; 431 } 432 433 //------------------------------------------------------------------- 434 // IKsPinPipe 435 // 436 437 HRESULT 438 STDMETHODCALLTYPE 439 CInputPin::KsGetPinFramingCache( 440 PKSALLOCATOR_FRAMING_EX *FramingEx, 441 PFRAMING_PROP FramingProp, 442 FRAMING_CACHE_OPS Option) 443 { 444 if (Option > Framing_Cache_Write || Option < Framing_Cache_ReadLast) 445 { 446 // invalid argument 447 return E_INVALIDARG; 448 } 449 450 // get framing properties 451 *FramingProp = m_FramingProp[Option]; 452 *FramingEx = m_FramingEx[Option]; 453 454 return NOERROR; 455 } 456 457 HRESULT 458 STDMETHODCALLTYPE 459 CInputPin::KsSetPinFramingCache( 460 PKSALLOCATOR_FRAMING_EX FramingEx, 461 PFRAMING_PROP FramingProp, 462 FRAMING_CACHE_OPS Option) 463 { 464 ULONG Index; 465 ULONG RefCount = 0; 466 467 if (m_FramingEx[Option]) 468 { 469 for(Index = 1; Index < 4; Index++) 470 { 471 if (m_FramingEx[Index] == m_FramingEx[Option]) 472 RefCount++; 473 } 474 475 if (RefCount == 1) 476 { 477 // existing framing is only used once 478 CoTaskMemFree(m_FramingEx[Option]); 479 } 480 } 481 482 // store framing 483 m_FramingEx[Option] = FramingEx; 484 m_FramingProp[Option] = *FramingProp; 485 486 return S_OK; 487 } 488 489 IPin* 490 STDMETHODCALLTYPE 491 CInputPin::KsGetConnectedPin() 492 { 493 return m_Pin; 494 } 495 496 IKsAllocatorEx* 497 STDMETHODCALLTYPE 498 CInputPin::KsGetPipe( 499 KSPEEKOPERATION Operation) 500 { 501 if (Operation == KsPeekOperation_AddRef) 502 { 503 if (m_KsAllocatorEx) 504 m_KsAllocatorEx->AddRef(); 505 } 506 return m_KsAllocatorEx; 507 } 508 509 HRESULT 510 STDMETHODCALLTYPE 511 CInputPin::KsSetPipe( 512 IKsAllocatorEx *KsAllocator) 513 { 514 if (KsAllocator) 515 KsAllocator->AddRef(); 516 517 if (m_KsAllocatorEx) 518 m_KsAllocatorEx->Release(); 519 520 m_KsAllocatorEx = KsAllocator; 521 return NOERROR; 522 } 523 524 ULONG 525 STDMETHODCALLTYPE 526 CInputPin::KsGetPipeAllocatorFlag() 527 { 528 return m_PipeAllocatorFlag; 529 } 530 531 532 HRESULT 533 STDMETHODCALLTYPE 534 CInputPin::KsSetPipeAllocatorFlag( 535 ULONG Flag) 536 { 537 m_PipeAllocatorFlag = Flag; 538 return NOERROR; 539 } 540 541 GUID 542 STDMETHODCALLTYPE 543 CInputPin::KsGetPinBusCache() 544 { 545 if (!m_bPinBusCacheInitialized) 546 { 547 CopyMemory(&m_PinBusCache, &m_Medium.Set, sizeof(GUID)); 548 m_bPinBusCacheInitialized = TRUE; 549 } 550 551 return m_PinBusCache; 552 } 553 554 HRESULT 555 STDMETHODCALLTYPE 556 CInputPin::KsSetPinBusCache( 557 GUID Bus) 558 { 559 CopyMemory(&m_PinBusCache, &Bus, sizeof(GUID)); 560 return NOERROR; 561 } 562 563 PWCHAR 564 STDMETHODCALLTYPE 565 CInputPin::KsGetPinName() 566 { 567 return (PWCHAR)m_PinName; 568 } 569 570 571 PWCHAR 572 STDMETHODCALLTYPE 573 CInputPin::KsGetFilterName() 574 { 575 return m_FilterName; 576 } 577 578 //------------------------------------------------------------------- 579 // ISpecifyPropertyPages 580 // 581 582 HRESULT 583 STDMETHODCALLTYPE 584 CInputPin::GetPages(CAUUID *pPages) 585 { 586 if (!pPages) 587 return E_POINTER; 588 589 pPages->cElems = 0; 590 pPages->pElems = NULL; 591 592 return S_OK; 593 } 594 595 //------------------------------------------------------------------- 596 // IMemInputPin 597 // 598 599 600 HRESULT 601 STDMETHODCALLTYPE 602 CInputPin::GetAllocator(IMemAllocator **ppAllocator) 603 { 604 #ifdef KSPROXY_TRACE 605 OutputDebugStringW(L"CInputPin::GetAllocator\n"); 606 #endif 607 608 return VFW_E_NO_ALLOCATOR; 609 } 610 611 HRESULT 612 STDMETHODCALLTYPE 613 CInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly) 614 { 615 HRESULT hr; 616 ALLOCATOR_PROPERTIES Properties; 617 618 hr = pAllocator->GetProperties(&Properties); 619 620 #ifdef KSPROXY_TRACE 621 WCHAR Buffer[100]; 622 swprintf(Buffer, L"CInputPin::NotifyAllocator hr %lx bReadOnly, %u cbAlign %u cbBuffer %u cbPrefix %u cBuffers %u\n", hr, bReadOnly, Properties.cbAlign, Properties.cbBuffer, Properties.cbPrefix, Properties.cBuffers); 623 OutputDebugStringW(Buffer); 624 #endif 625 626 if (pAllocator) 627 { 628 pAllocator->AddRef(); 629 } 630 631 if (m_MemAllocator) 632 { 633 m_MemAllocator->Release(); 634 } 635 636 m_MemAllocator = pAllocator; 637 m_ReadOnly = bReadOnly; 638 return NOERROR; 639 } 640 641 HRESULT 642 STDMETHODCALLTYPE 643 CInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) 644 { 645 KSALLOCATOR_FRAMING Framing; 646 KSPROPERTY Property; 647 HRESULT hr; 648 ULONG BytesReturned; 649 650 Property.Set = KSPROPSETID_Connection; 651 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; 652 Property.Flags = KSPROPERTY_TYPE_SET; 653 654 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); 655 if (SUCCEEDED(hr)) 656 { 657 pProps->cBuffers = Framing.Frames; 658 pProps->cbBuffer = Framing.FrameSize; 659 pProps->cbAlign = Framing.FileAlignment; 660 pProps->cbPrefix = 0; 661 } 662 else 663 hr = E_NOTIMPL; 664 665 #ifdef KSPROXY_TRACE 666 WCHAR Buffer[100]; 667 swprintf(Buffer, L"CInputPin::GetAllocatorRequirements hr %lx m_hPin %p cBuffers %u cbBuffer %u cbAlign %u cbPrefix %u\n", hr, m_hPin, pProps->cBuffers, pProps->cbBuffer, pProps->cbAlign, pProps->cbPrefix); 668 OutputDebugStringW(Buffer); 669 #endif 670 671 return hr; 672 } 673 674 HRESULT 675 STDMETHODCALLTYPE 676 CInputPin::Receive(IMediaSample *pSample) 677 { 678 #ifdef KSPROXY_TRACE 679 OutputDebugStringW(L"CInputPin::Receive NotImplemented\n"); 680 #endif 681 682 return E_NOTIMPL; 683 } 684 685 HRESULT 686 STDMETHODCALLTYPE 687 CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed) 688 { 689 #ifdef KSPROXY_TRACE 690 OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n"); 691 #endif 692 693 return E_NOTIMPL; 694 } 695 696 HRESULT 697 STDMETHODCALLTYPE 698 CInputPin::ReceiveCanBlock( void) 699 { 700 #ifdef KSPROXY_TRACE 701 OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n"); 702 #endif 703 704 return S_FALSE; 705 } 706 707 //------------------------------------------------------------------- 708 // IKsPin 709 // 710 711 HRESULT 712 STDMETHODCALLTYPE 713 CInputPin::KsQueryMediums( 714 PKSMULTIPLE_ITEM* MediumList) 715 { 716 HRESULT hr; 717 IKsObject * KsObjectParent; 718 HANDLE hFilter; 719 720 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 721 if (FAILED(hr)) 722 return hr; 723 724 hFilter = KsObjectParent->KsGetObjectHandle(); 725 726 KsObjectParent->Release(); 727 728 if (!hFilter) 729 return E_HANDLE; 730 731 return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList); 732 } 733 734 HRESULT 735 STDMETHODCALLTYPE 736 CInputPin::KsQueryInterfaces( 737 PKSMULTIPLE_ITEM* InterfaceList) 738 { 739 HRESULT hr; 740 IKsObject * KsObjectParent; 741 HANDLE hFilter; 742 743 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 744 if (FAILED(hr)) 745 return hr; 746 747 hFilter = KsObjectParent->KsGetObjectHandle(); 748 749 KsObjectParent->Release(); 750 751 if (!hFilter) 752 return E_HANDLE; 753 754 return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList); 755 } 756 757 HRESULT 758 STDMETHODCALLTYPE 759 CInputPin::KsCreateSinkPinHandle( 760 KSPIN_INTERFACE& Interface, 761 KSPIN_MEDIUM& Medium) 762 { 763 return CreatePin(&m_MediaFormat); 764 } 765 766 HRESULT 767 STDMETHODCALLTYPE 768 CInputPin::KsGetCurrentCommunication( 769 KSPIN_COMMUNICATION *Communication, 770 KSPIN_INTERFACE *Interface, 771 KSPIN_MEDIUM *Medium) 772 { 773 if (Communication) 774 { 775 *Communication = m_Communication; 776 } 777 778 if (Interface) 779 { 780 if (!m_hPin) 781 return VFW_E_NOT_CONNECTED; 782 783 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE)); 784 } 785 786 if (Medium) 787 { 788 if (!m_hPin) 789 return VFW_E_NOT_CONNECTED; 790 791 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM)); 792 } 793 return NOERROR; 794 } 795 796 HRESULT 797 STDMETHODCALLTYPE 798 CInputPin::KsPropagateAcquire() 799 { 800 KSPROPERTY Property; 801 KSSTATE State; 802 ULONG BytesReturned; 803 HRESULT hr; 804 805 assert(m_hPin != INVALID_HANDLE_VALUE); 806 807 Property.Set = KSPROPSETID_Connection; 808 Property.Id = KSPROPERTY_CONNECTION_STATE; 809 Property.Flags = KSPROPERTY_TYPE_SET; 810 811 State = KSSTATE_ACQUIRE; 812 813 hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned); 814 815 //TODO 816 //propagate to connected pin on the pipe 817 818 return hr; 819 } 820 821 HRESULT 822 STDMETHODCALLTYPE 823 CInputPin::KsDeliver( 824 IMediaSample* Sample, 825 ULONG Flags) 826 { 827 return E_FAIL; 828 } 829 830 HRESULT 831 STDMETHODCALLTYPE 832 CInputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment) 833 { 834 return NOERROR; 835 } 836 837 IMemAllocator * 838 STDMETHODCALLTYPE 839 CInputPin::KsPeekAllocator(KSPEEKOPERATION Operation) 840 { 841 if (Operation == KsPeekOperation_AddRef) 842 { 843 // add reference on allocator 844 m_MemAllocator->AddRef(); 845 } 846 847 return m_MemAllocator; 848 } 849 850 HRESULT 851 STDMETHODCALLTYPE 852 CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator) 853 { 854 855 if (MemAllocator) 856 { 857 MemAllocator->AddRef(); 858 } 859 860 if (m_MemAllocator) 861 { 862 m_MemAllocator->Release(); 863 } 864 865 m_MemAllocator = MemAllocator; 866 return NOERROR; 867 } 868 869 HRESULT 870 STDMETHODCALLTYPE 871 CInputPin::KsRenegotiateAllocator() 872 { 873 return E_FAIL; 874 } 875 876 LONG 877 STDMETHODCALLTYPE 878 CInputPin::KsIncrementPendingIoCount() 879 { 880 return InterlockedIncrement((volatile LONG*)&m_IoCount); 881 } 882 883 LONG 884 STDMETHODCALLTYPE 885 CInputPin::KsDecrementPendingIoCount() 886 { 887 return InterlockedDecrement((volatile LONG*)&m_IoCount); 888 } 889 890 HRESULT 891 STDMETHODCALLTYPE 892 CInputPin::KsQualityNotify( 893 ULONG Proportion, 894 REFERENCE_TIME TimeDelta) 895 { 896 #ifdef KSPROXY_TRACE 897 OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n"); 898 #endif 899 900 return E_NOTIMPL; 901 } 902 903 //------------------------------------------------------------------- 904 // IKsPinEx 905 // 906 907 VOID 908 STDMETHODCALLTYPE 909 CInputPin::KsNotifyError( 910 IMediaSample* Sample, 911 HRESULT hr) 912 { 913 #ifdef KSPROXY_TRACE 914 OutputDebugStringW(L"CInputPin::KsNotifyError NotImplemented\n"); 915 #endif 916 } 917 918 919 //------------------------------------------------------------------- 920 // IKsControl 921 // 922 HRESULT 923 STDMETHODCALLTYPE 924 CInputPin::KsProperty( 925 PKSPROPERTY Property, 926 ULONG PropertyLength, 927 LPVOID PropertyData, 928 ULONG DataLength, 929 ULONG* BytesReturned) 930 { 931 assert(m_hPin != INVALID_HANDLE_VALUE); 932 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned); 933 } 934 935 HRESULT 936 STDMETHODCALLTYPE 937 CInputPin::KsMethod( 938 PKSMETHOD Method, 939 ULONG MethodLength, 940 LPVOID MethodData, 941 ULONG DataLength, 942 ULONG* BytesReturned) 943 { 944 assert(m_hPin != INVALID_HANDLE_VALUE); 945 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned); 946 } 947 948 HRESULT 949 STDMETHODCALLTYPE 950 CInputPin::KsEvent( 951 PKSEVENT Event, 952 ULONG EventLength, 953 LPVOID EventData, 954 ULONG DataLength, 955 ULONG* BytesReturned) 956 { 957 assert(m_hPin != INVALID_HANDLE_VALUE); 958 959 if (EventLength) 960 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned); 961 else 962 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned); 963 } 964 965 966 //------------------------------------------------------------------- 967 // IKsPropertySet 968 // 969 HRESULT 970 STDMETHODCALLTYPE 971 CInputPin::Set( 972 REFGUID guidPropSet, 973 DWORD dwPropID, 974 LPVOID pInstanceData, 975 DWORD cbInstanceData, 976 LPVOID pPropData, 977 DWORD cbPropData) 978 { 979 ULONG BytesReturned; 980 981 if (cbInstanceData) 982 { 983 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); 984 if (!Property) 985 return E_OUTOFMEMORY; 986 987 Property->Set = guidPropSet; 988 Property->Id = dwPropID; 989 Property->Flags = KSPROPERTY_TYPE_SET; 990 991 CopyMemory((Property+1), pInstanceData, cbInstanceData); 992 993 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); 994 CoTaskMemFree(Property); 995 return hr; 996 } 997 else 998 { 999 KSPROPERTY Property; 1000 1001 Property.Set = guidPropSet; 1002 Property.Id = dwPropID; 1003 Property.Flags = KSPROPERTY_TYPE_SET; 1004 1005 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); 1006 return hr; 1007 } 1008 } 1009 1010 HRESULT 1011 STDMETHODCALLTYPE 1012 CInputPin::Get( 1013 REFGUID guidPropSet, 1014 DWORD dwPropID, 1015 LPVOID pInstanceData, 1016 DWORD cbInstanceData, 1017 LPVOID pPropData, 1018 DWORD cbPropData, 1019 DWORD *pcbReturned) 1020 { 1021 ULONG BytesReturned; 1022 1023 if (cbInstanceData) 1024 { 1025 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); 1026 if (!Property) 1027 return E_OUTOFMEMORY; 1028 1029 Property->Set = guidPropSet; 1030 Property->Id = dwPropID; 1031 Property->Flags = KSPROPERTY_TYPE_GET; 1032 1033 CopyMemory((Property+1), pInstanceData, cbInstanceData); 1034 1035 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); 1036 CoTaskMemFree(Property); 1037 return hr; 1038 } 1039 else 1040 { 1041 KSPROPERTY Property; 1042 1043 Property.Set = guidPropSet; 1044 Property.Id = dwPropID; 1045 Property.Flags = KSPROPERTY_TYPE_GET; 1046 1047 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); 1048 return hr; 1049 } 1050 } 1051 1052 HRESULT 1053 STDMETHODCALLTYPE 1054 CInputPin::QuerySupported( 1055 REFGUID guidPropSet, 1056 DWORD dwPropID, 1057 DWORD *pTypeSupport) 1058 { 1059 KSPROPERTY Property; 1060 ULONG BytesReturned; 1061 1062 Property.Set = guidPropSet; 1063 Property.Id = dwPropID; 1064 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; 1065 1066 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned); 1067 } 1068 1069 1070 //------------------------------------------------------------------- 1071 // IKsObject 1072 // 1073 HANDLE 1074 STDMETHODCALLTYPE 1075 CInputPin::KsGetObjectHandle() 1076 { 1077 assert(m_hPin); 1078 return m_hPin; 1079 } 1080 1081 //------------------------------------------------------------------- 1082 // IPin interface 1083 // 1084 HRESULT 1085 STDMETHODCALLTYPE 1086 CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) 1087 { 1088 #ifdef KSPROXY_TRACE 1089 OutputDebugStringW(L"CInputPin::Connect NotImplemented\n"); 1090 #endif 1091 return NOERROR; 1092 } 1093 1094 HRESULT 1095 STDMETHODCALLTYPE 1096 CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) 1097 { 1098 HRESULT hr; 1099 1100 if (m_Pin) 1101 { 1102 // already connected 1103 return VFW_E_ALREADY_CONNECTED; 1104 } 1105 1106 // first check format 1107 hr = CheckFormat(pmt); 1108 if (FAILED(hr)) 1109 { 1110 // format is not supported 1111 return hr; 1112 } 1113 1114 hr = CreatePin(pmt); 1115 if (FAILED(hr)) 1116 { 1117 return hr; 1118 } 1119 1120 m_Pin = pConnector; 1121 m_Pin->AddRef(); 1122 1123 return S_OK; 1124 } 1125 HRESULT 1126 STDMETHODCALLTYPE 1127 CInputPin::Disconnect( void) 1128 { 1129 if (!m_Pin) 1130 { 1131 // pin was not connected 1132 return S_FALSE; 1133 } 1134 1135 //FIXME 1136 //check if filter is active 1137 1138 m_Pin->Release(); 1139 m_Pin = NULL; 1140 1141 #ifdef KSPROXY_TRACE 1142 OutputDebugStringW(L"CInputPin::Disconnect\n"); 1143 #endif 1144 1145 return S_OK; 1146 } 1147 HRESULT 1148 STDMETHODCALLTYPE 1149 CInputPin::ConnectedTo(IPin **pPin) 1150 { 1151 if (!pPin) 1152 return E_POINTER; 1153 1154 if (m_Pin) 1155 { 1156 // increment reference count 1157 m_Pin->AddRef(); 1158 *pPin = m_Pin; 1159 return S_OK; 1160 } 1161 1162 *pPin = NULL; 1163 return VFW_E_NOT_CONNECTED; 1164 } 1165 HRESULT 1166 STDMETHODCALLTYPE 1167 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) 1168 { 1169 if (!m_Pin) 1170 return VFW_E_NOT_CONNECTED; 1171 1172 #ifdef KSPROXY_TRACE 1173 OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n"); 1174 #endif 1175 1176 return E_NOTIMPL; 1177 } 1178 HRESULT 1179 STDMETHODCALLTYPE 1180 CInputPin::QueryPinInfo(PIN_INFO *pInfo) 1181 { 1182 wcscpy(pInfo->achName, m_PinName); 1183 pInfo->dir = PINDIR_INPUT; 1184 pInfo->pFilter = m_ParentFilter; 1185 m_ParentFilter->AddRef(); 1186 1187 return S_OK; 1188 } 1189 HRESULT 1190 STDMETHODCALLTYPE 1191 CInputPin::QueryDirection(PIN_DIRECTION *pPinDir) 1192 { 1193 if (pPinDir) 1194 { 1195 *pPinDir = PINDIR_INPUT; 1196 return S_OK; 1197 } 1198 1199 return E_POINTER; 1200 } 1201 HRESULT 1202 STDMETHODCALLTYPE 1203 CInputPin::QueryId(LPWSTR *Id) 1204 { 1205 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR)); 1206 if (!*Id) 1207 return E_OUTOFMEMORY; 1208 1209 wcscpy(*Id, m_PinName); 1210 return S_OK; 1211 } 1212 1213 HRESULT 1214 STDMETHODCALLTYPE 1215 CInputPin::QueryAccept( 1216 const AM_MEDIA_TYPE *pmt) 1217 { 1218 return CheckFormat(pmt); 1219 } 1220 HRESULT 1221 STDMETHODCALLTYPE 1222 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) 1223 { 1224 HRESULT hr; 1225 ULONG MediaTypeCount = 0, Index; 1226 AM_MEDIA_TYPE * MediaTypes; 1227 IKsObject * KsObjectParent; 1228 HANDLE hFilter; 1229 1230 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 1231 if (FAILED(hr)) 1232 return hr; 1233 1234 hFilter = KsObjectParent->KsGetObjectHandle(); 1235 1236 KsObjectParent->Release(); 1237 1238 if (!hFilter) 1239 return E_HANDLE; 1240 1241 1242 // query media type count 1243 hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount); 1244 if (FAILED(hr) || !MediaTypeCount) 1245 return hr; 1246 1247 // allocate media types 1248 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount); 1249 if (!MediaTypes) 1250 { 1251 // not enough memory 1252 return E_OUTOFMEMORY; 1253 } 1254 1255 // zero media types 1256 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount); 1257 1258 for(Index = 0; Index < MediaTypeCount; Index++) 1259 { 1260 // get media type 1261 hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId); 1262 if (FAILED(hr)) 1263 { 1264 // failed 1265 CoTaskMemFree(MediaTypes); 1266 return hr; 1267 } 1268 } 1269 1270 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum); 1271 } 1272 1273 HRESULT 1274 STDMETHODCALLTYPE 1275 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) 1276 { 1277 #ifdef KSPROXY_TRACE 1278 OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n"); 1279 #endif 1280 return E_NOTIMPL; 1281 } 1282 HRESULT 1283 STDMETHODCALLTYPE 1284 CInputPin::EndOfStream( void) 1285 { 1286 #ifdef KSPROXY_TRACE 1287 OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n"); 1288 #endif 1289 return E_NOTIMPL; 1290 } 1291 HRESULT 1292 STDMETHODCALLTYPE 1293 CInputPin::BeginFlush( void) 1294 { 1295 #ifdef KSPROXY_TRACE 1296 OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n"); 1297 #endif 1298 return E_NOTIMPL; 1299 } 1300 HRESULT 1301 STDMETHODCALLTYPE 1302 CInputPin::EndFlush( void) 1303 { 1304 #ifdef KSPROXY_TRACE 1305 OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n"); 1306 #endif 1307 return E_NOTIMPL; 1308 } 1309 HRESULT 1310 STDMETHODCALLTYPE 1311 CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) 1312 { 1313 #ifdef KSPROXY_TRACE 1314 OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n"); 1315 #endif 1316 return E_NOTIMPL; 1317 } 1318 1319 1320 //------------------------------------------------------------------- 1321 HRESULT 1322 STDMETHODCALLTYPE 1323 CInputPin::CheckFormat( 1324 const AM_MEDIA_TYPE *pmt) 1325 { 1326 PKSMULTIPLE_ITEM MultipleItem; 1327 PKSDATAFORMAT DataFormat; 1328 HRESULT hr; 1329 IKsObject * KsObjectParent; 1330 HANDLE hFilter; 1331 1332 if (!pmt) 1333 return E_POINTER; 1334 1335 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 1336 if (FAILED(hr)) 1337 return hr; 1338 1339 hFilter = KsObjectParent->KsGetObjectHandle(); 1340 1341 KsObjectParent->Release(); 1342 1343 if (!hFilter) 1344 return E_HANDLE; 1345 1346 1347 hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem); 1348 if (FAILED(hr)) 1349 return S_FALSE; 1350 1351 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1); 1352 for(ULONG Index = 0; Index < MultipleItem->Count; Index++) 1353 { 1354 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) && 1355 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) && 1356 IsEqualGUID(pmt->formattype, DataFormat->Specifier)) 1357 { 1358 // format is supported 1359 CoTaskMemFree(MultipleItem); 1360 #ifdef KSPROXY_TRACE 1361 OutputDebugStringW(L"CInputPin::CheckFormat format OK\n"); 1362 #endif 1363 return S_OK; 1364 } 1365 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize); 1366 } 1367 //format is not supported 1368 CoTaskMemFree(MultipleItem); 1369 return S_FALSE; 1370 } 1371 1372 HRESULT 1373 STDMETHODCALLTYPE 1374 CInputPin::CreatePin( 1375 const AM_MEDIA_TYPE *pmt) 1376 { 1377 PKSMULTIPLE_ITEM MediumList; 1378 PKSMULTIPLE_ITEM InterfaceList; 1379 PKSPIN_MEDIUM Medium; 1380 PKSPIN_INTERFACE Interface; 1381 IKsInterfaceHandler * InterfaceHandler; 1382 HRESULT hr; 1383 1384 // query for pin medium 1385 hr = KsQueryMediums(&MediumList); 1386 if (FAILED(hr)) 1387 return hr; 1388 1389 // query for pin interface 1390 hr = KsQueryInterfaces(&InterfaceList); 1391 if (FAILED(hr)) 1392 { 1393 // failed 1394 CoTaskMemFree(MediumList); 1395 return hr; 1396 } 1397 1398 if (MediumList->Count) 1399 { 1400 //use first available medium 1401 Medium = (PKSPIN_MEDIUM)(MediumList + 1); 1402 } 1403 else 1404 { 1405 // default to standard medium 1406 Medium = &StandardPinMedium; 1407 } 1408 1409 if (InterfaceList->Count) 1410 { 1411 //use first available interface 1412 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1); 1413 } 1414 else 1415 { 1416 // default to standard interface 1417 Interface = &StandardPinInterface; 1418 } 1419 1420 if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE) 1421 { 1422 if (!m_InterfaceHandler) 1423 { 1424 // now load the IKsInterfaceHandler plugin 1425 hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler); 1426 if (FAILED(hr)) 1427 { 1428 // failed to load interface handler plugin 1429 #ifdef KSPROXY_TRACE 1430 OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n"); 1431 #endif 1432 CoTaskMemFree(MediumList); 1433 CoTaskMemFree(InterfaceList); 1434 1435 return hr; 1436 } 1437 1438 // now set the pin 1439 hr = InterfaceHandler->KsSetPin((IKsPin*)this); 1440 if (FAILED(hr)) 1441 { 1442 // failed to load interface handler plugin 1443 #ifdef KSPROXY_TRACE 1444 OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n"); 1445 #endif 1446 InterfaceHandler->Release(); 1447 CoTaskMemFree(MediumList); 1448 CoTaskMemFree(InterfaceList); 1449 return hr; 1450 } 1451 1452 // store interface handler 1453 m_InterfaceHandler = InterfaceHandler; 1454 } 1455 1456 // now create pin 1457 hr = CreatePinHandle(Medium, Interface, pmt); 1458 if (FAILED(hr)) 1459 { 1460 m_InterfaceHandler->Release(); 1461 m_InterfaceHandler = InterfaceHandler; 1462 } 1463 } 1464 else 1465 { 1466 #ifdef KSPROXY_TRACE 1467 WCHAR Buffer[100]; 1468 swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName); 1469 OutputDebugStringW(Buffer); 1470 #endif 1471 hr = E_FAIL; 1472 } 1473 1474 // free medium / interface / dataformat 1475 CoTaskMemFree(MediumList); 1476 CoTaskMemFree(InterfaceList); 1477 1478 return hr; 1479 } 1480 1481 HRESULT 1482 STDMETHODCALLTYPE 1483 CInputPin::CreatePinHandle( 1484 PKSPIN_MEDIUM Medium, 1485 PKSPIN_INTERFACE Interface, 1486 const AM_MEDIA_TYPE *pmt) 1487 { 1488 PKSPIN_CONNECT PinConnect; 1489 PKSDATAFORMAT DataFormat; 1490 ULONG Length; 1491 HRESULT hr; 1492 IKsObject * KsObjectParent; 1493 HANDLE hFilter; 1494 1495 if (!pmt) 1496 return E_POINTER; 1497 1498 hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); 1499 if (FAILED(hr)) 1500 return hr; 1501 1502 hFilter = KsObjectParent->KsGetObjectHandle(); 1503 1504 KsObjectParent->Release(); 1505 1506 if (!hFilter) 1507 return E_HANDLE; 1508 1509 1510 if (m_hPin != INVALID_HANDLE_VALUE) 1511 { 1512 // pin already exists 1513 //CloseHandle(m_hPin); 1514 //m_hPin = INVALID_HANDLE_VALUE; 1515 return S_OK; 1516 } 1517 1518 1519 // calc format size 1520 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat; 1521 1522 // allocate pin connect 1523 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length); 1524 if (!PinConnect) 1525 { 1526 // failed 1527 return E_OUTOFMEMORY; 1528 } 1529 1530 // setup request 1531 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE)); 1532 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM)); 1533 PinConnect->PinId = m_PinId; 1534 PinConnect->PinToHandle = NULL; 1535 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; 1536 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL; 1537 1538 // get dataformat offset 1539 DataFormat = (PKSDATAFORMAT)(PinConnect + 1); 1540 1541 // copy data format 1542 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat; 1543 DataFormat->Flags = 0; 1544 DataFormat->SampleSize = pmt->lSampleSize; 1545 DataFormat->Reserved = 0; 1546 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID)); 1547 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID)); 1548 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID)); 1549 1550 if (pmt->cbFormat) 1551 { 1552 // copy extended format 1553 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat); 1554 } 1555 1556 // create pin 1557 hr = KsCreatePin(hFilter, PinConnect, GENERIC_WRITE, &m_hPin); 1558 1559 if (SUCCEEDED(hr)) 1560 { 1561 // store current interface / medium 1562 CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM)); 1563 CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE)); 1564 CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE)); 1565 1566 #ifdef KSPROXY_TRACE 1567 LPOLESTR pMajor, pSub, pFormat; 1568 StringFromIID(m_MediaFormat.majortype, &pMajor); 1569 StringFromIID(m_MediaFormat.subtype , &pSub); 1570 StringFromIID(m_MediaFormat.formattype, &pFormat); 1571 1572 WCHAR Buffer[200]; 1573 swprintf(Buffer, L"CInputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat); 1574 CoTaskMemFree(pMajor); 1575 CoTaskMemFree(pSub); 1576 CoTaskMemFree(pFormat); 1577 OutputDebugStringW(Buffer); 1578 #endif 1579 1580 if (pmt->cbFormat) 1581 { 1582 m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat); 1583 if (!m_MediaFormat.pbFormat) 1584 { 1585 CoTaskMemFree(PinConnect); 1586 m_MediaFormat.pbFormat = NULL; 1587 m_MediaFormat.cbFormat = 0; 1588 return E_OUTOFMEMORY; 1589 } 1590 CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat); 1591 } 1592 1593 LPGUID pGuid; 1594 ULONG NumGuids = 0; 1595 1596 // get all supported sets 1597 hr = GetSupportedSets(&pGuid, &NumGuids); 1598 if (FAILED(hr)) 1599 { 1600 #ifdef KSPROXY_TRACE 1601 OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n"); 1602 #endif 1603 return hr; 1604 } 1605 1606 // load all proxy plugins 1607 hr = LoadProxyPlugins(pGuid, NumGuids); 1608 if (FAILED(hr)) 1609 { 1610 #ifdef KSPROXY_TRACE 1611 OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n"); 1612 #endif 1613 return hr; 1614 } 1615 1616 // free sets 1617 CoTaskMemFree(pGuid); 1618 1619 1620 //TODO 1621 // connect pin pipes 1622 1623 } 1624 1625 // free pin connect 1626 CoTaskMemFree(PinConnect); 1627 1628 return hr; 1629 } 1630 1631 HRESULT 1632 STDMETHODCALLTYPE 1633 CInputPin::GetSupportedSets( 1634 LPGUID * pOutGuid, 1635 PULONG NumGuids) 1636 { 1637 KSPROPERTY Property; 1638 LPGUID pGuid; 1639 ULONG NumProperty = 0; 1640 ULONG NumMethods = 0; 1641 ULONG NumEvents = 0; 1642 ULONG Length; 1643 ULONG BytesReturned; 1644 HRESULT hr; 1645 1646 Property.Set = GUID_NULL; 1647 Property.Id = 0; 1648 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; 1649 1650 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty); 1651 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods); 1652 KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents); 1653 1654 Length = NumProperty + NumMethods + NumEvents; 1655 1656 assert(Length); 1657 1658 // allocate guid buffer 1659 pGuid = (LPGUID)CoTaskMemAlloc(Length); 1660 if (!pGuid) 1661 { 1662 // failed 1663 return E_OUTOFMEMORY; 1664 } 1665 1666 NumProperty /= sizeof(GUID); 1667 NumMethods /= sizeof(GUID); 1668 NumEvents /= sizeof(GUID); 1669 1670 #ifdef KSPROXY_TRACE 1671 WCHAR Buffer[200]; 1672 swprintf(Buffer, L"CInputPin::GetSupportedSets NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents); 1673 OutputDebugStringW(Buffer); 1674 #endif 1675 1676 // get all properties 1677 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned); 1678 if (FAILED(hr)) 1679 { 1680 CoTaskMemFree(pGuid); 1681 return E_FAIL; 1682 } 1683 Length -= BytesReturned; 1684 1685 // get all methods 1686 if (Length && NumMethods) 1687 { 1688 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned); 1689 if (FAILED(hr)) 1690 { 1691 CoTaskMemFree(pGuid); 1692 return E_FAIL; 1693 } 1694 Length -= BytesReturned; 1695 } 1696 1697 // get all events 1698 if (Length && NumEvents) 1699 { 1700 hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned); 1701 if (FAILED(hr)) 1702 { 1703 CoTaskMemFree(pGuid); 1704 return E_FAIL; 1705 } 1706 Length -= BytesReturned; 1707 } 1708 1709 *pOutGuid = pGuid; 1710 *NumGuids = NumProperty+NumEvents+NumMethods; 1711 return S_OK; 1712 } 1713 1714 HRESULT 1715 STDMETHODCALLTYPE 1716 CInputPin::LoadProxyPlugins( 1717 LPGUID pGuids, 1718 ULONG NumGuids) 1719 { 1720 ULONG Index; 1721 LPOLESTR pStr; 1722 HKEY hKey, hSubKey; 1723 HRESULT hr; 1724 IUnknown * pUnknown; 1725 1726 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS) 1727 { 1728 OutputDebugStringW(L"CInputPin::LoadProxyPlugins failed to open MediaInterfaces key\n"); 1729 return E_FAIL; 1730 } 1731 1732 // enumerate all sets 1733 for(Index = 0; Index < NumGuids; Index++) 1734 { 1735 // convert to string 1736 hr = StringFromCLSID(pGuids[Index], &pStr); 1737 if (FAILED(hr)) 1738 return E_FAIL; 1739 1740 // now try open class key 1741 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) 1742 { 1743 // no plugin for that set exists 1744 CoTaskMemFree(pStr); 1745 continue; 1746 } 1747 1748 // try load plugin 1749 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown); 1750 if (SUCCEEDED(hr)) 1751 { 1752 // store plugin 1753 m_Plugins.push_back(pUnknown); 1754 } 1755 // close key 1756 RegCloseKey(hSubKey); 1757 } 1758 1759 // close media interfaces key 1760 RegCloseKey(hKey); 1761 return S_OK; 1762 } 1763 1764 HRESULT 1765 WINAPI 1766 CInputPin_Constructor( 1767 IBaseFilter * ParentFilter, 1768 LPCWSTR PinName, 1769 HANDLE hFilter, 1770 ULONG PinId, 1771 KSPIN_COMMUNICATION Communication, 1772 REFIID riid, 1773 LPVOID * ppv) 1774 { 1775 CInputPin * handler = new CInputPin(ParentFilter, PinName, PinId, Communication); 1776 1777 if (!handler) 1778 return E_OUTOFMEMORY; 1779 1780 if (FAILED(handler->QueryInterface(riid, ppv))) 1781 { 1782 /* not supported */ 1783 delete handler; 1784 return E_NOINTERFACE; 1785 } 1786 1787 return S_OK; 1788 } 1789