Функция 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\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-потока, а в другом — итоговый (восстановленный) кадр.