/**************************************************************************** * * PALMAP.C * * Stream handler to map to a palette. * * 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 #include #include #include "dibmap.h" #include "palmap.h" LONG FAR PASCAL AVIStreamMakePalette(PAVISTREAM pavi, LONG lSkip, HPALETTE FAR *lphpal, LPBYTE lp16to8, int nColors) { LPHISTOGRAM lpHist = NULL; LONG l, lEnd; LONG lRet = AVIERR_OK; PGETFRAME pgf = NULL; if (!pavi || !lphpal || nColors < 2 || nColors > 256) return AVIERR_BADPARAM; if (lSkip < 1) lSkip = 1; lpHist = InitHistogram(NULL); if (!lpHist) return AVIERR_MEMORY; pgf = AVIStreamGetFrameOpen(pavi, NULL); l = AVIStreamStart(pavi); lEnd = l + AVIStreamLength(pavi); for (l = AVIStreamStart(pavi), lEnd = l + AVIStreamLength(pavi); l < lEnd; l += lSkip) { LPBITMAPINFOHEADER lpbi; lpbi = AVIStreamGetFrame(pgf, l); if (!lpbi) { lRet = AVIERR_INTERNAL; goto error; } DibHistogram(lpbi, NULL, 0, 0, -1, -1, lpHist); } *lphpal = HistogramPalette(lpHist, lp16to8, nColors); if (!*lphpal) lRet = AVIERR_MEMORY; error: if (pgf) AVIStreamGetFrameClose(pgf); if (lpHist) FreeHistogram(lpHist); return lRet; } typedef struct { IAVIStreamVtbl FAR * lpVtbl; ULONG ulRefCount; // // instance data // PAVISTREAM pavi; PGETFRAME pgf; AVISTREAMINFO avistream; HPALETTE hpal; LPBYTE lp16to8; LONG lLastFrame; HANDLE hdibLast; } PALMAPSTREAM, FAR*PPALMAPSTREAM; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// HRESULT STDMETHODCALLTYPE PalMapStreamQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID FAR* ppvObj); HRESULT STDMETHODCALLTYPE PalMapStreamCreate (PAVISTREAM ps, LONG lParam1, LONG lParam2); ULONG STDMETHODCALLTYPE PalMapStreamAddRef (PAVISTREAM ps); ULONG STDMETHODCALLTYPE PalMapStreamRelease (PAVISTREAM ps); HRESULT STDMETHODCALLTYPE PalMapStreamInfo (PAVISTREAM ps, AVISTREAMINFO FAR * psi, LONG lSize); LONG STDMETHODCALLTYPE PalMapStreamFindKeyFrame (PAVISTREAM ps, LONG lPos, LONG lFlags); HRESULT STDMETHODCALLTYPE PalMapStreamReadFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat); HRESULT STDMETHODCALLTYPE PalMapStreamSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat); HRESULT STDMETHODCALLTYPE PalMapStreamRead (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, LONG FAR * plBytes,LONG FAR * plSamples); HRESULT STDMETHODCALLTYPE PalMapStreamWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG FAR *plSampWritten, LONG FAR *plBytesWritten); HRESULT STDMETHODCALLTYPE PalMapStreamDelete (PAVISTREAM ps, LONG lStart, LONG lSamples); HRESULT STDMETHODCALLTYPE PalMapStreamReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG FAR *lpcb); HRESULT STDMETHODCALLTYPE PalMapStreamWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG cb); IAVIStreamVtbl PalMapStreamHandler = { PalMapStreamQueryInterface, PalMapStreamAddRef, PalMapStreamRelease, PalMapStreamCreate, PalMapStreamInfo, PalMapStreamFindKeyFrame, PalMapStreamReadFormat, PalMapStreamSetFormat, PalMapStreamRead, PalMapStreamWrite, PalMapStreamDelete, PalMapStreamReadData, PalMapStreamWriteData }; LONG FAR PASCAL AVICreateMappedStream(PAVISTREAM FAR *ppsMapped, PAVISTREAM ps, int nColors) { PPALMAPSTREAM pavi; pavi = (PPALMAPSTREAM) GlobalAllocPtr(GHND, sizeof(PALMAPSTREAM)); if (pavi == NULL) return AVIERR_MEMORY; pavi->lpVtbl = &PalMapStreamHandler; (pavi->lpVtbl->Create)((PAVISTREAM) pavi, (LONG) ps, nColors); // !!! error check *ppsMapped = (PAVISTREAM) pavi; return AVIERR_OK; } /////////////////////////////////////////////////////////////////////////// // // PalMapStreamOpen() // // open a single stream of a particular type from a AVI file. // // params: // szFile - PAVISTREAM // fccType - must be streamtypeVIDEO // lParam - nColors // // returns: // a PAVISTREAM for the specifed stream or NULL. // /////////////////////////////////////////////////////////////////////////// HRESULT STDMETHODCALLTYPE PalMapStreamCreate(PAVISTREAM ps, LONG lParam1, LONG lParam2) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; LONG lRet = AVIERR_OK; if (AVIStreamAddRef((PAVISTREAM) lParam1) != AVIERR_OK) return ResultFromScode(AVIERR_FILEOPEN); pavi->pavi = (PAVISTREAM) lParam1; AVIStreamInfo(pavi->pavi, &pavi->avistream, sizeof(pavi->avistream)); if (pavi->avistream.fccType != streamtypeVIDEO) { lRet = AVIERR_INTERNAL; goto error; } pavi->pgf = AVIStreamGetFrameOpen(pavi->pavi, NULL); if (!pavi->pgf) { lRet = AVIERR_INTERNAL; goto error; } pavi->avistream.fccHandler = 0; if (lParam2 < 2 || lParam2 > 256) lParam2 = 256; pavi->lp16to8 = GlobalAllocPtr(GMEM_MOVEABLE, 32768L); if (!pavi->lp16to8) { lRet = AVIERR_MEMORY; goto error; } lRet = AVIStreamMakePalette(pavi->pavi, AVIStreamLength(pavi->pavi) / 30, &pavi->hpal, pavi->lp16to8, (int) lParam2); pavi->lLastFrame = -1; error: return ResultFromScode(lRet); } /////////////////////////////////////////////////////////////////////////// // // PalMapStreamAddRef() // // increase the reference count of the stream // /////////////////////////////////////////////////////////////////////////// ULONG STDMETHODCALLTYPE PalMapStreamAddRef(PAVISTREAM ps) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; return ++pavi->ulRefCount; } /////////////////////////////////////////////////////////////////////////// // // PalMapStreamRelease() // // close a PalMapStream stream // /////////////////////////////////////////////////////////////////////////// ULONG STDMETHODCALLTYPE PalMapStreamRelease(PAVISTREAM ps) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; if (--pavi->ulRefCount) return pavi->ulRefCount; if (pavi->pgf) AVIStreamGetFrameClose(pavi->pgf); pavi->pgf = 0; if (pavi->pavi) AVIStreamClose(pavi->pavi); pavi->pavi = 0; if (pavi->lp16to8) { GlobalFreePtr(pavi->lp16to8); pavi->lp16to8 = 0; } if (pavi->hpal) { DeleteObject(pavi->hpal); pavi->hpal = 0; } if (pavi->hdibLast) { GlobalFree(pavi->hdibLast); pavi->hdibLast = 0; } GlobalFreePtr(pavi); return 0; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// HRESULT STDMETHODCALLTYPE PalMapStreamReadFormat(PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; LPBITMAPINFOHEADER lpbi; LONG lSize; PalMapStreamRead(ps, lPos, 1, NULL, 0, NULL, NULL); if (pavi->hdibLast == 0) return ResultFromScode(AVIERR_INTERNAL); lpbi = (LPBITMAPINFOHEADER) GlobalLock(pavi->hdibLast); lSize = lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD); if (lpFormat) hmemcpy(lpFormat, lpbi, min(*lpcbFormat, lSize)); *lpcbFormat = lSize; return 0; } LONG STDMETHODCALLTYPE PalMapStreamFindKeyFrame(PAVISTREAM ps, LONG lPos, LONG lFlags) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; return lPos; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// HRESULT STDMETHODCALLTYPE PalMapStreamInfo(PAVISTREAM ps, AVISTREAMINFO FAR * psi, LONG lSize) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; if (psi) hmemcpy(psi, &pavi->avistream, min(lSize, sizeof(pavi->avistream))); return 0; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// HRESULT STDMETHODCALLTYPE PalMapStreamRead(PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, LONG FAR * plBytes, LONG FAR * plSamples) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; LPBITMAPINFOHEADER lpbi; LPVOID lp; if (lStart != pavi->lLastFrame) { pavi->lLastFrame = -1; lpbi = AVIStreamGetFrame(pavi->pgf, lStart); if (!lpbi) goto ReadNothing; if (pavi->hdibLast) { GlobalFree(pavi->hdibLast); pavi->hdibLast = 0; } pavi->hdibLast = DibReduce(lpbi, NULL, pavi->hpal, pavi->lp16to8); pavi->lLastFrame = lStart; } lpbi = (LPBITMAPINFOHEADER) GlobalLock(pavi->hdibLast); // // a NULL buffer means return the size buffer needed to read // the given sample. // lp = (LPBYTE) lpbi + lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD); if (plBytes) *plBytes = lpbi->biSizeImage; if (plSamples) *plSamples = 1; if (lpBuffer) { if (cbBuffer >= (LONG) lpbi->biSizeImage) hmemcpy(lpBuffer, lp, lpbi->biSizeImage); else return ResultFromScode(AVIERR_BUFFERTOOSMALL); } return 0; ReadNothing: if (plBytes) *plBytes = 0; if (plSamples) *plSamples = 0; return ResultFromScode(AVIERR_BUFFERTOOSMALL); } // // // Extra unimplemented functions..... // // // HRESULT STDMETHODCALLTYPE PalMapStreamQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID FAR* ppvObj) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; return ResultFromScode(AVIERR_UNSUPPORTED); } HRESULT STDMETHODCALLTYPE PalMapStreamReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG FAR *lpcb) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; return ResultFromScode(AVIERR_UNSUPPORTED); } HRESULT STDMETHODCALLTYPE PalMapStreamSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; return ResultFromScode(AVIERR_UNSUPPORTED); } HRESULT STDMETHODCALLTYPE PalMapStreamWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG cb) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; return ResultFromScode(AVIERR_UNSUPPORTED); } HRESULT STDMETHODCALLTYPE PalMapStreamWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG FAR *plSampWritten, LONG FAR *plBytesWritten) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; return ResultFromScode(AVIERR_UNSUPPORTED); } HRESULT STDMETHODCALLTYPE PalMapStreamDelete (PAVISTREAM ps, LONG lStart, LONG lSamples) { PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps; return ResultFromScode(AVIERR_UNSUPPORTED); }