Пятница, 29.03.2024, 03:07
Приветствую Вас Гость

Не ошибается тот, кто ничего не делает.
Но и ничего не делать - ошибка.

Эмиль Кроткий

Меню сайта
Категории раздела
Работа с библиотеками BASS и DirectShow [14]
Статьи по написанию mp3 плеера, видеоплеера, работе с WEB камерой и т.д.
Форма входа

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0


















Тиц
Главная » Статьи » Мультимедиа » Работа с библиотеками BASS и DirectShow

Урок 3.1. Учимся работать с Web камерой в Delphi.
Содержание

Урок 2.1. Пишем видеоплеер (проигрыватель видео) на Delphi с использованием технологии DirectShow.

Урок 2.2. Пишем видеоплеер (проигрыватель видео) на Delphi с использованием технологии DirectShow (продолжение).

Урок 3.1. Учимся работать с Web камерой в Delphi через архитектуру DirectShow.

Урок 3.2. Учимся работать с Web камерой в Delphi (Грабим изображение с камеры в файл).



Урок 3.1.

Учимся работать с Web камерой в Delphi через архитектуру DirectShow.

Учимся работать с Web камерой в Delphi.      Продолжая серию уроков по DirectShow, сегодня мы научимся получать изображение с Web камеры на панели нашей формы и записывать полученное изображение  в  видео файл  AVI. Для этого необходимо   перечислить все устройства для захвата видео, которые у нас имеются. Все найденные устройства будем записывать в отдельный массив Моникеров. Затем необходимо  сформировать граф захвата и добавить туда нужный фильтр захвата.

      Итак запустим Delphi и создадим новое приложение. Разместим на форме следующие компоненты: Два компонента TPanel, в первый будем выводить изображение с камеры, а во второй режим записи или просмотра. Два компонента TListBox, в первый будем выводить список камер, а во второй список микрофонов (устройств для захвата звука). Пять компонентов TButton (кнопка), первую кнопку назовем «Запись», вторую «Стоп», третья «Параметры и разрешение камеры», четвертую «Свойства видео» и пятую «Свойства звука». И компонент TSaveDialog.

Учимся работать с Web камерой в Delphi.

Далее приступим к написанию кода:

Добавим в Uses модули  directshow9, ActiveX. Скачать заголовочные файлы DirectShow можно здесь.

В разделе type добавим три функции:

function Initializ: HResult;

function CreateGraph: HResult;

function  DisplayPropertyFrame(Filter: IBaseFilter; Handle: THandle): HResult;


      В первой мы будем перечислять  все устройства для захвата видео и звука, которые у нас имеются и записывать их в массивы Маникеров одновременно добавляя в ListBoxы.

Для справки:

Моникером называют СОМ-объект, реализующий интерфейс IMoniker и позволяющий клиенту получить указатель на объект, идентифицируемый этим моникером, через вызов метода IMoniker::BindToObject. По имени этого метода процесс получения объекта от моникера называют связыванием моникера или активизацией объекта.

     Во второй функции мы будем строить граф захвата видео и звука.



     Третья функция позволит получать информацию о свойствах фильтров.

Далее в раздел Var добавляем следующие глобальные переменные:

  FileName:string; //имя файла для записи
  RecMode: Boolean = False; //флаг записи
  DeviceName:OleVariant;  //имя устройства
  PropertyName:IPropertyBag; //
  pDevEnum:ICreateDEvEnum; //перечислитель устройств
  pEnum:IEnumMoniker; //перечислитель моникеров
  pMoniker:IMoniker;

  MArray1,MArray2: array of IMoniker; //Это список моникеров, из которго
                                                        //мы потом будем получать необходмый моникер


//интерфейсы
    FGraphBuilder:        IGraphBuilder;
    FCaptureGraphBuilder: ICaptureGraphBuilder2;
    FMux:                 IBaseFilter;
    FSink:                IFileSinkFilter;
    FMediaControl:        IMediaControl;
    FVideoWindow:         IVideoWindow;

    FVideoCaptureFilter:  IBaseFilter;
    FAudioCaptureFilter:  IBaseFilter;
//область вывода изображения
    FVideoRect:           TRect;

Затем в разделе implementation пишем код:

для функции function TForm1.Initializ: HResult;
для функции function TForm1.CreateGraph:HResult;
для функции function TForm1.DisplayPropertyFrame(Filter: IBaseFilter; Handle: THandle): HResult;

