2016-11-14 16 views
1

ビデオファイルからフレームをキャプチャするためにネットからコードを取得し、すべてのフレームをキャプチャしてbmpイメージとして保存するように修正しました。C++でdirectshowフィルタを使用してビデオからフレームをキャプチャ

HRESULT GrabVideoBitmap(PCWSTR pszVideoFile) 
{ 
    IGraphBuilder *pGraph = NULL; 
    IMediaControl *pControl = NULL; 
    IMediaEventEx *pEvent = NULL; 
    IBaseFilter *pGrabberF = NULL; 
    ISampleGrabber *pGrabber = NULL; 
    IBaseFilter *pSourceF = NULL; 
    IEnumPins *pEnum = NULL; 
    IPin *pPin = NULL; 
    IBaseFilter *pNullF = NULL; 

    long evCode; 

    wchar_t temp[10]; 
    wchar_t framename[50] = IMAGE_FILE_PATH; // L"D:\\sampleframe"; 

    BYTE *pBuffer = NULL; 
    HRESULT hr = CoInitialize(NULL); 
    if (FAILED(hr)) 
     return 0; 

    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
          IID_PPV_ARGS(&pGraph)); 

    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl)); 

    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent)); 

    // Create the Sample Grabber filter. 
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, 
          IID_PPV_ARGS(&pGrabberF)); 

    hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber"); 

    hr = pGrabberF->QueryInterface(IID_PPV_ARGS(&pGrabber)); 


    // Displays the metadata of the file 
    DisplayFileInfo((wchar_t*)pszVideoFile); // to display video information 

    AM_MEDIA_TYPE mt; 
    ZeroMemory(&mt, sizeof(mt)); 
    mt.majortype = MEDIATYPE_Video; 
    mt.subtype = MEDIASUBTYPE_RGB24; 

    hr = pGrabber->SetMediaType(&mt); 

    hr = pGraph->AddSourceFilter(pszVideoFile, L"Source", &pSourceF); 

    hr = pSourceF->EnumPins(&pEnum); 

    while (S_OK == pEnum->Next(1, &pPin, NULL)) 
    { 
     hr = ConnectFilters(pGraph, pPin, pGrabberF); 
     SafeRelease(&pPin); 
     if (SUCCEEDED(hr)) 
     { 
      break; 
     } 
    } 

    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, 
          IID_PPV_ARGS(&pNullF)); 

    hr = pGraph->AddFilter(pNullF, L"Null Filter"); 

    hr = ConnectFilters(pGraph, pGrabberF, pNullF); 

    hr = pGrabber->SetOneShot(TRUE); 

    hr = pGrabber->SetBufferSamples(TRUE); 

    hr = pControl->Run(); 


    hr = pEvent->WaitForCompletion(INFINITE, &evCode); 

    for (int i = 0; i < 10; i++) 
    { 
     // Find the required buffer size. 
     long cbBuffer; 
     hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL); 

     pBuffer = (BYTE*)CoTaskMemAlloc(cbBuffer); 

     hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer); 

     hr = pGrabber->GetConnectedMediaType(&mt); 

     // Examine the format block. 
     if ((mt.formattype == FORMAT_VideoInfo) && 
      (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) && 
      (mt.pbFormat != NULL)) 
     { 

      swprintf(temp, 5, L"%d", i); 
      wcscat_s(framename, temp); 
      wcscat_s(framename, L".bmp"); 

      VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat; 
      hr = WriteBitmap((PCWSTR)framename, &pVih->bmiHeader, 
        mt.cbFormat - SIZE_PREHEADER, pBuffer, cbBuffer); 
      wcscpy_s(framename, IMAGE_FILE_PATH); 
     } 
     else 
     { 
      // Invalid format. 
      hr = VFW_E_INVALIDMEDIATYPE; 
     } 

     FreeMediaType(mt); 
    } 
done: 
    CoTaskMemFree(pBuffer); 
    SafeRelease(&pPin); 
    SafeRelease(&pEnum); 
    SafeRelease(&pNullF); 
    SafeRelease(&pSourceF); 
    SafeRelease(&pGrabber); 
    SafeRelease(&pGrabberF); 
    SafeRelease(&pControl); 
    SafeRelease(&pEvent); 
    SafeRelease(&pGraph); 
    return hr; 
} 

入力ビデオファイルは132フレームあります。 しかし、68個の画像しか生成されません。 また、ビデオの最後のフレームは、最後の38枚の画像についてキャプチャされます。

私は、DirectShowグラフが連続して実行されていて、WriteBitmap()にフレームがないと思います。

DirectXでコントロールを取得して1つのフレームをキャプチャし、bmpファイルに書き込んで次のフレームをキャプチャして、すべてのフレームをbmpイメージとしてキャプチャする方法。

おかげ アルン

答えて

2

あなたのアプローチが間違っています。現在、サンプルグラバーをワンショットに設定した後、グラフの完成を待ちます。この方法では、単一のフレームをキャプチャする場合にのみ機能します。 pGrabberのISampleGrabberCBコールバック内のフレームをキャプチャする必要があります。 ISampleGrabberCBインターフェイスを実装し、実装にポイントするためにISGraphber :: SetCallbackをpGrabberフィルタで使用する必要があります。その後、SampleCBまたはBufferCBのいずれかの方法でフレームをキャプチャできます。 http://www.infognition.com/blog/2013/accessing_raw_video_in_directshow.html

関連する問題