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:
parent
ecc77541f1
commit
234d45fabc
2 changed files with 121 additions and 26 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue