windows-nt/Source/XPSP1/NT/multimedia/dshow/vidctl/msvidctl/msvidaudiorenderer.cpp

256 lines
7.7 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//==========================================================================;
//
// Copyright (c) Microsoft Corporation 1999-2000.
//
//--------------------------------------------------------------------------;
//
// MSVidAudioRenderer.cpp : Implementation of CMSVidAudioRenderer
//
#include "stdafx.h"
#ifndef TUNING_MODEL_ONLY
#include "MSVidCtl.h"
#include "MSVidAudioRenderer.h"
#include "MSVidVideoRenderer.h"
#include "dvdmedia.h"
#include "sbe.h"
DEFINE_EXTERN_OBJECT_ENTRY(CLSID_MSVidAudioRenderer, CMSVidAudioRenderer)
/////////////////////////////////////////////////////////////////////////////
// CMSVidAudioRenderer
STDMETHODIMP CMSVidAudioRenderer::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IMSVidAudioRenderer
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CMSVidAudioRenderer::PreRun() {
if (m_fUseKSRenderer) {
return NOERROR;
}
// until sysaudio works correctly with ksproxy so that we only have 1 audio renderer
// filter for both digital and analog we have to have two different rendering filters and
// we don't which we're going to need. in the analog case, after we're done building
// we're left with the dsound renderer hooked up to the analog filter which creates a 1/2 second(or so)
// delayed echo. find this scenario if it exists and disconnect the dsound renderer from the wavein filter
TRACELM(TRACE_DEBUG, "CMSVidAudioRenderer::PreRun()");
if (m_iAudioRenderer == -1) {
TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() no dsr");
return VFW_E_NO_AUDIO_HARDWARE;
}
DSFilter dsr(m_Filters[m_iAudioRenderer]);
DSPin dsrin(*dsr.begin());
if (dsrin.GetDirection() != PINDIR_INPUT) {
TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() first dsound renderer pin not an input");
return E_UNEXPECTED;
}
DSPin upstreampin;
HRESULT hr = dsrin->ConnectedTo(&upstreampin);
if (FAILED(hr) || !upstreampin) {
// dsound renderer not connected to anything
TRACELM(TRACE_DEBUG, "CMSVidAudioRenderer::PreRun() dsr not connected");
return NOERROR;
}
DSFilter upstreamfilter(upstreampin.GetFilter());
if (!upstreamfilter) {
TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() upstream pin has no filter");
return E_UNEXPECTED;
}
PQAudioInputMixer p(upstreamfilter);
if (!p) {
TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() upstream filter not wavein");
#if 0
PQVidCtl pqCtl;
hr = m_pContainer->QueryInterface(IID_IMSVidCtl, reinterpret_cast<void**>(&pqCtl));
if(FAILED(hr)){
return hr;
}
CComQIPtr<IMSVidVideoRenderer> pq_VidVid;
hr = pqCtl->get_VideoRendererActive(&pq_VidVid);
if(FAILED(hr)){
return hr;
}
CComQIPtr<IMSVidStreamBufferSource> pq_SBESource;
CComQIPtr<IMSVidInputDevice> pq_Dev;
hr = pqCtl->get_InputActive(&pq_Dev);
if(FAILED(hr)){
return hr;
}
pq_SBESource = pq_Dev;
if(!pq_VidVid || !pq_SBESource){
return NOERROR;
}
VWGraphSegment vVid(pq_VidVid);
if(!vVid){
return E_NOINTERFACE;
}
VWGraphSegment::iterator iV;
for (iV = vVid.begin(); iV != vVid.end(); ++iV) {
if (IsVideoRenderer(*iV)) {
break;
}
}
if (iV == vVid.end()) {
TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() segment has no video mixer filter");
return E_FAIL;
}
CComQIPtr<IMediaFilter> pq_MFVid(*iV);
if(!pq_MFVid){
return E_NOINTERFACE;
}
CComQIPtr<IMediaFilter> pq_MFAud(dsr);
if(!pq_MFAud){
return E_NOINTERFACE;
}
CComQIPtr<IMediaFilter> pq_MFGph(m_pGraph);
if(!pq_MFGph){
return E_NOINTERFACE;
}
VWGraphSegment vSbe(pq_SBESource);
if(!vSbe){
return E_NOINTERFACE;
}
CComQIPtr<IStreamBufferSource> pq_SBE;
VWGraphSegment::iterator iS;
for (iS = vSbe.begin(); iS != vSbe.end(); ++iS) {
pq_SBE = (*iS);
if (!!pq_SBE) {
break;
}
}
if (iS == vSbe.end()) {
TRACELM(TRACE_ERROR, "CAnaCapComp::Compose() segment has no video mixer filter");
return E_FAIL;
}
CComQIPtr<IReferenceClock> pq_IClock;
hr = dsr->QueryInterface(&pq_IClock);
if(FAILED(hr)){
return hr;
}
if(!pq_IClock || !pq_MFVid || !pq_MFAud || !pq_MFGph){
return E_NOINTERFACE;
}
hr = pq_MFGph->SetSyncSource(pq_IClock);
if(FAILED(hr)){
return hr;
}
#if 0
hr = pq_MFilter2->SetSyncSource(pq_IClock);
if(FAILED(hr)){
return hr;
}
#endif
hr = pq_MFVid->SetSyncSource(pq_IClock);
if(FAILED(hr)){
return hr;
}
#endif
return NOERROR;
}
bool rc = m_pGraph.DisconnectFilter(dsr, false, false);
if (!rc) {
TRACELM(TRACE_ERROR, "CMSVidAudioRenderer::PreRun() disconnect filter failed");
return E_UNEXPECTED;
}
return NOERROR;
}
STDMETHODIMP CMSVidAudioRenderer::Build() {
if (!m_fInit || !m_pGraph) {
return Error(IDS_OBJ_NO_INIT, __uuidof(IMSVidAudioRenderer), CO_E_NOTINITIALIZED);
}
try {
CString csName;
DSFilter ar;
PQCreateDevEnum SysEnum(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER);
if(m_iAudioRenderer==-1){
if (m_fUseKSRenderer) {
csName = _T("KS System Renderer");
// undone: use ks system renderer
} else if (m_fAnalogOnly) {
csName = _T("Analog Audio Renderer");
DSDevices ARList(SysEnum, CLSID_AudioInputDeviceCategory);
if (ARList.begin() != ARList.end()) {
ar = m_pGraph.LoadFilter(*ARList.begin(), csName);
m_pAR = ar;
}
} else if (m_fDigitalOnly) {
csName = _T("Default DSound Renderer");
ar = DSFilter(CLSID_DSoundRender);
m_pAR = ar;
} else {
// NOTE: its important that digital audio be first so that we short circuit
// loading 8 billion audio codecs trying to connect a digital source
// to the analog renderer. there aren't any analog codecs(a physical impossiblity),
// so we don't have to worry about the reverse case.
csName = _T("Default DSound Renderer");
ar = DSFilter(CLSID_DSoundRender);
if (ar) {
m_pGraph.AddFilter(ar, csName);
m_Filters.push_back(ar);
}
csName = _T("Analog Audio Renderer");
DSDevices ARList(SysEnum, CLSID_AudioInputDeviceCategory);
if (ARList.begin() != ARList.end()) {
ar = m_pGraph.LoadFilter(*ARList.begin(), csName);
}
}
}
if (ar) {
m_pGraph.AddFilter(ar, csName);
m_Filters.push_back(ar);
m_iAudioRenderer = 0;
}
if(m_iAudioRenderer == -1){
return VFW_E_NO_AUDIO_HARDWARE;
}
else{
return NOERROR;
}
} catch (ComException &e) {
return e;
} catch (...) {
return E_UNEXPECTED;
}
}
#endif //TUNING_MODEL_ONLY
// end of file - msvidaudiorenderer.cpp