📄 videosource.cpp
字号:
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: %ld\n", 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 %ld\n", lFrameDesired, lLastFrame);
try {
restart:
do {
_RPT1(0,"VideoSourceAVI: decompressing frame %ld\n", 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 it\n", 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();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -