Lecture audio WMA Multichannel dans DirectShow
pour lire un fichier de Windows Media Audio multicanal dans DirectShow, vous devez définir la propriété _ _ HIRESOUTPUT MFPKEY WMADEC directement sur le décodeur une fois qu’il a été connecté au lecteur ASF WM. cette propriété est définie dans le fichier d’en-tête wmcodecdsp. h, qui est disponible dans le SDK Windows.
Notes
Cette procédure de configuration est prise en charge uniquement pour les fichiers qui ne sont pas protégés par le Rights Management numérique.
Les étapes de base pour activer la sortie multicanal sont les suivantes :
- Appelez RenderFile pour créer le graphique de filtre.
- obtenez un pointeur vers le filtre de Wrapper DMO.
- déconnectez le Wrapper de DMO du convertisseur Audio.
- Utilisez l’interface IPropertyBag pour définir la propriété _ _ HIRESOUTPUT WMADEC MFPKEY sur le décodeur. Le nom de la propriété est défini par la constante globale g _ wszWMACHiResOutput.
- reconnectez le Wrapper DMO et le convertisseur Audio.
- Exécutez le graphique.
Les extraits de code suivants illustrent ces étapes. Ce code suppose que le fichier source contient un flux audio et aucun flux vidéo. le codec vidéo DMO ne prend pas en charge la propriété MFPKEY _ WMADEC _ HIRESOUTPUT .
HRESULT BuildGraph(IGraphBuilder *pGraph, const WCHAR *wFileName)
{
HRESULT hr = S_OK;
IBaseFilter *pDmoWrapper = NULL;
IPin *pDmoOut = NULL;
IPin *pRendererIn = NULL;
IPropertyBag *pPropBag = NULL;
hr = pGraph->RenderFile(wFileName, NULL);
// Get pointers to the two DMO Wrapper interfaces we need.
// (Function bodies provided at the end of this snippet.)
if (SUCCEEDED(hr))
{
hr = GetDMOWrapper(pGraph, &pDmoWrapper);
}
//Disconnect the DMO Wrapper from the Audio Renderer.
if (SUCCEEDED(hr))
{
hr = GetPin(pDmoWrapper, PINDIR_OUTPUT, &pDmoOut);
}
if (SUCCEEDED(hr))
{
hr = DisconnectPin(pGraph, pDmoOut, &pRendererIn);
}
//Set the property on the DMO.
VARIANT varg;
::VariantInit(&varg);
varg.vt = VT_BOOL;
varg.boolVal = TRUE;
if (SUCCEEDED(hr))
{
hr = pDmoWrapper->QueryInterface(IID_IPropertyBag, (void**)&pPropBag);
}
if (SUCCEEDED(hr))
{
hr = pPropBag->Write(g_wszWMACHiResOutput, &varg);
}
// Reconnect the DMO Wrapper and the Audio Renderer
if (SUCCEEDED(hr))
{
hr = pGraph->Connect(pDmoOut, pRendererIn);
}
SAFE_RELEASE(pDmoWrapper);
SAFE_RELEASE(pDmoOut);
SAFE_RELEASE(pRendererIn);
SAFE_RELEASE(pPropBag);
return hr;
}
Les fonctions d’assistance de l’extrait de code précédent sont implémentées comme suit :
HRESULT GetDMOWrapper (IFilterGraph *pGraph, IBaseFilter** ppFilter)
{
BOOL bFound = FALSE;
IEnumFilters *pEnum = NULL;
IBaseFilter *pFilter = NULL;
IDMOWrapperFilter *pWrapper = NULL;
HRESULT hr = pGraph->EnumFilters(&pEnum);
if (SUCCEEDED(hr))
{
while(pEnum->Next(1, &pFilter, NULL) == S_OK)
{
// If we find the IDMOWrapperFilter interface, that means we
// have the DMO Wrapper filter.
hr = pFilter->QueryInterface(IID_IDMOWrapperFilter, (void**) &pWrapper);
if (SUCCEEDED(hr))
{
bFound = TRUE;
break;
}
SAFE_RELEASE(pFilter);
}
}
if (bFound)
{
*ppFilter = pFilter;
(*ppFilter)->AddRef();
}
else
{
hr = E_FAIL;
}
SAFE_RELEASE(pEnum);
SAFE_RELEASE(pFilter);
SAFE_RELEASE(pWrapper);
return hr;
}
HRESULT GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin** ppPin)
{
BOOL bFound = FALSE;
IEnumPins *pEnum = NULL;
IPin *pPin = NULL;
HRESULT hr = pFilter->EnumPins(&pEnum);
if (SUCCEEDED(hr))
{
while(pEnum->Next(1, &pPin, 0) == S_OK)
{
PIN_DIRECTION PinDirThis;
hr = pPin->QueryDirection(&PinDirThis);
if (FAILED(hr))
{
break;
}
if (PinDir == PinDirThis)
{
bFound = TRUE;
break;
}
SAFE_RELEASE(pPin);
}
}
if (bFound)
{
*ppPin = pPin;
(*ppPin)->AddRef();
}
else
{
hr = E_FAIL;
}
SAFE_RELEASE(pPin);
SAFE_RELEASE(pEnum);
return hr;
}
HRESULT DisconnectPin(IGraphBuilder *pGraph, IPin *pPin, IPin **ppConnected)
{
IPin *pConnected = NULL;
HRESULT hr = pPin->ConnectedTo(&pConnected);
if (SUCCEEDED(hr))
{
hr = pGraph->Disconnect(pPin);
}
if (SUCCEEDED(hr))
{
hr = pGraph->Disconnect(pConnected);
}
if (SUCCEEDED(hr))
{
*ppConnected = pConnected;
(*ppConnected)->AddRef();
}
SAFE_RELEASE(pConnected);
return hr;
}