Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
HACK F.A.Q 65535
Гостевая книга ... 65535
Содержание сайт... 65535
Вызов хранимых ... 65535
Эмулятор микроп... 65535
Бип из системно... 60764
Invision Power ... 58649
Организация зап... 58615
Модуль Forms 57076
Приложение «Про... 56862
Оператор выбора... 56299
Создание отчето... 56025
Подключение Mic... 55891
ТЕХНОЛОГИИ ДОСТ... 52226
Программируемая... 49543
Пример работы с... 48069
Имитационное мо... 47770
21 ошибка прогр... 42736
Реклама
Сейчас на сайте
Гостей: 6
На сайте нет зарегистрированных пользователей

Пользователей: 13,022
новичок: igra87
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Моделирование процесса передачи данных по магистрали с основным и резерв...
База данных электронного документооборота на Delphi + бд Intebase
Сравнение двух бинарных деревьев на Turbo Pascal + отчет

Реклама

Direct Show и Delphi
На этот раз речь пойдет о DirectShow. Для чего нам может понадобиться DirectShow?
DirectShow - это архитектура для воспроизведения, перехвата и обработки потоков мультимедиа. Звучит туманно? Поясняю - c помощью этого API можно:

• проигрывать мультимедийные файлы различного формата, такие как MPEG (Motion Picture Experts Group), AVI (Audio-Video Interleaved), MP3 (MPEG Audio Layer-3), DVD и конечно WAV;
• перехватывать видео-поток с различного рода TV-карт, видеокамер и т.п.;
• создавать нестандартные обработчики мультимедиа-потоков и свои собственные форматы файлов (что, впрочем, вряд ли понадобится простым смертным);
• обращаться непосредственно к видео и аудио потокам, чтобы выводить их на Surface DirectDraw (что для нас как раз интересно).


Звучит заманчиво. Но для чего это может понадобиться, спросите Вы, вспоминая родной и привычный MediaPlayer. Представьте себе, что Вы запрограммировали трехмерный мир, с анимированными спрайтами, трехмерными объектами и т.п. И в отсвете выстрелов очередной "бродилки-стрелялки", пораженный пользователь нового шедевра, видит видео клип, воспроизводимый прямо на костях очередного пораженного монстра. :-) Каково? Убедил? Тогда продолжим. Кстати, раз уж упомянули DirectDraw - DirectShow интегрирован с DirectX так, что использует DirectDraw и DirectSound для вывода изображения и звука, и, при наличии аппаратного ускорения, автоматически им воспользуется.

Для работы с DirectShow Вам понадобятся:

