Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Захват видео (фотография) видеокамерой

Автор: FHWAT
Дата сообщения: 04.01.2011 10:39
Нужно произвести захват видеокадра с камеры (камера может быть любой - USB, подключенная к спец. плате). вроде бы все хорошо, но проблемма состоит в том чтобы инициалицировать камеру, т.е. задать размер кадра, тип медиаданных, глубину цвета и т.д.. Использую для тестов встроенную вэбкамеру в ноутбук и подключенную к плате цифровую камеру (CNB или DSP 220 Digital Zoom - если это кому-то что-то говорит ).
В случае вэбкамеры инициализация идет видимо по умолчанию (640х480, 24 bit, RGB24) и хоть какой-то захват идет... Но все попытки поменять данные - ни к чему не приводят - упрямо остаются такими же на выходе, хотя в MediaType SampleGrabber'а они все же записываются (проверял в режиме debug'a). А вот в случае подключенной к плате - вообще ничего - как телевизор без антены, однако если ее инициализирровать запустив другую программу (есть такая, но без исходников) и после запустить мою прогу, то вроде все идет, но с установками, той, другой программы.

Может кто знает как разрешить проблему? Меня пока устроило бы даже частичное решение - пусть любая камера инициализируется хоть какими-то значениями, лишь на медиаконтроле было изображение и метод SampleGrabber.GetBitmap(...) давал бы не 0-картинку. Но хотелось бы все же нормальной работы - метод StretchDraw все же искажает изображения, а речь идет о фото на документы.
Версия Delphi - 2010. Но можно и С++ Builder.

Вот мой код - попытка инициализации. Я понимаю до совершенства далеко, но не до "вылизывания" мне - начальство по маковке стучит: мол поскорее нужно... Закоменчены результаты всевозможных экспериментов.


Код:
procedure TVideoForm.BitBtn3Click(Sender: TObject);
var
SMTeeFilter : IBaseFilter;
m_VideoType: PAMMediaType;
hr: HResult;
StreamConfig: IAMStreamConfig;
begin
{
Колмпоненты на форме
DSPack:
Filter - TFilter
FilterGraph - TFilterGraph
SampleGrabber - TSampleGrabber
VideoWindow - TVideoWindow

ComboBox1 - список устройств видеозахвата (будет одна камера - потому
можно будет "упразднить")
кроме того имеется TImage - но он не обязателен
}
try
// CoCreateInstance(CLSID_SmartTee, nil,
// CLSCTX_INPROC, IID_IBaseFilter, SMTeeFilter);
// hr := (FilterGraph as IGraphBuilder).AddFilter(SMTeeFilter, 'Smart Tee');
// не работает - пишет, что "интерфейс не поддерживается"
StreamConfig := NIL;
m_VideoType := nil;

FilterGraph.ClearGraph();
FilterGraph.Active := False;
Filter.BaseFilter.Moniker := SysDev.GetMoniker(ComboBox1.ItemIndex);

Filter.FilterGraph := FilterGraph;
FilterGraph.Active := True;

with FilterGraph as ICaptureGraphBuilder2 do begin
hr := FindInterface(@PIN_CATEGORY_CAPTURE,
@MEDIATYPE_Video,
Filter as IBaseFilter,
IID_IAMStreamConfig, StreamConfig);

