Стэн Трухильо - Графика для Windows средствами DirectDraw
- Название:Графика для Windows средствами DirectDraw
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стэн Трухильо - Графика для Windows средствами DirectDraw краткое содержание
Графика для Windows средствами DirectDraw - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Перейдем к функции, которая непосредственно открывает AVI-файл. Функция LoadAvi()приведена в листинге 8.3.
Листинг 8.3. Функция LoadAvi()
BOOL AviPlayWin::LoadAvi() {
long r;
CWaitCursor cur;
if (avistream) AVIStreamRelease(avistream), avistream=0;
r=AVIStreamOpenFromFile(&avistream, filename, streamtypeVIDEO, 0, OF_READ | OF_SHARE_EXCLUSIVE, 0);
TRACE("AVIStreamOpenFromFile: %s\n", r==0 ? "OK" : "failed");
r=AVIStreamFormatSize(avistream, 0, &fmtlen);
TRACE("AVIStreamFormatSize: %s\n", r==0 ? "OK" : "failed");
int formatsize=fmtlen+sizeof(RGBQUAD)*256;
if (srcfmt) delete [] srcfmt;
srcfmt = (LPBITMAPINFOHEADER)new BYTE[formatsize];
ZeroMemory(srcfmt, formatsize);
if (dstfmt) delete [] dstfmt;
dstfmt = (LPBITMAPINFOHEADER)new BYTE[formatsize];
ZeroMemory(dstfmt, formatsize);
r=AVIStreamReadFormat(avistream, 0, srcfmt, &fmtlen);
TRACE("AVIStreamReadFormat: %s\n", r==0 ? "OK" : "failed");
TRACE(" --- %s ---\n", filename);
TRACE(" biSize: %d\n", srcfmt->biSize);
TRACE(" biWidth x biHeight: %dx%d\n", srcfmt->biWidth, srcfmt->biHeight);
if (srcfmt->biPlanes != 1) TRACE(" - biPlanes: %d\n", srcfmt->biPlanes);
TRACE(" biBitCount: %d\n", srcfmt->biBitCount);
CString comp;
switch (srcfmt->biCompression) {
case BI_RGB:
comp="BI_RGB";
break;
case BI_RLE8:
comp="BI_RLE8";
break;
case BI_RLE4:
comp="BI_RLE4";
break;
case BI_BITFIELDS:
comp="BI_BITFIELDS";
break;
}
TRACE(" biCompression: %s\n", comp);
TRACE(" biSizeImage: %d\n", srcfmt->biSizeImage);
TRACE(" ------------------\n");
memcpy(dstfmt, srcfmt, fmtlen);
dstfmt->biBitCount = 8;
dtfmt->biCompression = BI_RGB;
dstfmt->biSizeImage = dstfmt->biWidth * dstfmt->biHeight;
startframe = AVIStreamStart(avistream);
TRACE("stream start: %d\n", startframe);
endframe = AVIStreamEnd(avistream);
TRACE("stream end: %d\n", endframe);
r=AVIStreamInfo(avistream, &streaminfo, sizeof(streaminfo));
TRACE("AVIStreamInfo: %s\n", r==0 ? "OK" : "failed" );
buflen = dstfmt->biSizeImage;
int finalbuflen=((dstfmt->biWidth+3) & ~3) * dstfmt->biHeight;
if (streaminfo.dwSuggestedBufferSize) if ((LONG)streaminfo.dwSuggestedBufferSize < buflen) {
TRACE("adjusting buflen to suggested size\n");
buflen = (LONG)streaminfo.dwSuggestedBufferSize;
}
if (decomp) ICClose(decomp);
decomp = ICDecompressOpen(ICTYPE_VIDEO, streaminfo.fccHandler, srcfmt, dstfmt);
TRACE("ICDecompressOpen: %s\n", decomp ? "OK" : "failed");
if (rawdata) {
TRACE("delete [] rawdata...\n");
delete [] rawdata;
}
rawdata = new BYTE[buflen];
if (finaldata) {
TRACE("delete [] finaldata...\n");
delete [] finaldata;
}
finaldata = new BYTE[finalbuflen];
return TRUE;
}
В функции LoadAvi()используются функции VFW. Сначала LoadAvi()закрывает открытый ранее AVI-поток функцией AVIStreamRelease(), а затем открывает новый поток функцией AVIStreamOpenFromFile(), которой в числе прочих аргументов передается имя открываемого AVI-файла.
Обратите внимание — третьим аргументом функции AVIStreamOpenFromFile()является флаг, определяющий тип открываемого потока. В нашем случае использован флаг видеопотока streamtypeVIDEO, но с помощью трех оставшихся флагов ( streamtypeAUDIO, streamtypeMIDIи streamtypeTEXT) можно открывать и потоки других типов.
Затем мы получаем данные о формате потока функцией AVIStreamReadFormat()(пользуясь при этом функцией AVIStreamFormatSize()). Я специально оставил в этом фрагменте отладочные макросы TRACE(), чтобы продемонстрировать, какую информацию можно получить об AVI-файле.
На этой стадии инициализируются некоторые важные переменные класса. Например, мы присваиваем значения переменным startframeи endframe, чтобы во время извлечения кадров были известны допустимые значения их индексов.
Затем мы получаем доступ к декомпрессору. Функция ICDecompressorOpen()по структуре, описывающей AVI-файл и желательный формат вывода, возвращает логический номер модуля декомпрессии. Позднее этот модуль используется для восстановления кадров. Наконец, мы выделяем память под два буфера: в одном хранятся необработанные (сжатые) данные, извлеченные из AVI-потока, а в другом — итоговый (восстановленный) кадр.
Теперь у нашего приложения есть открытый AVI-поток и информация в объеме, достаточном для извлечения кадров. Но что же делать с кадром после того, как он будет прочитан и восстановлен? Нам понадобится поверхность для хранения полученных данных, и тогда воспроизведение видеоролика сведется к простому блиттингу содержимого этой поверхности во вторичный буфер приложения с последующим переключением страниц. Эта промежуточная поверхность создается функцией CreateAviSurface():
BOOL AviPlayWin::CreateAviSurface() {
if (avisurf) avisurf->Release(), avisurf=0;
avisurf=CreateSurface(srcfmt->biWidth, srcfmt->biHeight);
CRect displayrect=GetDisplayRect();
x=(displayrect.Width()-srcfmt->biWidth)/2;
y=0;
return TRUE;
}
После освобождения поверхности, созданной ранее, функция CreateAviSurface()с помощью функции CreateSurface()интерфейса DirectDrawсоздает поверхность, размеры которой совпадают с размерами кадра. Кроме того, функция CreateAviSurface()инициализирует переменные xи y, определяющие положение поверхности AVI на вторичном буфере. В нашем случае кадры будут выравниваться по центру экрана, поэтому в вычислениях применяется функция DirectDrawWin::GetDisplayRect()для определения размеров экрана.
С помощью файлового формата AVI и VFW API можно получить палитру, оптимально подходящую для просмотра видеоролика. Функция InstallPalette()извлекает необходимые данные и использует их для конструирования палитры DirectDraw. Функция InstallPalette()выглядит так:
BOOL AviPlayWin::InstallPalette() {
ICDecompressGetPalette(decomp, srcfmt, dstfmt);
PALETTEENTRY pe[256];
LPBITMAPINFO info=(LPBITMAPINFO)dstfmt;
for (int i=0; i<256; i++) {
pe[i].peRed = info->bmiColors[i].rgbRed;
pe[i].peGreen = info->bmiColors[i].rgbGreen;
pe[i].peBlue = info->bmiColors[i].rgbBlue;
pe[i].peFlags = 0;
}
if (avipal) avipal->Release();
ddraw2->CreatePalette(DDPCAPS_8BIT, pe, &avipal, 0);
primsurf->SetPalette(avipal);
return TRUE;
}
Функция ICDecompressGetPalette()получает данные палитры и в цикле преобразует их в формат, который мы можем использовать. Полученный массив передается при вызове функции CreatePalette()интерфейса DirectDraw. Остается лишь присоединить созданную палитру к первичной поверхности.
Наконец, все готово к отображению кадров видеоролика. Для этого мы подготавливаем и выводим очередной кадр при каждом вызове функции DrawScene()классом DirectDrawWin. Функция DrawScene()выглядит так:
void AviPlayWin::DrawScene() {
long r;
r=AVIStreamRead(avistream, curframe, 1, rawdata, buflen, 0, 0);
if (r) {
TRACE("AVIStreamRead failed: ");
switch (r) {
case AVIERR_BUFFERTOOSMALL:
TRACE("BUFFERTOOSMALL\n");
break;
case AVIERR_MEMORY:
TRACE("MEMORY\n");
break;
case AVIERR_FILEREAD:
TRACE("FILEREAD\n");
Интервал:
Закладка: