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



Модуль VFW - часть 2


Поверхность FDDSImage, на которой будет воспроизводиться видео, создается с размерами, равными размерам кадра видео:

ZeroMemory (@ddsd, SizeOf(ddsd));
with ddsd do begin
dwSize := SizeOf(ddsd);
dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH;
ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN;
dwWidth := AviWidth;
dwHeight := AVIHeight;
end;
hRet := FDD.CreateSurface(ddsd, FDDSImage, nil);
if Failed(hRet) then ErrorOut(hRet, 'Create Second Surface');

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

После инициализации DirectDraw подготавливаемся к работе с потоковым видео:

procedure TfrmDD.FirstFrame;
var
wrkDC : HDC;
begin
AVIFilelnit; // Инициализация библиотеки
// Открываем AVI-файл для чтения
AVIStreamOpenFromFile(AviStream, AviName, streamtypeVIDEO,
0, OF_READ, nil);
// Загружаем поток
Frame := AVIStreamGetFrameOpen(AviStream, nil);
// Получаем первый кадр видео
pbmi := AVIStreamGetFrame(Frame, CurrFrame);
// Получаем указатель на картинку кадра
bits := Pointer(Integer(pbmi) + SizeOf(TBITMAPINFOHEADER));
// Получаем контекст для воспроизведения кадра на поверхность
if FDDSImage.GetDC (wrkDC) = DD_OK then begin
// Воспроизводим кадр во вспомогательный растр
TmpBmp.Handle := CreateDIBitmap(
// Вспомогательным контекстом служит HDC поверхности
wrkDC,
pbmi^, // Адрес размера растра и формата данных
CBM_INIT, // Флаг инициализации
bits, // Данные для инициализации
PBITMAPINFO(pbmi)^, // Данные о формате цвета
DIB RGB_COLORS); // Флаг цветности растра
// Переносим картинку из вспомогательного растра на поверхность
BitBlt (wrkDC, О, О, AVIWidth, AVIHeight,
TinpBmp. Canvas .Handle, 0, 0, SRCCOPY);
FDDSImage.ReleaseDC (wrkDC);
end;
AVIClock := GetTickCount; // Инициализация вспомогательного таймера
end;

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

procedure ТfrmDD,NextFrame;
var
wrkDC : HDC;
begin
// Настало время воспроизвести следующий кадр AVI
if GetTickCount - AVIClock > AVIDelay then begin
pbmi := AVIStreamGetFrame(Frame, CurrFrame);
if FDDSImage.GetDC (wrkDC) = DD_OK then begin
TmpBmp.Handle := CreateDIBitmap(wrkDC, pbmi^, CBM_INIT,
bits, PBITMAPINFO(pbmi) Л, DIB_RGB__COLORS) ;
BitBlt (wrkDC, 0, 0, AVIWidth, AVIHeight,
TmpBmp.Canvas.Handle, 0, 0, SRCCOPY);
FDDSImage.ReleaseDC (wrkDC);
end;
// Увеличиваем счетчик кадров
CurrFrame := (CurrFrame + 1) mod AVILength;
AVIClock := GetTickCount;
end;
end;

В этом примере AVI-файл воспроизводится бесконечно, вслед за последним кадром все повторяется с начала.
Кадр воспроизведен на поверхности FDDSimage, блиттинг которой осуществляется тривиальным способом.
По завершении работы добавились ожидаемые действия:

AVIStreamRelease(AviStream); // Закрытие потока
AVIFileExit; // Завершение работы с библиотекой
TmpBmp.Free; // Удаление вспомогательного растра

Итак, теперь вы способны делать видео частью ваших игр, но я должен предупредить, что библиотека может корректно работать не с каждым типом сжатия. По этой причине я рекомендую заставки игр воспроизводить стандартным для Delphi способом.




Содержание  Назад  Вперед