windows-nt/Source/XPSP1/NT/multimedia/dshow/vidctl/msvidctl/anacap.h

253 lines
9.1 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//==========================================================================;
//
// 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