function TForm1.Initializ: HResult;
begin
//Создаем объект для перечисления устройств
Result:=CoCreateInstance(CLSID_SystemDeviceEnum, NIL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, pDevEnum);
if Result<>S_OK then EXIT;

//Перечислитель устройств Video
Result:=pDevEnum.CreateClassEnumerator(CLSID_VideoInputDeviceCategory, pEnum, 0);
if Result<>S_OK then EXIT;
//Обнуляем массив в списке моникеров
setlength(MArray1,0);
//Пускаем массив по списку устройств
while (S_OK=pEnum.Next(1,pMoniker,Nil)) do
begin
setlength(MArray1,length(MArray1)+1); //Увеличиваем массив на единицу
MArray1[length(MArray1)-1]:=pMoniker; //Запоминаем моникер в масиве
Result:=pMoniker.BindToStorage(NIL, NIL, IPropertyBag, PropertyName); //Линкуем моникер устройства к формату хранения IPropertyBag
if FAILED(Result) then Continue;
Result:=PropertyName.Read('FriendlyName', DeviceName, NIL); //Получаем имя устройства
if FAILED(Result) then Continue;
//Добавляем имя устройства в списки
Listbox1.Items.Add(DeviceName);
end;

//Перечислитель устройств Audio
Result:=pDevEnum.CreateClassEnumerator(CLSID_AudioInputDeviceCategory, pEnum, 0);
if Result<>S_OK  then EXIT;
//Обнуляем массив в списке моникеров
setlength(MArray2,0);
//Пускаем массив по списку устройств
while (S_OK=pEnum.Next(1,pMoniker,Nil)) do
begin
setlength(MArray2,length(MArray2)+1); //Увеличиваем массив на единицу
MArray2[length(MArray2)-1]:=pMoniker; //Запоминаем моникер в масиве
Result:=pMoniker.BindToStorage(NIL, NIL, IPropertyBag, PropertyName); //Линкуем моникер устройства к формату хранения IPropertyBag
if FAILED(Result) then Continue;
Result:=PropertyName.Read('FriendlyName', DeviceName, NIL); //Получаем имя устройства
if FAILED(Result) then Continue;
//Добавляем имя устройства в списки
Listbox2.Items.Add(DeviceName);
end;
//Первоначальный выбор устройств для захвата видео и звука
//Выбираем из спика камеру
if ListBox1.Count=0 then
   begin
      ShowMessage('Камера не обнаружена');
      Result:=E_FAIL;;
      Exit;
   end;
Listbox1.ItemIndex:=0;
//Выбираем из спика устройства для записи звука
if ListBox2.Count=0 then
    begin
      ShowMessage('Микрофон не обнаружен');
    end
                    else  Listbox2.ItemIndex:=0;

//если все ОК
Result:=S_OK;
end;

function TForm1.CreateGraph:HResult;
var
  pConfigMux: IConfigAviMux;
begin
//Чистим граф
  FAudioCaptureFilter  := NIL;
  FVideoCaptureFilter  := NIL;
  FVideoWindow         := NIL;
  FMediaControl        := NIL;
  FSink                := NIL;
  FMux                 := NIL;
  FCaptureGraphBuilder := NIL;
  FGraphBuilder        := NIL;

//Создаем объект для графа фильтров
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;

//выбор устройств ListBox - ов
if Listbox1.ItemIndex>=0 then
           begin
              //получаем устройство для захвата видео из списка моникеров
              MArray1[Listbox1.ItemIndex].BindToObject(NIL, NIL, IID_IBaseFilter, FVideoCaptureFilter);
              //добавляем устройство в граф фильтров
              FGraphBuilder.AddFilter(FVideoCaptureFilter, 'VideoCaptureFilter');
           end;
if Listbox2.ItemIndex>=0 then
           begin
              //получаем устройство для захвата звука из списка моникеров
              MArray2[Listbox2.ItemIndex].BindToObject(NIL, NIL, IID_IBaseFilter, FAudioCaptureFilter);
              //добавляем устройство в граф фильтров
              FGraphBuilder.AddFilter(FAudioCaptureFilter, 'AudioCaptureFilter');
              //строим граф для вывода звука
              Result:=FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Audio,
              FAudioCaptureFilter, NIL, NIL);
              if FAILED(Result) then EXIT;
           end;

//строим граф для вывода изображения
Result:=FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, FVideoCaptureFilter, NIL, NIL);
if FAILED(Result) then EXIT;

