1st step to
understand DirectShow その4 (SampleGrabber 2) 2.SampleGrabberを、one shot mode
で使う // Since we
are using DX9, we cannot include qedit.h. Necessary API elements, copied
below. EXTERN_C
const CLSID CLSID_SampleGrabber; EXTERN_C
const CLSID CLSID_NullRenderer; EXTERN_C
const IID IID_ISampleGrabberCB; MIDL_INTERFACE("0579154A-2B53-4994-B0D0-E773148EFF85") ISampleGrabberCB : public IUnknown
{ public: virtual
HRESULT STDMETHODCALLTYPE SampleCB( double SampleTime,IMediaSample
*pSample) = 0; virtual
HRESULT STDMETHODCALLTYPE BufferCB( double SampleTime,BYTE *pBuffer,long
BufferLen) = 0; }; EXTERN_C
const IID IID_ISampleGrabber; MIDL_INTERFACE("6B652FFF-11FE-4fce-92AD-0266B5D7C78F") ISampleGrabber : public IUnknown { public: virtual
HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot) =
0; virtual
HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType) =
0; virtual
HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType) =
0; virtual
HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem) =
0; virtual
HRESULT STDMETHODCALLTYPE GetCurrentBuffer( /* [out][in] */ long
*pBufferSize,/* [out] */ long *pBuffer) = 0; virtual
HRESULT STDMETHODCALLTYPE GetCurrentSample( /* [retval][out] */
IMediaSample **ppSample) = 0; virtual
HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback,long
WhichMethodToCallback) = 0; }; // === END
ELEMENTS FROM QEDIT.H === HRESULT
AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
void
RemoveFromRot(DWORD pdwRegister) HRESULT
GetUnconnectedPin( HRESULT ConnectFilters( // ダウンストリーム フィルタの入力ピンを検索する。 // 最初のフィルタの出力ピンを検索する。 CoInitialize(NULL); ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// IBaseFilter
*pGrabberF=0; ISampleGrabber *pGrabber=0; hr=pGrabberF->QueryInterface( IID_ISampleGrabber,
(void**)&pGrabber ); } IBaseFilter *pSrc; hr=ConnectFilters(pGraph,pGrabberF,pNullRenderer); hr=pGrabber->SetOneShot(TRUE); IMediaControl *pMediaControl = NULL; //ここで、WaveFormatEXを確かめておく。 int *buffer = NULL; //32bit=int while(bufsize<=0) buffer = (int*)malloc(sizeof(char)*bufsize); hr =
pGrabber->GetCurrentBuffer(&bufsize,(long*)buffer); //to view buffer contents ////////////////////////////////////////////////////////////// pGraph->Release(); CoUninitialize();
1.GraphEditで、SampleGrabber graphを、確かめる
GraphEditで、自分のプログラムしたGraphを確かめる事ができます、素晴らしい!
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/directx9_c/directx/htm/loadingagraphfromanexternalprocess.asp
最初、GraphEditに、私の作ったGraphが表示されなくて、困りました。
プロセスは、確認できるのですが、Graphが表示されません。
ここを見て、解決しました。ありがとうございます。
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1465251&SiteID=1
WindowsXp の場合
c:\windows\system32\quarts.dll
を、レジストリーに登録する。
regsvr32
quarts.dll
もし、proppage.dll
が、レジストリーに登録されていたら、除外する。
regsvr32/u
proppage.dll
Windows
VISTA の場合は、反対に
proppage.dll
をレジストリーに登録する必要があるそうです。(私は、VSITAを持ってないので、よく解りません。)
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/DirectX9_c/directx/htm/usingthesamplegrabber.asp
ここに書いてある例を、試してみました。
ちょっとだけ、modify して、WAVEFORMATEX構造体を、確かめておきました。
どうやら、うまく作動しているようです。
Wave Parser
は、自動的に挿入されるようですね、素晴らしい機能をありがとうございます。
以下は、今回テストしたプログラム全体です。
//Sample
Grabber{C1F400A0-3F08-11D3-9F0B-006008039E37}
#include
"stdafx.h"
#include "Dshow.h"
{
IMoniker * pMoniker;
IRunningObjectTable *pROT;
if
(FAILED(GetRunningObjectTable(0, &pROT)))
{
return
E_FAIL;
}
WCHAR
wsz[256];
wsprintfW(wsz, L"FilterGraph %08p pid
%08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
HRESULT hr = CreateItemMoniker(L"!", wsz,
&pMoniker);
if (SUCCEEDED(hr))
{
hr = pROT->Register(0,
pUnkGraph, pMoniker,
pdwRegister);
pMoniker->Release();
}
pROT->Release();
return
hr;
}
{
IRunningObjectTable *pROT;
if
(SUCCEEDED(GetRunningObjectTable(0, &pROT)))
{
pROT->Revoke(pdwRegister);
pROT->Release();
}
}
IBaseFilter *pFilter,
// フィルタへのポインタ。
PIN_DIRECTION PinDir, //
検索するピンの方向。
IPin
**ppPin) //
ピンへのポインタを受け取る。
{
*ppPin =
0;
IEnumPins *pEnum = 0;
IPin
*pPin = 0;
HRESULT hr =
pFilter->EnumPins(&pEnum);
if
(FAILED(hr))
{
return
hr;
}
while (pEnum->Next(1,
&pPin, NULL) == S_OK)
{
PIN_DIRECTION
ThisPinDir;
pPin->QueryDirection(&ThisPinDir);
if (ThisPinDir == PinDir)
{
IPin *pTmp =
0;
hr =
pPin->ConnectedTo(&pTmp);
if (SUCCEEDED(hr)) //
既に接続済み、必要なピンではない。
{
pTmp->Release();
}
else //
未接続、これが必要なピンである。
{
pEnum->Release();
*ppPin =
pPin;
return
S_OK;
}
}
pPin->Release();
}
pEnum->Release();
//
一致するピンが見つからなかった。
return
E_FAIL;
}
HRESULT AddFilterByCLSID(
IGraphBuilder
*pGraph, // フィルタ グラフ マネージャへのポインタ。
const
GUID& clsid, // 作成するフィルタの
CLSID。
LPCWSTR
wszName, //
フィルタの名前。
IBaseFilter
**ppF) //
フィルタへのポインタを受け取る。
{
if (!pGraph || ! ppF) return
E_POINTER;
*ppF = 0;
IBaseFilter *pF = 0;
HRESULT hr =
CoCreateInstance(clsid, 0,
CLSCTX_INPROC_SERVER,
IID_IBaseFilter,
reinterpret_cast<void**>(&pF));
if
(SUCCEEDED(hr))
{
hr =
pGraph->AddFilter(pF,
wszName);
if
(SUCCEEDED(hr))
*ppF = pF;
else
pF->Release();
}
return
hr;
}
IGraphBuilder *pGraph, //
フィルタ グラフ マネージャ。
IPin
*pOut,
// アップストリーム フィルタの出力ピン。
IBaseFilter
*pDest) // ダウンストリーム フィルタ。
{
if
((pGraph == NULL) || (pOut == NULL) || (pDest ==
NULL))
{
return
E_POINTER;
}
#ifdef
debug
PIN_DIRECTION
PinDir;
pOut->QueryDirection(&PinDir);
_ASSERTE(PinDir == PINDIR_OUTPUT);
#endif
IPin *pIn = 0;
HRESULT hr = GetUnconnectedPin(pDest,
PINDIR_INPUT, &pIn);
if
(FAILED(hr))
{
return
hr;
}
//
接続を試す。
hr = pGraph->Connect(pOut,
pIn);
pIn->Release();
return hr;
}
HRESULT ConnectFilters(
IGraphBuilder
*pGraph,
IBaseFilter *pSrc,
IBaseFilter *pDest)
{
if ((pGraph == NULL) ||
(pSrc == NULL) || (pDest == NULL))
{
return
E_POINTER;
}
IPin
*pOut = 0;
HRESULT hr = GetUnconnectedPin(pSrc,
PINDIR_OUTPUT, &pOut);
if (FAILED(hr))
{
return hr;
}
hr =
ConnectFilters(pGraph, pOut, pDest);
pOut->Release();
return hr;
}
int _tmain(int argc, _TCHAR*
argv[])
{
HRESULT
hr;
IGraphBuilder *pGraph;
// フィルタ グラフ
マネージャを作成する。
CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
(void**)&pGraph);
DWORD dwRegister;
#ifdef _DEBUG
hr = AddToRot(pGraph,
&dwRegister);
#endif
hr=CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,
IID_IBaseFilter,(void**)&pGrabberF);
hr=pGraph->AddFilter(pGrabberF,L"Sample
Grabber");
AM_MEDIA_TYPE
mt;
if(hr==S_OK)
{
ZeroMemory(&mt,sizeof(AM_MEDIA_TYPE));
mt.majortype=MEDIATYPE_Audio;
//mt.subtype=MEDIASUBTYPE_None;
mt.formattype=FORMAT_WaveFormatEx
;
pGrabber->SetMediaType(&mt);
hr=
pGraph->AddSourceFilter(L"mywave.wav",L"Source",&pSrc);
if(hr!=S_OK)
{
}
hr=ConnectFilters(pGraph,pSrc,pGrabberF);
if(hr!=S_OK)
{
}
IBaseFilter
*pNullRenderer;
hr=CoCreateInstance(CLSID_NullRenderer,NULL,CLSCTX_INPROC_SERVER,
IID_IBaseFilter,(void**)&pNullRenderer);
hr=pGraph->AddFilter(pNullRenderer,L"Null
Renderer");
hr=pGrabber->SetBufferSamples(TRUE);
pGraph->QueryInterface(IID_IMediaControl, (void
**)&pMediaControl);
pMediaControl->Run();
hr=pGrabber->GetConnectedMediaType(&mt);//AM_MEDIA_TYPE
mt;
WAVEFORMATEX
*ex=reinterpret_cast<WAVEFORMATEX*>(mt.pbFormat);
int
buf2[24000];
long bufsize = 0;
{
pGrabber->GetCurrentBuffer(&bufsize,NULL);
}
int
i=0;
for(i=0;i<24000;i++)
{
buf2[i]=0;
buf2[i]=*(buffer+i);
}
//FreeMediaType(mt);
::getchar();
pMediaControl->Stop();
delete[]
buffer;
//////////////////////////////////////////////////////////////
#ifdef
_DEBUG
RemoveFromRot(dwRegister);
#endif
done:
pNullRenderer->Release();
pSrc->Release();
pMediaControl->Release();
pGrabber->Release();
pGrabberF->Release();
}
H.20.3.2