Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1072 lines
24 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. render.cpp
  5. Abstract:
  6. Implementation of CRtpRenderFilter class.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. 06-Nov-1996 DonRyan
  11. Created.
  12. --*/
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // //
  15. // Include files //
  16. // //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include "globals.h"
  19. ///////////////////////////////////////////////////////////////////////////////
  20. // //
  21. // CRtpRenderFilter methods //
  22. // //
  23. ///////////////////////////////////////////////////////////////////////////////
  24. CRtpRenderFilter::CRtpRenderFilter(
  25. LPUNKNOWN pUnk,
  26. HRESULT * phr // MUST be a valid pointer
  27. )
  28. /*++
  29. Routine Description:
  30. Constructor for CRtpRenderFilter class.
  31. Arguments:
  32. pUnk - IUnknown interface of the delegating object.
  33. phr - pointer to the general OLE return value.
  34. Return Values:
  35. Returns an HRESULT value.
  36. --*/
  37. : CBaseFilter(
  38. NAME("CRtpRenderFilter"),
  39. pUnk,
  40. &m_cStateLock,
  41. CLSID_RTPRenderFilter,
  42. phr // No point passing this, base class doesn't even touch it
  43. ),
  44. CPersistStream(pUnk, phr),
  45. m_iPins(0),
  46. m_paStreams(NULL)
  47. {
  48. TraceDebug((
  49. TRACE_TRACE,
  50. TRACE_DEVELOP,
  51. TEXT("[%x:0x%X]CRtpRenderFilter::CRtpRenderFilter]"),
  52. GetCurrentThreadId(), this
  53. ));
  54. WSADATA WSAData;
  55. WORD VersionRequested = MAKEWORD(2,0);
  56. // initialize winsock first
  57. if (WSAStartup(VersionRequested, &WSAData)) {
  58. TraceDebug((
  59. TRACE_ERROR,
  60. TRACE_DEVELOP,
  61. TEXT("WSAStartup returned %d"),
  62. WSAGetLastError()
  63. ));
  64. *phr = E_FAIL;
  65. return; // bail...
  66. }
  67. // create default input pin object
  68. CRtpInputPin * pPin = new CRtpInputPin(
  69. this,
  70. GetOwner(),
  71. phr
  72. );
  73. if (FAILED(*phr)) {
  74. TraceDebug((
  75. TRACE_ERROR,
  76. TRACE_DEVELOP,
  77. TEXT("CRtpRenderFilter::CRtpRenderFilter: "
  78. "new CRtpInputPin() failed: 0x%X"),
  79. *phr
  80. ));
  81. return;
  82. }
  83. // validate pointer
  84. if (pPin == NULL) {
  85. TraceDebug((
  86. TRACE_ERROR,
  87. TRACE_DEVELOP,
  88. TEXT("Could not create CRtpInputPin")
  89. ));
  90. // return default
  91. *phr = E_OUTOFMEMORY;
  92. return; // bail...
  93. }
  94. ASSERT(m_paStreams != NULL);
  95. //
  96. // pins add themselves to filters's array...
  97. //
  98. }
  99. CRtpRenderFilter::~CRtpRenderFilter(
  100. )
  101. /*++
  102. Routine Description:
  103. Destructor for CRtpRenderFilter class.
  104. Arguments:
  105. None.
  106. Return Values:
  107. None.
  108. --*/
  109. {
  110. TraceDebug((
  111. TRACE_TRACE,
  112. TRACE_DEVELOP,
  113. TEXT("[%x:0x%X]CRtpRenderFilter::~CRtpRenderFilter"),
  114. GetCurrentThreadId(), this
  115. ));
  116. // rally thru pins
  117. while (m_iPins != 0) {
  118. // nuke each pin in array
  119. delete m_paStreams[m_iPins - 1];
  120. }
  121. // shutdown now
  122. if (WSACleanup()) {
  123. TraceDebug((
  124. TRACE_ERROR,
  125. TRACE_DEVELOP,
  126. TEXT("WSACleanup returned %d"),
  127. WSAGetLastError()
  128. ));
  129. }
  130. ASSERT(m_paStreams == NULL);
  131. //
  132. // pins delete themselves from filter's array
  133. //
  134. }
  135. CUnknown *
  136. CRtpRenderFilter::CreateInstance(
  137. LPUNKNOWN punk,
  138. HRESULT * phr
  139. )
  140. /*++
  141. Routine Description:
  142. Called by COM to create a CRtpRenderFilter object.
  143. Arguments:
  144. pUnk - pointer to the owner of this object.
  145. phr - pointer to an HRESULT value for resulting information.
  146. Return Values:
  147. None.
  148. --*/
  149. {
  150. TraceDebug((
  151. TRACE_TRACE,
  152. TRACE_ALWAYS,
  153. TEXT("CRtpRenderFilter::CreateInstance")
  154. ));
  155. // attempt to create rtp sender object
  156. CRtpRenderFilter * pNewObject = new CRtpRenderFilter(punk, phr);
  157. // validate pointer
  158. if (pNewObject == NULL) {
  159. TraceDebug((
  160. TRACE_ERROR,
  161. TRACE_DEVELOP,
  162. TEXT("Could not create CRtpRenderFilter")
  163. ));
  164. // return default
  165. *phr = E_OUTOFMEMORY;
  166. }
  167. // return object
  168. return pNewObject;
  169. }
  170. HRESULT
  171. CRtpRenderFilter::AddPin(
  172. CRtpInputPin * pPin
  173. )
  174. /*++
  175. Routine Description:
  176. Adds a pin to the network sink filter.
  177. Arguments:
  178. pPin - input pin to be added to the filter.
  179. Return Values:
  180. Returns an HRESULT value.
  181. --*/
  182. {
  183. TraceDebug((
  184. TRACE_TRACE,
  185. TRACE_ALWAYS,
  186. TEXT("CRtpRenderFilter::AddPin")
  187. ));
  188. // object lock on this object
  189. CAutoLock LockThis(&m_cStateLock);
  190. // allocate temporary array to hold the stream pointers
  191. CRtpInputPin ** paStreams = new CRtpInputPin *[m_iPins + 1];
  192. // validate pointer
  193. if (paStreams == NULL) {
  194. TraceDebug((
  195. TRACE_ERROR,
  196. TRACE_DEVELOP,
  197. TEXT("Could not create CRtpInputPin array")
  198. ));
  199. return E_OUTOFMEMORY; // bail...
  200. }
  201. // see if array exists
  202. if (m_paStreams != NULL) {
  203. // transfer existing pointers
  204. CopyMemory(
  205. (PVOID)paStreams,
  206. (PVOID)m_paStreams,
  207. m_iPins * sizeof(m_paStreams[0])
  208. );
  209. // nuke old array
  210. delete [] m_paStreams;
  211. }
  212. // save new array pointer
  213. m_paStreams = paStreams;
  214. // add new pin to array
  215. m_paStreams[m_iPins] = pPin;
  216. // add
  217. m_iPins++;
  218. return S_OK;
  219. }
  220. HRESULT
  221. CRtpRenderFilter::RemovePin(
  222. CRtpInputPin * pPin
  223. )
  224. /*++
  225. Routine Description:
  226. Removes a pin from the network sink filter.
  227. Arguments:
  228. pPin - input pin to be removed from the filter.
  229. Return Values:
  230. Returns an HRESULT value.
  231. --*/
  232. {
  233. TraceDebug((
  234. TRACE_TRACE,
  235. TRACE_ALWAYS,
  236. TEXT("CRtpRenderFilter::RemovePin")
  237. ));
  238. // object lock on this object
  239. CAutoLock LockThis(&m_cStateLock);
  240. int i;
  241. // process each pin
  242. for (i = 0; i < m_iPins; i++) {
  243. // see if this is the one
  244. if (m_paStreams[i] == pPin) {
  245. // single pin?
  246. if (m_iPins == 1) {
  247. // need to nuke array
  248. delete [] m_paStreams;
  249. // re-initialize
  250. m_paStreams = NULL;
  251. } else {
  252. // adjust rest of pins
  253. while (++i < m_iPins) {
  254. // slide pointers over one slot
  255. m_paStreams[i - 1] = m_paStreams[i];
  256. }
  257. }
  258. // delete
  259. m_iPins--;
  260. return S_OK;
  261. }
  262. }
  263. return S_FALSE;
  264. }
  265. ///////////////////////////////////////////////////////////////////////////////
  266. // //
  267. // CBaseFilter overrided methods //
  268. // //
  269. ///////////////////////////////////////////////////////////////////////////////
  270. CBasePin *
  271. CRtpRenderFilter::GetPin(
  272. int n
  273. )
  274. /*++
  275. Routine Description:
  276. Obtains specific CBasePin object associated with filter.
  277. Arguments:
  278. n - number of the specified pin.
  279. Return Values:
  280. Returns pointer to specified pin.
  281. --*/
  282. {
  283. TraceDebug((
  284. TRACE_TRACE,
  285. TRACE_ALWAYS,
  286. TEXT("CRtpRenderFilter::GetPin %d"), n
  287. ));
  288. // object lock on filter object
  289. CAutoLock LockThis(&m_cStateLock);
  290. // validate index passed in
  291. if ((n >= 0) && (n < m_iPins)) {
  292. ASSERT(m_paStreams[n]);
  293. // return input pin
  294. return m_paStreams[n];
  295. }
  296. return NULL;
  297. }
  298. int
  299. CRtpRenderFilter::GetPinCount(
  300. )
  301. /*++
  302. Routine Description:
  303. Obtains number of pins supported by filter.
  304. Arguments:
  305. None.
  306. Return Values:
  307. Returns the number of supported pins.
  308. --*/
  309. {
  310. TraceDebug((
  311. TRACE_TRACE,
  312. TRACE_ALWAYS,
  313. TEXT("CRtpRenderFilter::GetPinCount")
  314. ));
  315. // object lock on filter object
  316. CAutoLock LockThis(&m_cStateLock);
  317. // return count
  318. return m_iPins;
  319. }
  320. LPAMOVIESETUP_FILTER
  321. CRtpRenderFilter::GetSetupData(
  322. )
  323. /*++
  324. Routine Description:
  325. Called by ActiveMovie to retrieve filter setup information.
  326. Arguments:
  327. None.
  328. Return Values:
  329. Returns pointer to filter info structure.
  330. --*/
  331. {
  332. TraceDebug((
  333. TRACE_TRACE,
  334. TRACE_ALWAYS,
  335. TEXT("CRtpRenderFilter::GetSetupData")
  336. ));
  337. // get sink filter info
  338. return &g_RtpRenderFilter;
  339. }
  340. ///////////////////////////////////////////////////////////////////////////////
  341. // //
  342. // IBaseFilter implemented methods //
  343. // //
  344. ///////////////////////////////////////////////////////////////////////////////
  345. STDMETHODIMP
  346. CRtpRenderFilter::QueryVendorInfo(
  347. LPWSTR * ppVendorInfo
  348. )
  349. /*++
  350. Routine Description:
  351. Returns a vendor information string.
  352. Arguments:
  353. ppVendorInfo - Pointer to a string containing vendor information.
  354. Return Values:
  355. Returns an HRESULT value.
  356. --*/
  357. {
  358. TraceDebug((
  359. TRACE_TRACE,
  360. TRACE_ALWAYS,
  361. TEXT("CRtpRenderFilter::QueryVendorInfo")
  362. ));
  363. // validate pointer
  364. CheckPointer(ppVendorInfo,E_POINTER);
  365. // allocate the description string
  366. *ppVendorInfo = (LPWSTR)CoTaskMemAlloc(
  367. (lstrlenW(g_VendorInfo)+1) * sizeof(WCHAR)
  368. );
  369. // validate pointer
  370. if (*ppVendorInfo == NULL) {
  371. TraceDebug((
  372. TRACE_ERROR,
  373. TRACE_ALWAYS,
  374. TEXT("Could not allocate vendor info")
  375. ));
  376. return E_OUTOFMEMORY; // bail...
  377. }
  378. // copy vendor description string
  379. lstrcpyW(*ppVendorInfo,g_VendorInfo);
  380. return S_OK;
  381. }
  382. //-----------------------------------------------------------------------//
  383. // IAMFilterMiscFlags implemented methods //
  384. //-----------------------------------------------------------------------//
  385. /*++
  386. Routine Description:
  387. Implement the IAMFilterMiscFlags::GetMiscFlags method. Retrieves the
  388. miscelaneous flags. This consists of whether or not the filter moves
  389. data out of the graph system through a Bridge or None pin.
  390. Arguments:
  391. None.
  392. --*/
  393. STDMETHODIMP_(ULONG)
  394. CRtpRenderFilter::GetMiscFlags(void)
  395. {
  396. return(AM_FILTER_MISC_FLAGS_IS_RENDERER);
  397. }
  398. ///////////////////////////////////////////////////////////////////////////////
  399. // //
  400. // IPersistStream implemented methods //
  401. // //
  402. ///////////////////////////////////////////////////////////////////////////////
  403. STDMETHODIMP
  404. CRtpRenderFilter::GetClassID(
  405. CLSID *pClsid
  406. )
  407. /*++
  408. Routine Description:
  409. Retrieves the class identifier for this filter.
  410. Arguments:
  411. pClsid - Pointer to a CLSID structure.
  412. Return Values:
  413. Returns an HRESULT value.
  414. --*/
  415. {
  416. TraceDebug((
  417. TRACE_TRACE,
  418. TRACE_ALWAYS,
  419. TEXT("CRtpRenderFilter::GetClassID")
  420. ));
  421. // transfer filter class id
  422. *pClsid = CLSID_RTPRenderFilter;
  423. return S_OK;
  424. }
  425. // ZCS: 6-22-97: copied this from the Demux filter code and modified it...
  426. //
  427. // Name : WriteEntry
  428. // Purpose : A macro that implements the stuff we do to write
  429. // a property of this filter to its persistent stream.
  430. // Context : Used in WriteToStream() to improve readability.
  431. // Returns : Will only return if an error is detected.
  432. // Params :
  433. // Entry Pointer to a buffer containing the value to write.
  434. // InSize Integer indicating the length of the buffer
  435. // OutSize Integer to store the written length.
  436. // Description Char string used to describe the entry.
  437. // Notes :
  438. #define WriteEntry(Entry, InSize, OutSize, Description) \
  439. { TraceDebug((TRACE_TRACE, 4, TEXT("CRtpRenderFilter::WriteToStream: Writing %s"), Description)); \
  440. hr = pStream->Write(Entry, InSize, &OutSize); \
  441. if (FAILED(hr)) { \
  442. TraceDebug((TRACE_ERROR, 2, TEXT("CRtpRenderFilter::WriteToStream: Error 0x%08x writing %s"), hr, Description)); \
  443. return hr; \
  444. } else if (OutSize != InSize) { \
  445. TraceDebug((TRACE_ERROR, 2, \
  446. TEXT("CRtpRenderFilter::WriteToStream: Too few (%d/%d) bytes written for %s"), \
  447. uBytesWritten, sizeof(int), Description)); \
  448. return E_INVALIDARG; \
  449. } /* if */ }
  450. HRESULT
  451. CRtpRenderFilter::WriteToStream(
  452. IStream *pStream
  453. )
  454. /*++
  455. Routine Description:
  456. Writes the filter's data to the given stream.
  457. Arguments:
  458. pStream - Pointer to an IStream to write the filter's data to.
  459. Return Values:
  460. Returns an HRESULT value.
  461. --*/
  462. {
  463. TraceDebug((
  464. TRACE_TRACE,
  465. TRACE_ALWAYS,
  466. TEXT("CRtpRenderFilter::WriteToStream")
  467. ));
  468. // validate pointer
  469. CheckPointer(pStream,E_POINTER);
  470. // obtain lock to this object
  471. CAutoLock LockThis(&m_cStateLock);
  472. //
  473. // Rest of this function added 6-22-97 by ZCS
  474. //
  475. HRESULT hr; // used in the WriteEntry macro
  476. ULONG uBytesWritten = 0;
  477. DWORD dwRtpAddr;
  478. WORD wRtpPort;
  479. DWORD dwMulticastScope;
  480. DWORD dwQOSstate;
  481. DWORD dwMCLoopBack;
  482. // get the RTP session object so we can see the address, port, scope
  483. CRtpSession *pCRtpSession;
  484. ASSERT(m_iPins == 1);
  485. EXECUTE_ASSERT(SUCCEEDED((**m_paStreams).GetSession(&pCRtpSession)));
  486. // retrieve the address of the rtp stream object
  487. // for a sender, remote port matters
  488. EXECUTE_ASSERT(SUCCEEDED(pCRtpSession->GetAddress(NULL,
  489. &wRtpPort,
  490. &dwRtpAddr)));
  491. // retrieve multicast scope of rtp stream object
  492. EXECUTE_ASSERT(SUCCEEDED(pCRtpSession->GetMulticastScope(&dwMulticastScope)));
  493. // retrieve QOS state of rtp stream object
  494. EXECUTE_ASSERT(SUCCEEDED(pCRtpSession->GetQOSstate(&dwQOSstate)));
  495. // retrieve Multicast Loopback state of rtp stream object
  496. EXECUTE_ASSERT(SUCCEEDED(pCRtpSession->GetMulticastLoopBack(&dwMCLoopBack)));
  497. // write RTP address/port and multicast to the PersistStream
  498. WriteEntry(&dwRtpAddr, sizeof(dwRtpAddr), uBytesWritten, "RTP address");
  499. WriteEntry(&wRtpPort, sizeof(wRtpPort), uBytesWritten, "RTP port");
  500. WriteEntry(&dwMulticastScope, sizeof(dwMulticastScope), uBytesWritten, "multicast scope");
  501. WriteEntry(&dwQOSstate, sizeof(dwQOSstate), uBytesWritten, "QOS state");
  502. WriteEntry(&dwMCLoopBack, sizeof(dwMCLoopBack), uBytesWritten, "Multicast Loopback state");
  503. return S_OK;
  504. }
  505. // ZCS: 6-22-97: copied this from the Demux filter code and modified it...
  506. //
  507. // Name : ReadEntry
  508. // Purpose : A macro that implements the stuff we do to read
  509. // a property of this filter from its persistent stream.
  510. // Context : Used in ReadFromStream() to improve readability.
  511. // Returns : Will only return if an error is detected.
  512. // Params :
  513. // Entry Pointer to a buffer containing the value to read.
  514. // InSize Integer indicating the length of the buffer
  515. // OutSize Integer to store the written length.
  516. // Description Char string used to describe the entry.
  517. // Notes :
  518. #define ReadEntry(Entry, InSize, OutSize, Description) \
  519. { TraceDebug((TRACE_TRACE, 4, TEXT("CRtpRenderFilter::ReadFromStream: Reading %s"), Description)); \
  520. hr = pStream->Read(Entry, InSize, &OutSize); \
  521. if (FAILED(hr)) { \
  522. TraceDebug((TRACE_ERROR, 2, TEXT("CRtpRenderFilter::ReadFromStream: Error 0x%08x reading %s"), hr, Description)); \
  523. return hr; \
  524. } else if (OutSize != InSize) { \
  525. TraceDebug((TRACE_ERROR, 2, \
  526. TEXT("CRtpRenderFilter::ReadFromStream: Too few (%d/%d) bytes read for %s"), \
  527. OutSize, InSize, Description)); \
  528. return E_INVALIDARG; \
  529. } /* if */ }
  530. HRESULT
  531. CRtpRenderFilter::ReadFromStream(
  532. IStream *pStream
  533. )
  534. /*++
  535. Routine Description:
  536. Reads the filter's data from the given stream.
  537. Arguments:
  538. pStream - Pointer to an IStream to read the filter's data from.
  539. Return Values:
  540. Returns an HRESULT value.
  541. --*/
  542. {
  543. TraceDebug((
  544. TRACE_TRACE,
  545. TRACE_ALWAYS,
  546. TEXT("CRtpRenderFilter::ReadFromStream")
  547. ));
  548. // validate pointer
  549. CheckPointer(pStream,E_POINTER);
  550. // obtain lock to this object
  551. CAutoLock LockThis(&m_cStateLock);
  552. //
  553. // Rest of this function added 6-22-97 by ZCS based mostly on
  554. // Don Ryan's property page code...
  555. //
  556. HRESULT hr;
  557. ULONG uBytesWritten = 0;
  558. DWORD dwRtpAddr;
  559. WORD wRtpPort;
  560. DWORD RtpScope;
  561. DWORD QOSstate;
  562. DWORD MCLoopBack;
  563. // get the RTP session object so we can see the address, port, scope
  564. CRtpSession *pCRtpSession = NULL;
  565. ASSERT(m_iPins == 1);
  566. EXECUTE_ASSERT(SUCCEEDED((**m_paStreams).GetSession(&pCRtpSession)));
  567. ASSERT(!IsBadReadPtr(pCRtpSession, sizeof(pCRtpSession)));
  568. // retrieve RTP address and port from stream
  569. ReadEntry(&dwRtpAddr, sizeof(dwRtpAddr), uBytesWritten, "RTP address");
  570. ReadEntry(&wRtpPort, sizeof(wRtpPort), uBytesWritten, "RTP port");
  571. // attempt to modify the rtp address
  572. // in unicast, the local port is what matters for a receiver
  573. // in multicast, they have to be the same, SetAddress takes care
  574. hr = pCRtpSession->SetAddress(wRtpPort, wRtpPort, dwRtpAddr);
  575. // validate
  576. if (FAILED(hr)) {
  577. TraceDebug((
  578. TRACE_ERROR,
  579. TRACE_ALWAYS,
  580. TEXT("IRTPStream::SetAddress returns 0x%08lx"), hr
  581. ));
  582. return hr; // bail...
  583. }
  584. // retrieve multicast scope from stream
  585. ReadEntry(&RtpScope, sizeof(RtpScope), uBytesWritten, "multicast scope");
  586. // attempt to modify the scope
  587. hr = pCRtpSession->SetMulticastScope(RtpScope);
  588. // validate
  589. if (FAILED(hr)) {
  590. TraceDebug((
  591. TRACE_ERROR,
  592. TRACE_ALWAYS,
  593. TEXT("IRTPStream::SetScope returns 0x%08lx"), hr
  594. ));
  595. return hr; // bail...
  596. }
  597. // retrieve QOS state from stream
  598. ReadEntry(&QOSstate, sizeof(QOSstate), uBytesWritten, "QOS state");
  599. // attempt to modify the QOS state
  600. hr = pCRtpSession->SetQOSstate(QOSstate);
  601. // validate
  602. if (FAILED(hr)) {
  603. TraceDebug((
  604. TRACE_ERROR,
  605. TRACE_ALWAYS,
  606. TEXT("IRTPStream::SetQOSstate returns 0x%08lx"), hr
  607. ));
  608. return hr; // bail...
  609. }
  610. // retrieve Multicast Loopback state from stream
  611. ReadEntry(&MCLoopBack, sizeof(MCLoopBack), uBytesWritten, "Multicast Loopback state");
  612. // attempt to modify the Multicast Loopback state
  613. MCLoopBack = (MCLoopBack)? TRUE:FALSE;
  614. hr = pCRtpSession->SetMulticastLoopBack(MCLoopBack);
  615. // validate
  616. if (FAILED(hr)) {
  617. TraceDebug((
  618. TRACE_ERROR,
  619. TRACE_ALWAYS,
  620. TEXT("IRTPStream::SetMulticastLoopBack returns 0x%08lx"), hr
  621. ));
  622. return hr; // bail...
  623. }
  624. return S_OK;
  625. }
  626. int
  627. CRtpRenderFilter::SizeMax(
  628. )
  629. /*++
  630. Routine Description:
  631. Returns an interface and increments the reference count.
  632. Arguments:
  633. riid - reference identifier.
  634. ppv - pointer to the interface.
  635. Return Values:
  636. Returns a pointer to the interface.
  637. --*/
  638. {
  639. TraceDebug((
  640. TRACE_TRACE,
  641. TRACE_ALWAYS,
  642. TEXT("CRtpRenderFilter::SizeMax")
  643. ));
  644. // object lock on this object
  645. CAutoLock LockThis(&m_cStateLock);
  646. //
  647. // CODEWORK...
  648. //
  649. return S_OK;
  650. }
  651. ///////////////////////////////////////////////////////////////////////////////
  652. // //
  653. // ISpecifyPropertyPages implemented methods //
  654. // //
  655. ///////////////////////////////////////////////////////////////////////////////
  656. STDMETHODIMP
  657. CRtpRenderFilter::GetPages(
  658. CAUUID * pPages
  659. )
  660. /*++
  661. Routine Description:
  662. Returns property class id associated with filter.
  663. Arguments:
  664. pPages - pointer to received property page class id.
  665. Return Values:
  666. Returns an HRESULT value.
  667. --*/
  668. {
  669. TraceDebug((
  670. TRACE_TRACE,
  671. TRACE_ALWAYS,
  672. TEXT("CRtpRenderFilter::GetPages")
  673. ));
  674. // object lock on this object
  675. CAutoLock LockThis(&m_cStateLock);
  676. // number of pages
  677. pPages->cElems = 1;
  678. // allocate space to place property page guid
  679. pPages->pElems = (GUID *)CoTaskMemAlloc(sizeof(GUID));
  680. // validate pointer
  681. if (pPages->pElems == NULL) {
  682. TraceDebug((
  683. TRACE_ERROR,
  684. TRACE_ALWAYS,
  685. TEXT("Could not allocate property page guid")
  686. ));
  687. return E_OUTOFMEMORY;
  688. }
  689. // transfer property page guid to caller
  690. *(pPages->pElems) = CLSID_RTPRenderFilterProperties;
  691. return S_OK;
  692. }
  693. ///////////////////////////////////////////////////////////////////////////////
  694. // //
  695. // INonDelegatingUnknown implemented methods //
  696. // //
  697. ///////////////////////////////////////////////////////////////////////////////
  698. STDMETHODIMP
  699. CRtpRenderFilter::NonDelegatingQueryInterface(
  700. REFIID riid,
  701. void ** ppv
  702. )
  703. /*++
  704. Routine Description:
  705. Returns an interface and increments the reference count.
  706. Arguments:
  707. riid - reference identifier.
  708. ppv - pointer to the interface.
  709. Return Values:
  710. Returns a pointer to the interface.
  711. --*/
  712. {
  713. #ifdef DEBUG_CRITICAL_PATH
  714. TraceDebug((
  715. TRACE_TRACE,
  716. TRACE_CRITICAL,
  717. TEXT("CRtpRenderFilter::NonDelegatingQueryInterface")
  718. ));
  719. #endif // DEBUG_CRITICAL_PATH
  720. // validate pointer
  721. CheckPointer(ppv,E_POINTER);
  722. // obtain proper interface
  723. if (riid == IID_IPersistStream) {
  724. // return pointer to this object
  725. return GetInterface((IPersistStream *)this, ppv);
  726. } else if (riid == IID_ISpecifyPropertyPages) {
  727. // return pointer to this object
  728. return GetInterface((ISpecifyPropertyPages *)this, ppv);
  729. } else if ((riid == IID_IBaseFilter) || (riid == IID_IMediaFilter)) {
  730. // return pointer to this object
  731. return GetInterface((IBaseFilter *)this, ppv);
  732. } else if (riid == IID_IAMFilterMiscFlags) {
  733. // return pointer to this object
  734. return GetInterface((IAMFilterMiscFlags *)this, ppv);
  735. } else if (riid == IID_IRTPStream ||
  736. riid == IID_IRTCPStream ||
  737. riid == IID_IRTPParticipant) {
  738. // obtain pointer to default output pin object
  739. CRtpInputPin * pRtpInputPin = (CRtpInputPin *)GetPin(0);
  740. // forward request to default pin object
  741. return pRtpInputPin->NonDelegatingQueryInterface(riid, ppv);
  742. } else {
  743. // forward this request to the base object
  744. return CBaseFilter::NonDelegatingQueryInterface(riid, ppv);
  745. }
  746. }