иметь некоторое представление о технологии COM (Component Object Model) - хотя быть знатоком этой технологии вовсе не обязательно - просто достаточно знать, что для получения COM-интерфейса нужно вызвать QueryInterface;
скачать заголовочные файлы DirectShow API, переведенные на Delphi в рамках проекта JEDI - (http://www.delphi-jedi.org/DelphiGraphics/DirectX/DX5Media.zip) и либо поместить их в каталог Delphi\Lib либо добавить путь к каталогу, в котором они находятся в установках Delphi Library Path. DirectShow скорее всего уже установлен на Вашем компьютере - он входит в стандартную поставку Windows 9x, Windows NT 4 (Service Pack 3 и выше), Windows 2000 (если Вы программируете для UNIX или DOS - то я вообще не понимаю зачем Вы читаете эту статью).

Основы DirectShow

В концепции DirectShow мультимедийные данные - это поток, который проходит через несколько обрабатывающих блоков. Блоки, обрабатывающие поток данных, передают данные по цепочке друг другу, таким образом можно представить себе несколько "устройств", каждое из которых выполняет какую-то обработку данных и передает их соседнему "устройству". Эти "устройства" или "блоки обработки" данных называют фильтрами. Цепочка, по которой передаются данные, содержит несколько фильтров, связанных определенным образом.

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

Для создания такой "цепочки обработки" (которая, кстати, официально называются Filter Graph - "граф фильтров" или, в несколько вольном переводе - "схема соединения фильтров"), так вот для создания схемы соединения фильтров, предназначен самый базовый и лежащий в основе всех основ компонет DirectShow, под названием Filter Graph Manager - Менеджер Графа Фильтров.

Фильтры делятся на три типа:

Фильтры-источники (Source filters) - эти фильтры просто получают данные из какого-то источника, с диска (как фильтр File Source (Async) на рисунке), с CD или DVD дисковода или с TV- карты или карты, к которой подключена цифровая видеокамера.
Фильтры-преобразователи (Transform filters) - эти фильтры как видно из названия преобразуют поток данных, проходящий через них каким-либо образом, например - разделяет поток данных на кадры, производят декомпрессию и т.п. На нашем рисунке к таким фильтрам относятся AVI Splitter и AVI Decompressor.
Фильтры вывода (Renderer filters) - фильтры, которые получают полностью обработанные данные и выводят их на монитор, звуковую карту, пишут на диск или выводят на еще какое-нибудь устройство.
Итак из фильтров-кубиков можно высстраивать граф. Делается это с помощью интерфейса IGraphBuilder. Создать объект типа IGraphBuilder можно так:


CoCreateInstance(CLSID_FilterGraph,nil,CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,MyGraphBuilder);





Здесь переменная MyGraphBuilder имеет тип IGraphBuilder; идентификатор класса CLSID_FilterGraph и IID_IGraphBuilder обьявлены в файле DShow.pas, поэтому не забудьте добавить


uses DShow.pas

Итак, интерфейс IGraphBuilder получен. Можно построить граф фильтров, такой, какой нам нужно. Впрочем, все не так сложно, IGraphBuilder достаточно интеллектуален, он может сам, автоматически, построить граф, в зависимости от того какие файлы мы собираемся воспроизводить. Интерфейс IGraphBuilder имеет метод RenderFile, который получает имя файла в качестве параметра и, в зависимости от типа файла (которое определяется по расширению и по специальным сигнатурам в файле), сканирует реестр, в поисках необходимой для построения графа информации, создает необходимые фильтры и строит граф, предназначенный для воспроизведения файлов этого типа (WAV, AVI, MP3, MPG и т.д.).

После построения графа DirectShow готов к воспроизведению. Для управления потоком данных через граф обработки предназначен интерфейс IMediaControl - он имеет методы Run, Pause и Stop (названия говорят сами за себя)

Давайте попробуем все это на примере:

uses
...DShow, ActiveX, ComObj;

var
MyGraphBuilder: IGraphBuilder;
MyMediaControl: IMediaControl;

begin

CoInitialize(nil);
{получаем интерфейс IGraphBuilder}
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, MyGraphBuilder);

{вызываем RenderFile - граф фильтров строится автоматически}
MyGraphBuilder.RenderFile(cool.avi',nil);

{получаем интерфейс ImediaControl}
MyGraphBuilder.QueryInterface(IID_IMediaControl, MyMediaControl);

{Примечание - MyMediaControl - переменная типа IMediaControl}

{проигрываем видео}
MyMediaControl.Run;

{ждем пока пользователь не нажмет ОК
(видео воспроизводится в отдельном (thread) потоке)}
ShowMessage('Нажмите OК');

CoUninitialize;

end;






Если Вы не поленитесь скопировать этот кусок кода в Delphi и запустить его то заметите, что avi-файл проигрывается в отдельном окошке, которое не принадлежит нашему приложению. Для управления окошком, в котором воспроизводится видео предназначен специальный интерфейс IVideoWindow. Получить этот интерфейс можно из экземпляра IGraphBuilder, вызвав QueryInterface и передав в качестве идентификатора интерфейса константу IID_IvideoWindow.

Интерфейс IVideoWindow содержит методы для управления заголовком, стилем, местоположением и размерами окошка в котором проигрывается видео.

Давайте попробуем переделать наш пример так, чтобы видео выводилось не в отдельном окошке, а, скажем на компоненте TPanel, расположенном в нашей форме. Добавьте на форму компонет TPanel, пусть он называется Panel1.

uses
...DShow, ActiveX, ComObj;

procedure TForm1.Button1Click(Sender: TObject);

var
MyGraphBuilder: IGraphBuilder;
MyMediaControl: IMediaControl;
VideoWindow: IVideoWindow;

begin

CoInitialize(nil);
{получаем интерфейс IGraphBuilder}
CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, MyGraphBuilder);

