Leaked source code of windows server 2003
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.

863 lines
20 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. bgaudio.cpp
  5. Abstract:
  6. Implementation of the audio bridge filters.
  7. Author:
  8. Mu Han (muhan) 11/16/1998
  9. --*/
  10. #include "stdafx.h"
  11. CTAPIAudioBridgeSinkFilter::CTAPIAudioBridgeSinkFilter(
  12. IN LPUNKNOWN pUnk,
  13. IN IDataBridge * pIDataBridge,
  14. OUT HRESULT * phr
  15. )
  16. : CTAPIBridgeSinkFilter(pUnk, pIDataBridge, phr)
  17. {
  18. }
  19. HRESULT CTAPIAudioBridgeSinkFilter::CreateInstance(
  20. IN IDataBridge * pIDataBridge,
  21. OUT IBaseFilter ** ppIBaseFilter
  22. )
  23. /*++
  24. Routine Description:
  25. This method create a instance of the bridge's sink filter.
  26. Arguments:
  27. ppIBaseFilter - the returned filter interface pointer.
  28. Return Value:
  29. E_OUTOFMEMORY - no memory for the new object.
  30. --*/
  31. {
  32. ENTER_FUNCTION("CTAPIAudioBridgeSinkFilter::CreateInstance");
  33. BGLOG((BG_TRACE, "%s entered.", __fxName));
  34. HRESULT hr = S_OK;
  35. CUnknown* pUnknown = new CTAPIAudioBridgeSinkFilter(NULL, pIDataBridge, &hr);
  36. if (pUnknown == NULL)
  37. {
  38. hr = E_OUTOFMEMORY;
  39. BGLOG((BG_ERROR,
  40. "%s, out of memory creating the filter",
  41. __fxName));
  42. }
  43. else if (FAILED(hr))
  44. {
  45. BGLOG((BG_ERROR,
  46. "%s, the filter's constructor failed, hr:%d",
  47. __fxName, hr));
  48. delete pUnknown;
  49. }
  50. else
  51. {
  52. pUnknown->NonDelegatingAddRef();
  53. hr = pUnknown->NonDelegatingQueryInterface(
  54. __uuidof(IBaseFilter), (void **)ppIBaseFilter
  55. );
  56. pUnknown->NonDelegatingRelease();
  57. }
  58. BGLOG((BG_TRACE,
  59. "%s, returning:%p, hr:%x", __fxName, *ppIBaseFilter, hr));
  60. return hr;
  61. }
  62. HRESULT CTAPIAudioBridgeSinkFilter::GetMediaType(
  63. IN int iPosition,
  64. OUT CMediaType *pMediaType
  65. )
  66. /*++
  67. Routine Description:
  68. Get the media type that this filter wants to support. Currently we
  69. only support PCM L16 8KHz samples.
  70. Arguments:
  71. IN int iPosition,
  72. the index of the media type, zero based..
  73. In CMediaType *pMediaType
  74. Pointer to a CMediaType object to save the returned media type.
  75. Return Value:
  76. S_OK - success
  77. E_OUTOFMEMORY - no memory
  78. --*/
  79. {
  80. ENTER_FUNCTION("CTAPIAudioBridgeSinkFilter::GetMediaType");
  81. BGLOG((BG_TRACE,
  82. "%s, iPosition:%d, pMediaType:%p",
  83. __fxName, iPosition, pMediaType));
  84. HRESULT hr = VFW_S_NO_MORE_ITEMS;
  85. BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
  86. return hr;
  87. }
  88. HRESULT CTAPIAudioBridgeSinkFilter::CheckMediaType(
  89. const CMediaType *pMediaType
  90. )
  91. /*++
  92. Routine Description:
  93. Check the media type that this filter wants to support. Currently we
  94. only support PCM L16 8KHz samples.
  95. Arguments:
  96. In CMediaType *pMediaType
  97. Pointer to a CMediaType object to save the returned media type.
  98. Return Value:
  99. S_OK - success
  100. E_OUTOFMEMORY - no memory
  101. E_UNEXPECTED - internal media type not set
  102. VFW_E_TYPE_NOT_ACCEPTED - media type rejected
  103. VFW_E_INVALIDMEDIATYPE - bad media type
  104. --*/
  105. {
  106. ENTER_FUNCTION("CTAPIAudioBridgeSinkFilter::CheckMediaType");
  107. BGLOG((BG_TRACE,
  108. "%s, pMediaType:%p", __fxName, pMediaType));
  109. ASSERT(!IsBadReadPtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
  110. // media type is only stored in source filter
  111. // return S_OK here
  112. // if error, the source filter will detect it anyway
  113. HRESULT hr = S_OK;
  114. BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
  115. return hr;
  116. }
  117. CTAPIAudioBridgeSourceFilter::CTAPIAudioBridgeSourceFilter(
  118. IN LPUNKNOWN pUnk,
  119. OUT HRESULT * phr
  120. )
  121. : CTAPIBridgeSourceFilter(pUnk, phr)
  122. {
  123. m_fPropSet = FALSE; // allocator properties not set yet
  124. m_fMtSet = FALSE; // media type not set yet
  125. // m_last_wall_time, m_last_stream_time not initiated
  126. m_fClockStarted = FALSE;
  127. m_fJustBurst = FALSE;
  128. m_nInputSize = 0;
  129. m_nOutputSize = 0;
  130. m_nOutputFree = 0;
  131. m_pOutputSample = NULL;
  132. }
  133. CTAPIAudioBridgeSourceFilter::~CTAPIAudioBridgeSourceFilter ()
  134. {
  135. if (m_fMtSet)
  136. {
  137. FreeMediaType (m_mt);
  138. }
  139. if (NULL != m_pOutputSample)
  140. {
  141. m_pOutputSample->Release ();
  142. }
  143. }
  144. HRESULT CTAPIAudioBridgeSourceFilter::CreateInstance(
  145. OUT IBaseFilter ** ppIBaseFilter
  146. )
  147. /*++
  148. Routine Description:
  149. This method create a instance of the bridge's sink filter.
  150. Arguments:
  151. ppIBaseFilter - the returned filter interface pointer.
  152. Return Value:
  153. E_OUTOFMEMORY - no memory for the new object.
  154. --*/
  155. {
  156. ENTER_FUNCTION("CTAPIAudioBridgeSourceFilter::CreateInstance");
  157. BGLOG((BG_TRACE, "%s entered.", __fxName));
  158. HRESULT hr = S_OK;
  159. CUnknown* pUnknown = new CTAPIAudioBridgeSourceFilter(NULL, &hr);
  160. if (pUnknown == NULL)
  161. {
  162. hr = E_OUTOFMEMORY;
  163. BGLOG((BG_ERROR,
  164. "%s, out of memory creating the filter",
  165. __fxName));
  166. }
  167. else if (FAILED(hr))
  168. {
  169. BGLOG((BG_ERROR,
  170. "%s, the filter's constructor failed, hr:%d",
  171. __fxName, hr));
  172. delete pUnknown;
  173. }
  174. else
  175. {
  176. pUnknown->NonDelegatingAddRef();
  177. hr = pUnknown->NonDelegatingQueryInterface(
  178. __uuidof(IBaseFilter), (void **)ppIBaseFilter
  179. );
  180. pUnknown->NonDelegatingRelease();
  181. }
  182. BGLOG((BG_TRACE,
  183. "%s, returning:%p, hr:%x", __fxName, *ppIBaseFilter, hr));
  184. return hr;
  185. }
  186. HRESULT CTAPIAudioBridgeSourceFilter::GetMediaType(
  187. IN int iPosition,
  188. OUT CMediaType *pMediaType
  189. )
  190. /*++
  191. Routine Description:
  192. Get the media type that this filter wants to support. Currently we
  193. only support PCM L16 8KHz samples.
  194. Arguments:
  195. IN int iPosition,
  196. the index of the media type, zero based..
  197. In CMediaType *pMediaType
  198. Pointer to a CMediaType object to save the returned media type.
  199. Return Value:
  200. S_OK - success
  201. E_OUTOFMEMORY - no memory
  202. --*/
  203. {
  204. ENTER_FUNCTION("CTAPIAudioBridgeSourceFilter::GetMediaType");
  205. BGLOG((BG_TRACE,
  206. "%s, iPosition:%d, pMediaType:%p",
  207. __fxName, iPosition, pMediaType));
  208. ASSERT(!IsBadWritePtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
  209. HRESULT hr;
  210. if (iPosition == 0)
  211. {
  212. AM_MEDIA_TYPE *pmt = NULL;
  213. hr = m_pOutputPin->GetFormat (&pmt);
  214. if (FAILED(hr))
  215. return hr;
  216. *pMediaType = *pmt;
  217. FreeMediaType (*pmt);
  218. free (pmt);
  219. }
  220. else
  221. {
  222. hr = VFW_S_NO_MORE_ITEMS;
  223. }
  224. // END
  225. BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
  226. return hr;
  227. }
  228. HRESULT CTAPIAudioBridgeSourceFilter::CheckMediaType(
  229. const CMediaType *pMediaType
  230. )
  231. /*++
  232. Routine Description:
  233. Check the media type that this filter wants to support. Currently we
  234. only support PCM L16 8KHz samples.
  235. Arguments:
  236. In CMediaType *pMediaType
  237. Pointer to a CMediaType object to save the returned media type.
  238. Return Value:
  239. S_OK - success
  240. E_OUTOFMEMORY - no memory
  241. VFW_E_TYPE_NOT_ACCEPTED - media type rejected
  242. VFW_E_INVALIDMEDIATYPE - bad media type
  243. --*/
  244. {
  245. ENTER_FUNCTION("CTAPIAudioBridgeSourceFilter::CheckMediaType");
  246. BGLOG((BG_TRACE,
  247. "%s, pMediaType:%p", __fxName, pMediaType));
  248. ASSERT(!IsBadReadPtr(pMediaType, sizeof(AM_MEDIA_TYPE)));
  249. if (!m_fMtSet)
  250. {
  251. BGLOG ((BG_ERROR, "%s tries to check media type before setting", __fxName));
  252. return E_UNEXPECTED;
  253. }
  254. // create media type based on stored AM_MEDIA_TYPE
  255. CMediaType *pmediatype = new CMediaType (m_mt);
  256. if (NULL == pmediatype)
  257. {
  258. BGLOG ((BG_ERROR, "%s failed to new media type class", __fxName));
  259. return E_OUTOFMEMORY;
  260. }
  261. HRESULT hr;
  262. if (*pMediaType == *pmediatype)
  263. hr = S_OK;
  264. else
  265. {
  266. hr = VFW_E_TYPE_NOT_ACCEPTED;
  267. BGLOG ((BG_TRACE, "%s rejects media type class %p", __fxName, pMediaType));
  268. }
  269. delete pmediatype;
  270. BGLOG((BG_TRACE, "%s returns %d", __fxName, hr));
  271. return hr;
  272. }
  273. HRESULT CTAPIAudioBridgeSourceFilter::SendSample(
  274. IN IMediaSample *pSample
  275. )
  276. /*++
  277. Routine Description:
  278. Process a sample from the bridge sink filter. Overides the base implementation
  279. Arguments:
  280. pSample - The media sample object.
  281. Return Value:
  282. HRESULT.
  283. --*/
  284. {
  285. HRESULT hr;
  286. ENTER_FUNCTION ("CTAPIAudioBridgeSourceFilter::SendSample");
  287. CAutoLock Lock(m_pLock);
  288. _ASSERT(m_pOutputPin != NULL);
  289. // we don't deliver anything if the filter is not in running state.
  290. if (m_State != State_Running)
  291. {
  292. return S_OK;
  293. }
  294. // if the sample is the 1st of the burst
  295. if (S_OK == pSample->IsDiscontinuity ())
  296. {
  297. LONGLONG start, end;
  298. m_fJustBurst = TRUE;
  299. if (S_OK != (hr = pSample->GetTime (&start, &end)))
  300. {
  301. BGLOG ((BG_TRACE, "%s, 1st sample in a burst, GetTime returns %x", __fxName, hr));
  302. // timestampes stored remain unchange
  303. return S_OK;
  304. }
  305. // else. in NT 5.1, 1st sample has valid timestamp.
  306. }
  307. // check if allocator properties is set
  308. if (!m_fPropSet)
  309. {
  310. BGLOG ((BG_ERROR, "%s tries to send sample before setting allocator property", __fxName));
  311. return E_UNEXPECTED;
  312. }
  313. // check if media type is set
  314. if (!m_fMtSet)
  315. {
  316. BGLOG ((BG_ERROR, "%s tries to send sample before setting media type", __fxName));
  317. return E_UNEXPECTED;
  318. }
  319. /*
  320. * get size info
  321. */
  322. // get input sample size and output allocator size
  323. HRESULT nInputSize, nOutputSize;
  324. nInputSize = pSample->GetActualDataLength ();
  325. nOutputSize = m_prop.cbBuffer;
  326. // 1st run, record size
  327. if (m_nInputSize == 0 || m_nOutputSize == 0)
  328. {
  329. m_nInputSize = nInputSize;
  330. m_nOutputSize = nOutputSize;
  331. }
  332. if (
  333. m_nInputSize != nInputSize ||
  334. m_nOutputSize != nOutputSize ||
  335. m_nInputSize == 0 ||
  336. m_nOutputSize == 0
  337. )
  338. {
  339. BGLOG ((BG_ERROR, "%s, sample size (%d => %d) or output size (%d => %d) is changed",
  340. __fxName, m_nInputSize, nInputSize, m_nOutputSize, nOutputSize));
  341. return E_UNEXPECTED;
  342. }
  343. /*
  344. * get time info
  345. */
  346. REFERENCE_TIME wall;
  347. // wall time
  348. if (FAILED (hr = m_pClock->GetTime (&wall)))
  349. {
  350. BGLOG ((BG_ERROR, "%s failed to get wall time", __fxName));
  351. return hr;
  352. }
  353. // if timestamp not initiated
  354. if (!m_fClockStarted)
  355. {
  356. m_last_stream_time = 0;
  357. m_last_wall_time = wall;
  358. m_fClockStarted = TRUE;
  359. // delta is the time of playing sample:
  360. m_output_sample_time = nOutputSize * 80000; // s->10000ns, bits->bytes
  361. m_output_sample_time /= ((WAVEFORMATEX*)m_mt.pbFormat)->wBitsPerSample *
  362. ((WAVEFORMATEX*)m_mt.pbFormat)->nSamplesPerSec;
  363. m_output_sample_time *= 1000; // bytes/100ns
  364. }
  365. /*
  366. * calculate new stream time
  367. */
  368. if (m_fJustBurst)
  369. {
  370. // 1st useful sample after burst
  371. m_last_stream_time += (wall - m_last_wall_time);
  372. m_last_wall_time = wall;
  373. m_fJustBurst = FALSE;
  374. // clear buffer
  375. if (NULL != m_pOutputSample)
  376. {
  377. m_pOutputSample->Release ();
  378. m_pOutputSample = NULL;
  379. m_nOutputFree = 0;
  380. }
  381. }
  382. REFERENCE_TIME end = m_last_stream_time + m_output_sample_time;
  383. /*
  384. * case 1: input size == output size
  385. */
  386. if (m_nInputSize == m_nOutputSize)
  387. {
  388. if (FAILED (pSample->SetTime (&m_last_stream_time, &end)))
  389. {
  390. BGLOG ((BG_ERROR, "%s failed to set time", __fxName));
  391. }
  392. // adjust time
  393. m_last_stream_time = end;
  394. m_last_wall_time += m_output_sample_time;
  395. // deliver directly
  396. return m_pOutputPin->Deliver(pSample);
  397. }
  398. /*
  399. * case 2: size differs
  400. */
  401. BYTE *pInputBuffer, *pOutputBuffer;
  402. if (FAILED (hr = pSample->GetPointer (&pInputBuffer)))
  403. {
  404. BGLOG ((BG_ERROR, "%s failed to get buffer pointer from input sample %p",
  405. __fxName, pSample));
  406. return hr;
  407. }
  408. LONG nNextPos = 0;
  409. // old fashion goto
  410. DELIVERY_BUFFER:
  411. // get delivery buffer if it's null
  412. if (NULL == m_pOutputSample)
  413. {
  414. hr = m_pOutputPin->GetDeliveryBuffer (
  415. &m_pOutputSample, // media sample **
  416. NULL, // start time
  417. NULL, // end time
  418. AM_GBF_NOTASYNCPOINT // dynamic format changes are not allowed,
  419. );
  420. if (FAILED (hr))
  421. {
  422. BGLOG ((BG_ERROR, "%s, output pin failed to get delivery buffer. return %d",
  423. __fxName, hr));
  424. return hr;
  425. }
  426. if (m_pOutputSample->GetSize() < m_nOutputSize)
  427. {
  428. // oops, what happend, the size should be the same
  429. BGLOG ((BG_ERROR, "%s, delivery buffer size %d and output size %d are inconsistent",
  430. __fxName, m_pOutputSample->GetSize(), m_nOutputSize));
  431. return E_UNEXPECTED;
  432. }
  433. // set size
  434. if (FAILED (hr = m_pOutputSample->SetActualDataLength (m_nOutputSize)))
  435. {
  436. BGLOG ((BG_ERROR, "%s failed to set output sample size", __fxName));
  437. return hr;
  438. }
  439. /*
  440. // set format
  441. if (FAILED (hr = m_pOutputSample->SetMediaType (&m_mt)))
  442. {
  443. BGLOG ((BG_ERROR, "%s failed to set media type for delivery buffer", __fxName));
  444. return hr;
  445. }
  446. */
  447. // set time
  448. if (FAILED (hr = m_pOutputSample->SetTime (&m_last_stream_time, &end)))
  449. {
  450. BGLOG ((BG_ERROR, "%s failed to set stream time for delivery buffer", __fxName));
  451. return hr;
  452. }
  453. // the whole buffer is free
  454. m_nOutputFree = m_nOutputSize;
  455. }
  456. // get buffer in output sample
  457. if (FAILED (hr = m_pOutputSample->GetPointer (&pOutputBuffer)))
  458. {
  459. BGLOG ((BG_ERROR, "%s failed to get buffer pointer from output sample %p",
  460. __fxName, m_pOutputSample));
  461. // release output sample
  462. m_pOutputSample->Release ();
  463. m_pOutputSample = NULL;
  464. m_nOutputFree = 0;
  465. return hr;
  466. }
  467. // if input buffer is smaller than free output buffer
  468. // copy input to output and return
  469. if (m_nInputSize-nNextPos < m_nOutputFree)
  470. {
  471. CopyMemory (
  472. (PVOID)(pOutputBuffer + (m_nOutputSize - m_nOutputFree)),
  473. (PVOID)(pInputBuffer + nNextPos),
  474. (DWORD)(m_nInputSize - nNextPos)
  475. );
  476. // reduce free buffer size
  477. m_nOutputFree -= m_nInputSize - nNextPos;
  478. return S_OK;
  479. }
  480. // else: input buffer is greater or equal to free output buffer
  481. CopyMemory (
  482. (PVOID)(pOutputBuffer + (m_nOutputSize - m_nOutputFree)),
  483. (PVOID)(pInputBuffer + nNextPos),
  484. (DWORD)(m_nOutputFree)
  485. );
  486. // now output sample is full, deliver it
  487. if (FAILED (hr = m_pOutputPin->Deliver (m_pOutputSample)))
  488. {
  489. BGLOG ((BG_ERROR, "%s failed to deliver copied sample. return %x", __fxName, hr));
  490. // clear sample
  491. m_pOutputSample->Release ();
  492. m_pOutputSample = NULL;
  493. m_nOutputFree = 0;
  494. return hr;
  495. }
  496. // adjust next position in input buffer
  497. nNextPos += m_nOutputFree;
  498. // clear output sample since it was deliverd
  499. m_pOutputSample->Release ();
  500. m_pOutputSample = NULL;
  501. m_nOutputFree = 0;
  502. // adjust time
  503. m_last_stream_time = end;
  504. m_last_wall_time += m_output_sample_time;
  505. // check if nothing left
  506. if (nNextPos == m_nInputSize)
  507. return S_OK;
  508. // there is more in input buffer
  509. goto DELIVERY_BUFFER;
  510. }
  511. HRESULT CTAPIAudioBridgeSourceFilter::GetAllocatorProperties (OUT ALLOCATOR_PROPERTIES *pprop)
  512. /*++
  513. Routine Description:
  514. Returns the allocator properties
  515. Arguments:
  516. pprop -
  517. The pointer to an ALLOCATOR_PROPERTIES
  518. Return Value:
  519. E_POINTER -
  520. if pprop is NULL
  521. S_OK
  522. --*/
  523. {
  524. ENTER_FUNCTION ("CTAPIAudioBridgeSourceFilter::GetAllocatorProperties");
  525. _ASSERT(pprop);
  526. if (!pprop)
  527. return E_POINTER;
  528. if (!m_fPropSet)
  529. {
  530. BGLOG ((BG_INFO, "%s retrieves allocator properties before setting", __fxName));
  531. // return default value anyway
  532. // buffer size = (16bits / 8bits) * 8khz * 30 ms = 480 bytes
  533. pprop->cBuffers = 1;
  534. pprop->cbBuffer = 480; // default
  535. pprop->cbAlign = 0;
  536. pprop->cbPrefix = 0;
  537. return S_OK;
  538. }
  539. // properties were set
  540. pprop->cBuffers = m_prop.cBuffers;
  541. pprop->cbBuffer = m_prop.cbBuffer;
  542. pprop->cbAlign = m_prop.cbAlign;
  543. pprop->cbPrefix = m_prop.cbPrefix;
  544. return S_OK;
  545. }
  546. HRESULT CTAPIAudioBridgeSourceFilter::SuggestAllocatorProperties (IN const ALLOCATOR_PROPERTIES *pprop)
  547. /*++
  548. Routine Description:
  549. Asks the pin to use the allocator buffer properties
  550. Arguments:
  551. pprop -
  552. The pointer to an ALLOCATOR_PROPERTIES
  553. Return Value:
  554. E_POINTER
  555. S_OK
  556. --*/
  557. {
  558. _ASSERT (pprop);
  559. if (!pprop)
  560. return E_POINTER;
  561. m_prop.cBuffers = pprop->cBuffers;
  562. m_prop.cbBuffer = pprop->cbBuffer;
  563. m_prop.cbAlign = pprop->cbAlign;
  564. m_prop.cbPrefix = pprop->cbPrefix;
  565. m_fPropSet = TRUE;
  566. return S_OK;
  567. }
  568. HRESULT CTAPIAudioBridgeSourceFilter::GetFormat (OUT AM_MEDIA_TYPE **ppmt)
  569. /*++
  570. Routine Description:
  571. Retrieves the stream format
  572. Arguments:
  573. ppmt -
  574. Address of a pointer to an AM_MEDIA_TYPE structure
  575. Return Value:
  576. E_PONTER
  577. E_OUTOFMEMORY
  578. HRESULT of SetFormat
  579. S_OK
  580. --*/
  581. {
  582. ENTER_FUNCTION ("CTAPIAudioBridgeSourceFilter::GetFormat");
  583. _ASSERT (ppmt);
  584. if (NULL == ppmt)
  585. return E_POINTER;
  586. if (NULL != *ppmt)
  587. BGLOG ((BG_INFO, "is media type structure freed when passed in %s?", __fxName));
  588. *ppmt = new AM_MEDIA_TYPE;
  589. if (NULL == *ppmt)
  590. {
  591. BGLOG ((BG_ERROR, "%s out of memory", __fxName));
  592. return E_OUTOFMEMORY;
  593. }
  594. if (!m_fMtSet)
  595. {
  596. BGLOG ((BG_INFO, "%s retrieves media type before setting. Default is to set.", __fxName));
  597. // st format
  598. HRESULT hr;
  599. AM_MEDIA_TYPE mt;
  600. WAVEFORMATEX wfx;
  601. wfx.wFormatTag = WAVE_FORMAT_PCM;
  602. wfx.wBitsPerSample = 16;
  603. wfx.nChannels = 1;
  604. wfx.nSamplesPerSec = 8000;
  605. wfx.nBlockAlign = wfx.wBitsPerSample * wfx.nChannels / 8;
  606. wfx.nAvgBytesPerSec = ((DWORD) wfx.nBlockAlign * wfx.nSamplesPerSec);
  607. wfx.cbSize = 0;
  608. mt.majortype = MEDIATYPE_Audio;
  609. mt.subtype = MEDIASUBTYPE_PCM;
  610. mt.bFixedSizeSamples = TRUE;
  611. mt.bTemporalCompression = FALSE;
  612. mt.lSampleSize = 0;
  613. mt.formattype = FORMAT_WaveFormatEx;
  614. mt.pUnk = NULL;
  615. mt.cbFormat = sizeof(WAVEFORMATEX);
  616. mt.pbFormat = (BYTE*)&wfx;
  617. hr = SetFormat (&mt);
  618. if (FAILED (hr))
  619. {
  620. BGLOG ((BG_ERROR, "%s, failed to set default format", __fxName));
  621. return hr;
  622. }
  623. }
  624. CopyMediaType (*ppmt, &m_mt);
  625. return S_OK;
  626. }
  627. HRESULT CTAPIAudioBridgeSourceFilter::SetFormat (IN AM_MEDIA_TYPE *pmt)
  628. /*++
  629. Routine Description:
  630. Sets the stream format
  631. Arguments:
  632. pmt -
  633. Pointer to an AM_MEDIA_TYPE structure
  634. Return Value:
  635. E_POINTER
  636. S_OK
  637. --*/
  638. {
  639. _ASSERT (pmt);
  640. if (NULL == pmt)
  641. return E_POINTER;
  642. CopyMediaType (&m_mt, pmt);
  643. m_fMtSet = TRUE;
  644. return S_OK;
  645. }