//Получаем интерфейс управления окном видео
Result:=FGraphBuilder.QueryInterface(IID_IVideoWindow, FVideoWindow);
if FAILED(Result) then EXIT;
//Задаем стиль окна вывода
FVideoWindow.put_WindowStyle(WS_CHILD or WS_CLIPSIBLINGS);
//Накладываем окно вывода на  Panel1
FVideoWindow.put_Owner(Panel1.Handle);
//Задаем размеры окна во всю панель
FVideoRect:=Panel1.ClientRect;
FVideoWindow.SetWindowPosition(FVideoRect.Left,FVideoRect.Top, FVideoRect.Right - FVideoRect.Left,FVideoRect.Bottom - FVideoRect.Top);
//показываем окно
FVideoWindow.put_Visible(TRUE);

//Запись
if RecMode then
begin
//Создаем файл для записи данных из графа
Result:=FCaptureGraphBuilder.SetOutputFileName(MEDIASUBTYPE_Avi, PWideChar(FileName), FMux, FSink);
if FAILED(Result) then EXIT;

//строим граф фильтров для захвата изображения
Result:=FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_CAPTURE, @MEDIATYPE_Video, FVideoCaptureFilter, Nil, FMux);
if FAILED(Result) then EXIT;
//если выбрано устройство для захвата звука
if Listbox2.ItemIndex>=0 then
    begin
        //строим граф фильтров для захвата звука
        Result:=FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_CAPTURE, @MEDIATYPE_Audio, FAudioCaptureFilter, Nil, FMux);
        if FAILED(Result) then EXIT;
        // При захвате видео со звуком устанавливаем звуковой поток в
        // качестве основного для синхронизации с другими потоками в файле
                pConfigMux := NIL;
                Result:=FMux.QueryInterface(IID_IConfigAviMux, pConfigMux);
                if FAILED(Result) then EXIT;
                begin
                  pConfigMux.SetMasterStream(1);
                  pConfigMux := NIL;
                end;
    end;
end;
//Запрашиваем интерфейс управления графом
Result:=FGraphBuilder.QueryInterface(IID_IMediaControl, FMediaControl);
if FAILED(Result) then Exit;
//Запускаем отображение просмотра с вебкамер
FMediaControl.Run();
end;

//Вызов страницы свойств заданного фильтра
function TForm1.DisplayPropertyFrame(Filter: IBaseFilter;
  Handle: THandle): HResult;

var
  PropertyPages: ISpecifyPropertyPages;
  Pages: CAUUID;
  FilterInfo: TFilterInfo;
  pfilterUnk: IUnknown;
begin
  // Результат по умолчанию
  Result := E_FAIL;

  // Если фильтр не определен, то завершаем работу
  if Filter = NIL then EXIT;

  // Пытаемся найти интерфейс управления страницами свойств фильтра
  Result := Filter.QueryInterface(ISpecifyPropertyPages, PropertyPages);

  if (SUCCEEDED(Result)) then
  begin
    // Получение имени фильтра и указателя на интерфейс IUnknown
    Filter.QueryFilterInfo(FilterInfo);
    Filter.QueryInterface(IUnknown, pfilterUnk);

    // Получаем массив страниц свойств
    PropertyPages.GetPages(Pages);
    PropertyPages := NIL;

    // Отображаем страницу свойств в виде модального диалога
    OleCreatePropertyFrame(
       Handle,
       0,
       0,
       FilterInfo.achName,
       1,
       @pfilterUnk,
       Pages.cElems,
       Pages.pElems,
       0,
       0,
       NIL
    );

    // Освобождаем память
    pfilterUnk := NIL;
    FilterInfo.pGraph := NIL;
    CoTaskMemFree(Pages.pElems);
  end;

end;


Далее пишем код для обработки событий формы и кнопок:

Для события OnCreate формы пишем:

procedure TForm1.FormCreate(Sender: TObject);
begin
CoInitialize(nil);// инициализировать OLE COM
//вызываем процедуру поиска и инициализации устройств захвата видео и звука
if FAILED(Initializ) then
    Begin
      ShowMessage('Внимание! Произошла ошибка при инициализации');
      Exit;
    End;