{вызываем RenderFile - граф фильтров строится автоматически}
MyGraphBuilder.RenderFile('C:\Program Files\Borland\Delphi5\Demos\Coolstuf\cool.avi', nil);

{получаем интерфейс ImediaControl}
MyGraphBuilder.QueryInterface(IID_IMediaControl, MyMediaControl);
{Примечание - MyMediaControl - переменная типа IMediaControl}

{получаем интерфейс IVideoWindow}
MyGraphBuilder.QueryInterface(IID_IVideoWindow, VideoWindow);
{Примечание - VideoWindow - переменная типа IVideoWindow}

{располагаем окошко с видео на панель}
VideoWindow.Set_Owner(Self.Panel1.Handle);
VideoWindow.Set_WindowStyle(WS_CHILD or WS_CLIPSIBLINGS);
VideoWindow.SetWindowPosition(0, 0, Panel1.ClientRect.Right,
Panel1.ClientRect.Bottom);

{проигрываем видео}
MyMediaControl.Run;

ShowMessage('Нажмите OК');

CoUninitialize;
end;






Надеюсь это проще, чем Вы ожидали?

DirectShow и DirectX

Для того, чтобы использовать DirectShow совместно с DirectX нужно разобраться с понятием Multimedia Streaming (потоки мультимедиа).

Multimedia Streaming - это архитектура, используемая в DirectShow для облегчения жизни программиста. Эта архитектура позволяет работать с мультимедиа данными, как с абстрактным потоком, не вдаваясь в подробности форматов хранения мультимедиа-файлов или специфику устройств-источников мультимедиа. Используя эту архитектуру, программист концентрируется не на расшифровке и преобразовании данных, а на управлении потоком данных, кадрами видео или аудио семплами.

На вершине иерархии находится базовый объект Multimedia Stream, который является контейнером для объектов Media Stream. Объект Multimedia Stream может содержать один или несколько объектов Media Stream. В то время как каждый объект типа Media Stream предназначен для работы с данными какого-то одного типа (видео, аудио и т.п.) - Multimedia Stream - просто содержит методы для обращения к содержащимся в нем объектам Media Stream и не зависит от типа данных.

Объект типа Stream Sample, доступ к которому можно получить из Media Stream - позволяет управлять непосредственно элементами мультимедийного потока (для видео каждый Sample - это кадр видеоизображения, для аудио он может содержать несколько семплов звука).

Однако хватит теории. Давайте перейдем к делу. Попробуем создать необходимые объекты, чтобы вывести видео на Surface DirectX. Для этого нам понадобится обращаться к кадрам видео изображения (т.е. к обьекту типа Stream Sample). Значит, придется пройтись по всей цепочке иерархии, чтобы добраться до обьектов StreamSample. Вообще цепочка обьектов, которую предстоит создать выглядит так:

IAMMultiMediaStream
+ IDirectDrawMediaStream
+ IDirectDrawStreamSample




Сравните это с нашим рисунком. Как видите на вершине находится объект типа MultiMediaStream, который будет содержать MediaStream конкретного, нужного нам типа (IDirectDrawMediaStream), а уж с помощью него мы получим доступ к конкретным видео кадрам через интерфейс IDirectDrawStreamSample.

Итак сейчас мы создадим объект типа IAMMultiMediaStream. Этот интерфейс унаследован от IMultimediaStream и содержит, кроме прочего, функцию OpenFile, которая автоматически строит граф фильтров для воспроизведения файла.

CoCreateInstance(CLSID_AMMultiMediaStream, nil, CLSCTX_INPROC_SERVER,
IID_IAMMultiMediaStream, AMStream);





Здесь переменная AMStream имеет тип IAMMultiMediaStream. Мы создали контейнер для мультимедийных потоков. Сверяемся с рисунком - мы на верхнем уровне иерархии. У нас есть объект типа IMultimediaStream - теперь в этот контейнер нужно проинициализировать и добавить один или несколько мультимедиа потоков, нужного нам типа. Сначала инициализация:

AMStream.Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, nil);




При инициализации указываем, что будут создаваться мультимедиа потоки для чтения, передав значение STREAMTYPE_READ (другие варианты STREAMTYPE_WRITE, STREAMTYPE_TRANSFORM).

