Захват видео в файл AVI с DirectShow

Я пытаюсь написать приложение C ++ с directshow, которое сохраняет захват видео в файл.
Шаги в коде:
1. Создайте Capture Graph Builder
2. Создайте перечислитель системных устройств
3. Создайте перечислитель системных устройств — чтобы получить фильтр захвата
4. Создайте перечислитель для категории захвата видео
5. Создайте запрос для захвата видео

Прикрепление кода

// gets the device filter
HRESULT getDeviceFilter(REFCLSID clsid, int order, IBaseFilter **pCap)
{

ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;

// Create the System Device Enumerator.
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
reinterpret_cast<void**>(&pDevEnum));

if (SUCCEEDED(hr))
{
// Create an enumerator for the video capture category.
hr = pDevEnum->CreateClassEnumerator( clsid, &pEnum, 0);
}

IMoniker *pMoniker = NULL;

if (pEnum->Next(1, &pMoniker, NULL) == S_OK)
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)pCap);

return hr;
}int main()
{
IGraphBuilder *pGraph = 0;
ICaptureGraphBuilder2 *pBuild = 0;
IBaseFilter *pCap = 0;
HRESULT hr = CoInitialize(NULL);

// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2,
(void**)&pBuild );ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;

// Create the System Device Enumerator.
hr = CoCreateInstance(CLSID_SystemDeviceEnum,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum,
reinterpret_cast<void**>(&pDevEnum));IBaseFilter *pMux = 0;
hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi,  // Specifies AVI for the target file.
L"C:\\Example.avi", // File name.
&pMux,              //     Receives a pointer to the mux.
NULL);              //     (Optional) Receives a pointer to the file sink.// gets the first device, VDM tv card
hr = getDeviceFilter(CLSID_VideoInputDeviceCategory, 0, &pCap);hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Video,      // Media type.
pCap,                  // Capture filter.
NULL,                  // Intermediate filter (optional).
pMux);                 // Mux or file sink filter.

// Release the mux filter.
pMux->Release();

IConfigAviMux *pConfigMux = NULL;
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);
if (SUCCEEDED(hr))
{
pConfigMux->SetMasterStream(1);
pConfigMux->Release();
}

return 0;
}

Однако по вызову RenderStream Я получаю E_INVALIDARG ошибка

Какие-либо предложения?

Спасибо

2

Решение

Взгляни на Эта тема. Кажется, вы пропустили несколько шагов.

Прежде всего, вы не используете pGraph в любом месте. Вы должны создать менеджер графиков, а затем инициализировать построитель графиков, предоставив ему указатель на менеджер графиков, используя SetFilterGraph.

// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void**)&pGraph);
if (SUCCEEDED(hr))
{
// Initialize the Capture Graph Builder.
pBuild->SetFiltergraph(pGraph);

// ...
}

Во-вторых, вы используете фильтры, которые не управляются менеджером графиков. Цитировать из Вот:

Все фильтры, указанные в pSource, pIntermediate и pSink, должны быть добавлены в график перед вызовом метода.

Вам нужно будет добавить фильтры pCap а также pMux в менеджер графиков, который вы создали ранее, используя AddFilter. Вы должны сделать это перед вызовом RenderStream. Это так, потому что RenderStream в конечном итоге вызывает методы соединения на менеджере.


Если описанные выше шаги не решают вашу проблему, есть несколько других вещей, которые вы можете попробовать.

Фильтр устройства. Вы используете первое устройство CLSID_VideoInputDeviceCategory, но вы уверены, что это правильное устройство? Веб-камеры и тому подобное также включены в эту категорию. Убедитесь, что не подключены другие устройства той же категории, и повторите попытку.

соединение. Каждое устройство отличается. Возможно, ваше устройство не может быть напрямую подключено к мультиплексору. В этом случае нам придется выяснить, почему, и определить, нужно ли подключать дополнительные фильтры (например, декодеры). GraphEdit это очень быстрый способ найти эти фильтры.

Категория Pin / Тип носителя. По моему опыту, E_INVALIDARG составляет 90% времени, вызванного первыми 2 параметрами RenderStream, Попробуйте установить категорию контактов или тип носителя в NULL,

Перечислитель системных устройств: Как вы описали сами, вы дважды создаете системный перечислитель устройств. Это кажется странным для меня, почему бы не использовать один для обеих целей?


Если ваш код все еще не работает, вы должны предоставить мне больше информации. Достигли ли вы своих целей при использовании GraphEdit? Как выглядит ваш ТВ-фильтр VDM (контакты, типы мультимедиа)?

1

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

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

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