1st
step to understand DirectShow その8 (Multimedia Streaming
2) 2.強引に、この形にする。 //HRESULT hr =
RenderFileToMMStream(argv[1], &pMMStream); ::getchar(); //////////////////////////////////////////////////////////////
IAMMultiMediaStream
*pAMStream; WCHAR wszName[MAX_PATH +
1]; //hr =
pAMStream->OpenFile(wszName, AMMSF_RUN); //NULL Rendererを追加 //Default
Rendererを除去 pEnum->Release();
1.再び Multimedia Streaming その2
audio Multimedia Streamingのサンプルコードは、1つしかありません。
これを改変して行きます。
しかし、これに挙げられている IAudioMediaStream、IAudioStreamSample、および IAudioData
は、
wFormatTag=WAVE_FORMAT_IEEE_FLOATに、対応していません。
えらいこっちゃ.....どないしょ?
wFormatTag=WAVE_FORMAT_PCMなら、うまく行きます。
そんで、wFormatTag=WAVE_FORMAT_IEEE_FLOATでも、
この形に、もって行こうと、する訳です。
上述のサンプルコードを、modifyします。
原文の main関数は
int __cdecl main(int argc,
char *argv[])
{
if (argc <
2)
{
printf("Specify a file
name.\n");
exit(0);
}
IMultiMediaStream *pMMStream;
CoInitialize(NULL);
HRESULT hr =
RenderFileToMMStream(argv[1], &pMMStream);
if
(SUCCEEDED(hr))
{
RenderStreamToDevice(pMMStream);
pMMStream->Release();
}
CoUninitialize();
return
0;
}
これを、先ず、もじります。
modified main function
int __cdecl
main(int argc, char *argv[])
{
//削除
/* if (argc
< 2)
{
printf("Specify a file
name.\n");
exit(0);
}
*/
IMultiMediaStream *pMMStream;
CoInitialize(NULL);
//fileをrenderして、自動的にgraphを作る関数を改変
HRESULT hr = RenderFileToMMStream("mywave.wav",
&pMMStream);
if
(SUCCEEDED(hr))
{
RenderStreamToDevice(pMMStream);
pMMStream->Release();
}
//////////////////////////////////////////////////////////////
#ifdef
_DEBUG
RemoveFromRot(dwRegister);
#endif
CoUninitialize();
return
0;
}
で、この RenderFileToMMStream("mywave.wav",
&pMMStream); を改造して行きます。
原文
HRESULT
RenderFileToMMStream(
const char * szFileName,
IMultiMediaStream
**ppMMStream)
{
if (strlen(szFileName) >
MAX_PATH)
{
return
E_INVALIDARG;
}
IAMMultiMediaStream *pAMStream;
HRESULT hr =
CoCreateInstance(CLSID_AMMultiMediaStream, NULL,
CLSCTX_INPROC_SERVER,
IID_IAMMultiMediaStream,
(void **)&pAMStream);
if
(FAILED(hr))
{
return
hr;
}
WCHAR
wszName[MAX_PATH + 1];
MultiByteToWideChar(CP_ACP,
0, szFileName, -1, wszName,
MAX_PATH + 1);
pAMStream->Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD,
NULL);
pAMStream->AddMediaStream(NULL,
&MSPID_PrimaryAudio, 0, NULL);
hr =
pAMStream->OpenFile(wszName, AMMSF_RUN);
{
if
(SUCCEEDED(hr))
{
hr
= pAMStream->QueryInterface(IID_IMultiMediaStream,
(void**)ppMMStream);
}
}
pAMStream->Release();
return
hr;
}
modified RenderFileToMMStream("mywave.wav",
&pMMStream)
原文のままは、黒字。新たに挿入した部分は、青色。
HRESULT
RenderFileToMMStream(
const char * szFileName,
IMultiMediaStream
**ppMMStream)
{
if (strlen(szFileName) >
MAX_PATH)
{
return
E_INVALIDARG;
}
HRESULT hr =
CoCreateInstance(CLSID_AMMultiMediaStream, NULL,
CLSCTX_INPROC_SERVER,
IID_IAMMultiMediaStream,
(void **)&pAMStream);
if
(FAILED(hr))
{
return
hr;
}
MultiByteToWideChar(CP_ACP, 0, szFileName, -1,
wszName,
MAX_PATH +
1);
pAMStream->Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD,
NULL);
//MSPID_PrimaryAudioは、
wformatTag=WAVE_FORMAT_IEEE_FLOATに非対応。
//以下は除外する
//pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, 0,
NULL);
//これを、改良する。AMMSF_RUN
-> AMMSF_RENDERALLSTREAMS
hr = pAMStream->OpenFile(wszName, AMMSF_RENDERALLSTREAMS);// ここが大切
if (SUCCEEDED(hr))
{
hr
= pAMStream->QueryInterface(IID_IMultiMediaStream,
(void**)ppMMStream);
}
}
////////////////////////////////////////////////////////////
hr=pAMStream->GetFilterGraph(&pGraph);
#ifdef
_DEBUG
hr = AddToRot(pGraph,
&dwRegister);
#endif
////////////////////////////////////////////////////////////
IBaseFilter
*pNullRenderer;
hr=CoCreateInstance(CLSID_NullRenderer,NULL,CLSCTX_INPROC_SERVER,
IID_IBaseFilter,(void**)&pNullRenderer);
hr=pGraph->AddFilter(pNullRenderer,L"Null Renderer");
IBaseFilter *pFilter=0;
hr=pGraph->FindFilterByName(L"Default DirectSound
Device",&pFilter);
hr=pGraph->RemoveFilter(pFilter);
pFilter=0;
//Wave Parserのoutput pinを見つけて、再接続。
hr=pGraph->FindFilterByName(L"Wave Parser",&pFilter);
IPin *pin;
hr=pFilter->FindPin(L"output",&pin);
hr=pGraph->Render(pin);
hr=pFilter->Release();
////////////////////////////////////////////////////////////
//remove SFilter Class (this is a CLSID
)
IEnumFilters
*pEnum=0;
pGraph->EnumFilters(&pEnum);
ULONG
fetched=0;
FILTER_INFO info;
while( (
hr=pEnum->Next(1,&pFilter,&fetched))==S_OK
)
{
pFilter->QueryFilterInfo(&info);
if(!info.achName[0]) //SFilter Class は no
name
pGraph->RemoveFilter(pFilter);
}
pin->Release();
pFilter->Release();
////////////////////////////////////////////////////////////
pAMStream->Release();
return
hr;
}
結果は
強引に、こじ付けました。
何のための Multimedia Streaming
やろ.....少し、疑問やわ。
//remove SFilter Class
(this is a CLSID name) の所が、解りにくいと、思います。
これは、
pAMStream->OpenFile(wszName,
AMMSF_RENDERALLSTREAMS);
が、自動的にくっ付ける SFilter Classです。(下の名前がないFilterの事)
SFilter Class
は、CLSIDです。 nameは、ありません。
どうやら、rendererのようです。
ですので、これを除去するのに
まず、graph内のFilterを列挙して
IEnumFilters *pEnum=0;
pGraph->EnumFilters(&pEnum);
FILTER_INFOから、そのnameを割り出し、
このnameがNULLなのです。name[0]が、"0"ですから、それで判別します。
ULONG fetched=0;
FILTER_INFO info;
while(
( hr=pEnum->Next(1,&pFilter,&fetched))==S_OK
)
{
pFilter->QueryFilterInfo(&info);
if( !info.achName[0] ) //SFilter
Class は no name
pGraph->RemoveFilter(pFilter);
}
これで、除去できました、やれやれ。(再掲)
次は、原文の
RenderStreamToDevice(pMMStream)を、改造しないと、なりません。
できるんやろか? わからん......
H.20.4.4