Создадим теперь мультимедиа потоки для видео и звука:

AMStream.AddMediaStream(DDraw, MSPID_PrimaryVideo, 0, NewMediaStremVideo);
AMStream.AddMediaStream(nil, MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER,
NewMediaStremAudio);





Вызываем метод OpenFile - файл загружается, и автоматически строится граф фильтов:


AMStream.OpenFile('cool.avi', 0);




Осталось направить видео поток мультимедиа поток на Surface. Вот процедура, которая делает это:

procedure TForm1.RenderStreamToSurface(Surface: IDirectDrawSurface;
MMStream: IMultiMediaStream);
var
PrimaryVidStream: IMediaStream;
DDStream: IDirectDrawMediaStream;
Sample: IDirectDrawStreamSample;
RECT: TRect;
ddsd: TDDSURFACEDESC;
Z: DWORD;
begin
MMStream.GetMediaStream(MSPID_PrimaryVideo, PrimaryVidStream);
PrimaryVidStream.QueryInterface(IID_IDirectDrawMediaStream, DDStream);
ddsd.dwSize := sizeof(ddsd);
DDStream.GetFormat(ddsd, Palitra, ddsd, Z);
rect.top := (480 - ddsd.dwHeight) div 2;
rect.left := (640 - ddsd.dwWidth) div 2;
rect.bottom := rect.top + ddsd.dwHeight;
rect.right := rect.left + ddsd.dwWidth;
DDStream.CreateSample(Surface, Rect, 0, Sample);
MMStream.SetState(STREAMSTATE_RUN);
end;






Как видите, в этой процедуре сначала получаем интерфейс типа IDirectDrawMediaStream (соответствующий второму уровню иерархии на нашем рисунке), потом из него получаем объект типа IDirectDrawStreamSample (переменная Sample), который соответствует третьему уровню иерархии нашего рисунка.

Теперь остается вызывать в цикле (в демо-программе это делается по таймеру - здесь для простоты опускаем):

hr := Sample.Update(0, 0, nil, 0);
if hr = $40003 {MS_S_ENDOFSTREAM} then
MMStream.Seek(0);





Метод IDirectDrawStreamSample.Update выводит очередной кадр на Surface. При достижении конца потока он вернет ошибку с кодом $40003 (MS_S_ENDOFSTREAM), я в этом случае просто перематываю поток к началу, методом Seek.
Опубликовал Kest November 29 2008 10:48:58 · 0 Комментариев · 14735 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Самоучитель C++
Allsubmitter 4.7 ...
CoolControls v3.0...
База англоязычных...
ScrollCredit
SUIPack
Шкрыль А. - Разра...
C++ для начинающих
Tenis [Исходник н...
Использование Lis...
Х. М. Дейтел, П. ...
Image Browser [Ис...
Клавиатурный трен...
C++ Builder в за...
PDA версия сайта
Handles
PDJ_Anima
PHP 5. Полное рук...
Delphi 2005 Учимс...
Панель "ссылки"

Топ загрузок
Приложение Клие... 100307
Delphi 7 Enterp... 77962
Converter AMR<-... 20021
Borland C++Buil... 10679
GPSS World Stud... 9277
Borland Delphi ... 7669
Turbo Pascal fo... 6884
Visual Studio 2... 4906
Калькулятор [Ис... 3997
FreeSMS v1.3.1 3486
Случайные статьи
Потоки ввода-вывод...
Еще про алгоритм find
Создание экземпляр...
Область применения
Создание дистрибут...
Страница сгенериро...
Типы модуляции
Проверьте режим пе...
• Когда домен рабо...
ФАНТОМНЫЕ ФАЙЛЫ
систем безопасност...
Invalid register c...
ПОСТРОЕНИЕ ЭКСПЕРТ...
Компоненты системы...
Переменные в FORMS
Ваша программа дол...
Перегрузка операций
Encryption Pack мо...
Убедитесь, что вы ...
ГОЛОВА И ХВОСТ СПИСКА
Группирование и уп...
Краткий обзор пото...
Просмотр списка по...
Canon: настройки д...
Продолжительность ...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?