//==========================================================================; // // Composition.h : Declaration of the custom composition class for gluing analog capture to ovmixer // Copyright (c) Microsoft Corporation 1999. // ///////////////////////////////////////////////////////////////////////////// #ifndef ANACAP_H #define ANACAP_H #pragma once #include #include "bdamedia.h" #include "MSVidTVTuner.h" #include "resource.h" // main symbols #include #include #include #include #include #include "devices.h" ///////////////////////////////////////////////////////////////////////////// // CAnaCapComp class ATL_NO_VTABLE __declspec(uuid("E18AF75A-08AF-11d3-B64A-00C04F79498E")) CAnaCapComp : public CComObjectRootEx, public CComCoClass, public IObjectWithSiteImplSec, public IMSVidCompositionSegmentImpl { public: CAnaCapComp() {} virtual ~CAnaCapComp() {} REGISTER_NONAUTOMATION_OBJECT(IDS_PROJNAME, IDS_REG_ANACAPCOMP_DESC, LIBID_MSVidCtlLib, __uuidof(CAnaCapComp)); DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CAnaCapComp) COM_INTERFACE_ENTRY(IMSVidCompositionSegment) COM_INTERFACE_ENTRY(IMSVidGraphSegment) COM_INTERFACE_ENTRY(IObjectWithSite) COM_INTERFACE_ENTRY(IPersist) END_COM_MAP() // IMSVidComposition public: // IMSVidGraphSegment // IMSVidCompositionSegment STDMETHOD(Compose)(IMSVidGraphSegment * upstream, IMSVidGraphSegment * downstream) { if (m_fComposed) { return NOERROR; } ASSERT(m_pGraph); try { TRACELM(TRACE_DETAIL, "CAnaCapComp::Compose()"); VWGraphSegment up(upstream); ASSERT(up.Graph() == m_pGraph); VWGraphSegment down(downstream); ASSERT(down.Graph() == m_pGraph); if (up.begin() == up.end()) { TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() can't compose empty up segment"); return E_INVALIDARG; } if (down.begin() == down.end()) { TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() can't compose empty down segment"); return E_INVALIDARG; } VWGraphSegment::iterator iOv; for (iOv = down.begin(); iOv != down.end(); ++iOv) { if (IsVideoRenderer(*iOv)) { break; } } if (iOv == down.end()) { TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() downstream segment has no ov mixer filter"); return E_FAIL; } TRACELM(TRACE_DETAIL, "CAnaCapComp::Compose() found vr"); ASSERT((*iOv).GetGraph() == m_pGraph); DSFilter pOv(*iOv); CComQIPtr qiITV(upstream); CMSVidTVTuner* qiTV; qiTV = static_cast(qiITV.p); DSPin pVidPin; VWGraphSegment::iterator iCap; for (iCap = up.begin(); iCap != up.end(); ++iCap) { if (IsAnalogVideoCapture(*iCap)) { break; } } if (iCap == up.end()) { TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() upstream segment has no capture filter"); return E_FAIL; } ASSERT((*iCap).GetGraph() == m_pGraph); TRACELM(TRACE_DETAIL, "CAnaCapComp::Compose() found capture filter"); DSFilter pCap(*iCap); DSFilter::iterator iCapPin; DSFilter::iterator iPrePin; for (iCapPin = pCap.begin(); iCapPin != pCap.end(); ++iCapPin) { if (IsAnalogVideoCaptureViewingPin(*iCapPin)) { break; } } for (iPrePin = pCap.begin(); iPrePin != pCap.end(); ++iPrePin) { if (IsAnalogVideoCapturePreviewPin(*iPrePin)) { break; } } if (iCapPin == pCap.end() && iPrePin == pCap.end()) { TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() no video pin on capture"); bool fDeMux = false; // See if this is an error or not PQVidCtl pqCtl; if(!!m_pContainer){ HRESULT hr = m_pContainer->QueryInterface(IID_IMSVidCtl, reinterpret_cast(&pqCtl)); if(FAILED(hr)){ return hr; } PQFeatures fa; hr = pqCtl->get_FeaturesActive(&fa); if(FAILED(hr)){ return hr; } CFeatures* pC = static_cast(fa.p); DeviceCollection::iterator i; for(i = pC->m_Devices.begin(); i != pC->m_Devices.end(); ++i){ if(VWGraphSegment(*i).ClassID() == CLSID_MSVidEncoder){ break; } } if(i != pC->m_Devices.end()){ fDeMux = true; } } if (fDeMux){ TRACELM(TRACE_DETAIL, "CAnaCapComp::Compose() no viewing or previewing pin found but encoder active"); return NOERROR; } else{ TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() no viewing or previewing pin found"); return E_FAIL; } } TRACELM(TRACE_DETAIL, "CAnaCapComp::Compose() found viewing or previewing pin"); // this is an intelligent connect so that we can bring in xforms // for example certain usb tuners want to have media type jpg not yuv which // means we need a jpg/yuv xform between capture and render // this will also bring in the vpm if necessary DSPin pCapPin(*iCapPin); DSPin pPrePin(*iPrePin); if(iCapPin != pCap.end()){ if (pCapPin.HasCategory(PIN_CATEGORY_VIDEOPORT)) { DSFilter vpm; bool fVPMalreadyloaded = false; for (DSGraph::iterator i = m_pGraph.begin(); i != m_pGraph.end(); ++i) { DSFilter f(*i); if (IsVPM(f)) { vpm = f; fVPMalreadyloaded = true; break; } } if (!fVPMalreadyloaded) { HRESULT hr = vpm.CoCreateInstance(CLSID_VideoPortManager); if (FAILED(hr)) { TRACELM(TRACE_DETAIL, "CAnaCapComp::Compose() can't create vpm"); return E_UNEXPECTED; } CString csName; hr = m_pGraph.AddFilter(vpm, csName); if (FAILED(hr)) { TRACELM(TRACE_DETAIL, "CAnaCapComp::Compose() can't insert vpm in graph"); return E_UNEXPECTED; } } if (vpm && !fVPMalreadyloaded) { m_Filters.push_back(vpm); } DSFilter::iterator iVPVBI; for (iVPVBI = pCap.begin(); iVPVBI != pCap.end(); ++iVPVBI) { DSPin pVPVBI(*iVPVBI); if (pVPVBI.HasCategory(PIN_CATEGORY_VIDEOPORT_VBI)) { HRESULT hr = pVPVBI.IntelligentConnect(vpm, m_Filters); if (SUCCEEDED(hr)) { break; } } } } } HRESULT hr = E_FAIL; DSFilterList intermediates; if(iCapPin != pCap.end()){ hr = pCapPin.IntelligentConnect(pOv, intermediates); } if(FAILED(hr)){ if(iPrePin != pCap.end()){ pPrePin = *iPrePin; hr = pPrePin.IntelligentConnect(pOv, intermediates); } } if (FAILED(hr)) { return Error(IDS_CANT_CONNECT_CAP_VR, __uuidof(IMSVidCtl), E_UNEXPECTED); } m_Filters.insert(m_Filters.end(), intermediates.begin(), intermediates.end()); TRACELM(TRACE_DETAIL, "CAnaCapComp::Compose() SUCCEEDED"); m_fComposed = true; return NOERROR; } catch (ComException &e) { HRESULT hr = e; TRACELSM(TRACE_ERROR, (dbgDump << "CAnaCapComp::Compose() exception = " << hexdump(hr)), ""); return e; } catch (...) { TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() exception ... "); return E_UNEXPECTED; } } }; #endif // ANACAP_H // end of file - anacap.h