//проверяем найденный список устройств
if Listbox1.Count>0 then
    Begin
        //если необходимые для работы устройства найдены,
        //то вызываем процедуру построения графа фильтров
        if FAILED(CreateGraph) then
            Begin
              ShowMessage('Внимание! Произошла ошибка при построении графа фильтров');
              Exit;
            End;
        Panel2.Caption:='Режим просмотра';
    end else
            Begin
              ShowMessage('Внимание! Камера не обнаружена.');
              //Application.Terminate;
            End;
end;

Для события OnDestroy формы пишем:

procedure TForm1.FormDestroy(Sender: TObject);
begin
// Освобождаем память
        pEnum := NIL;
        pDevEnum := NIL;
        pMoniker := NIL;
        PropertyName := NIL;
        DeviceName:=Unassigned;
        CoUninitialize;// деинициализировать OLE COM
end;

Для кнопки «Запись» событие OnClick пишем:

//Запись с камеры в файл
procedure TForm1.Button1Click(Sender: TObject);
begin
//проверяем если устройства для захвата Video
if Listbox1.Count=0 then
    Begin
      ShowMessage('Внимание! Камера не обнаружена.');
      Exit;
    End;
//если запись уже идет, то выходим
If RecMode then Exit;
//задаем текущий каталог для записи
SaveDialog1.InitialDir:=GetCurrentDir;
// Установка расширения по умолчанию
SaveDialog1.DefaultExt := 'avi';
if not (SaveDialog1.Execute) then  exit;
//получаем имя файла для записи
FileName:=SaveDialog1.FileName;
//устанавливаем флаг записи
RecMode:=True;
//вызываем процедуру построения графа фильтров
if FAILED(CreateGraph) then
    Begin
      ShowMessage('Внимание! Произошла ошибка при построении графа фильтров');
      RecMode:=False;
      Exit;
    End;
//Выводим на панель надпись
Panel2.Caption:='Идет запись';
end;

Для кнопки «Стоп» событие OnClick пишем:

//Остановка записи и переход в режим просмотра
procedure TForm1.Button2Click(Sender: TObject);
begin
//если запись не идет, то выходим
If not(RecMode) then Exit;
// Останавливаем работу графа
FMediaControl.Stop;
//устанавливаем флаг записи
RecMode:=False;
//перестраиваем граф
if FAILED(CreateGraph) then
    Begin
      ShowMessage('Внимание! Произошла ошибка при построении графа фильтров');
      Exit;
    End;
Panel2.Caption:='Режим просмотра';
end;

Для кнопки «Параметры и разрешение камеры» событие OnClick пишем:

procedure TForm1.Button3Click(Sender: TObject);
//Вызов страницы свойств Web-камеры
var
  StreamConfig: IAMStreamConfig;
  PropertyPages: ISpecifyPropertyPages;
  Pages: CAUUID;
begin
//если запись уже идет - выходим
If RecMode then Exit;
  // Если отсутствует интерфейс работы с видео, то завершаем работу
  if FVideoCaptureFilter = NIL then EXIT;
  // Останавливаем работу графа
  FMediaControl.Stop;
  try
    // Ищем интерфейс управления форматом данных выходного потока
    // Если интерфейс найден, то ...
    if SUCCEEDED(FCaptureGraphBuilder.FindInterface(@PIN_CATEGORY_CAPTURE,
      @MEDIATYPE_Video, FVideoCaptureFilter, IID_IAMStreamConfig, StreamConfig)) then
    begin
      // ... пытаемся найти интерфейс управления страницами свойств ...
      // ... и, если он найден, то ...
      if SUCCEEDED(StreamConfig.QueryInterface(ISpecifyPropertyPages, PropertyPages)) then
      begin
        // ... получаем массив страниц свойств
        PropertyPages.GetPages(Pages);
        PropertyPages := NIL;

        // Отображаем страницу свойств в виде модального диалога
        OleCreatePropertyFrame(
           Handle,
           0,
           0,
           PWideChar(ListBox1.Items.Strings[listbox1.ItemIndex]),
           1,
           @StreamConfig,
           Pages.cElems,
           Pages.pElems,
           0,
           0,
           NIL
        );

        // Освобождаем память
        StreamConfig := NIL;
        CoTaskMemFree(Pages.pElems);
      end;
    end;

  finally
    // Восстанавливаем работу графа
    FMediaControl.Run;
  end;
end;

Для кнопки «Свойства видео» событие OnClick пишем:

//Вызов страницы свойств устройства работы с видео
procedure TForm1.Button4Click(Sender: TObject);
begin
If RecMode then Exit;
DisplayPropertyFrame(FVideoCaptureFilter, Handle);
end;

