1st step to understand DirectShow その8 (Multimedia Streaming 2) 



1.再び Multimedia Streaming  その2

   audio Multimedia Streamingのサンプルコードは、1つしかありません。

    これを改変して行きます。
 

    しかし、これに挙げられている IAudioMediaStreamIAudioStreamSampleおよび IAudioData は、

    wFormatTag=WAVE_FORMAT_IEEE_FLOATに、対応していません。

    

    えらいこっちゃ.....どないしょ?

    wFormatTag=WAVE_FORMAT_PCMなら、うまく行きます。

    

    そんで、wFormatTag=WAVE_FORMAT_IEEE_FLOATでも、

    この形に、もって行こうと、する訳です。
 

 2.強引に、この形にする。

    上述のサンプルコードを、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);

    //HRESULT hr = RenderFileToMMStream(argv[1], &pMMStream);
 //fileをrenderして、自動的にgraphを作る関数を改変
    HRESULT
hr = RenderFileToMMStream("mywave.wav", &pMMStream);

 ::getchar();
    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;
    }

    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);
 
//MSPID_PrimaryAudioは、 wformatTag=WAVE_FORMAT_IEEE_FLOATに非対応。
 //以下は除外する
 //pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, 0, NULL);

 //hr = pAMStream->OpenFile(wszName, AMMSF_RUN);
 //これを、改良する。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;

  //NULL Rendererを追加
  hr=CoCreateInstance(CLSID_NullRenderer,NULL,CLSCTX_INPROC_SERVER,
  IID_IBaseFilter,(void**)&pNullRenderer);
  hr=pGraph->AddFilter(pNullRenderer,L"Null Renderer");

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

 pEnum->Release();
 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