windows-nt/Source/XPSP1/NT/multimedia/media/avi/avifile/aviview/palmap.c
2020-09-26 16:20:57 +08:00

430 lines
11 KiB
C

/****************************************************************************
*
* 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 <windows.h>
#include <windowsx.h>
#include <win32.h>
#include <mmsystem.h>
#include <vfw.h>
#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);
}