Для кнопки « Свойства звука» событие OnClick пишем:

//Вызов страницы свойств устройства работы со звуком
procedure TForm1.Button5Click(Sender: TObject);
begin
If RecMode then Exit;
DisplayPropertyFrame(FAudioCaptureFilter, Handle);
end;

Для ListBox1 событие OnDblClick пишем:

//Выбор устройств из ListBox1
procedure TForm1.ListBox1DblClick(Sender: TObject);
begin
if ListBox1.Count=0 then
    Begin
       ShowMessage('Камера не найдена');
       Exit;
    End;
//перестраиваем  граф при смене камеры
if FAILED(CreateGraph) then
    Begin
      ShowMessage('Внимание! Произошла ошибка при построении графа фильтров');
      Exit;
    End;
Panel2.Caption:='Режим просмотра';
end;

Для ListBox2 событие OnDblClick пишем:

//Выбор устройств из ListBox2
procedure TForm1.ListBox2DblClick(Sender: TObject);
begin
if ListBox1.Count>0 then
    begin
    //перестраиваем граф при смене устройства захвата звука
      if FAILED(CreateGraph) then
            Begin
              ShowMessage('Внимание! Произошла ошибка при построении графа фильтров');
              Exit;
            End;
Panel2.Caption:='Режим просмотра';
     end else
            Begin
               ShowMessage('Камера не выбрана');
               Exit;
            End;
end;

Сохраняем и тестируем проект:

Захват видео с Web камеры в Delphi.

       Весь код приведен с подробными комментариями, думаю, что разобраться с ним будет не сложно. Если возникнут вопросы, пишите в комментариях.

В статье использованы материалы из книги "Есенин С.А. DirectX и Delphi. Разработка графических и мультимедийных приложений".

На этом урок закончен, скачать исходники к уроку можно здесь.

Автор xaramamburu, сайт автора basicsprog.ucoz.ru.





Категория: Работа с библиотеками BASS и DirectShow | Добавил: xaramamburu (30.10.2011) W
Просмотров: 37405 | Комментарии: 41 | Теги: DirectShow, захват видео, Web камера | Рейтинг: 4.5/6
Всего комментариев: 411 2 »
41 oleksiy20  
0
всем привет. Как такое можно на с++ buildere сделать? пробовал перевести код.. так как не особо знаю делфи и загвоздки возникли особенно в моменте массив с аймоников

40 a-beliaMAIL  
0
Спасибо!

32 AK-74  
0
Уважаемый, xaramamburu , мне очень понравился Ваш проект.1. Не могли бы Высделать ещё урок, где выводится изображение с двух WEB камер на форму?2. Прирастягивании окна Вашей программы видео на панели не увеличивается
пропорционально окну (вообще не реагирует на растягивание формы и панели).                Чтопосоветуете?

33 xaramamburu  
0
 
Цитата
При растягивании окна Вашей программы видео на панели не увеличивается.   Что посоветуете?

Посмотрите урок 2.2 по видеоплееру процедура:

Код
//Процедура изменения размеов окна проигрывания при изменении размеров панели
procedure TForm1.Panel1Resize(Sender: TObject);
begin
  if mode=play then
  begin
  pVideoWindow.SetWindowPosition(0,0,Panel1.ClientRect.Right,Panel1.ClientRect.Bot tom);
end;
end;
или здесь на форуме http://basicsprog.ucoz.ru/forum/6-53-1
 
Цитата
Не могли бы Вы сделать ещё урок, где выводится изображение с двух WEB камер на форму?

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

34 AK-74  
0
Уважаемый Xaramamburu, огромное спасибо за Ваши советы.Попробовал – всё получилось biggrin . Но, если можно, не могли бы Вы ещё подсказать итакую вещь: еcли работают одновременно две камеры, то
запись идёт почему-то только с одной камеры, а мне надо - с двух одновременно (когда
идет запись на одной камере – всё хорошо, как только включаю запись на второй
камере – запись на первой камере отключается автоматически) . Что подскажете?
А пока закину то, что у меня получилось: может кому-то пригодится.  http://webfiles.ru/files/42405543

