Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.02.2013, 12:32   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
Вопрос Как сделать скриншот с вебкамеры с использованием DirectShow

всем привет.
подключаюсь к вебкамере через DirectShow.
как сделать скриншот с камеры?
в интернете читал, что это можно сделать с помощью ISampleGrabber.
но не могу понять, как его правильно подцепить к графу и как, собственно, получить сам скриншот.
DSpack не предлагать.

Последний раз редактировалось BLACK_RAIN; 26.02.2013 в 13:08.
BLACK_RAIN вне форума Ответить с цитированием
Старый 26.02.2013, 14:56   #2
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

http://www.programmersforum.ru/showp...44&postcount=8
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 26.02.2013, 15:58   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

видимо, я не совсем точно сформулировал вопрос.
Цитата:
Сообщение от raxp Посмотреть сообщение
подобный код я видел почти везде.
теория мне ясна. Создаем сэмплГраббер, задаем ему MediaType и цепляем его к GraphBuilder.
мне не понятно, что писать на обработчике кнопки, чтобы получить скриншот. В какой переменной он придет и как например сохранить его в BMP?
вот мой код:
Код:
var
  fsampleGrabber : ISampleGrabber;
grabber : IBaseFilter;

CoCreateInstance(CLSID_SampleGrabber, NIL, CLSCTX_INPROC_SERVER,
                    IID_IBaseFilter, grabber);
grabber.QueryInterface(IID_ISampleGrabber,fSampleGrabber);

FillChar(MediaType, SizeOf(MediaType), 0);
MediaType.majortype := MEDIATYPE_Video;
MediaType.subtype := MEDIASUBTYPE_RGB24;
fSampleGrabber.SetMediaType(MediaType);
fSampleGrabber.SetBufferSamples(True);
fSampleGrabber.SetOneShot(False);
//SampleGrabber.SetCallback(Self, 0); // это зачем? как сделать, если без формы?
fGraphBuilder.AddFilter(grabber, 'Sample Grabber');
тут всё правильно? предварительно, разумеется, создаю GraphBuilder.
BLACK_RAIN вне форума Ответить с цитированием
Старый 26.02.2013, 21:17   #4
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

Цитата:
подобный код я видел почти везде.
теория мне ясна.
это как раз не теория, а практика

Цитата:
мне не понятно, что писать на обработчике кнопки
http://www.programmersforum.ru/showp...31&postcount=6 (обратите ваше внимание на каллбэк BufferCB(), вам лишь остается сохранять готовый hbitmap/bitmap).
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 27.02.2013, 15:29   #5
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

raxp
простите, но я всё-равно не могу уловить последовательность действий, которые должен сделать.
сегодня утром копался в MSDN и нашел это: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
из этого попытался сделать следующее.
создаем GraphBuiler, фильтр захвата видео и SampleGrabber:
Код:
var
  pGrabberF : IBaseFilter;
  fSampleGrabber : ISampleGrabber;

Result:=CoCreateInstance(CLSID_FilterGraph, NIL, CLSCTX_INPROC_SERVER,
 IID_IGraphBuilder, FGraphBuilder);
if FAILED(Result) then EXIT;
Result:=CoCreateInstance(CLSID_CaptureGraphBuilder2, NIL, CLSCTX_INPROC_SERVER,
               IID_ICaptureGraphBuilder2, FCaptureGraphBuilder);
if FAILED(Result) then EXIT;
Result:=FCaptureGraphBuilder.SetFiltergraph(FGraphBuilder);
if FAILED(Result) then EXIT;
  n := lbcount(lb_cameras); //возвращает кол-во элементов в ListBox'e
