1
0
Fork 0

Add patch: "

[ 1425902 ] Zipped Motion Block Vector VFW codec fixes" from virtualdub


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2484
This commit is contained in:
Peter Veenstra 2006-02-12 12:35:13 +00:00
parent ecc77541f1
commit 234d45fabc
2 changed files with 121 additions and 26 deletions

View file

@ -480,14 +480,46 @@ void VideoCodec::Output_UpsideDown_24(void *output) {
int i;
unsigned char *r;
unsigned char *w = (unsigned char *)output;
int pad = width & 3;
for (i=height-1;i>=0;i--) {
r = newframe + pixelsize*(MAX_VECTOR+(i+MAX_VECTOR)*pitch);
for (int j=0;j<width;j++) {
int c=r[j];
*w++=palette[c*4+2];
*w++=palette[c*4+1];
*w++=palette[c*4+0];
r = newframe + pixelsize*(MAX_VECTOR+(i+MAX_VECTOR)*pitch);
switch (format) {
case ZMBV_FORMAT_8BPP:
for (int j=0;j<width;j++) {
int c=r[j];
*w++=palette[c*4+2];
*w++=palette[c*4+1];
*w++=palette[c*4+0];
}
break;
case ZMBV_FORMAT_15BPP:
for (int j=0;j<width;j++) {
unsigned short c = *(unsigned short *)&r[j*2];
*w++ = (unsigned char)(((c & 0x001f) * 0x21) >> 2);
*w++ = (unsigned char)(((c & 0x03e0) * 0x21) >> 7);
*w++ = (unsigned char)(((c & 0x7c00) * 0x21) >> 12);
}
break;
case ZMBV_FORMAT_16BPP:
for (int j=0;j<width;j++) {
unsigned short c = *(unsigned short *)&r[j*2];
*w++ = (unsigned char)(((c & 0x001f) * 0x21) >> 2);
*w++ = (unsigned char)(((c & 0x07e0) * 0x41) >> 9);
*w++ = (unsigned char)(((c & 0xf800) * 0x21) >> 13);
}
break;
case ZMBV_FORMAT_32BPP:
for (int j=0;j<width;j++) {
*w++ = r[j*4+0];
*w++ = r[j*4+1];
*w++ = r[j*4+2];
}
break;
}
// Maintain 32-bit alignment for scanlines.
w += pad;
}
}

View file

@ -160,7 +160,7 @@ DWORD CodecInst::GetInfo(ICINFO* icinfo, DWORD dwSize) {
icinfo->dwSize = sizeof(ICINFO);
icinfo->fccType = ICTYPE_VIDEO;
memcpy(&icinfo->fccHandler,CODEC_4CC, 4);
icinfo->dwFlags = VIDCF_FASTTEMPORALC | VIDCF_FASTTEMPORALD | VIDCF_TEMPORAL | VIDCF_QUALITY;
icinfo->dwFlags = VIDCF_FASTTEMPORALC | VIDCF_FASTTEMPORALD | VIDCF_TEMPORAL;
icinfo->dwVersion = VERSION;
icinfo->dwVersionICM = ICVERSION;
@ -173,36 +173,82 @@ DWORD CodecInst::GetInfo(ICINFO* icinfo, DWORD dwSize) {
/********************************************************************
****************************************************************/
static bool CanCompress(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
static int GetInputBitDepth(const BITMAPINFOHEADER *lpbiIn) {
if (lpbiIn->biCompression == BI_RGB) {
if (lpbiIn->biPlanes != 1)
return -1;
switch(lpbiIn->biBitCount) {
case 8:
return 8;
case 16:
return 15; // Standard Windows 16-bit RGB is 1555.
case 32:
return 32;
}
} else if (lpbiIn->biCompression == BI_BITFIELDS) {
// BI_BITFIELDS RGB masks lie right after the BITMAPINFOHEADER structure,
// at (ptr+40). This is true even for a BITMAPV4HEADER or BITMAPV5HEADER.
const DWORD *masks = (const DWORD *)(lpbiIn + 1);
if (lpbiIn->biBitCount == 16) {
// Test for 16 (555)
if (masks[0] == 0x7C00 && masks[1] == 0x03E0 && masks[2] == 0x001F)
return 15;
// Test for 16 (565)
if (masks[0] == 0xF800 && masks[1] == 0x07E0 && masks[2] == 0x001F)
return 16;
} else if (lpbiIn->biBitCount == 32) {
if (masks[0] == 0xFF0000 && masks[1] == 0x00FF00 && masks[2] == 0x0000FF)
return 32;
}
}
return -1;
}
static bool CanCompress(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut, bool requireOutput) {
if (lpbiIn) {
if (lpbiIn->biCompression) return false;
if (lpbiIn->biBitCount==24) return false;
if (GetInputBitDepth(lpbiIn) < 0)
return false;
} else return false;
if (lpbiOut) {
if (memcmp(&lpbiOut->biCompression,CODEC_4CC, 4))
return false;
} else return false;
} else return !requireOutput;
return true;
}
/********************************************************************
****************************************************************/
DWORD CodecInst::CompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
if (CanCompress(lpbiIn,lpbiOut)) return ICERR_OK;
if (CanCompress(lpbiIn,lpbiOut,false)) return ICERR_OK;
return ICERR_BADFORMAT;
}
DWORD CodecInst::CompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
if (!lpbiOut)
return sizeof(BITMAPINFOHEADER);
if (!CanCompress(lpbiIn,lpbiOut))
return ICERR_BADFORMAT;
lpbiOut->biSize = sizeof(BITMAPINFOHEADER);
lpbiOut->biWidth = lpbiIn->biWidth;
lpbiOut->biHeight = lpbiIn->biHeight;
lpbiOut->biPlanes = 1;
lpbiOut->biCompression = *(const DWORD *)CODEC_4CC;
lpbiOut->biBitCount = lpbiIn->biBitCount;
lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * lpbiIn->biBitCount/8 + 1024;
lpbiOut->biXPelsPerMeter = lpbiIn->biXPelsPerMeter;
lpbiOut->biYPelsPerMeter = lpbiIn->biYPelsPerMeter;
lpbiOut->biClrUsed = 0;
lpbiOut->biClrImportant = 0;
return ICERR_OK;
}
DWORD CodecInst::CompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
CompressEnd(); // free resources if necessary
if (!CanCompress(lpbiIn, lpbiOut))
if (!CanCompress(lpbiIn, lpbiOut, true))
return ICERR_BADFORMAT;
codec = new VideoCodec();
if (!codec)
@ -213,7 +259,7 @@ DWORD CodecInst::CompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpb
}
DWORD CodecInst::CompressGetSize(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
if (!CanCompress(lpbiIn, lpbiOut))
if (!CanCompress(lpbiIn, lpbiOut, true))
return ICERR_BADFORMAT;
return lpbiIn->biWidth * lpbiIn->biHeight * lpbiIn->biBitCount/8 + 1024;
}
@ -223,11 +269,11 @@ DWORD CodecInst::Compress(ICCOMPRESS* icinfo, DWORD dwSize) {
zmbv_format_t format;
LPBITMAPINFOHEADER lpbiIn=icinfo->lpbiInput;
LPBITMAPINFOHEADER lpbiOut=icinfo->lpbiOutput;
if (!CanCompress(lpbiIn, lpbiOut))
if (!CanCompress(lpbiIn, lpbiOut, true))
return ICERR_BADFORMAT;
if (!icinfo->lpInput || !icinfo->lpOutput)
return ICERR_ABORT;
switch (lpbiIn->biBitCount) {
switch (GetInputBitDepth(lpbiIn)) {
case 8:
format = ZMBV_FORMAT_8BPP;
pitch = lpbiIn->biWidth;
@ -245,13 +291,28 @@ DWORD CodecInst::Compress(ICCOMPRESS* icinfo, DWORD dwSize) {
pitch = lpbiIn->biWidth * 4;
break;
}
codec->PrepareCompressFrame( 0, format, 0, icinfo->lpOutput, 99999999);
char *readPt = (char *)icinfo->lpbiInput;
// DIB scanlines for RGB formats are always aligned to DWORD.
pitch = (pitch + 3) & ~3;
// force a key frame if requested by the client
int flags = 0;
if (icinfo->dwFlags & ICCOMPRESS_KEYFRAME)
flags |= 1;
codec->PrepareCompressFrame( flags, format, 0, icinfo->lpOutput, 99999999);
char *readPt = (char *)icinfo->lpInput + pitch*(lpbiIn->biHeight - 1);
for(i = 0;i<lpbiIn->biHeight;i++) {
codec->CompressLines(1, (void **)&readPt );
readPt += pitch;
readPt -= pitch;
}
lpbiOut->biSizeImage = codec->FinishCompressFrame();
if (flags & 1)
*icinfo->lpdwFlags = AVIIF_KEYFRAME;
else
*icinfo->lpdwFlags = 0;
return ICERR_OK;
}
@ -291,10 +352,13 @@ DWORD CodecInst::DecompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEAD
return ICERR_BADFORMAT;
if (!lpbiOut) return sizeof(BITMAPINFOHEADER);
*lpbiOut = *lpbiIn;
lpbiOut->biPlanes = 1;
lpbiOut->biSize=sizeof(BITMAPINFOHEADER);
lpbiOut->biBitCount=24;
lpbiOut->biCompression=0;
lpbiOut->biPlanes = 1;
lpbiOut->biSize = sizeof(BITMAPINFOHEADER);
lpbiOut->biBitCount = 24;
lpbiOut->biSizeImage = ((lpbiOut->biWidth*3 + 3) & ~3) * lpbiOut->biHeight;
lpbiOut->biCompression = BI_RGB;
lpbiOut->biClrUsed = 0;
lpbiOut->biClrImportant = 0;
return ICERR_OK;
}
@ -315,7 +379,6 @@ DWORD CodecInst::Decompress(ICDECOMPRESS* icinfo, DWORD dwSize) {
return ICERR_ABORT;
if (codec->DecompressFrame( icinfo->lpInput, icinfo->lpbiInput->biSizeImage)) {
codec->Output_UpsideDown_24(icinfo->lpOutput);
icinfo->lpbiOutput->biSizeImage=icinfo->lpbiOutput->biWidth*icinfo->lpbiOutput->biHeight*icinfo->lpbiOutput->biBitCount/8;
} else return ICERR_DONTDRAW;
return ICERR_OK;
}