1
0
Fork 0

ZMBV codec for avi capturing

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2451
This commit is contained in:
Sjoerd van der Berg 2006-01-30 10:10:04 +00:00
parent b032209b75
commit 40c0e26781
10 changed files with 1265 additions and 0 deletions

212
src/libs/zmbv/drvproc.cpp Normal file
View file

@ -0,0 +1,212 @@
/*
* Copyright (C) 2002-2005 The DOSBox Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//
// Zipped Motion Block Video
//
// Based on Huffyuv by Ben Rudiak-Gould.
// which was based on MSYUV sample code, which is:
// Copyright (c) 1993 Microsoft Corporation.
// All Rights Reserved.
//
#include "zmbv_vfw.h"
/***************************************************************************
* DriverProc - The entry point for an installable driver.
*
* PARAMETERS
* dwDriverId: For most messages, <dwDriverId> is the DWORD
* value that the driver returns in response to a <DRV_OPEN> message.
* Each time that the driver is opened, through the <DrvOpen> API,
* the driver receives a <DRV_OPEN> message and can return an
* arbitrary, non-zero value. The installable driver interface
* saves this value and returns a unique driver handle to the
* application. Whenever the application sends a message to the
* driver using the driver handle, the interface routes the message
* to this entry point and passes the corresponding <dwDriverId>.
* This mechanism allows the driver to use the same or different
* identifiers for multiple opens but ensures that driver handles
* are unique at the application interface layer.
*
* The following messages are not related to a particular open
* instance of the driver. For these messages, the dwDriverId
* will always be zero.
*
* DRV_LOAD, DRV_FREE, DRV_ENABLE, DRV_DISABLE, DRV_OPEN
*
* hDriver: This is the handle returned to the application by the
* driver interface.
*
* uiMessage: The requested action to be performed. Message
* values below <DRV_RESERVED> are used for globally defined messages.
* Message values from <DRV_RESERVED> to <DRV_USER> are used for
* defined driver protocols. Messages above <DRV_USER> are used
* for driver specific messages.
*
* lParam1: Data for this message. Defined separately for
* each message
*
* lParam2: Data for this message. Defined separately for
* each message
*
* RETURNS
* Defined separately for each message.
*
***************************************************************************/
LRESULT PASCAL DriverProc(DWORD dwDriverID, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2) {
CodecInst* pi = (CodecInst*)dwDriverID;
switch (uiMessage) {
case DRV_LOAD:
return (LRESULT)1L;
case DRV_FREE:
return (LRESULT)1L;
case DRV_OPEN:
// GAAH! This used to return a pointer to 0xFFFF0000 when lParam==0!
return (LRESULT)(DWORD)(UINT) Open((ICOPEN*) lParam2);
case DRV_CLOSE:
if (pi) Close(pi);
return (LRESULT)1L;
/*********************************************************************
state messages
*********************************************************************/
// cwk
case DRV_QUERYCONFIGURE: // configuration from drivers applet
return (LRESULT)1L;
case DRV_CONFIGURE:
pi->Configure((HWND)lParam1);
return DRV_OK;
case ICM_CONFIGURE:
//
// return ICERR_OK if you will do a configure box, error otherwise
//
if (lParam1 == -1)
return pi->QueryConfigure() ? ICERR_OK : ICERR_UNSUPPORTED;
else
return pi->Configure((HWND)lParam1);
case ICM_ABOUT:
//
// return ICERR_OK if you will do a about box, error otherwise
//
if (lParam1 == -1)
return pi->QueryAbout() ? ICERR_OK : ICERR_UNSUPPORTED;
else
return pi->About((HWND)lParam1);
case ICM_GETSTATE:
return pi->GetState((LPVOID)lParam1, (DWORD)lParam2);
case ICM_SETSTATE:
return pi->SetState((LPVOID)lParam1, (DWORD)lParam2);
case ICM_GETINFO:
return pi->GetInfo((ICINFO*)lParam1, (DWORD)lParam2);
case ICM_GETDEFAULTQUALITY:
if (lParam1) {
*((LPDWORD)lParam1) = 10000;
return ICERR_OK;
}
break;
/*********************************************************************
compression messages
*********************************************************************/
case ICM_COMPRESS_QUERY:
return pi->CompressQuery((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2);
case ICM_COMPRESS_BEGIN:
return pi->CompressBegin((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2);
case ICM_COMPRESS_GET_FORMAT:
return pi->CompressGetFormat((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2);
case ICM_COMPRESS_GET_SIZE:
return pi->CompressGetSize((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2);
case ICM_COMPRESS:
return pi->Compress((ICCOMPRESS*)lParam1, (DWORD)lParam2);
case ICM_COMPRESS_END:
return pi->CompressEnd();
/*********************************************************************
decompress messages
*********************************************************************/
case ICM_DECOMPRESS_QUERY:
return pi->DecompressQuery((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2);
case ICM_DECOMPRESS_BEGIN:
return pi->DecompressBegin((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2);
case ICM_DECOMPRESS_GET_FORMAT:
return pi->DecompressGetFormat((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2);
case ICM_DECOMPRESS_GET_PALETTE:
return pi->DecompressGetPalette((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2);
case ICM_DECOMPRESS:
return pi->Decompress((ICDECOMPRESS*)lParam1, (DWORD)lParam2);
case ICM_DECOMPRESS_END:
return pi->DecompressEnd();
/*********************************************************************
standard driver messages
*********************************************************************/
case DRV_DISABLE:
case DRV_ENABLE:
return (LRESULT)1L;
case DRV_INSTALL:
case DRV_REMOVE:
return (LRESULT)DRV_OK;
}
if (uiMessage < DRV_USER)
return DefDriverProc(dwDriverID, hDriver, uiMessage, lParam1, lParam2);
else
return ICERR_UNSUPPORTED;
}
HMODULE hmoduleCodec=0;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD, LPVOID) {
hmoduleCodec = (HMODULE) hinstDLL;
return TRUE;
}

21
src/libs/zmbv/resource.h Normal file
View file

@ -0,0 +1,21 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by zmbv_vfw.rc
//
#define IDD_ABOUT 101
#define IDD_CONFIGURE 102
#define IDC_HOMEPAGE 1000
#define IDC_EMAIL 1001
#define IDC_SLIDER1 1008
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1009
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

516
src/libs/zmbv/zmbv.cpp Normal file
View file

@ -0,0 +1,516 @@
/*
* Copyright (C) 2002-2005 The DOSBox Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <zlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "zmbv.h"
#define DBZV_VERSION_HIGH 0
#define DBZV_VERSION_LOW 1
#define COMPRESSION_NONE 0
#define COMPRESSION_ZLIB 1
#define MAX_VECTOR 16
#define Mask_KeyFrame 0x01
#define Mask_DeltaPalette 0x02
zmbv_format_t BPPFormat( int bpp ) {
switch (bpp) {
case 8:
return ZMBV_FORMAT_8BPP;
case 15:
return ZMBV_FORMAT_15BPP;
case 16:
return ZMBV_FORMAT_16BPP;
case 32:
return ZMBV_FORMAT_32BPP;
}
return ZMBV_FORMAT_NONE;
}
int VideoCodec::NeededSize( int _width, int _height, zmbv_format_t _format) {
int f;
switch (_format) {
case ZMBV_FORMAT_8BPP:f = 1;break;
case ZMBV_FORMAT_15BPP:f = 2;break;
case ZMBV_FORMAT_16BPP:f = 2;break;
case ZMBV_FORMAT_32BPP:f = 4;break;
default:
return -1;
}
f = f*_width*_height + 2*(1+(_width/8)) * (1+(_height/8))+1024;
return f + f/1000;
}
bool VideoCodec::SetupBuffers(zmbv_format_t _format, int blockwidth, int blockheight) {
FreeBuffers();
palsize = 0;
switch (_format) {
case ZMBV_FORMAT_8BPP:
pixelsize = 1;
palsize = 256;
break;
case ZMBV_FORMAT_15BPP:
pixelsize = 2;
break;
case ZMBV_FORMAT_16BPP:
pixelsize = 2;
break;
case ZMBV_FORMAT_32BPP:
pixelsize = 4;
break;
default:
return false;
};
bufsize = (height+2*MAX_VECTOR)*pitch*pixelsize+2048;
buf1 = new unsigned char[bufsize];
buf2 = new unsigned char[bufsize];
work = new unsigned char[bufsize];
int xblocks = (width/blockwidth);
int xleft = width % blockwidth;
if (xleft) xblocks++;
int yblocks = (height/blockheight);
int yleft = height % blockheight;
if (yleft) yblocks++;
blockcount=yblocks*xblocks;
blocks=new FrameBlock[blockcount];
if (!buf1 || !buf2 || !work || !blocks) {
FreeBuffers();
return false;
}
int y,x,i;
i=0;
for (y=0;y<yblocks;y++) {
for (x=0;x<xblocks;x++) {
blocks[i].start=((y*blockheight)+MAX_VECTOR)*pitch+
(x*blockwidth)+MAX_VECTOR;
if (xleft && x==(xblocks-1)) {
blocks[i].dx=xleft;
} else {
blocks[i].dx=blockwidth;
}
if (yleft && y==(yblocks-1)) {
blocks[i].dy=yleft;
} else {
blocks[i].dy=blockheight;
}
i++;
}
}
memset(buf1,0,bufsize);
memset(buf2,0,bufsize);
memset(work,0,bufsize);
oldframe=buf1;
newframe=buf2;
format = _format;
return true;
}
void VideoCodec::CreateVectorTable(void) {
int x,y,s;
VectorCount=1;
VectorTable[0].x=VectorTable[0].y=0;
for (s=1;s<=10;s++) {
for (y=0-s;y<=0+s;y++) for (x=0-s;x<=0+s;x++) {
if (abs(x)==s || abs(y)==s) {
VectorTable[VectorCount].x=x;
VectorTable[VectorCount].y=y;
VectorCount++;
}
}
}
}
template<class P>
INLINE int VideoCodec::PossibleBlock(int vx,int vy,FrameBlock * block) {
int ret=0;
P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx;
P * pnew=((P*)newframe)+block->start;;
for (int y=0;y<block->dy;y+=4) {
for (int x=0;x<block->dx;x+=4) {
int test=0-((pold[x]-pnew[x])&0x00ffffff);
ret-=(test>>31);
}
pold+=pitch*4;
pnew+=pitch*4;
}
return ret;
}
template<class P>
INLINE int VideoCodec::CompareBlock(int vx,int vy,FrameBlock * block) {
int ret=0;
P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx;
P * pnew=((P*)newframe)+block->start;;
for (int y=0;y<block->dy;y++) {
for (int x=0;x<block->dx;x++) {
int test=0-((pold[x]-pnew[x])&0x00ffffff);
ret-=(test>>31);
}
pold+=pitch;
pnew+=pitch;
}
return ret;
}
template<class P>
INLINE void VideoCodec::AddXorBlock(int vx,int vy,FrameBlock * block) {
P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx;
P * pnew=((P*)newframe)+block->start;
for (int y=0;y<block->dy;y++) {
for (int x=0;x<block->dx;x++) {
*((P*)&work[workUsed])=pnew[x] ^ pold[x];
workUsed+=sizeof(P);
}
pold+=pitch;
pnew+=pitch;
}
}
template<class P>
void VideoCodec::AddXorFrame(void) {
int written=0;
int lastvector=0;
signed char * vectors=(signed char*)&work[workUsed];
/* Align the following xor data on 4 byte boundary*/
workUsed=(workUsed + blockcount*2 +3) & ~3;
int totalx=0;
int totaly=0;
for (int b=0;b<blockcount;b++) {
FrameBlock * block=&blocks[b];
int bestvx = 0;
int bestvy = 0;
int bestchange=CompareBlock<P>(0,0, block);
int possibles=64;
for (int v=0;v<VectorCount && possibles;v++) {
if (bestchange<4) break;
int vx = VectorTable[v].x;
int vy = VectorTable[v].y;
if (PossibleBlock<P>(vx, vy, block) < 4) {
possibles--;
// if (!possibles) Msg("Ran out of possibles, at %d of %d best %d\n",v,VectorCount,bestchange);
int testchange=CompareBlock<P>(vx,vy, block);
if (testchange<bestchange) {
bestchange=testchange;
bestvx = vx;
bestvy = vy;
}
}
}
vectors[b*2+0]=(bestvx << 1);
vectors[b*2+1]=(bestvy << 1);
if (bestchange) {
vectors[b*2+0]|=1;
AddXorBlock<P>(bestvx, bestvy, block);
}
}
}
bool VideoCodec::SetupCompress( int _width, int _height ) {
width = _width;
height = _height;
pitch = _width + 2*MAX_VECTOR;
format = ZMBV_FORMAT_NONE;
if (deflateInit (&zstream, 4) != Z_OK)
return false;
return true;
}
bool VideoCodec::SetupDecompress( int _width, int _height) {
width = _width;
height = _height;
pitch = _width + 2*MAX_VECTOR;
format = ZMBV_FORMAT_NONE;
if (inflateInit (&zstream) != Z_OK)
return false;
return true;
}
bool VideoCodec::PrepareCompressFrame(int flags, zmbv_format_t _format, char * pal, void *writeBuf, int writeSize) {
int i;
unsigned char *firstByte;
if (_format != format) {
if (!SetupBuffers( _format, 16, 16))
return false;
flags|=1; //Force a keyframe
}
/* replace oldframe with new frame */
unsigned char *copyFrame = newframe;
newframe = oldframe;
oldframe = copyFrame;
compress.linesDone = 0;
compress.writeSize = writeSize;
compress.writeDone = 1;
compress.writeBuf = (unsigned char *)writeBuf;
/* Set a pointer to the first byte which will contain info about this frame */
firstByte = compress.writeBuf;
*firstByte = 0;
//Reset the work buffer
workUsed = 0;workPos = 0;
if (flags & 1) {
/* Make a keyframe */
*firstByte |= Mask_KeyFrame;
KeyframeHeader * header = (KeyframeHeader *)(compress.writeBuf + compress.writeDone);
header->high_version = DBZV_VERSION_HIGH;
header->low_version = DBZV_VERSION_LOW;
header->compression = COMPRESSION_ZLIB;
header->format = format;
header->blockwidth = 16;
header->blockheight = 16;
compress.writeDone += sizeof(KeyframeHeader);
/* Copy the new frame directly over */
if (palsize) {
if (pal)
memcpy(&palette, pal, sizeof(palette));
else
memset(&palette,0, sizeof(palette));
/* keyframes get the full palette */
for (i=0;i<palsize;i++) {
work[workUsed++] = palette[i*4+0];
work[workUsed++] = palette[i*4+1];
work[workUsed++] = palette[i*4+2];
}
}
/* Restart deflate */
deflateReset(&zstream);
} else {
if (palsize && pal && memcmp(pal, palette, palsize * 4)) {
*firstByte |= Mask_DeltaPalette;
for(i=0;i<palsize;i++) {
work[workUsed++]=palette[i*4+0] ^ pal[i*4+0];
work[workUsed++]=palette[i*4+1] ^ pal[i*4+1];
work[workUsed++]=palette[i*4+2] ^ pal[i*4+2];
}
memcpy(&palette,pal, palsize * 4);
}
}
return true;
}
void VideoCodec::CompressLines(int lineCount, void *lineData[]) {
int linePitch = pitch * pixelsize;
int lineWidth = width * pixelsize;
int i = 0;
unsigned char *destStart = newframe + pixelsize*(MAX_VECTOR+(compress.linesDone+MAX_VECTOR)*pitch);
while ( i < lineCount && (compress.linesDone < height)) {
memcpy(destStart, lineData[i], lineWidth );
destStart += linePitch;
i++;compress.linesDone++;
}
}
int VideoCodec::FinishCompressFrame( void ) {
unsigned char firstByte = *compress.writeBuf;
if (firstByte & Mask_KeyFrame) {
int i;
/* Add the full frame data */
unsigned char * readFrame = newframe + pixelsize*(MAX_VECTOR+MAX_VECTOR*pitch);
for (i=0;i<height;i++) {
memcpy(&work[workUsed], readFrame, width*pixelsize);
readFrame += pitch*pixelsize;
workUsed += width*pixelsize;
}
} else {
/* Add the delta frame data */
switch (format) {
case ZMBV_FORMAT_8BPP:
AddXorFrame<char>();
break;
case ZMBV_FORMAT_15BPP:
case ZMBV_FORMAT_16BPP:
AddXorFrame<short>();
break;
case ZMBV_FORMAT_32BPP:
AddXorFrame<long>();
break;
}
}
/* Create the actual frame with compression */
zstream.next_in = (Bytef *)work;
zstream.avail_in = workUsed;
zstream.total_in = 0;
zstream.next_out = (Bytef *)(compress.writeBuf + compress.writeDone);
zstream.avail_out = compress.writeSize - compress.writeDone;
zstream.total_out = 0;
int res = deflate(&zstream, Z_SYNC_FLUSH);
return compress.writeDone + zstream.total_out;
}
template<class P>
INLINE void VideoCodec::UnXorBlock(int vx,int vy,FrameBlock * block) {
P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx;
P * pnew=((P*)newframe)+block->start;
for (int y=0;y<block->dy;y++) {
for (int x=0;x<block->dx;x++) {
pnew[x]=pold[x]^*((P*)&work[workPos]);
workPos+=sizeof(P);
}
pold+=pitch;
pnew+=pitch;
}
}
template<class P>
INLINE void VideoCodec::CopyBlock(int vx,int vy,FrameBlock * block) {
P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx;
P * pnew=((P*)newframe)+block->start;
for (int y=0;y<block->dy;y++) {
for (int x=0;x<block->dx;x++) {
pnew[x]=pold[x];
}
pold+=pitch;
pnew+=pitch;
}
}
template<class P>
void VideoCodec::UnXorFrame(void) {
signed char * vectors=(signed char *)&work[workPos];
workPos=(workPos + blockcount*2 + 3) & ~3;
for (int b=0;b<blockcount;b++) {
FrameBlock * block=&blocks[b];
int xor = vectors[b*2+0] & 1;
int vx = vectors[b*2+0] >> 1;
int vy = vectors[b*2+1] >> 1;
if (xor) UnXorBlock<P>(vx,vy,block);
else CopyBlock<P>(vx,vy,block);
}
}
bool VideoCodec::DecompressFrame(void * framedata, int size) {
unsigned char *data=(unsigned char *)framedata;
unsigned char tag;int i;
tag = *data++;
if (--size<=0)
return false;
if (tag & Mask_KeyFrame) {
KeyframeHeader * header = (KeyframeHeader *)data;
size -= sizeof(KeyframeHeader);data += sizeof(KeyframeHeader);
if (size<=0)
return false;
if (header->low_version != DBZV_VERSION_LOW || header->high_version != DBZV_VERSION_HIGH)
return false;
if (format != (zmbv_format_t)header->format && !SetupBuffers((zmbv_format_t)header->format, header->blockwidth, header->blockheight))
return false;
inflateReset(&zstream);
}
zstream.next_in = (Bytef *)data;
zstream.avail_in = size;
zstream.total_in = 0;
zstream.next_out = (Bytef *)work;
zstream.avail_out = bufsize;
zstream.total_out = 0;
int res = inflate(&zstream, Z_FINISH);
workUsed= zstream.total_out;
workPos = 0;
if (tag & Mask_KeyFrame) {
if (palsize) {
for (i=0;i<palsize;i++) {
palette[i*4+0] = work[workPos++];
palette[i*4+1] = work[workPos++];
palette[i*4+2] = work[workPos++];
}
}
newframe = buf1;
oldframe = buf2;
unsigned char * writeframe = newframe + pixelsize*(MAX_VECTOR+MAX_VECTOR*pitch);
for (i=0;i<height;i++) {
memcpy(writeframe,&work[workPos],width*pixelsize);
writeframe+=pitch*pixelsize;
workPos+=width*pixelsize;
}
} else {
data = oldframe;
oldframe = newframe;
newframe = data;
if (tag & Mask_DeltaPalette) {
for (i=0;i<palsize;i++) {
palette[i*4+0] ^= work[workPos++];
palette[i*4+1] ^= work[workPos++];
palette[i*4+2] ^= work[workPos++];
}
}
switch (format) {
case ZMBV_FORMAT_8BPP:
UnXorFrame<char>();
break;
case ZMBV_FORMAT_15BPP:
case ZMBV_FORMAT_16BPP:
UnXorFrame<short>();
break;
case ZMBV_FORMAT_32BPP:
UnXorFrame<long>();
break;
}
}
return true;
}
void VideoCodec::Output_UpsideDown_24(void *output) {
int i;
unsigned char *r;
unsigned char *w = (unsigned char *)output;
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];
}
}
}
void VideoCodec::FreeBuffers(void) {
if (blocks) {
delete[] blocks;blocks=0;
}
if (buf1) {
delete[] buf1;buf1=0;
}
if (buf2) {
delete[] buf2;buf2=0;
}
if (work) {
delete[] work;work=0;
}
}
VideoCodec::VideoCodec() {
CreateVectorTable();
blocks = 0;
buf1 = 0;
buf2 = 0;
work = 0;
memset( &zstream, 0, sizeof(zstream));
}

4
src/libs/zmbv/zmbv.def Normal file
View file

@ -0,0 +1,4 @@
LIBRARY ZMBV
EXPORTS
DriverProc

112
src/libs/zmbv/zmbv.h Normal file
View file

@ -0,0 +1,112 @@
/*
* Copyright (C) 2002-2005 The DOSBox Team
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define INLINE __forceinline
#define CODEC_4CC "ZMBV"
typedef enum {
ZMBV_FORMAT_NONE = 0x00,
ZMBV_FORMAT_1BPP = 0x01,
ZMBV_FORMAT_2BPP = 0x02,
ZMBV_FORMAT_4BPP = 0x03,
ZMBV_FORMAT_8BPP = 0x04,
ZMBV_FORMAT_15BPP = 0x05,
ZMBV_FORMAT_16BPP = 0x06,
ZMBV_FORMAT_24BPP = 0x07,
ZMBV_FORMAT_32BPP = 0x08
} zmbv_format_t;
void Msg(const char fmt[], ...);
class VideoCodec {
private:
struct FrameBlock {
int start;
int dx,dy;
};
struct CodecVector {
int x,y;
int slot;
};
struct KeyframeHeader {
unsigned char high_version;
unsigned char low_version;
unsigned char compression;
unsigned char format;
unsigned char blockwidth,blockheight;
};
struct {
int linesDone;
int writeSize;
int writeDone;
unsigned char *writeBuf;
} compress;
CodecVector VectorTable[512];
int VectorCount;
unsigned char *oldframe, *newframe;
unsigned char *buf1, *buf2, *work;
int bufsize;
int blockcount;
FrameBlock * blocks;
int workUsed, workPos;
int palsize;
char palette[256*4];
int height, width, pitch;
zmbv_format_t format;
int pixelsize;
z_stream zstream;
// methods
void FreeBuffers(void);
void CreateVectorTable(void);
bool SetupBuffers(zmbv_format_t format, int blockwidth, int blockheight);
template<class P>
void AddXorFrame(void);
template<class P>
void UnXorFrame(void);
template<class P>
INLINE int PossibleBlock(int vx,int vy,FrameBlock * block);
template<class P>
INLINE int CompareBlock(int vx,int vy,FrameBlock * block);
template<class P>
INLINE void AddXorBlock(int vx,int vy,FrameBlock * block);
template<class P>
INLINE void UnXorBlock(int vx,int vy,FrameBlock * block);
template<class P>
INLINE void CopyBlock(int vx, int vy,FrameBlock * block);
public:
VideoCodec();
bool SetupCompress( int _width, int _height);
bool SetupDecompress( int _width, int _height);
zmbv_format_t BPPFormat( int bpp );
int NeededSize( int _width, int _height, zmbv_format_t _format);
void CompressLines(int lineCount, void *lineData[]);
bool PrepareCompressFrame(int flags, zmbv_format_t _format, char * pal, void *writeBuf, int writeSize);
int FinishCompressFrame( void );
bool DecompressFrame(void * framedata, int size);
void Output_UpsideDown_24(void * output);
};

54
src/libs/zmbv/zmbv.inf Normal file
View file

@ -0,0 +1,54 @@
;
; Zip Motion Block Video AVI codec
;
; Copyright (c) 2000 Ben Rudiak-Gould
;
; This Windows 9x Installation INF File by Rainbow Software
;
[version]
signature="$CHICAGO$"
[DefaultInstall]
CopyFiles=ZMBV.Files.Inf,ZMBV.Files.Dll
AddReg=ZMBV.Reg
UpdateInis=ZMBV.INIs
[DefaultUnInstall]
DelFiles=ZMBV.Files.Dll,ZMBV.Files.Inf,ZMBV.Files.Ini
DelReg=ZMBV.Reg
UpdateInis=ZMBV.INIs.Del
[SourceDisksNames]
1="Zip Motion Block Video codec","",1
[SourceDisksFiles]
ZMBV.INF=1
[DestinationDirs]
ZMBV.Files.Inf=17
ZMBV.Files.Dll=11
ZMBV.Files.Ini=25
[ZMBV.Files.Inf]
zmbv.inf
[ZMBV.Files.Dll]
zmbv.dll
[ZMBV.Files.Ini]
zmbv.ini
[ZMBV.Reg]
HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\icm\VIDC.ZMBV,Description,,"Zip Motion Block Video [ZMBV]"
HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\icm\VIDC.ZMBV,Driver,,"zmbv.dll"
HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\icm\VIDC.ZMBV,FriendlyName,,"Zip Motion Block Video [ZMBV]"
HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV
HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,DisplayName,,"Zip Motion Block Video codec (Remove Only)"
HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,UninstallString,,"rundll.exe setupx.dll,InstallHinfSection DefaultUninstall 132 %17%\ZMBV.INF"
[ZMBV.INIs]
system.ini, drivers32,, "VIDC.ZMBV=zmbv.dll"
[ZMBV.INIs.Del]
system.ini, drivers32, "VIDC.ZMBV=zmbv.dll"

21
src/libs/zmbv/zmbv.sln Normal file
View file

@ -0,0 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zmbv", "zmbv.vcproj", "{619CF3F9-C373-4BD5-93DA-025F5E16F8FA}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{619CF3F9-C373-4BD5-93DA-025F5E16F8FA}.Debug.ActiveCfg = Debug|Win32
{619CF3F9-C373-4BD5-93DA-025F5E16F8FA}.Debug.Build.0 = Debug|Win32
{619CF3F9-C373-4BD5-93DA-025F5E16F8FA}.Release.ActiveCfg = Release|Win32
{619CF3F9-C373-4BD5-93DA-025F5E16F8FA}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

141
src/libs/zmbv/zmbv.vcproj Normal file
View file

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="zmbv"
ProjectGUID="{619CF3F9-C373-4BD5-93DA-025F5E16F8FA}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="2"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
BufferSecurityCheck="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib odbc32.lib odbccp32.lib zlib.lib"
OutputFile="$(OutDir)/zmbv.dll"
LinkIncremental="2"
ModuleDefinitionFile="zmbv.def"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/zmbv.pdb"
SubSystem="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="2"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib odbc32.lib odbccp32.lib zlib.lib"
OutputFile="$(OutDir)/zmbv.dll"
LinkIncremental="1"
ModuleDefinitionFile="zmbv.def"
GenerateDebugInformation="TRUE"
MapExports="TRUE"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=".\drvproc.cpp">
</File>
<File
RelativePath=".\Resource.h">
</File>
<File
RelativePath=".\zmbv.cpp">
</File>
<File
RelativePath=".\zmbv.def">
</File>
<File
RelativePath=".\zmbv.h">
</File>
<File
RelativePath=".\zmbv_vfw.cpp">
</File>
<File
RelativePath=".\zmbv_vfw.rc">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

61
src/libs/zmbv/zmbv_vfw.h Normal file
View file

@ -0,0 +1,61 @@
//
// Huffyuv v2.1.1, by Ben Rudiak-Gould.
// http://www.math.berkeley.edu/~benrg/huffyuv.html
//
// This file is copyright 2000 Ben Rudiak-Gould, and distributed under
// the terms of the GNU General Public License, v2 or later. See
// http://www.gnu.org/copyleft/gpl.html.
//
// I edit these files in 10-point Verdana, a proportionally-spaced font.
// You may notice formatting oddities if you use a monospaced font.
//
#include <windows.h>
#include <vfw.h>
#include <zlib.h>
#include "zmbv.h"
#pragma hdrstop
extern HMODULE hmoduleCodec;
// huffyuv.cpp
class CodecInst {
private:
VideoCodec * codec;
public:
CodecInst();
~CodecInst();
BOOL QueryAbout();
DWORD About(HWND hwnd);
BOOL QueryConfigure();
DWORD Configure(HWND hwnd);
DWORD GetState(LPVOID pv, DWORD dwSize);
DWORD SetState(LPVOID pv, DWORD dwSize);
DWORD GetInfo(ICINFO* icinfo, DWORD dwSize);
DWORD CompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut);
DWORD CompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut);
DWORD CompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut);
DWORD CompressGetSize(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut);
DWORD Compress(ICCOMPRESS* icinfo, DWORD dwSize);
DWORD CompressEnd();
DWORD DecompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut);
DWORD DecompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut);
DWORD DecompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut);
DWORD Decompress(ICDECOMPRESS* icinfo, DWORD dwSize);
DWORD DecompressGetPalette(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut);
DWORD DecompressEnd();
};
CodecInst* Open(ICOPEN* icinfo);
DWORD Close(CodecInst* pinst);

123
src/libs/zmbv/zmbv_vfw.rc Normal file
View file

@ -0,0 +1,123 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUT DIALOGEX 0, 0, 167, 55
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "DOSBox Video Codec v0.1"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,131,34,29,14
CTEXT "Zipped Motion Block Video v 0.1\nCopyright 2005, DOSBox Team",
IDC_STATIC,7,7,153,25,SS_NOPREFIX
PUSHBUTTON "Email author",IDC_EMAIL,7,34,50,14
PUSHBUTTON "Visit home page",IDC_HOMEPAGE,59,34,58,14
END
IDD_CONFIGURE DIALOGEX 0, 0, 213, 146
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "ZMBV configuration dialog"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
PUSHBUTTON "Email author",IDC_EMAIL,44,86,50,14
PUSHBUTTON "Visit home page",IDC_HOMEPAGE,109,87,58,14
DEFPUSHBUTTON "OK",IDOK,44,125,50,14
PUSHBUTTON "Cancel",IDCANCEL,117,125,50,14
CONTROL "",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH |
TBS_NOTICKS | WS_TABSTOP,57,30,92,18
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 160
TOPMARGIN, 7
BOTTOMMARGIN, 48
END
IDD_CONFIGURE, DIALOG
BEGIN
LEFTMARGIN, 44
RIGHTMARGIN, 167
TOPMARGIN, 6
BOTTOMMARGIN, 139
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED