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.

255 lines
7.7 KiB

  1. //==========================================================================;
  2. //
  3. // Copyright (c) Microsoft Corporation 1999-2000.
  4. //
  5. //--------------------------------------------------------------------------;
  6. //
  7. // MSVidAudioRenderer.cpp : Implementation of CMSVidAudioRenderer
  8. //
  9. #include "stdafx.h"
  10. #ifndef TUNING_MODEL_ONLY
  11. #include "MSVidCtl.h"
  12. #include "MSVidAudioRenderer.h"
  13. #include "MSVidVideoRenderer.h"
  14. #include "dvdmedia.h"
  15. #include "sbe.h"
  16. DEFINE_EXTERN_OBJECT_ENTRY(CLSID_MSVidAudioRenderer, CMSVidAudioRenderer)
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CMSVidAudioRenderer
  19. STDMETHODIMP CMSVidAudioRenderer::InterfaceSupportsErrorInfo(REFIID riid)
  20. {
  21. static const IID* arr[] =
  22. {
  23. &IID_IMSVidAudioRenderer
  24. };
  25. for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
  26. {
  27. if (InlineIsEqualGUID(*arr[i],riid))
  28. return S_OK;
  29. }
  30. return S_FALSE;
  31. }
  32. STDMETHODIMP CMSVidAudioRenderer::PreRun() {
  33. if (m_fUseKSRenderer) {
  34. return NOERROR;
  35. }
  36. // until sysaudio works correctly with ksproxy so that we only have 1 audio renderer
  37. // filter for both digital and analog we have to have two different rendering filters and
  38. // we don't which we're going to need. in the analog case, after we're done building
  39. // we're left with the dsound renderer hooked up to the analog filter which creates a 1/2 second(or so)
  40. // delayed echo. find this scenario if it exists and disconnect the dsound renderer from the wavein filter
  41. TRACELM(TRACE_DEBUG, "CMSVidAudioRenderer::PreRun()");
  42. if (m_iAudioRenderer == -1) {
  43. TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() no dsr");
  44. return VFW_E_NO_AUDIO_HARDWARE;
  45. }
  46. DSFilter dsr(m_Filters[m_iAudioRenderer]);
  47. DSPin dsrin(*dsr.begin());
  48. if (dsrin.GetDirection() != PINDIR_INPUT) {
  49. TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() first dsound renderer pin not an input");
  50. return E_UNEXPECTED;
  51. }
  52. DSPin upstreampin;
  53. HRESULT hr = dsrin->ConnectedTo(&upstreampin);
  54. if (FAILED(hr) || !upstreampin) {
  55. // dsound renderer not connected to anything
  56. TRACELM(TRACE_DEBUG, "CMSVidAudioRenderer::PreRun() dsr not connected");
  57. return NOERROR;
  58. }
  59. DSFilter upstreamfilter(upstreampin.GetFilter());
  60. if (!upstreamfilter) {
  61. TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() upstream pin has no filter");
  62. return E_UNEXPECTED;
  63. }
  64. PQAudioInputMixer p(upstreamfilter);
  65. if (!p) {
  66. TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() upstream filter not wavein");
  67. #if 0
  68. PQVidCtl pqCtl;
  69. hr = m_pContainer->QueryInterface(IID_IMSVidCtl, reinterpret_cast<void**>(&pqCtl));
  70. if(FAILED(hr)){
  71. return hr;
  72. }
  73. CComQIPtr<IMSVidVideoRenderer> pq_VidVid;
  74. hr = pqCtl->get_VideoRendererActive(&pq_VidVid);
  75. if(FAILED(hr)){
  76. return hr;
  77. }
  78. CComQIPtr<IMSVidStreamBufferSource> pq_SBESource;
  79. CComQIPtr<IMSVidInputDevice> pq_Dev;
  80. hr = pqCtl->get_InputActive(&pq_Dev);
  81. if(FAILED(hr)){
  82. return hr;
  83. }
  84. pq_SBESource = pq_Dev;
  85. if(!pq_VidVid || !pq_SBESource){
  86. return NOERROR;
  87. }
  88. VWGraphSegment vVid(pq_VidVid);
  89. if(!vVid){
  90. return E_NOINTERFACE;
  91. }
  92. VWGraphSegment::iterator iV;
  93. for (iV = vVid.begin(); iV != vVid.end(); ++iV) {
  94. if (IsVideoRenderer(*iV)) {
  95. break;
  96. }
  97. }
  98. if (iV == vVid.end()) {
  99. TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() segment has no video mixer filter");
  100. return E_FAIL;
  101. }
  102. CComQIPtr<IMediaFilter> pq_MFVid(*iV);
  103. if(!pq_MFVid){
  104. return E_NOINTERFACE;
  105. }
  106. CComQIPtr<IMediaFilter> pq_MFAud(dsr);
  107. if(!pq_MFAud){
  108. return E_NOINTERFACE;
  109. }
  110. CComQIPtr<IMediaFilter> pq_MFGph(m_pGraph);
  111. if(!pq_MFGph){
  112. return E_NOINTERFACE;
  113. }
  114. VWGraphSegment vSbe(pq_SBESource);
  115. if(!vSbe){
  116. return E_NOINTERFACE;
  117. }
  118. CComQIPtr<IStreamBufferSource> pq_SBE;
  119. VWGraphSegment::iterator iS;
  120. for (iS = vSbe.begin(); iS != vSbe.end(); ++iS) {
  121. pq_SBE = (*iS);
  122. if (!!pq_SBE) {
  123. break;
  124. }
  125. }
  126. if (iS == vSbe.end()) {
  127. TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() segment has no video mixer filter");
  128. return E_FAIL;
  129. }
  130. CComQIPtr<IReferenceClock> pq_IClock;
  131. hr = dsr->QueryInterface(&pq_IClock);
  132. if(FAILED(hr)){
  133. return hr;
  134. }
  135. if(!pq_IClock || !pq_MFVid || !pq_MFAud || !pq_MFGph){
  136. return E_NOINTERFACE;
  137. }
  138. hr = pq_MFGph->SetSyncSource(pq_IClock);
  139. if(FAILED(hr)){
  140. return hr;
  141. }
  142. #if 0
  143. hr = pq_MFilter2->SetSyncSource(pq_IClock);
  144. if(FAILED(hr)){
  145. return hr;
  146. }
  147. #endif
  148. hr = pq_MFVid->SetSyncSource(pq_IClock);
  149. if(FAILED(hr)){
  150. return hr;
  151. }
  152. #endif
  153. return NOERROR;
  154. }
  155. bool rc = m_pGraph.DisconnectFilter(dsr, false, false);
  156. if (!rc) {
  157. TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() disconnect filter failed");
  158. return E_UNEXPECTED;
  159. }
  160. return NOERROR;
  161. }
  162. STDMETHODIMP CMSVidAudioRenderer::Build() {
  163. if (!m_fInit || !m_pGraph) {
  164. return Error(IDS_OBJ_NO_INIT, __uuidof(IMSVidAudioRenderer), CO_E_NOTINITIALIZED);
  165. }
  166. try {
  167. CString csName;
  168. DSFilter ar;
  169. PQCreateDevEnum SysEnum(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER);
  170. if(m_iAudioRenderer==-1){
  171. if (m_fUseKSRenderer) {
  172. csName = _T("KS System Renderer");
  173. // undone: use ks system renderer
  174. } else if (m_fAnalogOnly) {
  175. csName = _T("Analog Audio Renderer");
  176. DSDevices ARList(SysEnum, CLSID_AudioInputDeviceCategory);
  177. if (ARList.begin() != ARList.end()) {
  178. ar = m_pGraph.LoadFilter(*ARList.begin(), csName);
  179. m_pAR = ar;
  180. }
  181. } else if (m_fDigitalOnly) {
  182. csName = _T("Default DSound Renderer");
  183. ar = DSFilter(CLSID_DSoundRender);
  184. m_pAR = ar;
  185. } else {
  186. // NOTE: its important that digital audio be first so that we short circuit
  187. // loading 8 billion audio codecs trying to connect a digital source
  188. // to the analog renderer. there aren't any analog codecs(a physical impossiblity),
  189. // so we don't have to worry about the reverse case.
  190. csName = _T("Default DSound Renderer");
  191. ar = DSFilter(CLSID_DSoundRender);
  192. if (ar) {
  193. m_pGraph.AddFilter(ar, csName);
  194. m_Filters.push_back(ar);
  195. }
  196. csName = _T("Analog Audio Renderer");
  197. DSDevices ARList(SysEnum, CLSID_AudioInputDeviceCategory);
  198. if (ARList.begin() != ARList.end()) {
  199. ar = m_pGraph.LoadFilter(*ARList.begin(), csName);
  200. }
  201. }
  202. }
  203. if (ar) {
  204. m_pGraph.AddFilter(ar, csName);
  205. m_Filters.push_back(ar);
  206. m_iAudioRenderer = 0;
  207. }
  208. if(m_iAudioRenderer == -1){
  209. return VFW_E_NO_AUDIO_HARDWARE;
  210. }
  211. else{
  212. return NOERROR;
  213. }
  214. } catch (ComException &e) {
  215. return e;
  216. } catch (...) {
  217. return E_UNEXPECTED;
  218. }
  219. }
  220. #endif //TUNING_MODEL_ONLY
  221. // end of file - msvidaudiorenderer.cpp