258 lines
8.7 KiB
C
258 lines
8.7 KiB
C
|
//==========================================================================;
|
||
|
//
|
||
|
// Composition.h : Declaration of the custom composition class for gluing analog capture to ovmixer
|
||
|
// Copyright (c) Microsoft Corporation 1999.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
#ifndef ANADATA_H
|
||
|
#define ANADATA_H
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <winerror.h>
|
||
|
#include <algorithm>
|
||
|
#include <compimpl.h>
|
||
|
#include <seg.h>
|
||
|
#include "resource.h" // main symbols
|
||
|
#include <objectwithsiteimplsec.h>
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CAnaDataComp
|
||
|
class ATL_NO_VTABLE __declspec(uuid("C5702CD6-9B79-11d3-B654-00C04F79498E")) CAnaDataComp :
|
||
|
public CComObjectRootEx<CComSingleThreadModel>,
|
||
|
public CComCoClass<CAnaDataComp, &__uuidof(CAnaDataComp)>,
|
||
|
public IObjectWithSiteImplSec<CAnaDataComp>,
|
||
|
public IMSVidCompositionSegmentImpl<CAnaDataComp>
|
||
|
{
|
||
|
public:
|
||
|
CAnaDataComp() {}
|
||
|
virtual ~CAnaDataComp() {}
|
||
|
|
||
|
REGISTER_NONAUTOMATION_OBJECT(IDS_PROJNAME,
|
||
|
IDS_REG_ANADATACOMP_DESC,
|
||
|
LIBID_MSVidCtlLib,
|
||
|
__uuidof(CAnaDataComp));
|
||
|
|
||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||
|
|
||
|
BEGIN_COM_MAP(CAnaDataComp)
|
||
|
COM_INTERFACE_ENTRY(IMSVidCompositionSegment)
|
||
|
COM_INTERFACE_ENTRY(IMSVidGraphSegment)
|
||
|
COM_INTERFACE_ENTRY(IObjectWithSite)
|
||
|
COM_INTERFACE_ENTRY(IPersist)
|
||
|
END_COM_MAP()
|
||
|
|
||
|
public:
|
||
|
|
||
|
PQCreateDevEnum m_pSystemEnum;
|
||
|
|
||
|
//////////////
|
||
|
HRESULT ConnectCodecPin(DSPin& pCodecPin, DSFilter& pCap, DSFilter& pIPSink) {
|
||
|
// if this fails we just skip the pin not the whole filter so we don't need
|
||
|
// to check the return code from the connect
|
||
|
if (pCodecPin.IsInput()) {
|
||
|
pCodecPin.IntelligentConnect(pCap, m_Filters, 0, UPSTREAM);
|
||
|
} else {
|
||
|
pCodecPin.IntelligentConnect(pIPSink, m_Filters, DSGraph::ATTEMPT_MERIT_DO_NOT_USE);
|
||
|
}
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
//////////////
|
||
|
HRESULT AddCodec(const DSFilterMoniker& pCodecMkr, DSFilter& pCap, DSFilter& pIPSink) {
|
||
|
DSFilter pCodec = m_pGraph.AddMoniker(pCodecMkr);
|
||
|
if (!pCodec) {
|
||
|
// this can happen if a codec is uninstalled or the driver file is removed
|
||
|
// but the registry doesn't get cleaned up.
|
||
|
// also can happen on an upgrade if a codec has been removed from the product.
|
||
|
TRACELSM(TRACE_ERROR, (dbgDump << "CAnaDataComp::AddCodec() can't add mkr" << pCodecMkr), "");
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
m_Filters.push_back(pCodec);
|
||
|
//connect all input pins including hw slicing support
|
||
|
std::for_each(pCodec.begin(),
|
||
|
pCodec.end(),
|
||
|
bndr_obj_2_3<arity3pmf<CAnaDataComp, DSPin&, DSFilter&, DSFilter&, HRESULT> >(
|
||
|
*this,
|
||
|
arity3pmf<CAnaDataComp,
|
||
|
DSPin&,
|
||
|
DSFilter&,
|
||
|
DSFilter&,
|
||
|
HRESULT>(&CAnaDataComp::ConnectCodecPin),
|
||
|
pCap,
|
||
|
pIPSink
|
||
|
));
|
||
|
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
//////////////
|
||
|
HRESULT CapturePinPrep(DSPin& pCapPin, DSFilter& pMSTee, DSFilter& pVPM) {
|
||
|
if (pCapPin.GetConnection() || pCapPin.GetDirection() == PINDIR_INPUT) {
|
||
|
return NOERROR; // skip connected pins
|
||
|
}
|
||
|
HRESULT hr;
|
||
|
DSPin targ;
|
||
|
if (pCapPin.HasCategory(PIN_CATEGORY_VBI)) {
|
||
|
if (!pMSTee) {
|
||
|
DSDevices teelist(m_pSystemEnum, KSCATEGORY_SPLITTER);
|
||
|
pMSTee = m_pGraph.AddMoniker(*(teelist.begin()));
|
||
|
if (!pMSTee) {
|
||
|
TRACELM(TRACE_ERROR, "CAnaDataComp::Compose() can't add mstee moniker to graph");
|
||
|
THROWCOM(E_UNEXPECTED);
|
||
|
}
|
||
|
}
|
||
|
targ = pMSTee.FirstPin(PINDIR_INPUT);
|
||
|
ASSERT(targ);
|
||
|
hr = pCapPin.Connect(targ);
|
||
|
if (FAILED(hr)) {
|
||
|
TRACELSM(TRACE_ERROR, (dbgDump << "CAnaDataComp::CapturePinPrep() can't connect " << pCapPin << " " << pCapPin.GetFilter() << " to " << targ << " " << targ.GetFilter() << " hr = " << std::hex << hr), "");
|
||
|
THROWCOM(E_UNEXPECTED);
|
||
|
}
|
||
|
} else if (pCapPin.HasCategory(PIN_CATEGORY_VIDEOPORT_VBI)) {
|
||
|
// hook up vbi surf to pincat_vpvbi
|
||
|
if (!pVPM) {
|
||
|
CString csName(_T("VideoPort Manager"));
|
||
|
pVPM = m_pGraph.AddFilter(CLSID_VideoPortManager, csName);
|
||
|
if (!pVPM) {
|
||
|
TRACELM(TRACE_ERROR, "CAnaDataComp::Compose() can't create vbisurf");
|
||
|
THROWCOM(E_UNEXPECTED);
|
||
|
}
|
||
|
}
|
||
|
DSFilterList intermediates;
|
||
|
hr = pCapPin.IntelligentConnect(pVPM, intermediates);
|
||
|
if (FAILED(hr)) {
|
||
|
TRACELSM(TRACE_ERROR, (dbgDump << "CAnaDataComp::CapturePinPrep() can't connect " << pCapPin << " " << pCapPin.GetFilter() << " to " << targ << " " << targ.GetFilter() << " hr = " << std::hex << hr), "");
|
||
|
THROWCOM(E_UNEXPECTED);
|
||
|
}
|
||
|
m_Filters.insert(m_Filters.end(), intermediates.begin(), intermediates.end());
|
||
|
}
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
// IMSVidGraphSegment
|
||
|
// IMSVidCompositionSegment
|
||
|
STDMETHOD(Compose)(IMSVidGraphSegment * upstream, IMSVidGraphSegment * downstream)
|
||
|
{
|
||
|
if (m_fComposed) {
|
||
|
return NOERROR;
|
||
|
}
|
||
|
ASSERT(m_pGraph);
|
||
|
try {
|
||
|
VWGraphSegment up(upstream);
|
||
|
ASSERT(up.Graph() == m_pGraph);
|
||
|
VWGraphSegment down(downstream);
|
||
|
ASSERT(down.Graph() == m_pGraph);
|
||
|
if (up.begin() == up.end()) {
|
||
|
TRACELM(TRACE_ERROR, "CAnaDataComp::Compose() can't compose empty up segment");
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
if (down.begin() == down.end()) {
|
||
|
TRACELM(TRACE_ERROR, "CAnaDataComp::Compose() can't compose empty down segment");
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
VWGraphSegment::iterator iCap = std::find_if(up.begin(),
|
||
|
up.end(),
|
||
|
arity1_pointer(&IsAnalogVideoCapture));
|
||
|
if (iCap == up.end()) {
|
||
|
TRACELM(TRACE_ERROR, "CAnaDataComp::Compose() upstream segment has no capture filter");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
ASSERT((*iCap).GetGraph() == m_pGraph);
|
||
|
|
||
|
VWGraphSegment::iterator iIPSink = std::find_if(down.begin(),
|
||
|
down.end(),
|
||
|
arity1_pointer(&IsIPSink));
|
||
|
if (iIPSink == down.end()) {
|
||
|
TRACELM(TRACE_ERROR, "CAnaDataComp::Compose() downstream segment has no ip sink filter");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
if (!m_pSystemEnum) {
|
||
|
HRESULT hr = m_pSystemEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER);
|
||
|
if (FAILED(hr)) {
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
}
|
||
|
DSFilter ipsink(*iIPSink);
|
||
|
ASSERT(!!ipsink);
|
||
|
ASSERT(ipsink.GetGraph() == m_pGraph);
|
||
|
PQVidCtl pqCtl;
|
||
|
HRESULT hr = m_pContainer->QueryInterface(IID_IMSVidCtl, reinterpret_cast<void**>(&pqCtl));
|
||
|
if(FAILED(hr)){
|
||
|
return hr;
|
||
|
}
|
||
|
CComQIPtr<IMSVidVideoRenderer> spVidVid;
|
||
|
hr = pqCtl->get_VideoRendererActive(&spVidVid);
|
||
|
if(FAILED(hr)){
|
||
|
return hr;
|
||
|
}
|
||
|
DSFilter vpm;
|
||
|
bool fVPMalreadyloaded = false;
|
||
|
if(spVidVid){
|
||
|
for (DSGraph::iterator i = m_pGraph.begin(); i != m_pGraph.end(); ++i) {
|
||
|
DSFilter f(*i);
|
||
|
if (IsVPM(f)) {
|
||
|
vpm = f;
|
||
|
fVPMalreadyloaded = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
DSFilter mstee;
|
||
|
#if 0
|
||
|
std::for_each((*iCap).begin(),
|
||
|
(*iCap).end(),
|
||
|
bndr_obj_2_3<arity3pmf<CAnaDataComp, DSPin&, DSFilter&, DSFilter&, HRESULT> >(
|
||
|
*this,
|
||
|
arity3pmf<CAnaDataComp,
|
||
|
DSPin&,
|
||
|
DSFilter&,
|
||
|
DSFilter&,
|
||
|
HRESULT>(&CAnaDataComp::CapturePinPrep),
|
||
|
mstee,
|
||
|
vpm
|
||
|
));
|
||
|
#else
|
||
|
DSFilter::iterator i2;
|
||
|
for (i2 = (*iCap).begin(); i2 != (*iCap).end(); ++i2) {
|
||
|
CapturePinPrep(*i2, mstee, vpm);
|
||
|
}
|
||
|
#endif
|
||
|
if (!mstee) {
|
||
|
TRACELM(TRACE_ERROR, "CAnaDataComp::Compose() no vbi pins on capture filter");
|
||
|
return Error(IDS_E_NOVBI, __uuidof(CAnaCapComp), E_FAIL);
|
||
|
}
|
||
|
if (vpm && !fVPMalreadyloaded) {
|
||
|
m_Filters.push_back(vpm);
|
||
|
}
|
||
|
m_Filters.push_back(mstee);
|
||
|
//m_Filters.push_back(ipsink);
|
||
|
|
||
|
// create codec enumerator
|
||
|
DSDevices codeclist(m_pSystemEnum, KSCATEGORY_VBICODEC);
|
||
|
std::for_each(codeclist.begin(),
|
||
|
codeclist.end(),
|
||
|
bndr_obj_2_3<arity3pmf<CAnaDataComp, const DSFilterMoniker&, DSFilter&, DSFilter&, HRESULT> >(
|
||
|
*this,
|
||
|
arity3pmf<CAnaDataComp,
|
||
|
const DSFilterMoniker&,
|
||
|
DSFilter&,
|
||
|
DSFilter&,
|
||
|
HRESULT>(&CAnaDataComp::AddCodec),
|
||
|
(*iCap),
|
||
|
ipsink
|
||
|
));
|
||
|
return NOERROR;
|
||
|
} catch (ComException &e) {
|
||
|
return e;
|
||
|
} catch (...) {
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#endif // ANADATA_H
|
||
|
// end of file - anadata.h
|