35 xaramamburu  
0
Разнесите функцию построения графа для каждой камеры отдельно:
function TForm1.CreateGraph:HResult;
function TForm1.CreateGraph2:HResult;
или создайте какую-нибудь универсальную в которую можно будет передавать необходимые параметры для построения графа, но это уже сложнее.
Просто у вас сейчас при включении записи на одной из камер происходит перестроение графа и на другой камере, что автоматом отрубает запись с нее.))))

36 AK-74  
0
И ещё раз спасибо. (Сделал как Вы посоветовали – и опятьвсё получилось))))!) Только вот программа  оказалась с характером… Теперь, она видите ли,пытается меня удивить следующим окном:которое всплывает нерегулярно , но явно неспроста…,  когда надо просмотреть одно из двух видео послеодновременной записи с обоих камер.

37 AK-74  
0
Прошу прощения –
сайт не загрузил скрин окна, содержащего следующий текст:  «Индекс этого файла AVI повреждён илиотсутсвует, поэтому перемотка и переход может не работать. VLS не будет исправлять файл, но может временно
решить проблему, построив индекс в памяти. Для большего файла это может занять
много времини.»

38 xaramamburu  
0
С такой проблемой не сталкивался, но могу предположить, что у вас файл не освободился фильтром. Попробуйте просматривать видео после закрытия программы, чтобы оно освободила файлы в которые вы пишите.)))

39 AK-74  
0
Большое спасибо, попробую. smile

30 xaramamburu  
0
К сожалению, здесь вам помочь я не смогу. Бесплатных фильтров, позволяющих накладывать изображения и текст  на видео я не нашел, ну а платные надо покупать.(((

26 booratino  
0
Урок хороший, спасибо. Проблема с изображением: при запуске - черный квадрат. Нажал на Button3Click, закрыл окно - через 2-3 сек изображение появляется. Если убрать OleCreatePropertyFrame(...) - изображение не появится. Куда копать?

27 xaramamburu  
0
А зачем вы убираете OleCreatePropertyFrame(...)? Судя по всему у вас программа как то криво выбирает параметры фильтра камеры. Попробуйте задать параметры камеры при запуске (смотрите комментарии 15 и 4 к уроку 3.2.). А вообще прежде чем работать с DirectShow в начале поработайте с программой GraphStudio и посмотрите какой граф строится для вашей камеры и какой граф строит ваша программа( это можно посмотреть с помощью кода ниже):
Функция из пакета DsPack, которая позволяет сохранять граф в файл, а потом можно смотреть через GraphStudio. Очень удобная вещь.

const
wszStreamName: WideString = 'ActiveMovieGraph';
IID_IPersistStream : TGUID = '{00000109-0000-0000-C000-000000000046}';
function SaveGraphFile(pGraph: IGraphBuilder; wszPath: WideString): HRESULT;
var
Storage: IStorage;
Stream: IStream;
Persist: IPersistStream;
begin
Result := StgCreateDocfile(
PWideChar(wszPath),
STGM_CREATE or STGM_TRANSACTED or STGM_READWRITE or STGM_SHARE_EXCLUSIVE,
0, Storage);
if FAILED(Result) then Exit;
Result := Storage.CreateStream(
PWideChar(wszStreamName),
STGM_WRITE or STGM_CREATE or STGM_SHARE_EXCLUSIVE,
0, 0, Stream);
if FAILED(Result) then Exit;
pGraph.QueryInterface(IID_IPersistStream, Persist);
Result := Persist.Save(Stream, True);
Stream := nil;
Persist := nil;
if SUCCEEDED(Result) then Result := Storage.Commit(STGC_DEFAULT);
Storage := nil;
end;

Вроде выдрал все. Если что то она в модуле
DsUtil(Dsutils) пакта DsPack закидывайте его в папку с проектом и файл Jedi.inc из
пакета Dspack и подключите в Uses.

Вызываю так:
SaveGraphFile(FGraphBuilder,'d:\1.GRF');

Первый параметр сам граф,  второй  путь и имя файла для сохранения.
Ну а дальше нужно думать в зависимости от вида графа.)))

28 booratino  
0
>> А зачем вы убираете OleCreatePropertyFrame(...)?

чтобы понять какой кусок кода включает изображение.

За процедуру сохранения графа - отдельное спасибо. :)) ..... хоть что-то вообще стало видно в GraphStudio. Теперь бы еще узнать как делать "и посмотрите какой граф строится для вашей камеры", тогда еще понятнее стало бы. smile

Ваш урок 3.2 я тоже внимательно смотрел, и частично повторил. В  нем есть grabber, который встраивается Lav Video Decoder и Video Renderer. 

