меньше 640x480, он изменяется. Это сделано для того, чтобы диалоговое окно не выводилось в режиме Mode X. Поскольку этот режим не поддерживается Windows, такая попытка, скорее всего, закончится неудачей из-за нелинейной организации пикселей в режимах Mode X.

Возможно, у вас возник вопрос — а почему может действовать режим Mode X? Вспомните, что эта функция вызывается при каждом нажатии клавиши Escape, пробела или правой кнопки мыши во время воспроизведения видеоролика. Нельзя исключать того, что видеорежим Mode X был установлен для воспроизведения ролика, поэтому перед выводом диалогового окна необходимо проверить эту возможность.

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

После установки системной палитры мы вызываем функцию DirectDraw FlipToGDISurface(). Это гарантирует, что диалоговое окно Windows будет отображаться на видимой поверхности, а не во вторичном буфере. Кроме того, мы снова включаем курсор мыши (иначе пользователь не сможет нажимать кнопки диалогового окна и выбрать AVI-файл).

Если экземпляр класса AviDialog не был создан при предыдущем вызове функции ShowDialog(), мы создаем его. Обратите внимание на то, что при создании диалогового окна ему передается массив 8-битных видеорежимов, подготовленный в функции SelectInitialDisplayMode().

Затем мы закрываем существующий AVI-поток. Это делается из-за того, что класс AviDialog обладает собственными средствами для работы с файлами, с помощью которых он выводит размеры и количество кадров в выбранном AVI-файле. Если не закрыть ранее открытый файл, то при его повторном выборе диалоговое окно уже не сможет получить эту информацию.

Функция DoModal() отображает диалоговое окно, в котором пользователь может выбрать нужный файл. При нажатии кнопки Cancel мы посылаем сообщение WM_CLOSE. Если все идет нормально, мы получаем имя выбранного файла (в трех различных формах) вместе с индексом видеорежима (видеорежим необходимо выбрать до нажатия кнопки Play). Размеры выбранного видеорежима, взятые из массива displaymode, передаются функции SetDisplayMode().

Дальше следует вызов функции LoadAvi(). Как вы вскоре убедитесь, функция LoadAvi() на самом деле не загружает видеоролик — она лишь открывает файл и извлекает сведения о ролике (например, количество кадров и их размеры). Функция CreateAviSurface () по полученным размерам создает поверхность для хранения одного кадра видеопотока.

Функция InstallPalette() извлекает данные палитры из AVI-файла и строит по ним палитру DirectDraw, которая лучше всего подходит для просмотра. Наконец, переменной curframe, предназначенной для перебора кадров, присваивается значение переменной startframe.

Функция LoadAvi() 

Перейдем к функции, которая непосредственно открывает 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 ', r==0 ? 'OK' : 'failed');

 r=AVIStreamFormatSize(avistream, 0, &fmtlen);

 TRACE('AVIStreamFormatSize: %s ', 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 ', r==0 ? 'OK' : 'failed');

 TRACE(' --- %s --- ', filename);

 TRACE(' biSize: %d ', srcfmt->biSize);

 TRACE(' biWidth x biHeight: %dx%d ', srcfmt->biWidth, srcfmt->biHeight);

 if (srcfmt->biPlanes != 1) TRACE(' - biPlanes: %d ', srcfmt->biPlanes);

 TRACE(' biBitCount: %d ', 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 ', comp);

 TRACE(' biSizeImage: %d ', srcfmt->biSizeImage);

 TRACE(' ------------------ ');

 memcpy(dstfmt, srcfmt, fmtlen);

 dstfmt->biBitCount = 8;

 dtfmt->biCompression = BI_RGB;

 dstfmt->biSizeImage = dstfmt->biWidth * dstfmt->biHeight;

 startframe = AVIStreamStart(avistream);

 TRACE('stream start: %d ', startframe);

 endframe = AVIStreamEnd(avistream);

 TRACE('stream end: %d ', endframe);

 r=AVIStreamInfo(avistream, &streaminfo, sizeof(streaminfo));

 TRACE('AVIStreamInfo: %s ', 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 ');

  buflen = (LONG)streaminfo.dwSuggestedBufferSize;

 }

 if (decomp) ICClose(decomp);

 decomp = ICDecompressOpen(ICTYPE_VIDEO, streaminfo.fccHandler, srcfmt, dstfmt);

 TRACE('ICDecompressOpen: %s ', decomp ? 'OK' : 'failed');

 if (rawdata) {

  TRACE('delete [] rawdata... ');

  delete [] rawdata;

 }

 rawdata = new BYTE[buflen];

 if (finaldata) {

  TRACE('delete [] finaldata... ');

  delete [] finaldata;

 }

 finaldata = new BYTE[finalbuflen];

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату