home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / video / palmap / palmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  13.1 KB  |  615 lines

  1. /****************************************************************************
  2.  *
  3.  *  PALMAP.C
  4.  *
  5.  *  Stream handler to map to a palette.
  6.  *
  7.  ***************************************************************************/
  8.  
  9. /**************************************************************************
  10.  *
  11.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  12.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  14.  *  PURPOSE.
  15.  *
  16.  *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  17.  *
  18.  **************************************************************************/
  19.  
  20. #define INC_OLE2
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #include <mmsystem.h>
  24. #include <vfw.h>
  25. #include <string.h>
  26.  
  27. #include "dibmap.h"
  28. #include "palmap.h"
  29. #include "palmap.rc"
  30.  
  31. #define    INITGUID
  32. #include <initguid.h>
  33.  
  34. // Bring in the external GUIDs we need. Apparently compobj.lib doesn't define
  35. DEFINE_OLEGUID(IID_IUnknown,        0x00000000L, 0, 0);
  36.  
  37.  
  38. HINSTANCE    ghMod;
  39.  
  40. STDAPI AVIStreamMakePalette(
  41.     PAVISTREAM pavi,
  42.     LONG lSkip,
  43.     HPALETTE FAR *lphpal,
  44.     LPBYTE lp16to8,
  45.     int nColors)
  46. {
  47.     LPHISTOGRAM lpHist = NULL;
  48.     LONG    l, lEnd;
  49.     LONG    lRet = AVIERR_OK;
  50.     PGETFRAME    pgf = NULL;
  51.  
  52.     if (!pavi || !lphpal || nColors < 2 || nColors > 256)
  53.         return ResultFromScode(AVIERR_BADPARAM);
  54.  
  55.     if (lSkip < 1)
  56.         lSkip = 1;
  57.  
  58.     lpHist = InitHistogram(NULL);
  59.     if (!lpHist)
  60.         return ResultFromScode(AVIERR_MEMORY);
  61.  
  62.     pgf = AVIStreamGetFrameOpen(pavi, NULL);
  63.     
  64.     l = AVIStreamStart(pavi);
  65.     lEnd = l + AVIStreamLength(pavi);
  66.     for (l = AVIStreamStart(pavi), lEnd = l + AVIStreamLength(pavi);
  67.         l < lEnd;
  68.         l += lSkip) {
  69.         LPBITMAPINFOHEADER lpbi;
  70.  
  71.         lpbi = AVIStreamGetFrame(pgf, l);
  72.  
  73.         if (!lpbi) {
  74.             lRet = AVIERR_INTERNAL;
  75.             goto error;
  76.         }
  77.     
  78.         DibHistogram(lpbi, NULL, 0, 0, -1, -1, lpHist);
  79.     }
  80.  
  81.     *lphpal = HistogramPalette(lpHist, lp16to8, nColors);
  82.  
  83.     if (!*lphpal)
  84.         lRet = AVIERR_MEMORY;
  85.  
  86. error:
  87.     if (pgf)
  88.         AVIStreamGetFrameClose(pgf);
  89.     
  90.     if (lpHist)
  91.         FreeHistogram(lpHist);
  92.  
  93.     return ResultFromScode(lRet);
  94. }
  95.  
  96.  
  97.  
  98. typedef struct {
  99.     IAVIStreamVtbl FAR *    lpVtbl;
  100.  
  101.     ULONG            ulRefCount;
  102.  
  103.     //
  104.     // instance data
  105.     //
  106.     PAVISTREAM        pavi;
  107.     PGETFRAME        pgf;
  108.     AVISTREAMINFO        sinfo;
  109.     HPALETTE        hpal;
  110.     LPBYTE            lp16to8;
  111.     LONG            lLastFrame;
  112.     LPBITMAPINFOHEADER    lpdibLast;
  113. } PALMAPSTREAM, FAR*PPALMAPSTREAM;
  114.  
  115. ///////////////////////////////////////////////////////////////////////////
  116. ///////////////////////////////////////////////////////////////////////////
  117.  
  118. HRESULT STDMETHODCALLTYPE PalMapStreamQueryInterface(
  119.     PAVISTREAM ps,
  120.     REFIID riid,
  121.     LPVOID FAR* ppvObj);
  122. HRESULT STDMETHODCALLTYPE PalMapStreamCreate(
  123.     PAVISTREAM ps,
  124.     LONG lParam1,
  125.     LONG lParam2);
  126. ULONG    STDMETHODCALLTYPE PalMapStreamAddRef(
  127.     PAVISTREAM ps);
  128. ULONG    STDMETHODCALLTYPE PalMapStreamRelease(
  129.     PAVISTREAM ps);
  130. HRESULT STDMETHODCALLTYPE PalMapStreamInfo(
  131.     PAVISTREAM ps,
  132.     AVISTREAMINFOW FAR * psi,
  133.     LONG lSize);
  134. LONG    STDMETHODCALLTYPE PalMapStreamFindKeyFrame(
  135.     PAVISTREAM ps,
  136.     LONG lPos,
  137.     LONG lFlags);
  138. HRESULT STDMETHODCALLTYPE PalMapStreamReadFormat(
  139.     PAVISTREAM ps,
  140.     LONG lPos,
  141.     LPVOID lpFormat,
  142.     LONG FAR *lpcbFormat);
  143. HRESULT STDMETHODCALLTYPE PalMapStreamSetFormat(
  144.     PAVISTREAM ps,
  145.     LONG lPos,
  146.     LPVOID lpFormat,
  147.     LONG cbFormat);
  148. HRESULT STDMETHODCALLTYPE PalMapStreamRead(
  149.     PAVISTREAM ps,
  150.     LONG lStart,
  151.     LONG lSamples,
  152.     LPVOID lpBuffer,
  153.     LONG cbBuffer,
  154.     LONG FAR * plBytes,
  155.     LONG FAR * plSamples);
  156. HRESULT STDMETHODCALLTYPE PalMapStreamWrite(
  157.     PAVISTREAM ps,
  158.     LONG lStart,
  159.     LONG lSamples,
  160.     LPVOID lpBuffer,
  161.     LONG cbBuffer,
  162.     DWORD dwFlags,
  163.     LONG FAR *plSampWritten,
  164.     LONG FAR *plBytesWritten);
  165. HRESULT STDMETHODCALLTYPE PalMapStreamDelete(
  166.     PAVISTREAM ps,
  167.     LONG lStart,
  168.     LONG lSamples);
  169. HRESULT STDMETHODCALLTYPE PalMapStreamReadData(
  170.     PAVISTREAM ps,
  171.     DWORD fcc,
  172.     LPVOID lp,
  173.     LONG FAR *lpcb);
  174. HRESULT STDMETHODCALLTYPE PalMapStreamWriteData(
  175.     PAVISTREAM ps,
  176.     DWORD fcc,
  177.     LPVOID lp,
  178.     LONG cb);
  179. HRESULT STDMETHODCALLTYPE PalMapStreamSetInfo(
  180.         PAVISTREAM ps,
  181.         AVISTREAMINFOW FAR * psi,
  182.         LONG lSize);
  183.  
  184. IAVIStreamVtbl PalMapStreamHandler = {
  185.     PalMapStreamQueryInterface,
  186.     PalMapStreamAddRef,
  187.     PalMapStreamRelease,
  188.     PalMapStreamCreate,
  189.     PalMapStreamInfo,
  190.     PalMapStreamFindKeyFrame,
  191.     PalMapStreamReadFormat,
  192.     PalMapStreamSetFormat,
  193.     PalMapStreamRead,
  194.     PalMapStreamWrite,
  195.     PalMapStreamDelete,
  196.     PalMapStreamReadData,
  197.     PalMapStreamWriteData,
  198.         PalMapStreamSetInfo
  199. };
  200.  
  201. STDAPI AVICreateMappedStream(PAVISTREAM FAR *ppsMapped,
  202.     PAVISTREAM ps,
  203.     int nColors)
  204. {
  205.     PPALMAPSTREAM    pavi;
  206.     HRESULT        hr;
  207.  
  208.     *ppsMapped = 0;
  209.     
  210.     pavi = (PPALMAPSTREAM) GlobalAllocPtr(GHND, sizeof(PALMAPSTREAM));
  211.     if (pavi == NULL)
  212.         return ResultFromScode(AVIERR_MEMORY);
  213.  
  214.     pavi->lpVtbl = &PalMapStreamHandler;
  215.     
  216.     hr = (pavi->lpVtbl->Create)((PAVISTREAM) pavi, (LONG) ps, nColors);
  217.  
  218.     if (hr != NOERROR) {
  219.         (pavi->lpVtbl->Release)((PAVISTREAM) pavi);
  220.         return hr;
  221.     }
  222.     
  223.     *ppsMapped = (PAVISTREAM) pavi;
  224.  
  225.     return AVIERR_OK;
  226.  
  227.  
  228. }
  229.  
  230. ///////////////////////////////////////////////////////////////////////////
  231. //
  232. //  PalMapStreamOpen()
  233. //
  234. //  open a single stream of a particular type from a AVI file.
  235. //
  236. //  params:
  237. //      szFile      - PAVISTREAM
  238. //      fccType     - must be streamtypeVIDEO
  239. //      lParam        - nColors
  240. //
  241. //  returns:
  242. //      a PAVISTREAM for the specifed stream or NULL.
  243. //
  244. ///////////////////////////////////////////////////////////////////////////
  245.  
  246. HRESULT STDMETHODCALLTYPE PalMapStreamCreate(
  247.     PAVISTREAM ps,
  248.     LONG lParam1,
  249.     LONG lParam2)
  250. {
  251.     PPALMAPSTREAM    pavi = (PPALMAPSTREAM) ps;
  252.     TCHAR        achTemp[128];
  253.     TCHAR        achTemplate[64];
  254.  
  255.     LONG        lRet = AVIERR_OK;
  256.  
  257.     pavi->ulRefCount = 1;
  258.     
  259.     AVIStreamAddRef((PAVISTREAM) lParam1);
  260.  
  261.     pavi->pavi = (PAVISTREAM) lParam1;
  262.     
  263.     AVIStreamInfo(pavi->pavi, &pavi->sinfo, sizeof(pavi->sinfo));
  264.  
  265.     if (pavi->sinfo.fccType != streamtypeVIDEO) {
  266.     lRet = AVIERR_INTERNAL;
  267.     goto error;
  268.     }
  269.  
  270.     pavi->pgf = AVIStreamGetFrameOpen(pavi->pavi, NULL);
  271.  
  272.     if (!pavi->pgf) {
  273.     lRet = AVIERR_INTERNAL;
  274.     goto error;
  275.     }
  276.  
  277.     pavi->sinfo.fccHandler = 0;
  278.  
  279.     // Fix up stream name
  280.     LoadString(ghMod, IDS_STREAMNAME, achTemplate,
  281.             sizeof(achTemplate) / sizeof(TCHAR));
  282.     wsprintf(achTemp, achTemplate, pavi->sinfo.szName, lParam2);
  283.     lstrcpyn(pavi->sinfo.szName, achTemp,
  284.             sizeof(pavi->sinfo.szName) / sizeof(TCHAR));
  285.     pavi->sinfo.szName[sizeof(pavi->sinfo.szName) / sizeof(TCHAR) - 1] =
  286.                 TEXT('\0');
  287.  
  288.     // default to 256 colors
  289.     if (lParam2 < 2 || lParam2 > 256)
  290.     lParam2 = 256;
  291.  
  292.     pavi->lp16to8 = GlobalAllocPtr(GMEM_MOVEABLE, 32768L);
  293.     if (!pavi->lp16to8) {
  294.     lRet = AVIERR_MEMORY;
  295.     goto error;
  296.     }
  297.     
  298.     lRet = GetScode(AVIStreamMakePalette(pavi->pavi,
  299.                 AVIStreamLength(pavi->pavi) / 30,
  300.                 &pavi->hpal, pavi->lp16to8,
  301.                 (int) lParam2));
  302.  
  303.     pavi->lLastFrame = -1;
  304.     
  305. error:
  306.     return ResultFromScode(lRet);
  307. }
  308.  
  309. ///////////////////////////////////////////////////////////////////////////
  310. //
  311. //  PalMapStreamQueryInterface()
  312. //
  313. //      let other people know what interfaces we support
  314. //
  315. ///////////////////////////////////////////////////////////////////////////
  316. HRESULT STDMETHODCALLTYPE PalMapStreamQueryInterface(
  317.     PAVISTREAM ps,
  318.     REFIID riid,
  319.     LPVOID FAR* ppvObj)
  320. {
  321.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  322.     
  323.     if (IsEqualIID(riid, &IID_IUnknown))
  324.         *ppvObj = ps;
  325.     else if (IsEqualIID(riid, &IID_IAVIStream))
  326.         *ppvObj = ps;
  327.     else
  328.         return ResultFromScode(E_NOINTERFACE);
  329.     
  330.     pavi->ulRefCount++;
  331.     return NOERROR;
  332. }
  333.  
  334. ///////////////////////////////////////////////////////////////////////////
  335. //
  336. //  PalMapStreamAddRef()
  337. //
  338. //      increase the reference count of the stream
  339. //
  340. ///////////////////////////////////////////////////////////////////////////
  341.  
  342. ULONG STDMETHODCALLTYPE PalMapStreamAddRef(
  343.     PAVISTREAM ps)
  344. {
  345.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  346.  
  347.     return ++pavi->ulRefCount;
  348. }
  349.  
  350. ///////////////////////////////////////////////////////////////////////////
  351. //
  352. //  PalMapStreamRelease()
  353. //
  354. //      close a PalMapStream stream
  355. //
  356. ///////////////////////////////////////////////////////////////////////////
  357.  
  358. ULONG STDMETHODCALLTYPE PalMapStreamRelease(
  359.     PAVISTREAM ps)
  360. {
  361.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  362.  
  363.     if (!pavi)
  364.         return 0;
  365.     
  366.     if (--pavi->ulRefCount)
  367.         return pavi->ulRefCount;
  368.  
  369.     if (pavi->pgf)
  370.         AVIStreamGetFrameClose(pavi->pgf);
  371.     pavi->pgf = 0;
  372.     
  373.     if (pavi->pavi)
  374.         AVIStreamClose(pavi->pavi);
  375.     pavi->pavi = 0;
  376.  
  377.     if (pavi->lp16to8) {
  378.         GlobalFreePtr(pavi->lp16to8);
  379.         pavi->lp16to8 = 0;
  380.     }
  381.  
  382.     if (pavi->hpal) {
  383.         DeletePalette(pavi->hpal);
  384.         pavi->hpal = 0;
  385.     }
  386.     
  387.     if (pavi->lpdibLast) {
  388.         GlobalFreePtr(pavi->lpdibLast);
  389.         pavi->lpdibLast = 0;
  390.     }
  391.     
  392.     GlobalFreePtr(pavi);
  393.     
  394.     return 0;
  395. }
  396.  
  397. ///////////////////////////////////////////////////////////////////////////
  398. ///////////////////////////////////////////////////////////////////////////
  399.  
  400. HRESULT STDMETHODCALLTYPE PalMapStreamReadFormat(
  401.     PAVISTREAM ps,
  402.     LONG lPos,
  403.     LPVOID lpFormat,
  404.     LONG FAR *lpcbFormat)
  405. {
  406.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  407.     LONG            lSize;
  408.     
  409.     PalMapStreamRead(ps, lPos, 1, NULL, 0, NULL, NULL);
  410.  
  411.     if (pavi->lpdibLast == 0)
  412.         return ResultFromScode(AVIERR_INTERNAL);
  413.     lSize = pavi->lpdibLast->biSize
  414.         + pavi->lpdibLast->biClrUsed * sizeof(RGBQUAD);
  415.  
  416.     if (lpFormat)
  417.         hmemcpy(lpFormat, pavi->lpdibLast,
  418.             min(*lpcbFormat, lSize));
  419.  
  420.     *lpcbFormat = lSize;
  421.     
  422.     return 0;
  423. }
  424.  
  425. LONG STDMETHODCALLTYPE PalMapStreamFindKeyFrame(
  426.     PAVISTREAM ps,
  427.     LONG lPos,
  428.     LONG lFlags)
  429. {
  430.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  431.  
  432.     return lPos;
  433. }
  434.  
  435.  
  436. ///////////////////////////////////////////////////////////////////////////
  437. ///////////////////////////////////////////////////////////////////////////
  438.  
  439. HRESULT STDMETHODCALLTYPE PalMapStreamInfo(
  440.     PAVISTREAM ps,
  441.     AVISTREAMINFOW FAR * psi,        // OLE interfaces are ALWAYS UNICODE
  442.     LONG lSize)
  443. {
  444.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  445.  
  446.     if (psi)
  447.     hmemcpy(psi, &pavi->sinfo, min(lSize, sizeof(pavi->sinfo)));
  448.     
  449.     return 0;
  450. }
  451.  
  452.  
  453. ///////////////////////////////////////////////////////////////////////////
  454. ///////////////////////////////////////////////////////////////////////////
  455.  
  456. HRESULT STDMETHODCALLTYPE PalMapStreamRead(
  457.     PAVISTREAM    ps,
  458.     LONG        lStart,
  459.     LONG        lSamples,
  460.     LPVOID        lpBuffer,
  461.     LONG        cbBuffer,
  462.     LONG FAR *    plBytes,
  463.     LONG FAR *    plSamples)
  464. {
  465.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  466.  
  467.     LPBITMAPINFOHEADER    lpbi;
  468.     LPVOID            lp;
  469.  
  470.     if (lStart != pavi->lLastFrame) {
  471.         pavi->lLastFrame = -1;
  472.         lpbi = AVIStreamGetFrame(pavi->pgf, lStart);
  473.     
  474.         if (!lpbi)
  475.             goto ReadNothing;
  476.  
  477.         if (pavi->lpdibLast) {
  478.             GlobalFreePtr(pavi->lpdibLast);
  479.             pavi->lpdibLast = 0;
  480.         }
  481.  
  482.         pavi->lpdibLast = DibReduce(lpbi, NULL, pavi->hpal, pavi->lp16to8);
  483.         pavi->lLastFrame = lStart;
  484.     }
  485.  
  486.     lpbi = pavi->lpdibLast;    
  487.     //
  488.     // a NULL buffer means return the size buffer needed to read
  489.     // the given sample.
  490.     //
  491.     lp = (LPBYTE) lpbi + lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
  492.     
  493.     if (plBytes)
  494.         *plBytes = lpbi->biSizeImage;
  495.  
  496.     if (plSamples)
  497.         *plSamples = 1;
  498.  
  499.     if (lpBuffer) {
  500.         if (cbBuffer >= (LONG) lpbi->biSizeImage)
  501.             hmemcpy(lpBuffer, lp, lpbi->biSizeImage);
  502.         else
  503.             goto ReadNothing;
  504.     }
  505.     
  506.     return 0;
  507.     
  508. ReadNothing:
  509.     if (plBytes)
  510.         *plBytes = 0;
  511.  
  512.     if (plSamples)
  513.         *plSamples = 0;
  514.  
  515.     return ResultFromScode(AVIERR_BUFFERTOOSMALL);
  516. }
  517.  
  518.  
  519.  
  520. //
  521. //
  522. // Extra unimplemented functions.....
  523. //
  524. //
  525. //
  526. HRESULT STDMETHODCALLTYPE PalMapStreamReadData(
  527.     PAVISTREAM ps,
  528.     DWORD fcc,
  529.     LPVOID lp,
  530.     LONG FAR *lpcb)
  531. {
  532.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  533.     return ResultFromScode(AVIERR_UNSUPPORTED);
  534. }
  535.  
  536. HRESULT STDMETHODCALLTYPE PalMapStreamSetFormat(
  537.     PAVISTREAM ps,
  538.     LONG lPos,
  539.     LPVOID lpFormat,
  540.     LONG cbFormat)
  541. {
  542.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  543.     return ResultFromScode(AVIERR_UNSUPPORTED);
  544. }
  545.  
  546. HRESULT STDMETHODCALLTYPE PalMapStreamWriteData(
  547.     PAVISTREAM ps,
  548.     DWORD fcc,
  549.     LPVOID lp,
  550.     LONG cb)
  551. {
  552.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  553.     return ResultFromScode(AVIERR_UNSUPPORTED);
  554. }
  555.  
  556. HRESULT STDMETHODCALLTYPE PalMapStreamWrite(
  557.     PAVISTREAM ps,
  558.     LONG lStart,
  559.     LONG lSamples,
  560.     LPVOID lpBuffer,
  561.     LONG cbBuffer,
  562.     DWORD dwFlags,
  563.     LONG FAR *plSampWritten,
  564.     LONG FAR *plBytesWritten)
  565. {
  566.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  567.     return ResultFromScode(AVIERR_UNSUPPORTED);
  568. }
  569.  
  570. HRESULT STDMETHODCALLTYPE PalMapStreamDelete(
  571.     PAVISTREAM ps,
  572.     LONG lStart,
  573.     LONG lSamples)
  574. {
  575.     PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  576.     return ResultFromScode(AVIERR_UNSUPPORTED);
  577. }
  578.  
  579. HRESULT STDMETHODCALLTYPE PalMapStreamSetInfo(
  580.    PAVISTREAM ps,
  581.    AVISTREAMINFOW FAR * psi,
  582.    LONG lSize)
  583. {
  584.     return ResultFromScode(AVIERR_UNSUPPORTED);
  585. }
  586.  
  587. EXTERN_C int CALLBACK WEP(
  588.     BOOL fSystemExit)
  589. {
  590.     return TRUE;
  591. }
  592.  
  593.  
  594. EXTERN_C BOOL APIENTRY DllMain(HANDLE, DWORD, LPVOID);
  595. EXTERN_C BOOL APIENTRY DllMain(
  596.     HANDLE hModule,
  597.     DWORD dwReason,
  598.     LPVOID lpReserved )
  599. {
  600.     switch( dwReason)
  601.     {
  602.         case DLL_PROCESS_ATTACH:
  603.             if(ghMod == NULL)
  604.                 ghMod = (HMODULE)hModule;
  605.             break;
  606.         case DLL_THREAD_ATTACH:
  607.             break;
  608.         case DLL_THREAD_DETACH:
  609.             break;
  610.         case DLL_PROCESS_DETACH:
  611.             break;
  612.     }
  613.     return TRUE;
  614. }
  615.