/**************************************************************************** * * DRAWPROC.C * * Standard AVI drawing handler. * * InstallAVIDrawHandler() * * Copyright (c) 1992 Microsoft Corporation. All Rights Reserved. * * You have a royalty-free right to use, modify, reproduce and * distribute the Sample Files (and/or any modified version) in * any way you find useful, provided that you agree that * Microsoft has no warranty obligations or liability for any * Sample Application Files which are modified. * ***************************************************************************/ #include #include #include "common.h" #include "mciavi.h" #define FOURCC_VIDS mmioFOURCC('v','i','d','s') #define FOURCC_AVIDraw mmioFOURCC('D','R','A','W') #define VERSION_AVIDraw 0x00010000 // 1.00 #ifdef DEBUG HDRAWDIB ghdd; #endif #ifndef HUGE #define HUGE _huge #endif /*************************************************************************** ***************************************************************************/ typedef struct { HDRAWDIB hdd; HDC hdc; // HDC to draw to int xDst; // destination rectangle int yDst; int dxDst; int dyDst; int xSrc; // source rectangle int ySrc; int dxSrc; int dySrc; BOOL fBackground; BOOL fRle; DWORD biSizeImage; BOOL fNeedUpdate; LONG rate; // playback rate (uSec / frame) } INSTINFO, *PINSTINFO; // static stuff in this file. LONG FAR PASCAL _loadds ICAVIDrawProc(DWORD id, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2); static LONG AVIDrawOpen(ICOPEN FAR * icopen); static LONG AVIDrawClose(PINSTINFO pi); static LONG AVIDrawGetInfo(ICINFO FAR *icinfo, LONG lSize); static LONG AVIDrawQuery(PINSTINFO pi, LPBITMAPINFOHEADER lpbiIn); static LONG AVIDrawSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd); static LONG AVIDrawBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd); static LONG AVIDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd); static LONG AVIDrawEnd(PINSTINFO pi); static LONG AVIDrawChangePalette(PINSTINFO pi, LPBITMAPINFOHEADER lpbi); /*************************************************************************** ***************************************************************************/ LONG FAR PASCAL _loadds ICAVIDrawProc(DWORD id, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2) { INSTINFO *pi = (INSTINFO *)(UINT)id; switch (uiMessage) { case DRV_LOAD: case DRV_FREE: return 1; /********************************************************************* open *********************************************************************/ case DRV_OPEN: if (lParam2 == 0L) return 1; return AVIDrawOpen((ICOPEN FAR *)lParam2); case DRV_CLOSE: return AVIDrawClose(pi); /********************************************************************* Configure/Info messages *********************************************************************/ case DRV_QUERYCONFIGURE: // configuration from drivers applet return 0; case DRV_CONFIGURE: return 1; case ICM_CONFIGURE: case ICM_ABOUT: return ICERR_UNSUPPORTED; /********************************************************************* state messages *********************************************************************/ case ICM_GETSTATE: case ICM_SETSTATE: return 0L; // case ICM_GETINFO: // return AVIDrawGetInfo((ICINFO FAR *)lParam1, lParam2); /********************************************************************* decompress messages *********************************************************************/ case ICM_DRAW_QUERY: return AVIDrawQuery(pi, (LPBITMAPINFOHEADER)lParam1); case ICM_DRAW_SUGGESTFORMAT: return AVIDrawSuggestFormat(pi, (ICDRAWSUGGEST FAR *) lParam1, lParam2); case ICM_DRAW_BEGIN: return AVIDrawBegin(pi, (ICDRAWBEGIN FAR *) lParam1, lParam2); case ICM_DRAW_REALIZE: pi->hdc = (HDC) lParam1; if (!pi->hdc || !pi->hdd) break; pi->fBackground = (BOOL) lParam2; return DrawDibRealize(pi->hdd, pi->hdc, pi->fBackground); case ICM_DRAW_GET_PALETTE: if (!pi->hdd) break; return (LONG) DrawDibGetPalette(pi->hdd); case ICM_DRAW: return AVIDraw(pi, (ICDRAW FAR *)lParam1, lParam2); case ICM_DRAW_CHANGEPALETTE: return AVIDrawChangePalette(pi, (LPBITMAPINFOHEADER) lParam1); case ICM_DRAW_END: return AVIDrawEnd(pi); case ICM_DRAW_START: return DrawDibStart(pi->hdd, pi->rate); case ICM_DRAW_STOP: return DrawDibStop(pi->hdd); /********************************************************************* standard driver messages *********************************************************************/ case DRV_DISABLE: case DRV_ENABLE: return 1; case DRV_INSTALL: case DRV_REMOVE: return 1; } return ICERR_UNSUPPORTED; } /***************************************************************************** * * AVIDrawOpen() is called from the DRV_OPEN message * ****************************************************************************/ static LONG AVIDrawOpen(ICOPEN FAR * icopen) { INSTINFO * pinst; if (icopen->dwFlags & ICMODE_COMPRESS) return 0; if (icopen->dwFlags & ICMODE_DECOMPRESS) return 0; pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO)); if (!pinst) { icopen->dwError = ICERR_MEMORY; return 0; } DPF2(("*** AVIDrawOpen()\n")); // // init structure // pinst->hdd = DrawDibOpen(); #ifdef DEBUG ghdd = pinst->hdd; #endif // // return success. // icopen->dwError = ICERR_OK; return (LONG) (UINT) pinst; } /***************************************************************************** * * Close() is called on the DRV_CLOSE message. * ****************************************************************************/ static LONG AVIDrawClose(PINSTINFO pi) { DPF2(("*** AVIDrawClose()\n")); if (pi->hdd) { DrawDibClose(pi->hdd); } LocalFree((HLOCAL) pi); return 1; } #if 0 /***************************************************************************** * * AVIDrawGetInfo() implements the ICM_GETINFO message * ****************************************************************************/ static LONG AVIDrawGetInfo(ICINFO FAR *icinfo, LONG lSize) { if (icinfo == NULL) return sizeof(ICINFO); if (lSize < sizeof(ICINFO)) return 0; icinfo->dwSize = sizeof(ICINFO); icinfo->fccType = FOURCC_VIDS; icinfo->fccHandler = FOURCC_AVIDraw; icinfo->dwFlags = VIDCF_DRAW; // supports inter-frame icinfo->dwVersion = VERSION_AVIDraw; icinfo->dwVersionICM = ICVERSION; icinfo->szName[0] = 0; icinfo->szDescription[0]= 0; return sizeof(ICINFO); } #endif /***************************************************************************** * * AVIDrawQuery() implements ICM_DRAW_QUERY * ****************************************************************************/ static LONG AVIDrawQuery(PINSTINFO pi, LPBITMAPINFOHEADER lpbiIn) { // // determine if the input DIB data is in a format we like. // if (lpbiIn == NULL) return ICERR_BADFORMAT; // // determine if the input DIB data is in a format we like. // // !!! Do we need a DrawDibQuery or something here to let this handle // any compressed format? #ifdef DRAWDIBNODECOMPRESS if (lpbiIn->biCompression != BI_RGB && #if 0 !(lpbiIn->biBitCount == 8 && lpbiIn->biCompression == BI_RLE8)) #else 1) #endif return ICERR_BADFORMAT; #endif return ICERR_OK; } static LONG AVIDrawSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd) { HIC hic; if (lpicd->lpbiSuggest == NULL) return sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD); hic = ICGetDisplayFormat(NULL, lpicd->lpbiIn, lpicd->lpbiSuggest, 0, lpicd->dxDst, lpicd->dyDst); if (hic) ICClose(hic); return sizeof(BITMAPINFOHEADER) + lpicd->lpbiSuggest->biClrUsed * sizeof(RGBQUAD); } /***************************************************************************** * * AVIDrawBegin() implements ICM_DRAW_BEGIN * ****************************************************************************/ static LONG AVIDrawBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd) { LONG l; UINT wFlags; if (lpicd->dwFlags & ICDRAW_FULLSCREEN) return ICERR_UNSUPPORTED; l = AVIDrawQuery(pi, lpicd->lpbi); if ((l != 0) || (lpicd->dwFlags & ICDRAW_QUERY)) return l; // Copy over whatever we want to remember pi->hdc = lpicd->hdc; pi->xDst = lpicd->xDst; pi->yDst = lpicd->yDst; pi->dxDst = lpicd->dxDst; pi->dyDst = lpicd->dyDst; pi->xSrc = lpicd->xSrc; pi->ySrc = lpicd->ySrc; pi->dxSrc = lpicd->dxSrc; pi->dySrc = lpicd->dySrc; pi->rate = muldiv32(lpicd->dwScale,1000000,lpicd->dwRate); // !!! Should this be done somewhere else? drawdib mabey! if (pi->hdc) SetStretchBltMode(pi->hdc, COLORONCOLOR); wFlags = 0; // !!! We need some way to have a "stupid" mode here.... if (lpicd->dwFlags & ICDRAW_BUFFER) wFlags |= DDF_BUFFER; // Don't animate if we're realizing in the background if (lpicd->dwFlags & ICDRAW_ANIMATE && !(pi->fBackground)) wFlags |= DDF_ANIMATE; // // remember if this is RLE because we may need to hack it later. // pi->fRle = lpicd->lpbi->biCompression == BI_RLE8; pi->biSizeImage = (DWORD)(((UINT)lpicd->lpbi->biWidth+3)&~3)*(DWORD)(UINT)lpicd->lpbi->biHeight; DPF2(("*** AVIDrawBegin()\n")); if (lpicd->hpal == (HPALETTE)MCI_AVI_SETVIDEO_PALETTE_HALFTONE) { DrawDibSetPalette(pi->hdd, NULL); wFlags |= DDF_HALFTONE; } else DrawDibSetPalette(pi->hdd, lpicd->hpal); if (!DrawDibBegin(pi->hdd, pi->hdc, pi->dxDst, pi->dyDst, lpicd->lpbi, pi->dxSrc, pi->dySrc, wFlags)) return ICERR_UNSUPPORTED; if (pi->hdc) DrawDibRealize(pi->hdd, pi->hdc, pi->fBackground); return ICERR_OK; } /***************************************************************************** * * AVIDraw() implements ICM_DRAW * ****************************************************************************/ static LONG AVIDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd) { UINT wFlags; BOOL f; wFlags = DDF_SAME_DRAW|DDF_SAME_HDC; // !!! Right flags? if ((lpicd->lpData == NULL) || (lpicd->cbData == 0)) { if ((lpicd->dwFlags & ICDRAW_UPDATE) || pi->fNeedUpdate) { DrawDibRealize(pi->hdd, pi->hdc, pi->fBackground); wFlags |= DDF_UPDATE; pi->fNeedUpdate = FALSE; } else return ICERR_OK; // no data to draw. } else { if (lpicd->dwFlags & ICDRAW_PREROLL) { wFlags |= DDF_DONTDRAW; pi->fNeedUpdate = TRUE; } else if (lpicd->dwFlags & ICDRAW_HURRYUP) { wFlags |= DDF_HURRYUP; pi->fNeedUpdate = TRUE; } else pi->fNeedUpdate = FALSE; if (lpicd->dwFlags & ICDRAW_NOTKEYFRAME) wFlags |= DDF_NOTKEYFRAME; // // if we get a update while playing and we are drawing RLE delta's // make sure we update. // if (pi->fRle && (lpicd->dwFlags & ICDRAW_UPDATE)) { DrawDibDraw(pi->hdd, pi->hdc, pi->xDst, pi->yDst, 0,0,NULL,NULL,0,0,0,0,DDF_UPDATE|DDF_SAME_HDC|DDF_SAME_DRAW); } } // // We need a hack here for the RLE case, to make sure that // DIBs are marked correctly as BI_RLE8 or BI_RGB.... // if (pi->fRle) { if (lpicd->cbData == pi->biSizeImage) ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RGB; else ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RLE8; } f = DrawDibDraw(pi->hdd, pi->hdc, pi->xDst, pi->yDst, pi->dxDst, pi->dyDst, lpicd->lpFormat, lpicd->lpData, pi->xSrc, pi->ySrc, pi->dxSrc, pi->dySrc, wFlags); if (pi->fRle) ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RLE8; if (!f) { if (wFlags & DDF_UPDATE) DPF(("DrawDibUpdate failed\n")); else DPF(("DrawDibDraw failed\n")); if (wFlags & DDF_UPDATE) return ICERR_CANTUPDATE; else return ICERR_ERROR; } return ICERR_OK; } static LONG AVIDrawChangePalette(PINSTINFO pi, LPBITMAPINFOHEADER lpbi) { PALETTEENTRY ape[256]; LPRGBQUAD lprgb; int i; lprgb = (LPRGBQUAD) ((LPBYTE) lpbi + lpbi->biSize); for (i = 0; i < (int) lpbi->biClrUsed; i++) { ape[i].peRed = lprgb[i].rgbRed; ape[i].peGreen = lprgb[i].rgbGreen; ape[i].peBlue = lprgb[i].rgbBlue; ape[i].peFlags = 0; } DrawDibChangePalette(pi->hdd, 0, (int) lpbi->biClrUsed, (LPPALETTEENTRY)ape); return ICERR_OK; } /***************************************************************************** * * AVIDrawEnd() implements ICM_DRAW_END * ****************************************************************************/ static LONG AVIDrawEnd(PINSTINFO pi) { return ICERR_OK; }