Кто занимался написанием программ видеозахвата?

  • Автор темы skysun
  • Дата начала
S

skysun

Гость
#1
Уважаемые, помогите!
2 дня удараюсь головой... как сделать, что бы моя прога позволяла осуществлять
следующие функции - захват в AVI-файл, компрессия, грабинг кадра - параллельно.

Без проблем получается несжатое видео и возможность граббинга кадра или сжатое видео, но без
граббинга файла.

В какой последовательности и к каким Pin-ам цеплять фильтры?

(Вот такая вот байда!)
 
S

skysun

Гость
#3
Спасибо большое, European. Но это к делу неотносится.

Хотя вопрос снят. Дело, как, я и думал оказалось в последовательности, в которой я подключал фильтры.
:(

Если кому интересно могу поделится опытом.
 

tyko

New Member
02.11.2007
4
0
#4
если предложение еще в силе, очень был бы рад пообщатся...
Уже вторую неделю бьюсь над написанием приложения, работающим с видео: захват с вебкамеры, скриншоты эрана, компресинг, сохранение и воспроизведение видео;
много вопросов, непоняток...
 
S

skysun

Гость
#5
Для: tyko
Давай пообщаемся. Я не против. Помогу чем смогу!
 

tyko

New Member
02.11.2007
4
0
#6
чтобы по мелочам не доставать тебя, может подкинешь для начала какие то полезные ссылки по данной теме.
Я в данной теме новичок, так что будет все интересно.
(пишу я на маке в XCode, и все пока читаю из хелпы, на хорошие ресурсы пока не натыкался).
проэкт только в начальном этапе, так что если "споемся", думаю будем друг-другу полезны :)
 
S

skysun

Гость
#7
ссылки:
1)MSDN-разделы DirectX,DirectDraw-очень подробные статьи(особенно если с английским проблем нет)
2)http://www.codeproject.com/ - буржуйский портал(сплошные китайцы и индусы), много исходников по теме.

Мне этой инф-ы оказалось достаточно. Будут вопросы пиши!
 

tyko

New Member
02.11.2007
4
0
#8
разобрался как захватывать видео и сохранять в муви, а как сохранить в mpeg-4(avi)?
 
S

skysun

Гость
#9
1)запрашиваешь список всех видео компрессоров
Код:
BOOL CCapture::GetCompressorsList(CStringList& CompressorsList)
{
//************************************************************
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
IMoniker *pMoniker = NULL;

hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, 
(void**)&pSysDevEnum);
if (FAILED(hr))
{
return FALSE;
}	

hr = pSysDevEnum->CreateClassEnumerator(
CLSID_VideoCompressorCategory, &pEnum, 0);
if (hr == S_OK) // S_FALSE means nothing in this category.
{
while (S_OK == pEnum->Next(1, &pMoniker, NULL))
{
IPropertyBag *pPropBag = NULL;
pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
(void **)&pPropBag);
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr))
{
USES_CONVERSION;
CComBSTR bstrName(varName.bstrVal);
CompressorsList.AddTail(OLE2A(bstrName));
bstrName.Empty();			
}  
VariantClear(&varName); 
pPropBag->Release();
pMoniker->Release();
}
}
pSysDevEnum->Release();
pEnum->Release();

//************************************************************

return TRUE;
}

2)аттачишся к нужном тебе. Примерно так CComPtr<IBaseFilter> pVC прикрепляется к компрессору с заданным именем:
Код:
BOOL CCapture::FindVideoCompressor(CString CompressorName)
{
HRESULT hr = E_FAIL;
CComPtr<IBaseFilter> pFilter;
CComPtr<ICreateDevEnum> pSysDevEnum;
CComPtr<IEnumMoniker> pEnumCat = NULL;

// Create the System Device Enumerator.
hr=pSysDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum);
if(FAILED(hr))
return FALSE;

// Obtain a class enumerator for the video compressor category.
hr=pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);
if(FAILED(hr)||(hr==S_FALSE)||(hr==E_OUTOFMEMORY)||(hr==E_POINTER))
return FALSE;

// Enumerate the monikers.
CComPtr<IMoniker> pMoniker;
ULONG cFetched=0;

while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
/////////////////////////////////////////////////////
CComPtr<IPropertyBag> pProp;
hr=pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pProp);
if(SUCCEEDED(hr))
{
VARIANT varName;
VariantInit(&varName); // Try to match the friendly name.
hr = pProp->Read(L"FriendlyName", &varName, 0); 
if (SUCCEEDED(hr))
{
CComBSTR bstrDevName(varName.bstrVal);
USES_CONVERSION;
if(bstrDevName == T2OLE(CompressorName))
{
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter);
if (SUCCEEDED(hr))
{
pVC = pFilter;
pVC.p->AddRef(); // Add ref on the way out.
return TRUE;
}
else
return FALSE;
break;
}
}
VariantClear(&varName);
}
pMoniker = NULL; // Release for the next loop.
cFetched=0;
/////////////////////////////////////////////////////
}
return FALSE;
}

3)затем SetOutputFileName и RenderStream. Пример

Код:
CComPtr<IBaseFilter> pVFW;// Create the video file-writing(VFW) portion.
CComPtr<IBaseFilter> pVC;//Video compressor filter
CComPtr<IBaseFilter> pSrc;//фильтр прикрепленный к устройству
CComQIPtr<IMediaControl> pControl;
…
…
…

hr = pBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, L"C:\\Example.avi", &pVFW, NULL);

// Render the capture pin on the video capture filter
hr = pBuilder->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category
&MEDIATYPE_Video,	  // Media type
pSrc,				  // Capture filter
pVC,	 // Compression filter (optional)
pVFW					// Multiplexer or renderer filter	
);
pControl->Run()
Кажись все.
 
S

skysun

Гость
#10
Кстати забыл! Дело в том, что компрессия "на лету" требует от ПК огромных ресурсов и чем выше качество и уровень компрессии тем сильнее все тормозит и качество конечного ролика оставляет желать лучшего. Может быть имеет смысл уже после захвата видео во временный файл его сжимать. Тогда это делается чуть по другому. Видел статью в MSDN, как точно сказать не могу, но если память меня не подводит разница только в том, что pSrc(в моем примере) должен быть прикреплен к файлу а не к устройству-захвата. Даже спец. метод для этого описывался.

Удачи!