Коренное отличие в следующем: в уроке 3.1 4й пареметр = nil

FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, FVideoCaptureFilter, NIL, NIL);

в уроке 3.2 4й параметер = FBaseFilter

FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, nil, FVideoCaptureFilter ,FBaseFilter  ,nil);

Как только заменяю FBaseFilter на nil - получаю Малевича.

>> Попробуйте задать параметры камеры при запуске (смотрите комментарии 15 и 4 к уроку 3.2.).

Да, пробовал. Это отдельный вопрос будет, я его сейчас задам в другой ветке с Вашего позволения. smile

29 xaramamburu  
0

Цитата
->Теперь бы еще узнать как делать "и посмотрите какой граф строится для вашей камеры", тогда еще понятнее стало бы.

Работать в GraphStudio достаточно просто, правда у меня версия v0.3.2.0 beta, но меня все устраивает. выбираете в меню Graph->Insert Filter-> категория Video Capture Source->там выбираете вашу камеру. Далее в меню Graph->Insert Video Renderer->Video Mixing Renderer9 и соединяете выход вашей камеры с ренедерером. Программа добавит все промежуточные фильтры сама, если они нужны.

Цитата
-> Коренное отличие в следующем: в уроке 3.1 4й пареметр = nil

FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, FVideoCaptureFilter, NIL, NIL);

Это команда интеллектуального построения графа. Три последних параметра - это фильтры:
Первый - это фильтр источника (откуда будет строиться граф), в данном случае это наша камера;
Второй - это промежуточный фильтр (например фильтр для компрессии или декомпрессии видео, грабинга видео);
Третий - это конечный фильтр, как правило это какой то Renderer.
Если в качестве параметров стоит NIL, это значит, что граф должен подобрать нужные фильтры сам. Это делается по следующему алгоритму:
В начале поиск фильтров происходит из списка, который вы создаете сами с помощью команды FGraphBuilder.AddFilter(...), если найденных фильтров достаточно для построения графа, то он его строит, если нет, то он начинает искать фильтры установленные в системе. К сожалению это не всегда корректно работает.
Судя потому, что у вас квадрат "Малевича", это как раз ваш случай. Вам необходимо добавить в Graph фильтр VideoMixingRenderer, а затем указать его в качестве последнего параметра в место NIL.

Код
var
FVideoRender : IBaseFilter = nil; //интерфейс фильтра вывода видео
------------------------
------------------------

//создаем объект для фильтра вывода видео FVideoRende
CoCreateInstance(CLSID_VideoMixingRenderer, nil, CLSCTX_INPROC, IID_IBaseFilter, FVideoRender);
//добавляем его в граф
FGraphBuilder.AddFilter(FVideoRender, 'Video Renderer');   

-----------------------
-----------------------
FCaptureGraphBuilder.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, FVideoCaptureFilter, NIL, FVideoRender);

Да, если будете задавать вопросы, то создайте тему на форуме, а то здесь это не совсем удобно.)))

25 Palvitkab  
0
Пробовал запускать прогу и экзишник, и из под Дельфи. После нажатия на "параметры и разрешение камеры" в окне появляется динамическая картинка от камеры, она некоторое время (несколько секунд) работает нормально, а потом то ли зависает, то ли тормоза жуткие начинаются. После повторного нажатия на эту кнопку всё повторяется заново, сначало нормально, потом тормоза. Винда ХР SP3.

20 xaramamburu  
0
Дрова от камеры родные стоят? Попробуйте через программу GraphStudio построить граф и поменять в свойствах фильтра захвата видео разрешения камеры, будет ли работать?

21 spurt  
0
Камер пробовал 5 разных. В программе AVS VideoRecoder нормально всё меняется. Так что дело не в драйверах. Но пишет в цветовом формате YUV. А в DirectX 9 такого формат вообще нет. Камеры все довольно новые FullHD. Может DirectX устарел? Хотя не работают и уменьшенные разрешения. Может надо граф не останавливать,а перестраивать?

22 xaramamburu  
0
Так сложно, что то сказать, у меня все камеры простенькие и поддерживают только формат rgb24. Скачайте программу GraphStudio, она позволяет посмотреть визуально какой строится граф фильтров и какие directshow фильтры используются. Попробуйте в ней построить граф и посмотреть в свойствах фильтров будут ли меняться разрешение. Если все будет работать, то тогда можно программно пытаться  построить аналогичный граф. Просто в данной версии программы на сайте используется так называемый интеллектуальный режим построения графа, возможно он просто не может подобрать какой то фильтр и его необходимо добавить в граф руками, но для этого нужно знать вообще какие фильтры используются для работы с вашей камерой.)))

