1st step to understand DirectShow その4 (SampleGrabber 2)



 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を持ってないので、よく解りません。) 

 2.SampleGrabberを、one shot mode で使う

   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"

// 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)
{
    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;
}

void RemoveFromRot(DWORD pdwRegister)
{
    IRunningObjectTable *pROT;
    if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
        pROT->Revoke(pdwRegister);
        pROT->Release();
    }
}

HRESULT GetUnconnectedPin(
    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;
}

HRESULT ConnectFilters(
    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;

CoInitialize(NULL);


  // フィルタ グラフ マネージャを作成する。
  CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
      IID_IGraphBuilder, (void**)&pGraph);

  //////////////////////////////////////////////////////////////
   DWORD dwRegister;
#ifdef _DEBUG
hr = AddToRot(pGraph, &dwRegister);
#endif

  ////////////////////////////////////////////////////////////// 

  IBaseFilter *pGrabberF=0;
  hr=CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,
   IID_IBaseFilter,(void**)&pGrabberF);
  hr=pGraph->AddFilter(pGrabberF,L"Sample Grabber");

  ISampleGrabber *pGrabber=0;

  hr=pGrabberF->QueryInterface( IID_ISampleGrabber, (void**)&pGrabber );
  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);

  }

  IBaseFilter *pSrc;
  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=ConnectFilters(pGraph,pGrabberF,pNullRenderer);

  hr=pGrabber->SetOneShot(TRUE);
  hr=pGrabber->SetBufferSamples(TRUE);

    IMediaControl *pMediaControl = NULL;
   pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);


   pMediaControl->Run();

   //ここで、WaveFormatEXを確かめておく。 
   hr=pGrabber->GetConnectedMediaType(&mt);//AM_MEDIA_TYPE mt;
   WAVEFORMATEX *ex=reinterpret_cast<WAVEFORMATEX*>(mt.pbFormat);

   int *buffer = NULL; //32bit=int
   int buf2[24000];
   long bufsize = 0;

   while(bufsize<=0)
   {
   pGrabber->GetCurrentBuffer(&bufsize,NULL);
   }

   buffer = (int*)malloc(sizeof(char)*bufsize);

   hr = pGrabber->GetCurrentBuffer(&bufsize,(long*)buffer);

   //to view buffer contents
   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();

  pGraph->Release();

CoUninitialize();
}

    H.20.3.2