windows-nt/Source/XPSP1/NT/drivers/wdm/capture/codec/tsbyuv/msyuv.c
2020-09-26 16:20:57 +08:00

607 lines
16 KiB
C

/*----------------------------------------------------------------------+
| msyuv.c - Microsoft YUV Codec |
| |
| Copyright (c) 1993 Microsoft Corporation. |
| All Rights Reserved. |
| |
+----------------------------------------------------------------------*/
#include <windows.h>
#include <windowsx.h>
//#include <mmsystem.h>
#ifndef _WIN32
#include "stdarg.h"
#endif
#ifdef _WIN32
#include <memory.h> /* for memcpy */
#endif
#include "msyuv.h"
WCHAR szDescription[] = L"Toshiba YUV Codec";
WCHAR szName[] = L"Toshiba YUV411";
WCHAR szAbout[] = L"About";
#define VERSION 0x00010000 // 1.0
/*****************************************************************************
****************************************************************************/
INSTINFO * NEAR PASCAL Open(ICOPEN FAR * icinfo)
{
INSTINFO * pinst;
//
// refuse to open if we are not being opened as a Video compressor
//
if (icinfo->fccType != ICTYPE_VIDEO)
return NULL;
//
// dwFlags contain wMode
//
if( icinfo->dwFlags != ICMODE_QUERY // Open for infomational purpose
&& icinfo->dwFlags != ICMODE_DECOMPRESS
#ifdef ICM_COMPRESS_SUPPORTED
&& icinfo->dwFlags != ICMODE_COMPRESS
#endif
#ifdef ICM_DRAW_SUPPORTED
&& icinfo->dwFlags != ICMODE_DRAW
#endif
) {
dprintf1((TEXT("Open: unsupported wMode=%d\n"), icinfo->dwFlags));
return NULL;
}
pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO));
if (!pinst) {
icinfo->dwError = (DWORD)ICERR_MEMORY;
return NULL;
}
//
// init structure
//
pinst->dwFlags = icinfo->dwFlags;
pinst->pXlate = NULL;
//
// return success.
//
icinfo->dwError = ICERR_OK;
return pinst;
}
/*****************************************************************************
****************************************************************************/
DWORD NEAR PASCAL Close(INSTINFO * pinst)
{
if (pinst->pXlate) {
DecompressEnd(pinst);
}
#if ICM_DRAW_SUPPORTED
if (pinst->vh) {
DrawEnd(pinst);
}
#endif
LocalFree((HLOCAL)pinst);
return 1;
}
/*****************************************************************************
****************************************************************************/
BOOL NEAR PASCAL QueryAbout(INSTINFO * pinst)
{
return TRUE;
}
DWORD NEAR PASCAL About(INSTINFO * pinst, HWND hwnd)
{
MessageBoxW(hwnd,szDescription,szAbout,MB_OK|MB_ICONINFORMATION);
return ICERR_OK;
}
/*****************************************************************************
****************************************************************************/
BOOL NEAR PASCAL QueryConfigure(INSTINFO * pinst)
{
return FALSE;
}
DWORD NEAR PASCAL Configure(INSTINFO * pinst, HWND hwnd)
{
return (TRUE);
}
/*****************************************************************************
****************************************************************************/
/*
* lossless translation - hence no need for state adjustments
*/
DWORD NEAR PASCAL GetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
{
return 0;
}
/*****************************************************************************
****************************************************************************/
DWORD NEAR PASCAL SetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
{
return(0);
}
/*****************************************************************************
****************************************************************************/
DWORD NEAR PASCAL GetInfo(INSTINFO * pinst, ICINFO FAR *icinfo, DWORD dwSize)
{
if (icinfo == NULL)
return sizeof(ICINFO);
if (dwSize < sizeof(ICINFO))
return 0;
icinfo->dwSize = sizeof(ICINFO);
icinfo->fccType = ICTYPE_VIDEO;
icinfo->fccHandler = FOURCC_YUV411;
icinfo->dwFlags = 0;
icinfo->dwVersion = VERSION;
icinfo->dwVersionICM = ICVERSION;
wcscpy(icinfo->szDescription, szDescription);
wcscpy(icinfo->szName, szName);
return sizeof(ICINFO);
}
/*****************************************************************************
****************************************************************************/
DWORD FAR PASCAL CompressQuery(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
{
return ((DWORD) ICERR_BADFORMAT);
}
/*****************************************************************************
****************************************************************************/
DWORD FAR PASCAL CompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
{
return((DWORD) ICERR_BADFORMAT);
}
/*****************************************************************************
****************************************************************************/
DWORD FAR PASCAL CompressBegin(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
{
return((DWORD) ICERR_ERROR);
}
/*****************************************************************************
****************************************************************************/
DWORD FAR PASCAL CompressGetSize(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
{
return (0);
}
/*****************************************************************************
****************************************************************************/
DWORD FAR PASCAL Compress(INSTINFO * pinst, ICCOMPRESS FAR *icinfo, DWORD dwSize)
{
return((DWORD) ICERR_ERROR);
}
/*****************************************************************************
****************************************************************************/
DWORD FAR PASCAL CompressEnd(INSTINFO * pinst)
{
return (DWORD)ICERR_ERROR;
}
/*****************************************************************************
****************************************************************************/
DWORD NEAR PASCAL DecompressQuery(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
{
//
// determine if the input DIB data is in a format we like.
//
#ifdef TOSHIBA
#if DBG
// DbgBreakPoint();
#endif
if (lpbiIn == NULL ||
( (lpbiIn->biCompression != FOURCC_YUV411) &&
(lpbiIn->biCompression != FOURCC_YUV422) &&
(lpbiIn->biCompression != FOURCC_YUV9) && // add YUV9
(lpbiIn->biCompression != FOURCC_YUV12 ))) { // add YUV12
#else //TOSHIBA
if (lpbiIn == NULL ||
(lpbiIn->biBitCount != 16) ||
( (lpbiIn->biCompression != FOURCC_YUV411) &&
(lpbiIn->biCompression != FOURCC_YUV422))) {
#endif//TOSHIBA
dprintf((TEXT("bad input format")));
return (DWORD)ICERR_BADFORMAT;
}
//
// are we being asked to query just the input format?
//
if (lpbiOut == NULL) {
return ICERR_OK;
}
// check output format to make sure we can convert to this
// must be full dib
if (lpbiOut->biCompression == BI_RGB) {
pinst->bRGB565 = FALSE;
#ifdef TOSHIBA
#ifdef COLOR_MODIFY
if (lpbiOut->biBitCount == 24) {
pinst->bRGB24 = TRUE;
} else {
pinst->bRGB24 = FALSE;
}
#endif//COLOR_MODIFY
#endif//TOSHIBA
} else if ((lpbiOut->biCompression == BI_BITFIELDS) &&
(lpbiOut->biBitCount == 16) &&
(((LPDWORD)(lpbiOut+1))[0] == 0x00f800) &&
(((LPDWORD)(lpbiOut+1))[1] == 0x0007e0) &&
(((LPDWORD)(lpbiOut+1))[2] == 0x00001f)) {
dprintf1((TEXT("rgb565 output")));
pinst->bRGB565 = TRUE;
#ifdef TOSHIBA
#ifdef COLOR_MODIFY
pinst->bRGB24 = FALSE;
#endif//COLOR_MODIFY
#endif//TOSHIBA
} else {
dprintf1((TEXT("bad compression for output")));
return (DWORD)ICERR_BADFORMAT;
}
/* must be 1:1 (no stretching) */
if ((lpbiOut->biWidth != lpbiIn->biWidth) ||
(lpbiOut->biHeight != lpbiIn->biHeight)) {
dprintf1((TEXT("YUV can't stretch: %dx%d->%dx%d"),
lpbiIn->biWidth, lpbiIn->biHeight,
lpbiOut->biWidth, lpbiOut->biHeight
));
return((DWORD) ICERR_BADFORMAT);
}
/*
* we translate to 16 bits
*/
#ifdef TOSHIBA
#ifdef COLOR_MODIFY
if ((lpbiOut->biBitCount != 16) &&
(lpbiOut->biBitCount != 24)) {
dprintf1((TEXT("YUV to 16 or 24 only")));
return((DWORD) ICERR_BADFORMAT);
}
#else //COLOR_MODIFY
if (lpbiOut->biBitCount != 16) {
dprintf1((TEXT("YUV 16:16 only")));
return((DWORD) ICERR_BADFORMAT);
}
#endif//COLOR_MODIFY
#else //TOSHIBA
if (lpbiOut->biBitCount != 16) {
dprintf1((TEXT("YUV 16:16 only")));
return((DWORD) ICERR_BADFORMAT);
}
#endif//TOSHIBA
return ICERR_OK;
}
/*****************************************************************************
****************************************************************************/
DWORD DecompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
{
DWORD dw;
int dx,dy;
dw = DecompressQuery(pinst, lpbiIn, NULL);
if (dw != ICERR_OK) {
return dw;
}
//
// if lpbiOut == NULL then, return the size required to hold a output
// format
//
if (lpbiOut == NULL) {
dprintf2((TEXT("get format size query")));
return (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD);
}
memcpy(lpbiOut, lpbiIn,
(int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD));
dx = (int)lpbiIn->biWidth & ~3;
dy = (int)lpbiIn->biHeight & ~3;
lpbiOut->biWidth = dx;
lpbiOut->biHeight = dy;
#ifdef TOSHIBA
lpbiOut->biBitCount = 16;
#else //TOSHIBA
lpbiOut->biBitCount = lpbiIn->biBitCount; // convert 16->16
#endif//TOSHIBA
lpbiOut->biCompression = BI_RGB;
lpbiOut->biSizeImage = dx*dy*2;
return ICERR_OK;
}
/*****************************************************************************
****************************************************************************/
DWORD NEAR PASCAL DecompressBegin(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
{
DWORD dw;
/* check that the conversion formats are valid */
dw = DecompressQuery(pinst, lpbiIn, lpbiOut);
if (dw != ICERR_OK) {
return dw;
}
/* init the yuv-to-rgb55 xlate table if not already inited */
/* free up the existing table if the formats differ */
if (lpbiIn->biCompression != pinst->dwFormat) {
if (pinst->pXlate != NULL) {
DecompressEnd(pinst);
}
}
if (pinst->pXlate == NULL) {
switch(lpbiIn->biCompression) {
case FOURCC_YUV411:
if (pinst->bRGB565) {
pinst->pXlate = BuildYUVToRGB565(pinst);
} else {
pinst->pXlate = BuildYUVToRGB555(pinst);
}
break;
case FOURCC_YUV422:
if (pinst->bRGB565) {
pinst->pXlate = BuildYUV422ToRGB565(pinst);
} else {
pinst->pXlate = BuildYUV422ToRGB555(pinst);
}
break;
#ifdef TOSHIBA
#ifdef COLOR_MODIFY
case FOURCC_YUV12:
pinst->pXlate = BuildYUVToRB(pinst);
break;
case FOURCC_YUV9:
pinst->pXlate = BuildYUVToRB(pinst); // same to YUV12
break;
#else //COLOR_MODIFY
case FOURCC_YUV12:
if (pinst->bRGB565) {
pinst->pXlate = BuildYUV12ToRGB565(pinst);
} else {
pinst->pXlate = BuildYUV12ToRGB555(pinst);
}
break;
case FOURCC_YUV9:
if (pinst->bRGB565) {
pinst->pXlate = BuildYUV12ToRGB565(pinst); // same to YUV12
} else {
pinst->pXlate = BuildYUV12ToRGB555(pinst); // same to YUV12
}
break;
#endif//COLOR_MODIFY
#endif//TOSHIBA
default:
return((DWORD) ICERR_BADFORMAT);
}
if (pinst->pXlate == NULL) {
return((DWORD) ICERR_MEMORY);
}
pinst->dwFormat = lpbiIn->biCompression;
}
return(ICERR_OK);
}
/*****************************************************************************
****************************************************************************/
DWORD NEAR PASCAL Decompress(INSTINFO * pinst, ICDECOMPRESS FAR *icinfo, DWORD dwSize)
{
/* must have been a DecompressBegin first */
if (pinst->pXlate == NULL) {
return((DWORD) ICERR_ERROR);
}
#ifdef TOSHIBA
if (pinst->dwFormat == FOURCC_YUV9) {
#ifdef COLOR_MODIFY
if (pinst->bRGB24) {
YUV9ToRGB24(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
} else {
if (pinst->bRGB565) {
YUV9ToRGB565(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
} else {
YUV9ToRGB555(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
}
}
#else //COLOR_MODIFY
YUV9ToRGB(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
#endif//COLOR_MODIFY
} else
if (pinst->dwFormat == FOURCC_YUV12) {
#ifdef COLOR_MODIFY
if (pinst->bRGB24) {
YUV12ToRGB24(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
} else {
if (pinst->bRGB565) {
YUV12ToRGB565(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
} else {
YUV12ToRGB555(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
}
}
#else //COLOR_MODIFY
YUV12ToRGB(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
#endif//COLOR_MODIFY
} else
#endif//TOSHIBA
if (pinst->dwFormat == FOURCC_YUV411) {
YUV411ToRGB(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
} else {
/*
* for compatibility with 16-bit Spigot driver,
* check for Guard field at start of data
*/
LPDWORD lpInput = icinfo->lpInput;
if (*lpInput == FOURCC_YUV422) {
lpInput++;
}
YUV422ToRGB(pinst,
icinfo->lpbiInput,
icinfo->lpInput,
icinfo->lpbiOutput,
icinfo->lpOutput
);
}
return ICERR_OK;
}
/*****************************************************************************
*
* DecompressGetPalette() implements ICM_GET_PALETTE
*
* This function has no Compress...() equivalent
*
* It is used to pull the palette from a frame in order to possibly do
* a palette change.
*
****************************************************************************/
DWORD NEAR PASCAL DecompressGetPalette(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
{
dprintf2((TEXT("DecompressGetPalette()")));
/*
* only applies to 8-bit output formats. We only decompress to 16 bits
*/
return((DWORD) ICERR_BADFORMAT);
}
/*****************************************************************************
****************************************************************************/
DWORD NEAR PASCAL DecompressEnd(INSTINFO * pinst)
{
if (pinst->pXlate == NULL) {
return (DWORD)ICERR_ERROR;
}
FreeXlate(pinst);
pinst->dwFormat = 0;
return ICERR_OK;
}