23 spurt  
0
К сожалению моих познаний в DirectX не хватает, чтобы построить граф в ручном режиме. Если несложно, выложите пример настроек в ручном режиме для какой-нибудь современной камеры. Например, для самой распространённой Logitech C270. Это выведет статью на существенно более высокий уровень, так как большинству приведённого в Вашей статье функционала вполне достаточно. Единственный минус VGA разрешение, которое уже безнадёжно устарело.

24 xaramamburu  
0
Что бы построить граф в ручном режиме (т.е. добавляя нужные фильтры, а затем через поиск нужных пинов на этих фильтрах их соединить) нужно знать как вообще для данной камеры этот граф выглядит, а для этого нужно иметь эту камеру, а у меня ее нет. А чтобы создать некую универсальную программу, которая бы захватывала видеопоток с любой камеры нужно иметь несколько наиболее популярных камер и использовать несколько вариантов построения графа фильтров, начиная с интеллектуального (когда все фильтры добавляются автоматом), затем полу интеллектуального (когда ключевые фильтры добавляются руками, а промежуточные добавляются автоматом) и ручного построения графа. 
Да и по поводу вашей проблемы посмотрите комментарии в уроке 3.2 там у MikeBol и BLACK_CRAFTER666 была такая же проблема, BLACK_CRAFTER666 пытался ее решить, можете попробовать ему написать, он вроде как не плохо разобрался с DirectShow.)))

18 xaramamburu  
0
В строчке :
//Создаем файл для записи данных из графа
Result:=FCaptureGraphBuilder.SetOutputFileName(MEDIASUBTYPE_Avi, PWideChar(FileName), FMux, FSink);
замените MEDIASUBTYPE_Avi на MEDIASUBTYPE_Asf
А вот этот кусок кода:
// При захвате видео со звуком устанавливаем звуковой поток в
// качестве основного для синхронизации с другими потоками в файле
                pConfigMux := NIL;
                Result:=FMux.QueryInterface(IID_IConfigAviMux, pConfigMux);
                if FAILED(Result) then EXIT;
                begin
                  pConfigMux.SetMasterStream(1);
                  pConfigMux := NIL;
                end;
удалите. Должно работать.)))

19 S_Gur  
0
Большое спасибо. Заработало. MediaSubType я сразу менял, а вот звуковой поток проглядел...

16 speedy_racer  
0
ситуация такова: для начала, когда подключил скачанные файлы directshow9 и попробовал запустить проект, он мне начал выдавать ошибки типа ожидалось что-то, а найдено inline; . я закомментировал все инлайны и проект запустился. все сделал, как написано. при запуске индикатор камеры запускается, но в окне отображения ничего нет, просто черный прямоугольник. скачал исходники и тот же результат. камера рабочая. что может быть?

17 xaramamburu  
0
Так сложно, что то сказать, я с таким не встречался. У меня две камеры, одна на ноуте,а другая внешняя вроде проблем никаких не было, да и судя по комментариям никто с такой штукой не сталкивался. Попробуйте скачать программу GraphStudio и с ее помощью построить граф, посмотреть во первых будет ли работать, а во вторых какие фильтры она поставит, и если все будет работать, то далее строите аналогичный граф в Delphi.))))

31 AK-74  
0
Уважаемый, speedy_racer , доброго Вам времени суток. Я решил Вашу проблему с inline . Как я понимаю - проект написан на болееновой версии Delphi , чем у Вас.  Вамнадо скачать  следующую версию: DelphiXE3 . После обновления Delphi – просто запустите проект. Тогда  inline убирать (комментировать) не надо.

14 Ayriel  
0
А как можно исправить рассинхронизацию видео и аудио в полученной записи?

15 xaramamburu  
0
Почему это происходит можно почитать  здесь (как исправить это в программе не знаю, пока не пробовал), а исправить готовое видео можно с помощью сторонних программ, например VirtualDub.)))

1-10 11-15
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск
Наш опрос
Оцените мой сайт
Всего ответов: 585
Уголок общения



Copyright MyCorp © 2024Конструктор сайтов - uCoz