directx — захватывает кадр из видео, используя фильтры DirectShow в Stack Overflow

Я взял код из сети, чтобы захватить кадр из видеофайла, и изменил его, чтобы захватить все кадры и сохранить его как изображения BMP.

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 для захвата одного кадра и записи его в файл bmp, а также для захвата следующего кадра и, таким образом, для захвата всех кадров как изображений bmp.

Спасибо
Arun

1

Решение

Ваш подход неверен. В настоящее время вы устанавливаете образец захвата на один выстрел, и после этого вы ждете завершения графика. Таким образом, он работает только для захвата одного кадра. Вам нужно захватить кадры внутри обратного вызова ISampleGrabberCB вашего pGrabber. Вам необходимо реализовать интерфейс ISampleGrabberCB и использовать ISampleGrabber :: SetCallback в вашем фильтре pGrabber, чтобы указать его на вашу реализацию. После этого вы можете захватывать кадры внутри методов SampleCB или BufferCB. http://www.infognition.com/blog/2013/accessing_raw_video_in_directshow.html

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]