Здравствуйте, debuger, Вы писали:
D>У меня есть карточка для виделзахвата AVerMedia EZ Capture. D>Пишу я под Делфой(как ни прискорбно), пожалуйста, если захотели ответить куском D>кода, пусть он будет делфо-образным (не сюшным). Пасаибо
Ввод и показ видео при помощи AVerMedia EZ Capture
==================================================
Сергей Зобин * 2004 * sz@mc.carrier.kiev.ua
Полные исходники проекта доступны по запросу (AVER_Ex.zip, 60 kb)
Исходники созданы на базе анализа кода библиотечных DLL из SDK к AVER EZ Capture
*Примечание — в данной статье объясняются логически значимые части кода, полный код см. в исходниках проекта.
Глава 1. Построение графа
=========================
Для DxShow можно предварительно строить графы при помощи продукта GraphEdit — входящего в комплект MSDN раздел мультимедия размер 3Мб)
В нашем случае, когда все элементы графа уже известны, сделаем это при помощи собственной программы.
1) создаем экземпляр собственно графа
hRes:=CoCreateInstance(CLSID_FilterGraph, nil,
CLSCTX_INPROC, IID_IGraphBuilder, fGraphBuilder);
if hRes<>S_OK then begin
DoError(hRes, 'Cannot create FilterGraph!');
exit;
end;
2) Ищем фильтр, при помощи которого вводится видеоизображение, у AVerMedia EZ Capture он называется "Conexant Capture" по названию фирмы-производителя чипа Bt8x8
if not FindCaptureFilter(cCaptureFilterName, fCaptureFilter) then
exit;
3) Ищем кроссбар — это фильтр, при помощи которого переключаются входные цепи (для AVEr EZ Capture это "S-Video", "Composite"), его имя тоже известно — это "Conexant Crossbar"
if not FindCrossbarFilter(cCrossbarFilterName, fCrossbarFilter) then
exit;
4) Создаем построитель графа-захватчика видео (что является переводом CaptureGraphBuilder)
hRes:=CoCreateInstance(IID_ICaptureGraphBuilder, nil,
CLSCTX_INPROC, IID_ICaptureGraphBuilder, fCaptureGraphBuilder);
if hRes<>S_OK then begin
DoError(hRes, 'Cannot create Capture graph builder!');
exit;
end;
5) Создаем экземпляр фильтра "Pause", разработанного Aver Media специально для захвата одиночных кадров. Этот фильтр находится в файле PauseVideo.ax и устанавливается вмести с драйверами платы AVER EZ Capture
hRes:=CoCreateInstance(cGUID_PauseVideoFilter, nil,
CLSCTX_INPROC, IID_IBaseFilter, fPauseVideoFilter);
if hRes<>S_OK then begin
DoError(hRes, 'Cannot create Pause Video filter');
exit;
end;
6) Вносим в граф CaptureFilter
hRes:=fGraphBuilder.AddFilter(fCaptureFilter, nil);
if hRes<>S_OK then begin
DoError(hRes, 'AddFilter CaptureFilter is fail!');
exit;
end;
7) Вносим в граф построитель графа-захватчика видео
hRes:=fCaptureGraphBuilder.SetFiltergraph(fGraphBuilder);
if hRes<>S_OK then begin
DoError(hRes, 'Cannot give graph to builder');
exit;
end;
8) Вносим в граф фильтр "Pause"
hRes:=fGraphBuilder.AddFilter(fPauseVideoFilter, nil);
if hRes<>S_OK then begin
DoError(hRes, 'Add Pause Video Filter is fail!');
exit;
end;
9) Находим выходной пин фильтра, с которого вводим изображение. Для AVER EZ Capture — их 2 — "Просмотр" и "Запись". Первый применяется, как видно из его названия, для просмотра, второй — для записи видео. Т.к. сейчас строится граф для просмотра видео — то будет использоваться пин "Просмотр"
hRes:=fCaptureFilter.FindPin(cCaptureOutPinName, fCaptureOutPin);
if hRes<>S_OK then begin
DoError(hRes, 'Cannot find capture out pin: '+cCaptureOutPinName);
exit;
end;
11) Перечислим все поддерживаемые картой типы форматов видео (их можно использовать для дальнейшего выбора формата пользователем)
if not EnumOutMediaTypes then exit;
12) Соединяем выходной пин фильтра-источника изображения (у нас это fCaptureFilter) с входным пином фильтра паузы
hRes:=fPauseVideoFilter.FindPin('In', PauseInPin);
if hRes<>S_OK then begin
DoError(hRes, 'VideoPause.In pin not found');
exit;
end;
hRes:=fGraphBuilder.Connect(fCaptureOutPin, PauseInPin);
PauseInPin:=nil;
if hRes<>S_OK then begin
DoError(hRes, 'Connect Video Capture filter and Pause Video Filter failure!');
exit;
end;
13) Отдает построителю графа-захватчика команду достроить граф автоматически до окна отображения видео
hRes:=fPauseVideoFilter.FindPin('Out', PauseOutPin);
if hRes<>S_OK then begin
DoError(hRes, 'VideoPause.Out pin not found');
exit;
end;
hRes:=fCaptureGraphBuilder.RenderStream(nil, PauseOutPin, nil, nil);
PauseOutPin:=nil;
if hRes<>S_OK then begin
DoError(hRes, 'It is fail to render out pin of pause video filter');
exit;
end;
14) В построенном графе найдем фильтр вывода видео на экран
hRes:=fCaptureGraphBuilder.FindInterface(@PINNAME_VIDEO_PREVIEW, fCaptureFilter, IID_IVideoWindow, fVideoWindow);
if hRes<>S_OK then begin
DoError(hRes, 'VideoWindow not found in graph');
exit;
end;
15) Установим все ранее установленные пользователем настройки:
Источник видео
if not SetVideoSource(fParams.rConnector) then exit;
Видеоформат
if not SetVideoFormat(fParams.rVideoFormat) then exit;
Яркость
if not SetBrightness(fParams.rBrightness) then exit;
Контрастность
if not SetContrast(fParams.rContrast) then exit;
Цветность
if not SetHue(fParams.rHue) then exit;
16) Настроим фильтр вывода видео на экран
Для этого передадим Handle и размеры компонента, на котором будем отображать видео (на форме это может быть например TPanel или сама форма, если видео нужно изображать на всю форму)
hRes:=fVideoWindow.put_Owner(fHandle);
if hRes<>S_OK then begin
DoError(hRes, 'InitVideoWindow: put_Owner');
exit;
end;
hRes:=fVideoWindow.put_WindowStyle(lWindowStyle or WS_CHILD or WS_CLIPCHILDREN); // $4200 0000
if hRes<>S_OK then begin
DoError(hRes, 'InitVideoWindow: put_WindowStyle');
exit;
end;
hRes:=fVideoWindow.put_WindowStyleEx(lWindowStyleEx);
if hRes<>S_OK then begin
DoError(hRes, 'InitVideoWindow: put_WindowStyleEx');
exit;
end;
hRes:=fVideoWindow.put_MessageDrain(aHandle);
if hRes<>S_OK then begin
DoError(hRes, 'InitVideoWindow: put_MessageDrain');
exit;
end;
hRes:=fVideoWindow.SetWindowPosition(fViewRect.Left, fViewRect.Top, fViewRect.Right — fViewRect.Left, fViewRect.Bottom — fViewRect.Top);
if hRes<>S_OK then exit;
hRes:=fVideoWindow.put_Visible(True);
if hRes<>S_OK then exit;
17) Запустим граф в работу
hRes:=fGraphBuilder.QueryInterface(IID_IMediaControl, MediaControl);
if hRes<>S_OK then exit;
hRes:=MediaControl.Run;
MediaControl:=nil;
Итак в 17 шагов построен граф для отображения видео в окне от AVER EZ Capture
Глава 2. Ввод кадра
===================
1. Определим размеры выводимого изображения
Result:=DetectVideoSourceSize(lSize);
if not Result then exit;
2. запросим интерфейс для ввода кадра от фильтра PauseVideo. Его особенностью является то, что он вводит кадр асинхронно и прямо в процессе показа видео.
hRes:=fPauseVideoFilter.QueryInterface(cGUID_PauseIntf, PauseWaiter);
if hRes<>S_OK then exit;
3. Выделим и очистим память для изображения (хотя очищать ее не обязательно)
lBufSize:=lSize.X*lSize.Y*4;
GetMem(lDataBuf, lBufSize);
FillChar(lDataBuf^, lBufSize, #0);
4. Синхронизуем работу ввода — подождем окончания ввода или истечения тайм-аута
lTime:=GetTickCount;
while (gWaitFlag=0) and
(GetTickCount — lTime<=1000) do
Sleep(1);
PauseWaiter:=nil;
5. Если тайм-аут истек — что-то не сработало
if GetTickCount — lTime>=1000 then begin
DoError(0, 'Capture Frame time-out');
exit;
end
6. Преобразуем буфер в битмапу
case fCaptureBitPerPixel of
8: ConvertBuffer8ToBitmap(lDataBuf, aOutBitmap)
15: ConvertBuffer15ToBitmap(lDataBuf, aOutBitmap)
24: ConvertBuffer24ToBitmap(lDataBuf, aOutBitmap)
32: ConvertBuffer32ToBitmap(lDataBuf, aOutBitmap)
else begin
DoError(0, 'Unsupported video format: '+IntToStr(fCaptureBitPerPixel));
end;
end;
Преобразование нужно для того, чтобы перевернуть картинку и привести ее к формату GRB24