VideoSource.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:39k
- // VirtualDub - Video processing and capture application
- // Copyright (C) 1998-2001 Avery Lee
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- #include <crtdbg.h>
- #include <stdio.h>
- #include <windows.h>
- #include <vfw.h>
- #include "VideoSource.h"
- //#include "VBitmap.h"
- #include "AVIStripeSystem.h"
- //#include "ProgressDialog.h"
- //#include "MJPEGDecoder.h"
- //#include "crash.h"
- #include "error.h"
- #include "misc.h"
- #include "oshelper.h"
- //#include "helpfile.h"
- #include "resourceVD.h"
- ///////////////////////////
- extern const char *LookupVideoCodec(FOURCC);
- extern HINSTANCE g_hInst;
- extern HWND g_hWnd;
- ///////////////////////////
- const char g_szNoMPEG4Test[]="No MPEG-4 Test";
- static BOOL CALLBACK MP4CodecWarningDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) {
- switch(msg) {
- case WM_INITDIALOG:
- return TRUE;
- case WM_COMMAND:
- switch(LOWORD(wParam)) {
- case IDOK:
- // HelpContext(hdlg, IDH_WARN_MPEG4);
- MessageBox( NULL,"WarningMPEG4", "WarningMPEG4", MB_OK );
- case IDCANCEL:
- if (IsDlgButtonChecked(hdlg, IDC_NOMORE))
- SetConfigDword(NULL, g_szNoMPEG4Test, 1);
- EndDialog(hdlg, 0);
- break;
- }
- break;
- }
- return FALSE;
- }
- static bool CheckMPEG4Codec(HIC hic, bool isV3) {
- char frame[0x380];
- BITMAPINFOHEADER bih;
- DWORD dw;
- if (QueryConfigDword(NULL, g_szNoMPEG4Test, &dw) && dw)
- return true;
- // Form a completely black frame if it's V3.
- bih.biSize = 40;
- bih.biWidth = 320;
- bih.biHeight = 240;
- bih.biPlanes = 1;
- bih.biBitCount = 24;
- bih.biCompression = '24PM';
- bih.biSizeImage = 0;
- bih.biXPelsPerMeter = 0;
- bih.biYPelsPerMeter = 0;
- bih.biClrUsed = 0;
- bih.biClrImportant = 0;
- if (isV3) {
- int i;
- frame[0] = (char)0x3f;
- frame[1] = (char)0x71;
- frame[2] = (char)0x1b;
- frame[3] = (char)0x7c;
- for(i=4; i<0x179; i+=5) {
- frame[i+0] = (char)0x2f;
- frame[i+1] = (char)0x0b;
- frame[i+2] = (char)0xc2;
- frame[i+3] = (char)0xf0;
- frame[i+4] = (char)0xbc;
- }
- frame[0x179] = (char)0xf0;
- frame[0x17a] = (char)0xb8;
- frame[0x17b] = (char)0x01;
- bih.biCompression = '34PM';
- bih.biSizeImage = 0x17c;
- }
- // Attempt to decompress.
- HANDLE h;
- h = ICImageDecompress(hic, 0, (BITMAPINFO *)&bih, frame, NULL);
- // if (!h)
- // DialogBox(g_hInst, MAKEINTRESOURCE(IDD_WARN_MPEG4), g_hWnd, MP4CodecWarningDlgProc);
- // else
- // GlobalFree(h);
- if (h) {
- GlobalFree(h);
- return true;
- } else {
- return false;
- }
- }
- ///////////////////////////
- VideoSource::VideoSource() {
- lpvBuffer = NULL;
- hBufferObject = NULL;
- bmihDecompressedFormat = NULL;
- }
- VideoSource::~VideoSource() {
- freemem(bmihDecompressedFormat);
- FreeFrameBuffer();
- }
- void *VideoSource::AllocFrameBuffer(long size) {
- hBufferObject = CreateFileMapping(
- (HANDLE)0xFFFFFFFF,
- NULL,
- PAGE_READWRITE,
- 0,
- size,
- NULL);
- if (!hBufferObject) return NULL;
- lBufferOffset = 0;
- lpvBuffer = MapViewOfFile(hBufferObject, FILE_MAP_ALL_ACCESS, 0, lBufferOffset, size);
- if (!lpvBuffer) {
- CloseHandle(hBufferObject);
- hBufferObject = NULL;
- }
- return lpvBuffer;
- }
- void VideoSource::FreeFrameBuffer() {
- if (hBufferObject) {
- if (lpvBuffer)
- UnmapViewOfFile(lpvBuffer);
- CloseHandle(hBufferObject);
- } else
- freemem(lpvBuffer);
- lpvBuffer = NULL;
- hBufferObject = NULL;
- }
- bool VideoSource::setDecompressedFormat(int depth) {
- memcpy(bmihDecompressedFormat, getImageFormat(), getFormatLen());
- bmihDecompressedFormat->biSize = sizeof(BITMAPINFOHEADER);
- bmihDecompressedFormat->biPlanes = 1;
- bmihDecompressedFormat->biBitCount = depth;
- bmihDecompressedFormat->biCompression = BI_RGB;
- bmihDecompressedFormat->biSizeImage = ((bmihDecompressedFormat->biWidth * depth + 31)/32)*4*bmihDecompressedFormat->biHeight;
- if (depth>8) {
- bmihDecompressedFormat->biClrUsed = 0;
- bmihDecompressedFormat->biClrImportant = 0;
- }
- invalidateFrameBuffer();
- return true;
- }
- bool VideoSource::setDecompressedFormat(BITMAPINFOHEADER *pbih) {
- if (pbih->biCompression == BI_RGB) {
- setDecompressedFormat(pbih->biBitCount);
- return true;
- }
- return false;
- }
- void VideoSource::streamBegin(bool) {
- stream_current_frame = -1;
- }
- void VideoSource::streamSetDesiredFrame(long frame_num) {
- long key;
- key = isKey(frame_num) ? frame_num : prevKey(frame_num);
- if (key<0) key = lSampleFirst;
- stream_desired_frame = frame_num;
- if (stream_current_frame<key || stream_current_frame>frame_num)
- stream_current_frame = key-1;
- }
- long VideoSource::streamGetNextRequiredFrame(BOOL *is_preroll) {
- if (stream_current_frame == stream_desired_frame) {
- *is_preroll = FALSE;
- return -1;
- }
- *is_preroll = (++stream_current_frame != stream_desired_frame);
- return stream_current_frame;
- }
- int VideoSource::streamGetRequiredCount(long *pSize) {
- if (pSize) {
- long current = stream_current_frame;
- long size = 0, onesize;
- long samp;
- while(current < stream_desired_frame) {
- if (AVIERR_OK == read(current, 1, NULL, NULL, &onesize, &samp))
- size += onesize;
- ++current;
- }
- *pSize = size;
- }
- return stream_desired_frame - stream_current_frame;
- }
- void VideoSource::invalidateFrameBuffer() {
- }
- bool VideoSource::isKeyframeOnly() {
- return false;
- }
- bool VideoSource::isType1() {
- return false;
- }
- ///////////////////////////
- VideoSourceAVI::VideoSourceAVI(IAVIReadHandler *pAVI, AVIStripeSystem *stripesys, IAVIReadHandler **stripe_files, bool use_internal, int mjpeg_mode, FOURCC fccForceVideo, FOURCC fccForceVideoHandler) {
- pAVIFile = pAVI;
- pAVIStream = NULL;
- lpvBuffer = NULL;
- hicDecomp = NULL;
- bmihTemp = NULL;
- key_flags = NULL;
- mjpeg_reorder_buffer = NULL;
- mjpeg_reorder_buffer_size = 0;
- mjpeg_splits = NULL;
- mjpeg_last = -1;
- this->fccForceVideo = fccForceVideo;
- this->fccForceVideoHandler = fccForceVideoHandler;
- hbmLame = NULL;
- fUseGDI = false;
- // striping...
- stripe_streams = NULL;
- stripe_index = NULL;
- this->stripesys = stripesys;
- this->stripe_files = stripe_files;
- this->use_internal = use_internal;
- this->mjpeg_mode = mjpeg_mode;
- mdec = NULL;
- try {
- _construct();
- } catch(...) {
- _destruct();
- throw;
- }
- }
- void VideoSourceAVI::_destruct() {
- delete stripe_index;
- if (stripe_streams) {
- int i;
- for(i=0; i<stripe_count; i++)
- if (stripe_streams[i])
- delete stripe_streams[i];
- delete stripe_streams;
- }
- if (bmihTemp) freemem(bmihTemp);
- if (hicDecomp) ICClose(hicDecomp);
- if (pAVIStream) delete pAVIStream;
- delete mdec;
- freemem(mjpeg_reorder_buffer);
- mjpeg_reorder_buffer = NULL;
- delete[] mjpeg_splits;
- mjpeg_splits = NULL;
- delete[] key_flags; key_flags = NULL;
- if (hbmLame) {
- DeleteObject(hbmLame);
- hbmLame = NULL;
- }
- }
- VideoSourceAVI::~VideoSourceAVI() {
- _destruct();
- }
- void VideoSourceAVI::_construct() {
- LONG format_len;
- BITMAPINFOHEADER *bmih;
- bool is_mjpeg, is_dib;
- // 寻找标准的vids流
- bIsType1 = false;
- pAVIStream = pAVIFile->GetStream(streamtypeVIDEO, 0);
- if (!pAVIStream) {
- pAVIStream = pAVIFile->GetStream('svai', 0);
- if (!pAVIStream)
- throw MyError("No video stream found.");
- bIsType1 = true;
- }
- if (pAVIStream->Info(&streamInfo, sizeof streamInfo))
- throw MyError("Error obtaining video stream info.");
- // ADDITION FOR STRIPED AVI SUPPORT:
- //
- // If this is an index for a stripe system, then the video stream will have
- // 'VDST' as its fccHandler and video compression. This will probably
- // correspond to the "VDub Frameserver" compressor, but since VirtualDub can
- // connect to its own frameservers more efficiently though the AVIFile
- // interface, it makes sense to open striped files in native mode.
- //
- // For this to work, we must have been sent the striping specs beforehand,
- // or else we won't be able to open the stripes.
- if (streamInfo.fccHandler == 'TSDV') {
- int i;
- if (!stripesys)
- throw MyError("AVI file is striped - must be opened with stripe definition file.");
- // 为条纹流表分配内存空间
- stripe_count = stripesys->getStripeCount();
- if (!(stripe_streams = new IAVIReadStream *[stripe_count]))
- throw MyMemoryError();
- for(i=0; i<stripe_count; i++)
- stripe_streams[i] = NULL;
-
- format_stream = NULL;
- for(i=0; i<stripe_count; i++) {
- if (stripesys->getStripeInfo(i)->isVideo()) {
- stripe_streams[i] = stripe_files[i]->GetStream(streamtypeVIDEO, 0);
- if (!stripe_streams[i])
- throw MyError("Striping: cannot open video stream for stripe #%d", i+1);
- if (!format_stream) format_stream = stripe_streams[i];
- }
- }
- if (!format_stream)
- throw MyError("Striping: No video stripes found!");
-
- if (format_stream->Info(&streamInfo, sizeof streamInfo))
- throw MyError("Error obtaining video stream info from first video stripe.");
- // 初始化下标
- if (!(stripe_index = new AVIStripeIndexLookup(pAVIStream)))
- throw MyMemoryError();
-
- } else {
- if (stripesys)
- throw MyError("This is not a striped AVI file.");
- format_stream = pAVIStream;
- }
- // 读视频格式。如果遇到条纹,那么条纹的引索有一个虚拟格式
- // 所以必须从一个视频条纹得到它相应的格式。如果是格式是
- // type-1 DV,继续要虚拟之。
- if (bIsType1) {
- format_len = sizeof(BITMAPINFOHEADER);
- if (!(bmih = (BITMAPINFOHEADER *)allocFormat(format_len))) throw MyMemoryError();
- bmih->biSize = sizeof(BITMAPINFOHEADER);
- bmih->biWidth = 720;
- if (streamInfo.dwRate > streamInfo.dwScale*26i64)
- bmih->biHeight = 480;
- else
- bmih->biHeight = 576;
- bmih->biPlanes = 1;
- bmih->biBitCount = 24;
- bmih->biCompression = 'dsvd';
- bmih->biSizeImage = streamInfo.dwSuggestedBufferSize;
- bmih->biXPelsPerMeter = 0;
- bmih->biYPelsPerMeter = 0;
- bmih->biClrUsed = 0;
- bmih->biClrImportant = 0;
- } else {
- format_stream->FormatSize(0, &format_len);
- if (!(bmih = (BITMAPINFOHEADER *)allocFormat(format_len))) throw MyMemoryError();
- if (format_stream->ReadFormat(0, getFormat(), &format_len))
- throw MyError("Error obtaining video stream format.");
- }
- if (!(bmihTemp = (BITMAPINFOHEADER *)allocmem(format_len))) throw MyMemoryError();
- if (!(bmihDecompressedFormat = (BITMAPINFOHEADER *)allocmem(format_len))) throw MyMemoryError();
- // RGB8/16/24/32和YUY2颜色空间可以被处理
- is_dib = (bmih->biCompression == BI_RGB) || (bmih->biCompression == '2YUY');
- // 如果需要,强制转换视频格式
- if (fccForceVideo)
- getImageFormat()->biCompression = fccForceVideo;
- if (fccForceVideoHandler)
- streamInfo.fccHandler = fccForceVideoHandler;
- is_mjpeg = isEqualFOURCC(bmih->biCompression, 'GPJM')
- || isEqualFOURCC(fccForceVideo, 'GPJM')
- || isEqualFOURCC(bmih->biCompression, '1bmd')
- || isEqualFOURCC(fccForceVideo, '1bmd');
- // 如果格式为MJPEG,检查是否需要修改输出格式或者流信息
- lSampleFirst = pAVIStream->Start();
- lSampleLast = pAVIStream->End();
- if (is_mjpeg) {
- BITMAPINFOHEADER *pbih = getImageFormat();
- if (mjpeg_mode && mjpeg_mode != IFMODE_SWAP && pbih->biHeight > 288) {
- pbih->biHeight /= 2;
- if (mjpeg_mode == IFMODE_SPLIT1 || mjpeg_mode == IFMODE_SPLIT2) {
- streamInfo.dwRate *= 2;
- streamInfo.dwLength *= 2;
- lSampleLast = lSampleLast*2 - lSampleFirst;
- }
- }
- if (mjpeg_mode) {
- if (!(mjpeg_splits = new long[lSampleLast - lSampleFirst]))
- throw MyMemoryError();
- for(int i=0; i<lSampleLast-lSampleFirst; i++)
- mjpeg_splits[i] = -1;
- }
- } else
- mjpeg_mode = 0;
- memcpy(bmihTemp, getFormat(), format_len);
- // 分配帧缓存
- if (!AllocFrameBuffer(bmih->biWidth * 4 * bmih->biHeight + 4))
- throw MyMemoryError();
- // 取得解码器
- //
- // 'DIB '是标准的解码后的AVI文件标记值。不过有一些条纹程序使用
- // (null) 和 'RAW '
- hicDecomp = NULL;
- if (bmih->biCompression == BI_BITFIELDS || bmih->biCompression == BI_RLE8 || bmih->biCompression == BI_RLE4
- || (bmih->biCompression == BI_RGB && bmih->biBitCount<16 && bmih->biBitCount != 8)) {
- // 如果是冷僻的格式,用GDI处理
- fUseGDI = true;
- } else if (!is_dib) {
- FOURCC fccOriginalCodec = bmih->biCompression;
- // 如果是老式的MPEG-4解码器,尝试所有的已知的老式解码器
- // 它们都是同种的解码器,因此互相兼容
- switch(bmih->biCompression) {
- case '34PM': // Microsoft MPEG-4 V3
- case '3VID': // "DivX Low-Motion" (4.10.0.3917)
- case '4VID': // "DivX Fast-Motion" (4.10.0.3920)
- case '14PA': // "AngelPotion Definitive" (4.0.00.3688)
- if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
- bmih->biCompression = '34PM';
- if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
- bmih->biCompression = '3VID';
- if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
- bmih->biCompression = '4VID';
- if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
- bmih->biCompression = '14PA';
- default:
- if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
- break;
- }
- const char *s = LookupVideoCodec(fccOriginalCodec);
- throw MyError("Couldn't locate decompressor for format '%c%c%c%c' (%s)n"
- "n"
- "VirtualDub requires a Video for Windows (VFW) compatible codec to decompress "
- "video. DirectShow codecs, such as those used by Windows Media Player, are not "
- "suitable."
- ,(fccOriginalCodec ) & 0xff
- ,(fccOriginalCodec>> 8) & 0xff
- ,(fccOriginalCodec>>16) & 0xff
- ,(fccOriginalCodec>>24) & 0xff
- ,s ? s : "unknown");
- }
- }
- bool VideoSourceAVI::AttemptCodecNegotiation(BITMAPINFOHEADER *bmih, bool is_mjpeg) {
- // VideoMatrix sets streamInfo.fccHandler to NULL. Danger, Will Robinson.
- if (!use_internal) {
- // Try the handler specified in the file first. In some cases, it'll
- // be wrong or missing.
- if (streamInfo.fccHandler)
- hicDecomp = ICOpen(ICTYPE_VIDEO, streamInfo.fccHandler, ICMODE_DECOMPRESS);
- if (!hicDecomp || ICERR_OK!=ICDecompressQuery(hicDecomp, bmih, NULL)) {
- if (hicDecomp)
- ICClose(hicDecomp);
- // Pick a handler based on the biCompression field instead.
- hicDecomp = ICOpen(ICTYPE_VIDEO, bmih->biCompression, ICMODE_DECOMPRESS);
- if (!hicDecomp || ICERR_OK!=ICDecompressQuery(hicDecomp, bmih, NULL)) {
- if (hicDecomp)
- ICClose(hicDecomp);
- // AngelPotion f*cks us over here and overwrites our format if we keep this in.
- // So let's write protect the format. You'll see a nice C0000005 error when
- // the AP DLL tries to modify it.
- // hicDecomp = ICLocate(ICTYPE_VIDEO, NULL, getImageFormat(), NULL, ICMODE_DECOMPRESS);
- int siz = getFormatLen();
- BITMAPINFOHEADER *pbih_protected = (BITMAPINFOHEADER *)VirtualAlloc(NULL, siz, MEM_COMMIT, PAGE_READWRITE);
- if (pbih_protected) {
- DWORD dwOldProtect;
- memcpy(pbih_protected, bmih, siz);
- VirtualProtect(pbih_protected, siz, PAGE_READONLY, &dwOldProtect);
- hicDecomp = ICLocate(ICTYPE_VIDEO, NULL, pbih_protected, NULL, ICMODE_DECOMPRESS);
- VirtualFree(pbih_protected, 0, MEM_RELEASE);
- }
- }
- }
- }
- if (!hicDecomp) {
- // Is it MJPEG or I420? Maybe we can do it ourselves.
- if (is_mjpeg) {
- // if (!(mdec = CreateMJPEGDecoder(getImageFormat()->biWidth, getImageFormat()->biHeight)))
- // throw MyMemoryError();
- return true;
- } else {
- return false;
- }
- } else {
- // check for bad MPEG-4 V2/V3 codec
- if (isEqualFOURCC(bmih->biCompression, '24PM'))
- return CheckMPEG4Codec(hicDecomp, false);
- else if (isEqualFOURCC(bmih->biCompression, '34PM'))
- return CheckMPEG4Codec(hicDecomp, true);
- else
- return true;
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- void VideoSourceAVI::Reinit() {
- long nOldFrames, nNewFrames;
- nOldFrames = lSampleLast - lSampleFirst;
- nNewFrames = pAVIStream->End() - pAVIStream->Start();
- if (mjpeg_splits) {
- nOldFrames >>= 1;
- }
- if (nOldFrames != nNewFrames && (mjpeg_mode==IFMODE_SPLIT1 || mjpeg_mode==IFMODE_SPLIT2)) {
- // We have to resize the mjpeg_splits array.
- long *pNewSplits = new long[lSampleLast - lSampleFirst];
- if (!pNewSplits)
- throw MyMemoryError();
- int i;
- memcpy(pNewSplits, mjpeg_splits, sizeof(long)*nOldFrames);
- for(i=nOldFrames; i<nNewFrames; i++)
- pNewSplits[i] = -1;
- delete[] mjpeg_splits;
- mjpeg_splits = pNewSplits;
- }
- if (pAVIStream->Info(&streamInfo, sizeof streamInfo))
- throw MyError("Error obtaining video stream info.");
- lSampleFirst = pAVIStream->Start();
- if (mjpeg_splits) {
- streamInfo.dwRate *= 2;
- streamInfo.dwLength *= 2;
- lSampleLast = pAVIStream->End() * 2 - lSampleFirst;
- } else
- lSampleLast = pAVIStream->End();
- streamInfo.dwLength = lSampleLast - lSampleFirst;
- }
- void VideoSourceAVI::redoKeyFlags() {
- long lSample;
- long lMaxFrame=0;
- long lActualBytes, lActualSamples;
- int err;
- void *lpInputBuffer = NULL;
- void *lpKeyBuffer = NULL;
- BOOL fStreamBegun = FALSE;
- int iBytes;
- long *pFrameSums;
- if (!hicDecomp)
- return;
- iBytes = (lSampleLast+7-lSampleFirst)>>3;
- if (!(key_flags = new char[iBytes]))
- throw MyMemoryError();
- memset(key_flags, 0, iBytes);
- // Find maximum frame
- lSample = lSampleFirst;
- while(lSample < lSampleLast) {
- err = _read(lSample, 1, NULL, 0, &lActualBytes, &lActualSamples);
- if (err == AVIERR_OK)
- // throw MyAVIError("VideoSource", err);
- if (lActualBytes > lMaxFrame) lMaxFrame = lActualBytes;
- ++lSample;
- }
- if (!setDecompressedFormat(24))
- if (!setDecompressedFormat(32))
- if (!setDecompressedFormat(16))
- if (!setDecompressedFormat(8))
- throw MyError("Video decompressor is incapable of decompressing to an RGB format.");
- if (!(lpInputBuffer = new char[((lMaxFrame+7)&-8) + lMaxFrame]))
- throw MyMemoryError();
- if (!(pFrameSums = new long[lSampleLast - lSampleFirst])) {
- delete[] lpInputBuffer;
- throw MyMemoryError();
- }
- try {
- // ProgressDialog pd(NULL, "AVI Import Filter", "Rekeying video stream", (lSampleLast - lSampleFirst)*2, true);
- // pd.setValueFormat("Frame %ld of %ld");
- MessageBox( NULL, "AVI Import Filter", "Rekeying video stream", MB_OK);
- streamBegin(true);
- fStreamBegun = TRUE;
- lSample = lSampleFirst;
- while(lSample < lSampleLast) {
- long lBlackTotal=0, lWhiteTotal=0;
- long x, y;
- const long lWidth = (bmihDecompressedFormat->biWidth * bmihDecompressedFormat->biBitCount + 7)/8;
- const long lModulo = (4-lWidth)&3;
- const long lHeight = bmihDecompressedFormat->biHeight;
- unsigned char *ptr;
- _RPT1(0,"Rekeying frame %ldn", lSample);
- err = _read(lSample, 1, lpInputBuffer, lMaxFrame, &lActualBytes, &lActualSamples);
- if (err != AVIERR_OK)
- // throw MyAVIError("VideoSourceAVI", err);
- goto rekey_error;
- #if 0
- // decompress frame with an all black background
- memset(lpvBuffer, 0, bmihDecompressedFormat->biSizeImage);
- streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);
- ptr = (unsigned char *)lpvBuffer;
- y = lHeight;
- do {
- x = lWidth;
- do {
- lBlackTotal += (long)*ptr++;
- } while(--x);
- ptr += lModulo;
- } while(--y);
- // decompress frame with an all white background
- memset(lpvBuffer, 0xff, bmihDecompressedFormat->biSizeImage);
- streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);
- ptr = (unsigned char *)lpvBuffer;
- y = lHeight;
- do {
- x = lWidth;
- do {
- lWhiteTotal += (long)*ptr++;
- } while(--x);
- ptr += lModulo;
- } while(--y);
- #else
- streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);
- ptr = (unsigned char *)lpvBuffer;
- y = lHeight;
- do {
- x = lWidth;
- do {
- lWhiteTotal += (long)*ptr++;
- lWhiteTotal ^= 0xAAAAAAAA;
- } while(--x);
- ptr += lModulo;
- } while(--y);
- pFrameSums[lSample - lSampleFirst] = lWhiteTotal;
- #endif
- // if (lBlackTotal == lWhiteTotal)
- // key_flags[(lSample - lSampleFirst)>>3] |= 1<<((lSample-lSampleFirst)&7);
- rekey_error:
- ++lSample;
- // pd.advance(lSample - lSampleFirst);
- // pd.check();
- }
- lSample = lSampleFirst;
- do {
- long lBlackTotal=0, lWhiteTotal=0;
- long x, y;
- const long lWidth = (bmihDecompressedFormat->biWidth * bmihDecompressedFormat->biBitCount + 7)/8;
- const long lModulo = (4-lWidth)&3;
- const long lHeight = bmihDecompressedFormat->biHeight;
- unsigned char *ptr;
- _RPT1(0,"Rekeying frame %ldn", lSample);
- err = _read(lSample, 1, lpInputBuffer, lMaxFrame, &lActualBytes, &lActualSamples);
- if (err != AVIERR_OK)
- // throw MyAVIError("VideoSourceAVI", err);
- goto rekey_error2;
- streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);
- ptr = (unsigned char *)lpvBuffer;
- y = lHeight;
- do {
- x = lWidth;
- do {
- lWhiteTotal += (long)*ptr++;
- lWhiteTotal ^= 0xAAAAAAAA;
- } while(--x);
- ptr += lModulo;
- } while(--y);
- if (lWhiteTotal == pFrameSums[lSample - lSampleFirst])
- key_flags[(lSample - lSampleFirst)>>3] |= 1<<((lSample-lSampleFirst)&7);
- rekey_error2:
- if (lSample == lSampleFirst)
- lSample = lSampleLast-1;
- else
- --lSample;
- // pd.advance(lSampleLast*2 - (lSample+lSampleFirst));
- // pd.check();
- } while(lSample >= lSampleFirst+1);
- streamEnd();
- } catch(...) {
- if (fStreamBegun) streamEnd();
- delete[] lpInputBuffer;
- delete[] pFrameSums;
- throw;
- }
- delete[] lpInputBuffer;
- delete[] pFrameSums;
- }
- int VideoSourceAVI::_read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead) {
- IAVIReadStream *pSource = pAVIStream;
- bool phase = (lStart - lSampleFirst)&1;
- if (mjpeg_mode == IFMODE_SPLIT1 || mjpeg_mode == IFMODE_SPLIT2)
- lStart = lSampleFirst + (lStart - lSampleFirst)/2;
- // 如果被条纹化,那么寻找正确的条纹
- if (stripesys) {
- AVIStripeIndexEntry *asie;
- long offset;
- if (!(asie = stripe_index->lookup(lStart)))
- return AVIERR_FILEREAD;
- offset = lStart - asie->lSampleFirst;
- if (lCount > asie->lSampleCount-offset)
- lCount = asie->lSampleCount-offset;
- if (!stripe_streams[asie->lStripe])
- return AVIERR_FILEREAD;
- pSource = stripe_streams[asie->lStripe];
- lStart = asie->lStripeSample + offset;
- }
- // 是否为MJPEG修正模式?
- if (mjpeg_mode) {
- int res;
- LONG lBytes, lSamples;
- long lRealSample = lStart;
- long lOffset, lLength;
- // 是否和上次输入的sample相同?
- if (lStart == mjpeg_last) {
- lBytes = mjpeg_last_size;
- res = AVIERR_OK;
- } else {
- // 把sample读入内存。如果不知道放入的地址或者已经知道
- // 条纹在那里,仅仅返回sample的大小
- if (lpBuffer || mjpeg_splits[lStart - lSampleFirst]<0) {
- mjpeg_last = -1;
- if (mjpeg_reorder_buffer_size)
- res = pSource->Read(lStart, 1, mjpeg_reorder_buffer, mjpeg_reorder_buffer_size, &lBytes, &lSamples);
- if (res == AVIERR_BUFFERTOOSMALL || !mjpeg_reorder_buffer_size) {
- void *new_buffer;
- int new_size;
- res = pSource->Read(lStart, 1, NULL, 0, &lBytes, &lSamples);
- if (res == AVIERR_OK) {
- _ASSERT(lBytes != 0);
- new_size = (lBytes + 4095) & -4096;
- new_buffer = reallocmem(mjpeg_reorder_buffer, new_size);
- if (!new_buffer)
- return AVIERR_MEMORY;
- mjpeg_reorder_buffer = new_buffer;
- mjpeg_reorder_buffer_size = new_size;
- res = pSource->Read(lStart, 1, mjpeg_reorder_buffer, mjpeg_reorder_buffer_size, &lBytes, &lSamples);
- }
- }
- if (res == AVIERR_OK) {
- mjpeg_last = lStart;
- mjpeg_last_size = lBytes;
- }
- } else
- res = pSource->Read(lStart, 1, NULL, 0, &lBytes, &lSamples);
- }
- if (res != AVIERR_OK) {
- if (lBytesRead)
- *lBytesRead = 0;
- if (lSamplesRead)
- *lSamplesRead = 0;
- return res;
- } else if (!lBytes) {
- if (lBytesRead)
- *lBytesRead = 0;
- if (lSamplesRead)
- *lSamplesRead = 1;
- return AVIERR_OK;
- }
- // 在sample中寻找SOI标记
- lOffset = 0;
- lLength = lBytes;
- {
- int i;
- // 是否已经知道条纹在哪里?
- if (mjpeg_splits[lStart-lSampleFirst]<0) {
- for(i=2; i<lBytes-2; i++)
- if (((unsigned char *)mjpeg_reorder_buffer)[i] == (unsigned char)0xFF
- && ((unsigned char *)mjpeg_reorder_buffer)[i+1] == (unsigned char)0xD8)
- break;
- mjpeg_splits[lStart - lSampleFirst] = i;
- } else {
- i = mjpeg_splits[lStart - lSampleFirst];
- }
- if (i<lBytes-2) {
- if (mjpeg_mode != IFMODE_SWAP) {
- switch(mjpeg_mode) {
- case IFMODE_SPLIT2:
- phase = !phase;
- break;
- case IFMODE_DISCARD1:
- phase = false;
- break;
- case IFMODE_DISCARD2:
- phase = true;
- break;
- }
- if (phase) {
- lOffset = i;
- lLength = lBytes - i;
- } else {
- lOffset = 0;
- lLength = i;
- }
- } else
- lOffset = i;
- }
- }
- if (lpBuffer) {
- if (lSamplesRead)
- *lSamplesRead = 1;
- if (lBytesRead)
- *lBytesRead = lLength;
- if (cbBuffer < lLength)
- return AVIERR_BUFFERTOOSMALL;
- if (mjpeg_mode == IFMODE_SWAP) {
- char *pp1 = (char *)lpBuffer;
- char *pp2 = (char *)lpBuffer + (lBytes - lOffset);
- memcpy(pp1, (char *)mjpeg_reorder_buffer+lOffset, lBytes - lOffset);
- if (lOffset)
- memcpy(pp2, mjpeg_reorder_buffer, lOffset);
- if (((short *)pp1)[1]==(short)0xE0FF)
- pp1[10] = 1;
- if (((short *)pp2)[1]==(short)0xE0FF)
- pp2[10] = 2;
-
- } else {
- memcpy(lpBuffer, (char *)mjpeg_reorder_buffer+lOffset, lLength);
- // 通过APP0标记在MJPEG头打补丁
- // FFD8 FFE0 0010 'AVI1' 极性
- if (((short *)lpBuffer)[1]==(short)0xE0FF)
- ((char *)lpBuffer)[10] = 0;
- }
- return AVIERR_OK;
- } else {
- if (lSamplesRead)
- *lSamplesRead = 1;
- if (lBytesRead)
- *lBytesRead = lLength;
- return AVIERR_OK;
- }
- } else
- return pSource->Read(lStart, lCount, lpBuffer, cbBuffer, lBytesRead, lSamplesRead);
- }
- BOOL VideoSourceAVI::_isKey(LONG samp) {
- if ((mjpeg_mode & -2) == IFMODE_SPLIT1)
- samp = lSampleFirst + (samp - lSampleFirst)/2;
- if (key_flags) {
- samp -= lSampleFirst;
- return !!(key_flags[samp>>3] & (1<<(samp&7)));
- } else
- return pAVIStream->IsKeyFrame(samp);
- }
- LONG VideoSourceAVI::nearestKey(LONG lSample) {
- if (key_flags) {
- if (lSample < lSampleFirst || lSample >= lSampleLast)
- return -1;
- if (_isKey(lSample)) return lSample;
- return prevKey(lSample);
- }
- // if (lNear == -1)
- // throw MyError("VideoSourceAVI: error getting previous key frame");
- if ((mjpeg_mode & -2) == IFMODE_SPLIT1) {
- return pAVIStream->NearestKeyFrame(lSampleFirst + (lSample-lSampleFirst)/2)*2-lSampleFirst;
- } else {
- return pAVIStream->NearestKeyFrame(lSample);
- }
- }
- LONG VideoSourceAVI::prevKey(LONG lSample) {
- if ((mjpeg_mode & -2) == IFMODE_SPLIT1) {
- lSample = lSampleFirst + (lSample - lSampleFirst)/2;
- if (key_flags) {
- if (lSample >= lSampleLast) return -1;
- while(--lSample >= lSampleFirst)
- if (_isKey(lSample)) return lSample*2-lSampleFirst;
- return -1;
- } else
- return pAVIStream->PrevKeyFrame(lSample)*2-lSampleFirst;
- } else {
- if (key_flags) {
- if (lSample >= lSampleLast) return -1;
- while(--lSample >= lSampleFirst)
- if (_isKey(lSample)) return lSample;
- return -1;
- } else
- return pAVIStream->PrevKeyFrame(lSample);
- }
- }
- LONG VideoSourceAVI::nextKey(LONG lSample) {
- if ((mjpeg_mode & -2) == IFMODE_SPLIT1) {
- lSample = lSampleFirst + (lSample - lSampleFirst)/2;
- if (key_flags) {
- if (lSample < lSampleFirst) return -1;
- while(++lSample < lSampleLast)
- if (_isKey(lSample)) return lSample*2 - lSampleFirst;
- return -1;
- } else
- return pAVIStream->NextKeyFrame(lSample)*2 - lSampleFirst;
- } else {
- if (key_flags) {
- if (lSample < lSampleFirst) return -1;
- while(++lSample < lSampleLast)
- if (_isKey(lSample)) return lSample;
- return -1;
- } else
- return pAVIStream->NextKeyFrame(lSample);
- }
- }
- __int64 VideoSourceAVI::sampleOffset(LONG lSample)
- {
- return pAVIStream->FramePos(lSample);
- }
- bool VideoSourceAVI::setDecompressedFormat(int depth) {
- VideoSource::setDecompressedFormat(depth);
- if (fUseGDI) {
- void *pv;
- HDC hdc;
- if (depth != 24 && depth != 32 && depth != 16)
- return false;
- if (hbmLame)
- DeleteObject(hbmLame);
- hbmLame = NULL;
- if (hdc = CreateCompatibleDC(NULL)) {
- hbmLame = CreateDIBSection(hdc, (BITMAPINFO *)bmihDecompressedFormat, DIB_RGB_COLORS, &pv, hBufferObject, 0);
- DeleteDC(hdc);
- }
- return true;
- } else if (mdec)
- return depth == 32 || depth == 16;
- else if (hicDecomp)
- return ICERR_OK == ICDecompressQuery(hicDecomp, getImageFormat(), bmihDecompressedFormat);
- else if (getImageFormat()->biCompression == '024I')
- return depth == 32;
- else
- return depth == 32 || depth == 24 || depth == 16;
- }
- bool VideoSourceAVI::setDecompressedFormat(BITMAPINFOHEADER *pbih) {
- if (pbih->biCompression == BI_RGB)
- return setDecompressedFormat(pbih->biBitCount);
- if (mdec)
- return false;
- if (hicDecomp && ICERR_OK == ICDecompressQuery(hicDecomp, getImageFormat(), pbih)) {
- memcpy(bmihDecompressedFormat, pbih, sizeof(BITMAPINFOHEADER));
- invalidateFrameBuffer();
- return true;
- }
- return false;
- }
- ////////////////////////////////////////////////
- void DIBconvert(void *src0, BITMAPINFOHEADER *srcfmt, void *dst0, BITMAPINFOHEADER *dstfmt) {
- if (srcfmt->biCompression == '2YUY')
- // VBitmap(dst0, dstfmt).BitBltFromYUY2(0, 0, &VBitmap(src0, srcfmt), 0, 0, -1, -1);
- ;
- else if (srcfmt->biCompression == '024I')
- // VBitmap(dst0, dstfmt).BitBltFromI420(0, 0, &VBitmap(src0, srcfmt), 0, 0, -1, -1);
- ;
- else
- // VBitmap(dst0, dstfmt).BitBlt(0, 0, &VBitmap(src0, srcfmt), 0, 0, -1, -1);
- ;
- }
- ////////////////////////////////////////////////
- void VideoSourceAVI::invalidateFrameBuffer() {
- if (lLastFrame != -1 && hicDecomp)
- ICDecompressEnd(hicDecomp);
- lLastFrame = -1;
- }
- BOOL VideoSourceAVI::isFrameBufferValid() {
- return lLastFrame != -1;
- }
- char VideoSourceAVI::getFrameTypeChar(long lFrameNum) {
- if (lFrameNum<lSampleFirst || lFrameNum >= lSampleLast)
- return ' ';
- if (_isKey(lFrameNum))
- return 'K';
- long lBytes, lSamples;
- int err = _read(lFrameNum, 1, NULL, 0, &lBytes, &lSamples);
- if (err != AVIERR_OK)
- return ' ';
- return lBytes ? ' ' : 'D';
- }
- bool VideoSourceAVI::isStreaming() {
- return pAVIStream->isStreaming();
- }
- bool VideoSourceAVI::isKeyframeOnly() {
- return pAVIStream->isKeyframeOnly();
- }
- bool VideoSourceAVI::isType1() {
- return bIsType1;
- }
- void VideoSourceAVI::streamBegin(bool fRealTime) {
- DWORD err;
- stream_current_frame = -1;
- pAVIStream->BeginStreaming(lSampleFirst, lSampleLast, fRealTime ? 1000 : 2000);
- use_ICDecompressEx = FALSE;
- if (hicDecomp) {
- BITMAPINFOHEADER *bih_src = bmihTemp;
- BITMAPINFOHEADER *bih_dst = getDecompressedFormat();
- if (ICERR_OK != (err = ICDecompressBegin(
- hicDecomp,
- getImageFormat(),
- getDecompressedFormat()
- )))
- if (err == ICERR_UNSUPPORTED) {
- use_ICDecompressEx = TRUE;
- err = ICDecompressExBegin(
- hicDecomp,
- 0,
- bih_src,
- NULL,
- 0,0,
- bih_src->biWidth,bih_src->biHeight,
- bih_dst,
- lpvBuffer,
- 0,0,
- bih_dst->biWidth,bih_dst->biHeight
- );
-
- }
- if (ICERR_UNSUPPORTED != err && ICERR_OK != err)
- throw MyICError("VideoSourceAVI", err);
- }
- }
- void *VideoSourceAVI::streamGetFrame(void *inputBuffer, LONG data_len, BOOL is_key, BOOL is_preroll, long frame_num) {
- DWORD err;
- if (!data_len) return getFrameBuffer();
- if (fUseGDI) {
- if (!hbmLame)
- throw MyError("Insufficient GDI resources to convert frame.");
- SetDIBits(NULL, hbmLame, 0, getDecompressedFormat()->biHeight, inputBuffer, (BITMAPINFO *)getFormat(),
- DIB_RGB_COLORS);
- GdiFlush();
- } else if (hicDecomp) {
- // Asus ASV1 crashes with zero byte frames!!!
- if (data_len) {
- BITMAPINFOHEADER *bih_src = bmihTemp;
- BITMAPINFOHEADER *bih_dst = getDecompressedFormat();
- bmihTemp->biSizeImage = data_len;
- // VDCHECKPOINT;
- if (use_ICDecompressEx)
- err = ICDecompressEx(
- hicDecomp,
- // (is_preroll ? ICDECOMPRESS_PREROLL : 0) |
- // | (data_len ? 0 : ICDECOMPRESS_NULLFRAME)
- (is_key ? 0 : ICDECOMPRESS_NOTKEYFRAME),
- bih_src,
- inputBuffer,
- 0,0,
- bih_src->biWidth, bih_src->biHeight,
- bih_dst,
- lpvBuffer,
- 0,0,
- bih_dst->biWidth, bih_dst->biHeight
- );
- else
- err = ICDecompress(
- hicDecomp,
- // (is_preroll ? ICDECOMPRESS_PREROLL : 0) |
- // | (data_len ? 0 : ICDECOMPRESS_NULLFRAME)
- (is_key ? 0 : ICDECOMPRESS_NOTKEYFRAME),
- bih_src,
- inputBuffer,
- bih_dst,
- lpvBuffer
- );
- // VDCHECKPOINT;
- if (ICERR_OK != err)
- throw MyICError(use_ICDecompressEx ? "VideoSourceAVI [ICDecompressEx]" : "VideoSourceAVI [ICDecompress]", err);
- }
- } else if (mdec) {
- /* try {
- if (getDecompressedFormat()->biBitCount == 32)
- mdec->decodeFrame32((unsigned long *)getFrameBuffer(), (unsigned char *)inputBuffer, data_len);
- else
- mdec->decodeFrame16((unsigned long *)getFrameBuffer(), (unsigned char *)inputBuffer, data_len);
- } catch(char *s) {
- throw MyError(s);
- }
- */
- } else {
- if (data_len < getImageFormat()->biSizeImage)
- throw MyError("VideoSourceAVI: uncompressed frame is short (expected %d bytes, got %d)", getImageFormat()->biSizeImage, data_len);
- DIBconvert(inputBuffer, getImageFormat(), getFrameBuffer(), getDecompressedFormat());
- }
- // memcpy(getFrameBuffer(), inputBuffer, getDecompressedFormat()->biSizeImage);
- return getFrameBuffer();
- }
- void VideoSourceAVI::streamEnd() {
- // If an error occurs, but no one is there to hear it, was
- // there ever really an error?
- if (hicDecomp) {
- if (use_ICDecompressEx)
- ICDecompressExEnd(hicDecomp);
- else
- ICDecompressEnd(hicDecomp);
- }
- pAVIStream->EndStreaming();
- }
- void *VideoSourceAVI::getFrame(LONG lFrameDesired) {
- void *dataBuffer = NULL;
- LONG dataBufferSize = 0;
- LONG lFrameKey, lFrameNum, lFrameErr=-1;
- LONG lBytesRead, lSamplesRead;
- DWORD err;
- int aviErr;
- // illegal frame number?
- if (lFrameDesired < lSampleFirst || lFrameDesired >= lSampleLast)
- throw MyError("VideoSourceAVI: bad frame # (%d not within [%d, %d])", lFrameDesired, lSampleFirst, lSampleLast-1);
- // do we already have this frame?
- if (lLastFrame == lFrameDesired)
- return getFrameBuffer();
- if (hicDecomp) {
- // back us off to the last key frame if we need to
- lFrameNum = lFrameKey = nearestKey(lFrameDesired);
- _RPT1(0,"Nearest key frame: %ldn", lFrameKey);
- if (lLastFrame > lFrameKey && lLastFrame < lFrameDesired)
- lFrameNum = lLastFrame+1;
- // tell VCM we're going to do a little decompression...
- if (lLastFrame == -1) {
- err = ICDecompressBegin(hicDecomp, getImageFormat(), getDecompressedFormat());
- if (err != ICERR_OK) throw MyICError("VideoSourceAVI", err);
- }
- } else {
- lFrameNum = lFrameDesired;
- }
- _RPT2(0,"VideoSourceAVI: obtaining frame %ld, last was %ldn", lFrameDesired, lLastFrame);
- try {
- restart:
- do {
- _RPT1(0,"VideoSourceAVI: decompressing frame %ldn", lFrameNum);
- for(;;) {
- if (!dataBuffer)
- aviErr = AVIERR_BUFFERTOOSMALL;
- else
- aviErr = read(lFrameNum, 1, dataBuffer, dataBufferSize, &lBytesRead, &lSamplesRead);
- if (aviErr == AVIERR_BUFFERTOOSMALL) {
- void *newDataBuffer;
- aviErr = read(lFrameNum, 1, NULL, 0, &lBytesRead, &lSamplesRead);
- if (aviErr) throw MyAVIError("VideoSourceAVI", aviErr);
- dataBufferSize = (lBytesRead+65535) & -65535;
- if (!(newDataBuffer = reallocmem(dataBuffer, dataBufferSize)))
- throw MyMemoryError();
- dataBuffer = newDataBuffer;
- } else if (aviErr) {
- throw MyAVIError("VideoSourceAVI", aviErr);
- } else {
- // if (hicDecomp || lBytesRead) break;
- // --lFrameNum;
- break;
- }
- };
- if (!lBytesRead) continue;
- if (fUseGDI)
- streamGetFrame(dataBuffer, lBytesRead, TRUE, FALSE, lFrameNum);
- else if (hicDecomp) {
- bmihTemp->biSizeImage = lBytesRead;
- if (lBytesRead) {
- #if 0
- if( lFrameErr==lFrameNum ) {
- if( bit>16 ) {
- bit--;
- int byt = bit>>3;
- BYTE mask = 1 << (bit&7);
- BYTE *p = (BYTE*)dataBuffer;
- p[byt] ^= mask;
- } else {
- throw MyICError("VideoSourceAVI", err);
- }
- }
- #endif
- // VDCHECKPOINT;
- if (ICERR_OK != (err = ICDecompress(
- hicDecomp,
- // (lFrameNum<lFrameDesired ? ICDECOMPRESS_PREROLL : 0) |
- // (lBytesRead ? 0 : ICDECOMPRESS_NULLFRAME) |
- (lFrameNum > lFrameKey ? ICDECOMPRESS_NOTKEYFRAME : 0),
- bmihTemp,
- dataBuffer,
- getDecompressedFormat(),
- lpvBuffer))) {
- #if 0
- if( lFrameErr==lFrameNum ) {
- //lFrameNum = lFrameKey;
- goto restart;
- }
- if( lFrameErr<0 ) {
- bit = lBytesRead*8;
- lFrameErr = lFrameNum;
- lFrameNum = lFrameKey;
- goto restart;
- }
- #endif
- throw MyICError("VideoSourceAVI", err);
- }
- #if 0
- if( lFrameErr>=0 && (lFrameNum==lFrameErr) ) {
- _RPT2(0,"VideoSourceAVI: frame %ld has errors, xoring bit %ld corrects itn", lFrameNum, bit);
- }
- #endif
- // VDCHECKPOINT;
- }
- } else if (mdec) {
- /* try {
- if (getDecompressedFormat()->biBitCount == 32)
- mdec->decodeFrame32((unsigned long *)getFrameBuffer(), (unsigned char *)dataBuffer, lBytesRead);
- else
- mdec->decodeFrame16((unsigned long *)getFrameBuffer(), (unsigned char *)dataBuffer, lBytesRead);
- } catch(char *s) {
- throw MyError(s);
- }
- */ } else {
- if (lBytesRead < getImageFormat()->biSizeImage)
- throw MyError("VideoSourceAVI: uncompressed frame is short (expected %d bytes, got %d)", getImageFormat()->biSizeImage, lBytesRead);
- DIBconvert(dataBuffer, getImageFormat(), getFrameBuffer(), getDecompressedFormat());
- }
- // } else memcpy(getFrameBuffer(), dataBuffer, getDecompressedFormat()->biSizeImage);
- } while(++lFrameNum <= lFrameDesired);
- } catch(MyError e) {
- if (dataBuffer) freemem(dataBuffer);
- ICDecompressEnd(hicDecomp);
- lLastFrame = -1;
- throw e;
- }
- if (dataBuffer) freemem(dataBuffer);
- // if (hicDecomp) ICDecompressEnd(hicDecomp);
- lLastFrame = lFrameDesired;
- return getFrameBuffer();
- }