/*----------------------------------------------------------------------+ | msyuv.c - Microsoft YUV Codec | | | | Copyright (c) 1993 Microsoft Corporation. | | All Rights Reserved. | | | +----------------------------------------------------------------------*/ #include #include //#include #ifndef _WIN32 #include "stdarg.h" #endif #ifdef _WIN32 #include /* 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; }