if n>0 then
           begin
             i := lbgetindex(lb_cameras); // индекс ListBox'a
              //marray[1] - array моникеров с вебкамерами
              MArray1[i].BindToObject(NIL, NIL, IID_IBaseFilter, FVideoCaptureFilter);
              FGraphBuilder.AddFilter(FVideoCaptureFilter, 'VideoCaptureFilter');  
           end;
     ...........
  CoCreateInstance(CLSID_SampleGrabber,nil,CLSCTX_INPROC_SERVER,
                    IID_IBaseFilter,pGrabberF);
  FGraphBuilder.AddFilter(pGrabberF,'Sample Grabber');
  pGrabberF.QueryInterface(IID_ISampleGrabber,fSampleGrabber);
  fSampleGrabber.SetBufferSamples(True);
  ZeroMemory(@mt,SizeOf(mt));
  mt.majortype := MEDIATYPE_Video;
  mt.subtype := MEDIASUBTYPE_RGB24;
  mt.formattype := FORMAT_VideoInfo;
  fSampleGrabber.SetMediaType(mt);
  fSampleGrabber.SetOneShot(False);
.........
код кнопки:
Код:
var
  cbBuffer : integer;
  pBuffer : pointer;
  pvih : pVideoInfoHeader;
  mt : am_media_type;
begin
        cbBuffer := 0;
        pBuffer := nil;
        fSampleGrabber.GetCurrentBuffer(cbBuffer,nil);       // тут
        fSampleGrabber.GetCurrentBuffer(cbBuffer,pBuffer);//и тут cbbuffer=0
        fSampleGrabber.GetConnectedMediaType(mt);
        if (IsEqualGUID(mt.majortype,FORMAT_VideoInfo)  // тут =false
           and (mt.cbFormat>=SizeOf(tvideoinfoheader))
           and (Assigned(mt.pbFormat))) then
           pVih := mt.pbFormat 
           else
           Exit;
{        WriteBitmap('c:\rety.bmp', pVih.bmiHeader,
            mt.cbFormat - SIZE_PREHEADER, Byte(pBuffer), cbBuffer);}
в MSDN про Pin'ы не сказано (вернее, сказано. но я туплю). Зачем они нужны и что делают? Может, не получается из-за того, что я Pin'ы не использую? но, если я правильно понял, Pin'ы нужны, если грабить скриншот из видеофайла.

Последний раз редактировалось BLACK_RAIN; 27.02.2013 в 17:14.
BLACK_RAIN вне форума Ответить с цитированием
Старый 27.02.2013, 18:34   #6
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

...вот граббер из моего плеера (без каллбека):
Код:
procedure GetBitmap(_dsmp: TDSMP; Bitmap: TBitmap);
var hr        : HRESULT;
    BMIHeader : TBitmapInfoHeader;
    BufferSize: longint;
    AMediaType: TAMMediaType;
    buffer    : pointer;
    //
    BMPInfo : PBitmapInfo;
begin
 if not assigned(Bitmap) then exit;

  if not assigned(pGrabber) then exit;
  hr := pGrabber.GetConnectedMediaType(AMediaType);
  if (hr <> S_OK) then exit;
  if IsEqualGUID(AMediaType.majortype, MEDIATYPE_Video) then begin
   case Amediatype.formattype.D1 of
        $05589F80: BMIHeader := PVideoInfoHeader(Amediatype.pbFormat)^.bmiHeader;
        $F72A76A0: BMIHeader := PVideoInfoHeader2(Amediatype.pbFormat)^.bmiHeader;
   end;

   ZeroMemory(BMPInfo, sizeof(TBitmapInfo));
   CopyMemory(@BMPInfo.bmiHeader, @bmiHeader, sizeof(TBITMAPINFOHEADER));
   bitmap.Handle := CreateDIBSection(0, BMPInfo^, DIB_RGB_COLORS, buffer, 0, 0);
   HR := pGrabber.GetCurrentBuffer(BufferSize, buffer);
   if (hr <> S_OK) then exit;
  end;

  FreeMediaType(@AMediaType);
  buffer:= nil;
end;
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 27.02.2013, 19:17   #7
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

raxp
Код:
   HR := pGrabber.GetCurrentBuffer(BufferSize, buffer);
тут HR = VFW_E_WRONG_STATE, хотя я в самом начале ставлю граф на паузу.
Код:
   if (hr <> S_OK) then exit;
а тут после выхода экскепшн:

