253 lines
9.1 KiB
C++
253 lines
9.1 KiB
C++
//==========================================================================;
|
|
//
|
|
// 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 <uuids.h>
|
|
#include "bdamedia.h"
|
|
#include "MSVidTVTuner.h"
|
|
#include "resource.h" // main symbols
|
|
#include <winerror.h>
|
|
#include <algorithm>
|
|
#include <compimpl.h>
|
|
#include <seg.h>
|
|
#include <objectwithsiteimplsec.h>
|
|
#include "devices.h"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAnaCapComp
|
|
class ATL_NO_VTABLE __declspec(uuid("E18AF75A-08AF-11d3-B64A-00C04F79498E")) CAnaCapComp :
|
|
public CComObjectRootEx<CComSingleThreadModel>,
|
|
public CComCoClass<CAnaCapComp, &__uuidof(CAnaCapComp)>,
|
|
public IObjectWithSiteImplSec<CAnaCapComp>,
|
|
public IMSVidCompositionSegmentImpl<CAnaCapComp>
|
|
{
|
|
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<IMSVidAnalogTuner> qiITV(upstream);
|
|
CMSVidTVTuner* qiTV;
|
|
qiTV = static_cast<CMSVidTVTuner*>(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<void**>(&pqCtl));
|
|
if(FAILED(hr)){
|
|
return hr;
|
|
}
|
|
|
|
PQFeatures fa;
|
|
hr = pqCtl->get_FeaturesActive(&fa);
|
|
if(FAILED(hr)){
|
|
return hr;
|
|
}
|
|
|
|
CFeatures* pC = static_cast<CFeatures *>(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
|