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.

302 lines
11 KiB

  1. //==========================================================================;
  2. //
  3. // Composition.h : Declaration of the custom composition class for gluing analog capture to ovmixer
  4. // Copyright (c) Microsoft Corporation 1999.
  5. //
  6. /////////////////////////////////////////////////////////////////////////////
  7. #ifndef DAT2SIN_H
  8. #define DAT2SIN_H
  9. #pragma once
  10. #include <uuids.h>
  11. #include "bdamedia.h"
  12. #include "MSVidTVTuner.h"
  13. #include "resource.h" // main symbols
  14. #include <winerror.h>
  15. #include <algorithm>
  16. #include <compimpl.h>
  17. #include <seg.h>
  18. #include <objectwithsiteimplsec.h>
  19. #include <ksmedia.h>
  20. #include "enc2sin.h"
  21. typedef struct
  22. {
  23. KSPROPERTY m_ksThingy;
  24. VBICODECFILTERING_CC_SUBSTREAMS ccSubStreamMask;
  25. } KSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS;
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CDat2SinComp
  28. class ATL_NO_VTABLE __declspec(uuid("38F03426-E83B-4e68-B65B-DCAE73304838")) CDat2SinComp :
  29. public CComObjectRootEx<CComSingleThreadModel>,
  30. public CComCoClass<CDat2SinComp, &__uuidof(CDat2SinComp)>,
  31. public IObjectWithSiteImplSec<CDat2SinComp>,
  32. public IMSVidCompositionSegmentImpl<CDat2SinComp>
  33. {
  34. private:
  35. DSFilterList m_pEncFilters;
  36. public:
  37. CDat2SinComp() {}
  38. virtual ~CDat2SinComp() {}
  39. REGISTER_NONAUTOMATION_OBJECT(IDS_PROJNAME,
  40. IDS_REG_DAT2SINCOMP_DESC,
  41. LIBID_MSVidCtlLib,
  42. __uuidof(CDat2SinComp));
  43. DECLARE_PROTECT_FINAL_CONSTRUCT()
  44. BEGIN_COM_MAP(CDat2SinComp)
  45. COM_INTERFACE_ENTRY(IMSVidCompositionSegment)
  46. COM_INTERFACE_ENTRY(IMSVidGraphSegment)
  47. COM_INTERFACE_ENTRY(IObjectWithSite)
  48. COM_INTERFACE_ENTRY(IPersist)
  49. END_COM_MAP()
  50. // IMSVidComposition
  51. public:
  52. // IMSVidGraphSegment
  53. // IMSVidCompositionSegment
  54. STDMETHOD(CheckEncFilters)(){
  55. int j = 0;
  56. for(DSFilterList::iterator i = m_pEncFilters.begin(); i != m_pEncFilters.end(); ++i){
  57. TRACELM(TRACE_ERROR, "CAnaSinComp::CheckEncFilters checking filter " << j);
  58. CComQIPtr<IETFilterConfig> spETConfig;
  59. CComPtr<IUnknown> spUnkSecChan;
  60. spETConfig = (*i);
  61. if(!spETConfig){
  62. TRACELM(TRACE_ERROR, "CAnaSinComp::CheckEncFilters filter " << j << " could not get et filter config interface");
  63. return E_NOINTERFACE;
  64. }
  65. HRESULT hr = spETConfig->GetSecureChannelObject(&spUnkSecChan);
  66. hr = CheckIfSecureClient(spUnkSecChan);
  67. if(FAILED(hr)){
  68. TRACELM(TRACE_ERROR, "CAnaSinComp::CheckEncFilters filter " << j << " Failed");
  69. return E_FAIL;
  70. }
  71. ++j;
  72. }
  73. TRACELM(TRACE_ERROR, "CAnaSinComp::CheckEncFilters no failures");
  74. return NOERROR;
  75. }
  76. STDMETHOD(PreRun)(){
  77. return CheckEncFilters();
  78. }
  79. STDMETHOD(put_Container)(IMSVidGraphSegmentContainer *pCtl) {
  80. try {
  81. if (!pCtl) {
  82. m_pEncFilters.clear();
  83. return Unload();
  84. }
  85. if (m_pContainer) {
  86. if (!m_pContainer.IsEqualObject(VWSegmentContainer(pCtl))) {
  87. //undone: support moving to different graph
  88. return Error(IDS_OBJ_ALREADY_INIT, __uuidof(IMSVidGraphSegment), CO_E_ALREADYINITIALIZED);
  89. } else {
  90. return NO_ERROR;
  91. }
  92. }
  93. // DON'T addref the container. we're guaranteed nested lifetimes
  94. // and an addref creates circular refcounts so we never unload.
  95. m_pContainer.p = pCtl;
  96. m_pGraph = m_pContainer.GetGraph();
  97. } catch(...) {
  98. return E_UNEXPECTED;
  99. }
  100. return NOERROR;
  101. }
  102. STDMETHOD(SetSubstreamChannel)(IPin * pPinCCDecoder, DWORD dwSubStreamChannels){
  103. HRESULT hr;
  104. if(!(dwSubStreamChannels &
  105. (KS_CC_SUBSTREAM_ODD | KS_CC_SUBSTREAM_EVEN |
  106. KS_CC_SUBSTREAM_SERVICE_CC1 | KS_CC_SUBSTREAM_SERVICE_CC2 |
  107. KS_CC_SUBSTREAM_SERVICE_CC3 | KS_CC_SUBSTREAM_SERVICE_CC4 |
  108. KS_CC_SUBSTREAM_SERVICE_T1 | KS_CC_SUBSTREAM_SERVICE_T2 |
  109. KS_CC_SUBSTREAM_SERVICE_T3 | KS_CC_SUBSTREAM_SERVICE_T4 |
  110. KS_CC_SUBSTREAM_SERVICE_XDS))){
  111. return E_INVALIDARG;
  112. }
  113. try {
  114. IKsPropertySet *pksPSet = NULL;
  115. hr = pPinCCDecoder->QueryInterface(IID_IKsPropertySet, (void **) &pksPSet);
  116. if(SUCCEEDED(hr)){
  117. DWORD rgdwData[20];
  118. DWORD cbMax = sizeof(rgdwData);
  119. DWORD cbData;
  120. hr = pksPSet->Get(KSPROPSETID_VBICodecFiltering,
  121. KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_DISCOVERED_BIT_ARRAY,
  122. NULL, 0,
  123. (BYTE *) rgdwData, cbMax, &cbData);
  124. if(SUCCEEDED(hr)){
  125. KSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS ksThing = {0};
  126. ksThing.ccSubStreamMask.SubstreamMask = dwSubStreamChannels;
  127. // ring3 to ring0 propset call
  128. hr = pksPSet->Set(KSPROPSETID_VBICodecFiltering,
  129. KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_REQUESTED_BIT_ARRAY,
  130. &ksThing.ccSubStreamMask,
  131. sizeof(ksThing) - sizeof(KSPROPERTY),
  132. &ksThing,
  133. sizeof(ksThing));
  134. }
  135. pksPSet->Release();
  136. }
  137. } catch (HRESULT hrCatch) {
  138. // bad things happend
  139. hr = hrCatch;
  140. } catch (...) {
  141. // Threw Badly - Giving Up"
  142. hr = E_FAIL;
  143. }
  144. return hr;
  145. }
  146. STDMETHOD(Compose)(IMSVidGraphSegment * upstream, IMSVidGraphSegment * downstream)
  147. {
  148. if (m_fComposed) {
  149. return NOERROR;
  150. }
  151. ASSERT(m_pGraph);
  152. try {
  153. VWGraphSegment up(upstream);
  154. ASSERT(up.Graph() == m_pGraph);
  155. VWGraphSegment down(downstream);
  156. ASSERT(down.Graph() == m_pGraph);
  157. if (upstream == downstream) {
  158. return Error(IDS_CANT_COMPOSE_WITH_SELF, __uuidof(IMSVidCompositionSegment), E_INVALIDARG);
  159. }
  160. if (up.begin() == up.end()) {
  161. TRACELM(TRACE_ERROR, "CComposition::Compose() can't compose empty up segment");
  162. return NOERROR;
  163. }
  164. if (down.begin() == down.end()) {
  165. TRACELM(TRACE_ERROR, "CComposition::Compose() can't compose empty down segment");
  166. // this is not an error, for example, CA is an empty segment.
  167. return NOERROR;
  168. }
  169. // Making sure that only the cc pin is rendered to the sink and that the encrypter is added
  170. CMSVidStreamBufferSink* ds = (CMSVidStreamBufferSink*)downstream;
  171. DSFilter pSink(ds->m_Filters[0]);
  172. DSGraph::iterator gFilter;
  173. DSFilter::iterator fPin;
  174. DSPin::iterator pMedia;
  175. DSPin ccPin;
  176. DSMediaType mtL21(MEDIATYPE_AUXLine21Data, MEDIASUBTYPE_Line21_BytePair);
  177. for(gFilter = m_pGraph.begin(); gFilter != m_pGraph.end() && !ccPin; ++gFilter){
  178. for(fPin = (*gFilter).begin(); fPin != (*gFilter).end() && !ccPin; ++fPin){
  179. for(pMedia = (*fPin).begin(); pMedia != (*fPin).end() && !ccPin; ++pMedia){
  180. if((*pMedia) == mtL21){
  181. if(!(*fPin).IsConnected() && (*fPin).GetDirection() == PINDIR_OUTPUT){
  182. ccPin = *fPin;
  183. }
  184. }
  185. }
  186. }
  187. }
  188. if(!ccPin){
  189. return E_FAIL;
  190. }
  191. HRESULT hr = E_FAIL;
  192. DSFilterList intermediates;
  193. #if ENCRYPT_NEEDED
  194. CComBSTR encString(L"{C4C4C4F1-0049-4E2B-98FB-9537F6CE516D}");
  195. GUID2 encdecGuid (encString);
  196. CComPtr<IUnknown> spEncTagFilter(encdecGuid, NULL, CLSCTX_INPROC_SERVER);
  197. if (!spEncTagFilter) {
  198. TRACELM(TRACE_ERROR, "CMSVidStreamBufferSink::Build() can't load Tagger filter");
  199. return ImplReportError(__uuidof(IMSVidStreamBufferSink), IDS_CANT_CREATE_FILTER, __uuidof(IStreamBufferSink), E_UNEXPECTED);
  200. }
  201. DSFilter ETFilter(spEncTagFilter);
  202. if (!ETFilter) {
  203. ASSERT(false);
  204. return ImplReportError(__uuidof(IMSVidStreamBufferSink), IDS_CANT_CREATE_FILTER, __uuidof(IBaseFilter), E_UNEXPECTED);
  205. }
  206. m_Filters.push_back(ETFilter);
  207. m_pEncFilters.push_back(ETFilter);
  208. CString csName = _T("CC Encoder Tagger Filter");
  209. m_pGraph.AddFilter(ETFilter, csName);
  210. // Connect cc pin to the Tagger
  211. hr = ccPin.IntelligentConnect(ETFilter, intermediates);
  212. if(FAILED(hr)){
  213. TRACELM(TRACE_DETAIL, "CAnaSinComp::Compose() can't connect audio pin to CC Tagger");
  214. return E_UNEXPECTED;
  215. }
  216. ASSERT(intermediates.begin() == intermediates.end());
  217. m_Filters.insert(m_Filters.end(), intermediates.begin(), intermediates.end());
  218. hr = E_FAIL;
  219. DSFilter::iterator ETPin;
  220. for(ETPin = ETFilter.begin(); ETPin != ETFilter.end(); ++ETPin){
  221. if((*ETPin).GetDirection() == PINDIR_OUTPUT && !(*ETPin).IsConnected()){
  222. break;
  223. }
  224. }
  225. if(ETPin == ETFilter.end()){
  226. return E_UNEXPECTED;
  227. }
  228. for(fPin = pSink.begin(); fPin != pSink.end() && FAILED(hr); ++fPin){
  229. if((*fPin).GetDirection() == PINDIR_INPUT && !(*fPin).IsConnected()){
  230. hr = (*ETPin).Connect((*fPin));
  231. }
  232. }
  233. if(FAILED(hr)){
  234. return hr;
  235. }
  236. else{
  237. ASSERT(intermediates.begin() == intermediates.end());
  238. m_Filters.insert(m_Filters.end(), intermediates.begin(), intermediates.end());
  239. }
  240. #else
  241. for(fPin = pSink.begin(); fPin != pSink.end() && FAILED(hr); ++fPin){
  242. if((*fPin).GetDirection() == PINDIR_INPUT && !(*fPin).IsConnected()){
  243. hr = ccPin.Connect((*fPin));
  244. }
  245. }
  246. if(FAILED(hr)){
  247. return hr;
  248. }
  249. #endif
  250. // BUG in the cc codec makes it so we have to set the feilds as such
  251. // hr = SetSubstreamChannel(ccPin, KS_CC_SUBSTREAM_EVEN|KS_CC_SUBSTREAM_ODD);
  252. ASSERT(SUCCEEDED(hr));
  253. return NOERROR;
  254. } catch (ComException &e) {
  255. return e;
  256. } catch (...) {
  257. return E_UNEXPECTED;
  258. }
  259. }
  260. };
  261. #endif // Dat2Sin_H
  262. // end of file - Dat2Sin.h