DirectX Графика в проектах Delphi


Модуль DirectShow



Поскольку изложенный в предыдущем разделе способ годится не для каждого видео, нам придется бегло рассмотреть еще один способ воспроизведения видео, основанный на использовании модуля DirectShow. Эта библиотека также входит в состав DirectX, включает набор функций для работы с мультимедиа. Подробно рассматривать ее не будем, познакомимся с ее использованием на конкретном примере, проекте каталога Ех02, воспроизводящем AVI-файл на поверхности (рис. 6.2).

Модуль DirectShow

Рис. 6.2. Работа примера на тему использования модуля DirectShow

Файл видео для этого примера также взят мною из пакета DirectX SDK.
При воспроизведении файла с помощью модуля VFW картинка получается искаженной, поэтому и приходится прибегать к иному способу. Отказаться от первого способа мы также не можем, поскольку DirectShow тоже годится не для любого файла. Другая причина, по которой мы не можем усердствовать в изучении упомянутого модуля, состоит в том, что он может применяться лишь с интерфейсами ранних версий.
Модуль использует СОМ-модель, поэтому здесь мы встретим знакомые понятия главного объекта и дочерних интерфейсов:

var
AMStream : lAMMultiMediaStream; // Главный объект
PrimaryVidStream : IMediaStream; // Дочерний поток, связан с видео
Sample : IDirectDrawStreamSample; // Интерфейс для вывода на поверхность

В процедуру инициализации потока передается имя требуемого файла:

procedure TfrmDD.PlayMedia(const FileName: WideString);
var
hRet : HRESULT;
begin
// Создание главного объекта ('filter graph1)
AMStream:=IAMMultiMediaStream(CreateComObject
(CLSID_AMMultiMediaStream));
// Инициализация потока для чтения
hRet := AMStream.Initialize(STREAMTYPE_READ, 0, nil);
if Failed (hRet) then ErrorOut (hRet, 'Stream Initialize');
// Добавление потока видео к главному объекту
hRet := AMStream.AddMediaStream(FDD, MSPID_PrimaryVideo,
0, IMediaStream(ni!A));
if Failed (hRet) then ErrorOut (hRet, 'Add Video Stream');
// Открытие файла
hRet := AMStream.OpenFile(PWideChar(FileName) , 0);
if Failed (hRet) then ErrorOut (hRet, 'Open AVI File');
// Следующие действия предназначены для связывания потока и поверхности
// Получение дочернего потока
hRet := (AMStream as IMultiMediaStream).
GetMediaStream(MSPID_PrimaryVideo, PrimaryVidStream);
if Failed (hRet) then ErrorOut (hRet, 'GetMediaStream');
// Преобразование интерфейса в тип Isample
//и связывание его с поверхностью
hRet := (PrimaryVidStream as IDirectDrawMediaStream).
CreateSample (FDDS Image, TRect(nil/4), 0, Sample);
if Failed (hRet) then ErrorOut (hRet, 'CreateSample');
// Запуск потока
hRet := (AMStream as IMultiMediaStream).SetState(STREAMSTATE_RUN);
if Failed (hRet) then ErrorOut (hRet, 'SetState');
end;

Обработку возможных ошибок я оставил прежней, но коды ошибок не будут расшифровываться. Модуль DirectDraw не содержит, конечно, пояснения по этим ошибкам.
Перед блиттингом поверхности FDDS image обновляем позицию в видео:

if Sample.Update(0, 0, nil, 0) <> S_OK
then (AMStream as IMultiMediaStream).Seek (0);

Неудача свидетельствует о том, что видео прокручено до конца, в этом случае мы заново запускаем его.
Самостоятельно разберитесь, каким образом останавливается ролик при деактивизации окна приложения, и как заново запускается поток при восстановлении.



Содержание раздела