{ hr := FindInterface(@PIN_CATEGORY_CAPTURE,
@MEDIATYPE_Video,
SampleGrabber as IBaseFilter,
IID_IAMStreamConfig, StreamConfig); //возвращает hr < 0}

end;

if SUCCEEDED(hr) then begin
StreamConfig.GetFormat(m_VideoType);
PVideoInfoHeader(m_VideoType.pbFormat)^.bmiHeader.biWidth := 320;
PVideoInfoHeader(m_VideoType.pbFormat)^.bmiHeader.biHeight := 240;
PVideoInfoHeader(m_VideoType.pbFormat)^.bmiHeader.biBitCount := 24;
//25 fps
PVideoInfoHeader(m_VideoType.pbFormat)^.AvgTimePerFrame:= 10000000 div 25;

with PVideoInfoHeader(m_VideoType.pbFormat)^.bmiHeader do
m_VideoType.lSampleSize := biWidth * biHeight * biBitCount;

PVideoInfoHeader(m_VideoType.pbFormat)^.bmiHeader.biSizeImage :=
m_VideoType.lSampleSize;
m_VideoType.subtype := MEDIASUBTYPE_RGB24;
// StreamConfig.SetFormat(m_VideoType^); //толку никакого от этого медода
end;
// ShowMessage(IntTostr(sizeof(m_VideoType^))); - 72 байта
// SampleGrabber.MediaType.SetFormat(m_VideoType, sizeof(m_VideoType^));
// Результата этот метод не дает

//вручною записываю все данные
SampleGrabber.MediaType.InitMediaType();
SampleGrabber.MediaType.AMMediaType.majortype := m_VideoType.majortype;
SampleGrabber.MediaType.AMMediaType.subtype := m_VideoType.subtype;
SampleGrabber.MediaType.AMMediaType.bFixedSizeSamples := m_VideoType.bFixedSizeSamples;
SampleGrabber.MediaType.AMMediaType.bTemporalCompression := m_VideoType.bTemporalCompression;
SampleGrabber.MediaType.AMMediaType.lSampleSize := m_VideoType.lSampleSize;
SampleGrabber.MediaType.AMMediaType.formattype := m_VideoType.formattype;
SampleGrabber.MediaType.AMMediaType.pUnk := m_VideoType.pUnk;
SampleGrabber.MediaType.AMMediaType.cbFormat := m_VideoType.cbFormat;
SampleGrabber.MediaType.AMMediaType.pbFormat := m_VideoType.pbFormat;
//значения в MediaType - таким образом записаны, но
//SampleGrabber.GetBitmap(...) выдает 640х480х24
//если задать например m_VideoType.subtype := MEDIASUBTYPE_YUYV;
//то возникает error "Контакты не присоединены..." - что в общем - то понятно
//но камера подключенныя к плате такой тип поддерживает, но там тот же error.

//ниже следующий код - попытка "обновить" буфер захвата камеры
//но ничего он не дает...
SampleGrabber.UpdateMediaType();
FilterGraph.ClearGraph;
FilterGraph.Active := False;
Filter.BaseFilter.Moniker := SysDev.GetMoniker(ComboBox1.ItemIndex);
Filter.FilterGraph := FilterGraph;
FilterGraph.Active := True;

{ ShowMessage(intTostr((PVideoInfoHeader(SampleGrabber.MediaType.AMMediaType.pbFormat)^.bmiHeader.biWidth)));
- 320 пикселей как и записывали.
ShowMessage(intTostr(SizeOf(SampleGrabber.MediaType.AMMediaType^))); - 72 байта
}
m_VideoType := nil;
StreamConfig := nil;

with FilterGraph as ICaptureGraphBuilder2 do begin
//пробовалось - @PIN_CATEGORY_PREVIEW - на вэбкамере идет, на другой
//нет вообще ничего
//даже "шипения" на медиаконтроле
RenderStream(@PIN_CATEGORY_CAPTURE, nil,
Filter as IBaseFilter,
SampleGrabber as IBaseFilter,
VideoWindow as IbaseFilter);

{ RenderStream(nil, nil, SMTeeFilter as IBaseFilter,
SampleGrabber as IBaseFilter,
VideoWindow as IbaseFilter);
SMTeeFilter - вообще не вставляется.}
end;
FilterGraph.Play();
except
{}
end;

end;
Автор: Antonich1982
Дата сообщения: 10.02.2011 12:54
Зачем вы после установки настроек сбарасываете их, очищая FilterGraph? Закоментируйте ваши повторные строки:

FilterGraph.ClearGraph;
FilterGraph.Active := False;
Filter.BaseFilter.Moniker := SysDev.GetMoniker(ComboBox1.ItemIndex);
Filter.FilterGraph := FilterGraph;
FilterGraph.Active := True;

У меня всё заработало.
Автор: the_bmw
Дата сообщения: 27.12.2011 16:13
Как узнать что на USB камере была нажата кнопка. С определением и конфигурацией разобрался.

Страницы: 1

Предыдущая тема: Написание серверно-клиентской программы


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.