p.s. Что за функция FreeMediaType()? У меня в делфи7 есть только MoFreeMediaType(). Это одно и то же?
--------------------
переделал.
экскепшн пропал, но теперь
Код:
//        ZeroMemory(@mt,SizeOf(mt));
        hr := fSampleGrabber.GetConnectedMediaType(mt);
        if hr<>s_ok then
        begin
          case hr of
            E_POINTER:
            MessageBox(form1,PChar('MT E_POINTER'),'',MB_ICONERROR);
            VFW_E_NOT_CONNECTED:
            MessageBox(form1,PChar('MT VFW_E_NOT_CONNECTED'),'',MB_ICONERROR);
          end;
          Exit;
        end;
HR = VFW_E_NOT_CONNECTED
я же граббер к графу вроде цепляю и MediaType к грабберу тоже. почему тогда нот коннектед?
Код:
  CoCreateInstance(CLSID_SampleGrabber,nil,CLSCTX_INPROC_SERVER,
                    IID_IBaseFilter,pGrabberF);
  Result := FGraphBuilder.AddFilter(pGrabberF,'Sample Grabber');
  if Result = s_ok then
  begin
    MessageBox(0,PChar('Граббер подцеплен к Графу'),PChar('Граф Дракула'),MB_OK);
  pGrabberF.QueryInterface(IID_ISampleGrabber,fSampleGrabber);
  ZeroMemory(@DesiredMT,SizeOf(DesiredMT));
  DesiredMT.majortype := MEDIATYPE_Video;
  DesiredMT.subtype := MEDIASUBTYPE_RGB24;
  DesiredMT.formattype := FORMAT_VideoInfo;
  fSampleGrabber.SetMediaType(DesiredMT);
  fSampleGrabber.SetOneShot(False);
  fSampleGrabber.SetBufferSamples(True);
  end;
тут ок.
я нашел ошибку!
Result:=FCaptureGraphBuilder.Render Stream(@PIN_CATEGORY_PREVIEW,
@MEDIATYPE_Video, FVideoCaptureFilter, pGrabberF, NIL);
я забыл сюда граббер вписать.
но теперь появилась вообще не понятная хрень.
Код:
          ZeroMemory(BMPInfo, sizeof(BMPInfo));
на этой строчке дебаггер откидывает на смый последний end оконной функции и вылетает экскепшн.
без дебаггера то же самое.
что это значит?

Последний раз редактировалось BLACK_RAIN; 28.02.2013 в 16:20.
BLACK_RAIN вне форума Ответить с цитированием
Старый 28.02.2013, 16:47   #8
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

ура!!!!! я всё сделал. Скриншот камеры есть. Всем спасибо!
если кто-то еще не может разобраться, пишите в личку. Скину исходник.
а что же, всё-таки, не так с ZeroMemory? я заменил ее на New(). Так работает.

Последний раз редактировалось BLACK_RAIN; 28.02.2013 в 21:15.
BLACK_RAIN вне форума Ответить с цитированием
Старый 16.08.2014, 18:54   #9
tromani
Пользователь
 
Регистрация: 10.12.2010
Сообщений: 23
По умолчанию

чет я так и не понял как тут личное сообщение написать, так что может тут ответите... проблема таже, въехать никак не могу... че в итоге нада писать в обработчике кнопки... и в каком месте цеплять граббер))) в общем растолкуйте подробнее если можно
tromani вне форума Ответить с цитированием
Старый 14.10.2014, 23:15   #10
Daemvil
Пользователь
 
Регистрация: 23.12.2009
Сообщений: 56
По умолчанию

Доброго времени суток! Подскажите, пожалуйста, как через PIN_CATEGORY_STILL кадр снять? при использовании PIN_CATEGORY_STILL вместо PIN_CATEGORY_PREVIEW в стандартном коде, RenderStream выдает фэйл...
Nostra Sunt
Daemvil вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как сделать скриншот в формате jpeg egorzenit Мультимедиа в Delphi 22 12.02.2012 21:39
Как сделать скриншот определенной части экрана? JonMagon Помощь студентам 11 13.05.2011 09:45
Не получается сделать скриншот C# Ski1alec C# (си шарп) 5 24.01.2011 22:56
Помогите, нужень пример слайдера с использованием DirectShow big_big Мультимедиа в Delphi 1 22.08.2009 09:49
как сделать скриншот xakkkkker Общие вопросы Delphi 1 10.02.2008 15:24