DSEQF.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:37k
源码类别:
Windows编程
开发平台:
Visual C++
- /****************************************************************************
- *
- * DSEQF.CPP
- *
- * routines for reading DIB sequences
- *
- ***************************************************************************/
- /**************************************************************************
- *
- * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- * PURPOSE.
- *
- * Copyright (C) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
- *
- **************************************************************************/
- #define INC_OLE2
- #include <windows.h>
- #include <windowsx.h>
- #include <mmsystem.h>
- #include <string.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <ctype.h>
- #include <vfw.h>
- #include "handler.h"
- #include "handler.rc"
- static DWORD NEAR PASCAL dseqParseFileName(
- LPSTR lpszFileName,
- LPSTR lpszTemplate,
- DWORD FAR * lpdwMaxValue);
- #ifdef DEBUG
- static void CDECL dprintf(LPSTR, ...);
- #define DPF dprintf
- #else
- #define DPF ; / ## /
- #endif
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
- /* - - - - - - - - */
- UINT uUseCount;
- BOOL fLocked;
- /* - - - - - - - - */
- //
- // External function called by the Class Factory to create an instance of
- // the DIB sequence reader/writer
- //
- HRESULT CAVIFile::Create(
- IUnknown FAR* pUnknownOuter,
- const IID FAR& riid,
- void FAR* FAR* ppv)
- {
- IUnknown FAR* pUnknown;
- CAVIFile FAR* pAVIFile;
- HRESULT hresult;
- pAVIFile = new FAR CAVIFile(pUnknownOuter, &pUnknown);
- if (!pAVIFile)
- return ResultFromScode(E_OUTOFMEMORY);
- hresult = pUnknown->QueryInterface(riid, ppv);
- if (FAILED(GetScode(hresult)))
- delete pAVIFile;
- return hresult;
- }
- /* - - - - - - - - */
- //
- // Random C++ stuff: constructors & such...
- //
- CAVIFile::CAVIFile(
- IUnknown FAR* pUnknownOuter,
- IUnknown FAR* FAR* ppUnknown) :
- m_Unknown(this),
- m_AVIFile(this),
- m_Persist(this),
- #ifdef CUSTOMMARSHAL
- m_Marshal(this),
- #endif
- m_AVIStream(this)
- {
- if (pUnknownOuter)
- m_pUnknownOuter = pUnknownOuter;
- else
- m_pUnknownOuter = &m_Unknown;
- *ppUnknown = &m_Unknown;
- }
- /* - - - - - - - - */
- CAVIFile::CUnknownImpl::CUnknownImpl(
- CAVIFile FAR* pAVIFile)
- {
- m_pAVIFile = pAVIFile;
- m_refs = 0;
- }
- /* - - - - - - - - */
- //
- // This QueryInterface function allows a caller to move between the various
- // interfaces the object presents
- //
- STDMETHODIMP CAVIFile::CUnknownImpl::QueryInterface(
- const IID FAR& iid,
- void FAR* FAR* ppv)
- {
- if (iid == IID_IUnknown)
- *ppv = &m_pAVIFile->m_Unknown;
- else if (iid == IID_IAVIFile)
- *ppv = &m_pAVIFile->m_AVIFile;
- else if (iid == IID_IAVIStream)
- *ppv = &m_pAVIFile->m_AVIStream;
- else if (iid == IID_IPersistFile)
- *ppv = &m_pAVIFile->m_Persist;
- #ifdef CUSTOMMARSHAL
- else if (iid == IID_IMarshal)
- *ppv = &m_pAVIFile->m_Marshal;
- #endif
- else
- return ResultFromScode(E_NOINTERFACE);
- AddRef();
- return NULL;
- }
- /* - - - - - - - - */
- STDMETHODIMP_(ULONG) CAVIFile::CUnknownImpl::AddRef()
- {
- uUseCount++;
- return ++m_refs;
- }
- /* - - - - - - - - */
- //
- // All calls to AddRef, Release, QueryInterface for the file or stream
- // functions are redirected to the Unknown implementation...
- //
- CAVIFile::CAVIFileImpl::CAVIFileImpl(
- CAVIFile FAR* pAVIFile)
- {
- m_pAVIFile = pAVIFile;
- }
- /* - - - - - - - - */
- CAVIFile::CAVIFileImpl::~CAVIFileImpl()
- {
- }
- /* - - - - - - - - */
- STDMETHODIMP CAVIFile::CAVIFileImpl::QueryInterface(
- const IID FAR& iid,
- void FAR* FAR* ppv)
- {
- return m_pAVIFile->m_pUnknownOuter->QueryInterface(iid, ppv);
- }
- /* - - - - - - - - */
- STDMETHODIMP_(ULONG) CAVIFile::CAVIFileImpl::AddRef()
- {
- return m_pAVIFile->m_pUnknownOuter->AddRef();
- }
- /* - - - - - - - - */
- STDMETHODIMP_(ULONG) CAVIFile::CAVIFileImpl::Release()
- {
- return m_pAVIFile->m_pUnknownOuter->Release();
- }
- /* - - - - - - - - */
- CAVIFile::CAVIStreamImpl::CAVIStreamImpl(
- CAVIFile FAR* pAVIFile)
- {
- m_pAVIFile = pAVIFile;
- }
- /* - - - - - - - - */
- CAVIFile::CAVIStreamImpl::~CAVIStreamImpl()
- {
- }
- /* - - - - - - - - */
- STDMETHODIMP CAVIFile::CAVIStreamImpl::QueryInterface(
- const IID FAR& iid,
- void FAR* FAR* ppv)
- {
- return m_pAVIFile->m_pUnknownOuter->QueryInterface(iid, ppv);
- }
- /* - - - - - - - - */
- STDMETHODIMP_(ULONG) CAVIFile::CAVIStreamImpl::AddRef()
- {
- return m_pAVIFile->m_pUnknownOuter->AddRef();
- }
- /* - - - - - - - - */
- STDMETHODIMP_(ULONG) CAVIFile::CAVIStreamImpl::Release()
- {
- return m_pAVIFile->m_pUnknownOuter->Release();
- }
- // --- IPersistFile implementation --------------------------------------
- CAVIFile::CPersistFileImpl::CPersistFileImpl(CAVIFile FAR* pAVIFile)
- {
- m_pAVIFile = pAVIFile;
- }
- STDMETHODIMP
- CAVIFile::CPersistFileImpl::QueryInterface(REFIID riid, LPVOID FAR* ppv)
- {
- return m_pAVIFile->m_pUnknownOuter->QueryInterface(riid, ppv);
- }
- STDMETHODIMP_(ULONG)
- CAVIFile::CPersistFileImpl::AddRef()
- {
- return m_pAVIFile->m_pUnknownOuter->AddRef();
- }
- STDMETHODIMP_(ULONG)
- CAVIFile::CPersistFileImpl::Release()
- {
- return m_pAVIFile->m_pUnknownOuter->Release();
- }
- // *** IPersist methods ***
- STDMETHODIMP
- CAVIFile::CPersistFileImpl::GetClassID (LPCLSID lpClassID)
- {
- *lpClassID = CLSID_DIBSEQFileReader;
- return NOERROR;
- }
- // *** IPersistFile methods ***
- STDMETHODIMP
- CAVIFile::CPersistFileImpl::IsDirty ()
- {
- if (m_pAVIFile->fDirty) {
- return NOERROR;
- } else {
- return ResultFromScode(S_FALSE);
- }
- }
- /* - - - - - - - - */
- //
- // This function takes the name of the first file in a DIB sequence, and
- // returns a printf() specifier which can be used to create the names in
- // the sequence, along with minimum and maximum values that can be used.
- //
- //
- // Examples:
- // lpszFileName = "FOO0047.DIB"
- // -> lpszTemplate = "FOO%04d.DIB", dwMaxValue = 9999, return = 47
- //
- // lpszFileName = "TEST01.DIB"
- // -> lpszTemplate = "TEST%01d.DIB", dwMaxValue = 9, return = 1
- //
- // lpszFileName = "TEST1.DIB"
- // -> lpszTemplate = "TEST%d.DIB", dwMaxValue = 9999, return = 1
- //
- // lpszFileName = "SINGLE.DIB"
- // -> lpszTemplate = "SINGLE.DIB", dwMaxValue = 0, return = 0
- //
- static DWORD NEAR PASCAL dseqParseFileName(
- LPSTR lpszFileName,
- LPSTR lpszTemplate,
- DWORD FAR * lpdwMaxValue)
- {
- char achTemp[_MAX_PATH];
- DWORD dwFirst;
- WORD wFieldWidth;
- DWORD dwMult;
- BOOL fLeadingZero = FALSE;
- LPSTR lp;
- LPSTR lp2;
- LPSTR lpExt;
- /* Find end of string */
- lp2 = lpszFileName;
- lp = achTemp;
- while (*lp2)
- *lp++ = *lp2++;
- *lp = ' ';
- /* Make lp2 point at last character of base filename (w/o extension) */
- /* Make lpExt point at the extension (without the dot) */
- for (lp2 = lp; *lp2 != '.'; lp2--)
- {
- lpExt = lp2;
- if ((lp2 == achTemp) || (*lp2 == '\')
- || (*lp2 == ':') || (*lp2 == '!'))
- {
- /* There is no extension */
- lp2 = lp;
- lpExt = lp;
- break;
- }
- }
- lp2--;
- // Count the number of numeric characters here....
- dwFirst = 0;
- wFieldWidth = 0;
- dwMult = 1;
- while (lp2 >= achTemp && (*lp2 >= '0') && (*lp2 <= '9')) {
- fLeadingZero = (*lp2 == '0');
- dwFirst += dwMult * (*(lp2--) - '0');
- dwMult *= 10;
- wFieldWidth++;
- }
- *lpdwMaxValue = dwMult - 1;
- lp2++;
- *lp2 = ' ';
- // Make the format specifier....
- if (wFieldWidth) {
- if (fLeadingZero) {
- wsprintf((LPSTR) lpszTemplate,"%s%%0%ulu.%s",
- (LPSTR) achTemp, wFieldWidth,(LPSTR) lpExt);
- } else {
- wsprintf((LPSTR) lpszTemplate,"%s%%lu.%s",
- (LPSTR) achTemp, (LPSTR) lpExt);
- *lpdwMaxValue = 999999L;
- // !!! This should really be based on the number of
- // characters left after the base name....
- }
- } else
- wsprintf((LPSTR) lpszTemplate,"%s.%s",
- (LPSTR) achTemp, (LPSTR) lpExt);
- DPF("First = %lu, Width = %u, Template = '%s'n",dwFirst, wFieldWidth, lpszTemplate);
- return dwFirst;
- }
- /* - - - - - - - - */
- #define SLASH(c) ((c) == '/' || (c) == '\')
- /*--------------------------------------------------------------+
- | FileName - return a pointer to the filename part of szPath |
- | with no preceding path. |
- +--------------------------------------------------------------*/
- LPSTR FAR FileName(
- LPCSTR lszPath)
- {
- LPCSTR lszCur;
- for (lszCur = lszPath + lstrlen(lszPath); lszCur > lszPath && !SLASH(*lszCur) && *lszCur != ':';)
- lszCur = AnsiPrev(lszPath, lszCur);
- if (lszCur == lszPath)
- return (LPSTR)lszCur;
- else
- return (LPSTR)(lszCur + 1);
- }
- /* - - - - - - - - */
- //
- // "Open" a DIB sequence, by parsing the filename and counting the number
- // of frames actually present....
- //
- STDMETHODIMP
- CAVIFile::CPersistFileImpl::Load (LPCOLESTR szFile, DWORD mode)
- {
- CAVIFile FAR *p = m_pAVIFile;
- UINT ui;
- char ach[80];
- char szFileA[MAX_PATH];
- p->mode = mode;
- //
- // Parse the filename
- //
- wsprintf(szFileA, "%ls", szFile);
- p->dwFirstFrame = dseqParseFileName(szFileA,
- p->achFilenameTemplate,
- &p->dwMaxValue);
- //
- // Initialize the variables that keep track of what frame is cached
- //
- p->lCurFrame = -1;
- p->lpFrame = NULL;
- p->cbFrame = 0;
- p->cbFrameBuffer = 0;
- p->lpFormat = NULL;
- p->cbFormat = 0;
- p->cbFormatBuffer = 0;
- //
- // Build a stream header....
- //
- p->sinfo.fccType = streamtypeVIDEO;
- p->sinfo.fccHandler = 0;
- p->sinfo.dwFlags = 0;
- p->sinfo.wPriority = 0;
- p->sinfo.wLanguage = 0;
- p->sinfo.dwInitialFrames = 0;
- p->sinfo.dwScale = 1;
- p->sinfo.dwRate = 15;
- p->sinfo.dwStart = 0;
- p->sinfo.dwLength = 0;
- p->sinfo.dwSuggestedBufferSize = 0;
- p->sinfo.dwSampleSize = 0;
- LoadString(ghModule, IDS_STREAMNAME, ach, sizeof(ach));
- {
- char TempFileName[80];
- char TempName[80];
- wsprintf(TempFileName, "%ls", szFile);
- wsprintf(TempName, ach, FileName(TempFileName));
- wsprintfW(p->sinfo.szName, L"%hs", TempName);
- }
- //
- // ... and a file header.
- //
- _fmemset(&p->finfo, 0, sizeof(p->finfo));
- p->finfo.dwRate = 15;
- p->finfo.dwScale = 1;
- p->finfo.dwStreams = 1;
- p->finfo.dwWidth = 0;
- p->finfo.dwHeight = 0;
- LoadString(ghModule, IDS_FILETYPE,
- p->finfo.szFileType,
- sizeof(p->finfo.szFileType));
- p->finfo.dwCaps = AVIFILECAPS_CANREAD |
- AVIFILECAPS_CANWRITE |
- AVIFILECAPS_ALLKEYFRAMES;
- if (mode & OF_CREATE) {
- //
- // They're creating a "new" sequence
- //
- p->fStreamPresent = FALSE;
- } else {
- char ach[_MAX_PATH];
- OFSTRUCT of;
- DWORD dwFrame;
- HRESULT hr;
- //
- // They're opening an existing sequence, so we have to actually
- // count how many files are present
- //
- p->fStreamPresent = TRUE;
- ui = SetErrorMode(SEM_NOOPENFILEERRORBOX);
- for (dwFrame = 0; TRUE; dwFrame++) {
- if (dwFrame > p->dwMaxValue)
- break;
- wsprintf(ach,p->achFilenameTemplate, dwFrame + p->dwFirstFrame);
- // DPF("DIBSEQ: Checking frame %lu from '%s'n",dwFrame,(LPSTR) ach);
- /****************************************************************************/
- /* DOS share has a bug. If the file we're testing for existence is open */
- /* already by someone else, we have to give it the same flag for SHARE as */
- /* the other person is using. So we have to try both on and off. Only one */
- /* of these will return TRUE but if one of them does, the file exists. Also*/
- /* we have to turn off the system model error box for share violations. */
- /****************************************************************************/
- if (OpenFile((LPSTR)ach, &of, OF_EXIST) == HFILE_ERROR &&
- OpenFile((LPSTR)ach, &of, OF_EXIST | OF_SHARE_DENY_NONE) ==
- HFILE_ERROR)
- break;
- }
- SetErrorMode(ui);
- if (dwFrame == 0)
- goto error;
- //
- // Fix up the length in the header structures
- //
- p->sinfo.dwLength = dwFrame;
- p->finfo.dwLength = dwFrame;
- //
- // Load the first frame, so we'll be ready...
- //
- hr = p->LoadFrame(0);
- if (FAILED(GetScode(hr)))
- return hr;
- p->finfo.dwSuggestedBufferSize = p->cbFrame;
- p->sinfo.dwSuggestedBufferSize = p->cbFrame;
- p->finfo.dwWidth = ((LPBITMAPINFOHEADER) p->lpFormat)->biWidth;
- p->finfo.dwHeight = ((LPBITMAPINFOHEADER) p->lpFormat)->biHeight;
- p->sinfo.dwFlags = AVISTREAMINFO_FORMATCHANGES;
- SetRect(&p->sinfo.rcFrame,
- 0, 0, (int) p->finfo.dwWidth, (int) p->finfo.dwHeight);
- }
- //
- // all done return success.
- //
- return ResultFromScode(0); // success
- error:
- return ResultFromScode(AVIERR_FILEREAD);
- }
- STDMETHODIMP
- CAVIFile::CPersistFileImpl::Save (LPCOLESTR lpszFileName, BOOL fRemember)
- {
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- STDMETHODIMP
- CAVIFile::CPersistFileImpl::SaveCompleted (LPCOLESTR lpszFileName)
- {
- return NOERROR;
- }
- STDMETHODIMP
- CAVIFile::CPersistFileImpl::GetCurFile (LPOLESTR FAR * lplpszFileName)
- {
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- // -------------------- IAVIFile Implementation-----------------------
- //
- // The GetStream method returns an interface pointer to the video stream,
- // assuming one exists.
- //
- STDMETHODIMP CAVIFile::CAVIFileImpl::GetStream(
- PAVISTREAM FAR * ppavi,
- DWORD fccType,
- LONG lParam)
- {
- CAVIFile FAR * p = m_pAVIFile;
- int iStreamWant;
- iStreamWant = (int)lParam;
- if (!p->fStreamPresent)
- return ResultFromScode(-1);
- // We only support one stream
- if (lParam != 0)
- return ResultFromScode(-1);
- // We only support a video stream
- if (fccType && fccType != streamtypeVIDEO)
- return ResultFromScode(-1);
- //
- // Be sure to keep the reference count up to date...
- //
- AddRef();
- *ppavi = (PAVISTREAM) &(p->m_AVIStream);
- return ResultFromScode(AVIERR_OK);
- }
- //
- // If they opened the file with the OF_CREATE flag, they will use this
- // method to create the video stream.
- //
- STDMETHODIMP CAVIFile::CAVIFileImpl::CreateStream(
- PAVISTREAM FAR *ppstream,
- AVISTREAMINFOW FAR *psi
- )
- {
- CAVIFile FAR * p = m_pAVIFile;
- // If the stream was already there, we fail.
- if (p->fStreamPresent)
- return ResultFromScode(AVIERR_UNSUPPORTED);
- p->sinfo = *psi;
- p->sinfo.dwLength = 0;
- *ppstream = (PAVISTREAM) &(p->m_AVIStream);
- p->fStreamPresent = TRUE;
- // Keep the reference count correct
- AddRef();
- return ResultFromScode(AVIERR_OK);
- }
- STDMETHODIMP CAVIFile::CAVIFileImpl::WriteData(
- DWORD ckid,
- LPVOID lpData,
- LONG cbData)
- {
- CAVIFile FAR * p = m_pAVIFile;
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- STDMETHODIMP CAVIFile::CAVIFileImpl::ReadData(
- DWORD ckid,
- LPVOID lpData,
- LONG FAR *lpcbData)
- {
- CAVIFile FAR * p = m_pAVIFile;
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- STDMETHODIMP CAVIFile::CAVIFileImpl::EndRecord(void)
- {
- return ResultFromScode(AVIERR_OK);
- }
- STDMETHODIMP CAVIFile::CAVIFileImpl::Info(AVIFILEINFOW FAR * pfi, LONG lSize)
- {
- CAVIFile FAR * p = m_pAVIFile;
- hmemcpy(pfi, &p->finfo, min(lSize,sizeof(p->finfo)));
- return 0;
- }
- STDMETHODIMP CAVIFile::CAVIStreamImpl::Create(
- LONG lParam1,
- LONG lParam2)
- {
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- //
- // Returns where the last key frame before the given frame is.
- //
- // For now, we assume each DIB is a key frame.
- //
- STDMETHODIMP_(LONG) CAVIFile::CAVIStreamImpl::FindSample(
- LONG lPos,
- LONG lFlags)
- {
- CAVIFile FAR * p = m_pAVIFile;
- // some minimal error checking....
- if (lPos < 0 || lPos >= (LONG) p->sinfo.dwLength)
- return -1;
- // !!! Can we really assume every frame is non-empty and a key frame?
- // !!! Who knows where format changes are? Let's assume everywhere!
- return lPos;
- }
- #define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
- #define DIBWIDTHBYTES(bi) (int)WIDTHBYTES((int)(bi).biWidth * (int)(bi).biBitCount)
- #define BFT_BITMAP 0x4d42 /* 'BM' */
- //
- // Helper function to load a given frame into our cache.
- //
- // This is where the actual work is done; all other functions just return
- // the current format or frame out of the cache.
- //
- HRESULT NEAR PASCAL CAVIFile::LoadFrame(
- LONG lPos)
- {
- char ach[_MAX_PATH];
- HMMIO hmmio;
- BITMAPFILEHEADER bfh;
- BITMAPINFOHEADER bih;
- SCODE sc = 0;
- UINT ui;
- //
- // Check if we've already loaded this frame...
- //
- if (lPos == lCurFrame)
- return 0;
- //
- // Build the filename by printing using our template
- //
- wsprintf(ach, achFilenameTemplate, dwFirstFrame + lPos);
- // No system error box, please.
- ui = SetErrorMode(SEM_NOOPENFILEERRORBOX);
- //
- // Go try to read the frame... Because of SHARE we have to try
- // opening it two different ways.
- //
- hmmio = mmioOpen(ach, NULL, MMIO_READ | OF_SHARE_DENY_WRITE);
- if (!hmmio) {
- hmmio = mmioOpen(ach, NULL, MMIO_READ);
- if (!hmmio)
- return ResultFromScode(AVIERR_FILEOPEN);
- }
- SetErrorMode(ui);
- //
- // Read the BitmapFileHeader...
- //
- if (mmioRead(hmmio, (LPSTR) &bfh, sizeof(bfh)) != sizeof(bfh)) {
- sc = AVIERR_FILEREAD;
- goto error;
- }
- if (bfh.bfType != BFT_BITMAP) {
- sc = AVIERR_BADFORMAT;
- goto error;
- }
- //
- // Read the BitmapInfoHeader...
- //
- if (mmioRead(hmmio, (LPSTR) &bih, sizeof(bih)) != sizeof(bih)) {
- sc = AVIERR_FILEREAD;
- goto error;
- }
- if (bih.biSize < sizeof(bih)) {
- sc = AVIERR_BADFORMAT;
- goto error;
- }
- // Check that the width and height match....
- if ((finfo.dwWidth && finfo.dwWidth != (DWORD) bih.biWidth) ||
- (finfo.dwHeight && finfo.dwHeight != (DWORD) bih.biHeight)) {
- sc = AVIERR_BADFORMAT;
- goto error;
- }
- // Fix up some fields in the header...
- if (bih.biSizeImage == 0) {
- bih.biSizeImage = DIBWIDTHBYTES(bih) * bih.biHeight;
- }
- if (bih.biClrUsed == 0 && bih.biBitCount <= 8 && bih.biCompression <= BI_RLE8)
- bih.biClrUsed = 1 << bih.biBitCount;
- cbFormat = bih.biSize + bih.biClrUsed * sizeof(RGBQUAD);
- // Allocate space for the format
- if (cbFormat > cbFormatBuffer) {
- if (lpFormat) {
- GlobalFreePtr(lpFormat);
- lpFormat = 0;
- cbFormatBuffer = 0;
- }
- lpFormat = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_DDESHARE, cbFormat);
- if (!lpFormat) {
- sc = AVIERR_MEMORY;
- goto error;
- }
- cbFormatBuffer = cbFormat;
- }
- *((LPBITMAPINFOHEADER) lpFormat) = bih;
- // If the format is bigger than a BITMAPINFOHEADER, read the rest....
- if (cbFormat > sizeof(bih)) {
- if (mmioRead(hmmio, (LPSTR) lpFormat + sizeof(bih),
- cbFormat - (LONG)sizeof(bih))
- != cbFormat - (LONG)sizeof(bih))
- {
- sc = AVIERR_FILEREAD;
- goto error;
- }
- }
- //
- // Allocate enough space to read the frame in...
- //
- if (bih.biSizeImage > (DWORD) cbFrameBuffer) {
- if (lpFrame) {
- GlobalFreePtr(lpFrame);
- lpFrame = 0;
- cbFrameBuffer = 0;
- }
- lpFrame = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_DDESHARE, bih.biSizeImage);
- if (!lpFrame) {
- sc = AVIERR_MEMORY;
- goto error;
- }
- cbFrameBuffer = bih.biSizeImage;
- }
- cbFrame = bih.biSizeImage;
- //
- // and actually read the frame....
- //
- if (mmioRead(hmmio, (LPSTR) lpFrame, cbFrame) != cbFrame) {
- sc = AVIERR_FILEREAD;
- goto error;
- }
- lCurFrame = lPos;
- error:
- mmioClose(hmmio, 0);
- return ResultFromScode(sc);
- }
- //
- // The ReadFormat method returns the format of the specified frame....
- //
- STDMETHODIMP CAVIFile::CAVIStreamImpl::ReadFormat(
- LONG lPos,
- LPVOID lpFormat,
- LONG FAR *lpcbFormat)
- {
- CAVIFile FAR * p = m_pAVIFile;
- HRESULT hr;
- //
- // Try to get the correct frame
- //
- hr = p->LoadFrame(lPos);
- if (hr != 0)
- return hr;
- // No buffer to fill in, this means return the size needed.
- if (lpFormat == NULL || *lpcbFormat == 0) {
- *lpcbFormat = p->cbFormat;
- return 0;
- }
- //
- // and return as much of the format as will fit.
- //
- hmemcpy(lpFormat, p->lpFormat, min(*lpcbFormat, p->cbFormat));
- *lpcbFormat = p->cbFormat;
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
- STDMETHODIMP CAVIFile::CAVIStreamImpl::Info(AVISTREAMINFOW FAR * psi, LONG lSize)
- {
- CAVIFile FAR * p = m_pAVIFile;
- hmemcpy(psi,&p->sinfo, min(lSize,sizeof(p->sinfo)));
- // return sizeof(p->sinfo);
- return 0;
- }
- STDMETHODIMP_(ULONG) CAVIFile::CUnknownImpl::Release()
- {
- CAVIFile FAR * p = m_pAVIFile;
- uUseCount--;
- if (!--m_refs) {
- LONG lRet = AVIERR_OK;
- if (p->fDirty) {
- }
- goto success;
- success:
- if (p->lpFormat)
- GlobalFreePtr(p->lpFormat);
- p->lpFormat = NULL;
- p->cbFormat = 0;
- if (p->lpFrame)
- GlobalFreePtr(p->lpFrame);
- p->lpFrame = NULL;
- p->cbFrame = 0;
- delete this;
- return 0;
- }
- return m_refs;
- }
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
- STDMETHODIMP CAVIFile::CAVIStreamImpl::Read(
- LONG lStart,
- LONG lSamples,
- LPVOID lpBuffer,
- LONG cbBuffer,
- LONG FAR * plBytes,
- LONG FAR * plSamples)
- {
- CAVIFile FAR * p = m_pAVIFile;
- HRESULT hr;
- if (lStart < 0 || lStart >= (LONG) p->sinfo.dwLength) {
- if (plBytes)
- *plBytes = 0;
- if (plSamples)
- *plSamples = 0;
- return 0;
- }
- // We always read one frame at a time...
- lSamples = 1;
- // Load it into the cache....
- hr = p->LoadFrame(lStart);
- if (hr != 0)
- return hr;
- //
- // a NULL buffer means return the size buffer needed to read
- // the given sample.
- //
- if (lpBuffer == NULL || cbBuffer == 0) {
- if (plBytes)
- *plBytes = p->cbFrame;
- if (plSamples)
- *plSamples = lSamples;
- return 0;
- }
- //
- // They didn't give us enough space for the frame, so complain
- //
- if (cbBuffer < p->cbFrame) {
- if (plBytes)
- *plBytes = p->cbFrame;
- return ResultFromScode(AVIERR_BUFFERTOOSMALL);
- }
- //
- // Copy the frame into the caller's buffer
- //
- hmemcpy(lpBuffer, p->lpFrame, p->cbFrame);
- //
- // success return number of bytes and number of samples read
- //
- if (plBytes)
- *plBytes = p->cbFrame;
- if (plSamples)
- *plSamples = lSamples;
- return ResultFromScode(AVIERR_OK);
- }
- STDMETHODIMP CAVIFile::CAVIStreamImpl::SetFormat(
- LONG lPos,
- LPVOID lpFormat,
- LONG cbFormat)
- {
- CAVIFile FAR * p = m_pAVIFile;
- // Keep track of the format....
- p->cbFormat = cbFormat;
- p->lpFormat = (LPVOID) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_DDESHARE, cbFormat);
- if (p->lpFormat == NULL)
- return ResultFromScode(AVIERR_MEMORY);
- hmemcpy(p->lpFormat, lpFormat, cbFormat);
- p->finfo.dwWidth = ((LPBITMAPINFOHEADER) p->lpFormat)->biWidth;
- p->finfo.dwHeight = ((LPBITMAPINFOHEADER) p->lpFormat)->biHeight;
- SetRect(&p->sinfo.rcFrame,
- 0, 0, (int) p->finfo.dwWidth, (int) p->finfo.dwHeight);
- return 0L;
- }
- //
- // Helper function to save a single frame
- //
- HRESULT NEAR PASCAL CAVIFile::WriteFrame(
- LONG lPos,
- LPVOID lp,
- LONG cb)
- {
- char ach[_MAX_PATH];
- HMMIO hmmio;
- BITMAPFILEHEADER bfh;
- //
- // If they're overwriting the cached frame, invalidate the cache
- //
- if (lPos == lCurFrame)
- lCurFrame = -1;
- //
- // Build the filename to write to
- //
- wsprintf(ach, achFilenameTemplate, dwFirstFrame + lPos);
- // and write it.
- hmmio = mmioOpen(ach, NULL, MMIO_WRITE | MMIO_CREATE | OF_SHARE_EXCLUSIVE);
- if (!hmmio)
- return ResultFromScode(AVIERR_FILEOPEN);
- //
- // Write the BitmapFileHeader
- //
- bfh.bfType = BFT_BITMAP;
- bfh.bfOffBits = sizeof(bfh) + cbFormat;
- bfh.bfSize = bfh.bfOffBits + cb;
- if (mmioWrite(hmmio, (LPSTR) &bfh, sizeof(bfh)) != sizeof(bfh)) {
- error:
- mmioClose(hmmio, 0);
- return ResultFromScode(AVIERR_FILEWRITE);
- }
- ((LPBITMAPINFOHEADER) lpFormat)->biSizeImage = cb;
- //
- // Write the DIB format
- //
- if (mmioWrite(hmmio, (LPSTR) lpFormat, cbFormat) != cbFormat)
- goto error;
- //
- // Write the data
- //
- if (mmioWrite(hmmio, (LPSTR) lp, cb) != cb)
- goto error;
- //
- // Flush things so that we can be sure everything is written out
- //
- if (mmioFlush(hmmio, 0) != 0)
- goto error;
- mmioClose(hmmio, 0);
- return 0;
- }
- STDMETHODIMP CAVIFile::CAVIStreamImpl::Write(
- LONG lStart,
- LONG lSamples,
- LPVOID lpData,
- LONG cbData,
- DWORD dwFlags,
- LONG FAR *plSampWritten,
- LONG FAR *plBytesWritten)
- {
- CAVIFile FAR * p = m_pAVIFile;
- HRESULT hr;
- if ((p->mode & (OF_WRITE | OF_READWRITE)) == 0)
- return ResultFromScode(AVIERR_READONLY);
- if (p->lpFormat == NULL)
- return ResultFromScode(AVIERR_UNSUPPORTED);
- // < 0 means "at end"
- if (lStart < 0)
- lStart = p->sinfo.dwStart + p->sinfo.dwLength;
- if (lStart > (LONG) (p->sinfo.dwStart + p->sinfo.dwLength))
- return ResultFromScode(AVIERR_BADPARAM);
- // !!! Die if we've reached the limit of our numbers....
- if ((DWORD) lStart + p->dwFirstFrame > p->dwMaxValue)
- return ResultFromScode(AVIERR_FILEWRITE);
- if (lSamples != 1)
- return ResultFromScode(AVIERR_BADPARAM);
- // only allow key frames!
- if (!(dwFlags & AVIIF_KEYFRAME)) {
- DPF("Tried to write a non-key frame to a DIB sequence!n");
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- hr = p->WriteFrame(lStart, lpData, cbData);
- if (hr != AVIERR_OK)
- return hr;
- p->fDirty = TRUE;
- p->sinfo.dwLength =
- max((LONG) p->sinfo.dwLength,
- lStart + lSamples);
- p->finfo.dwLength = p->sinfo.dwLength;
- p->finfo.dwSuggestedBufferSize =
- max(p->finfo.dwSuggestedBufferSize, (DWORD) cbData);
- p->sinfo.dwSuggestedBufferSize =
- p->finfo.dwSuggestedBufferSize;
- if (plSampWritten)
- *plSampWritten = lSamples;
- if (plBytesWritten)
- *plBytesWritten = cbData;
- return ResultFromScode(AVIERR_OK);
- }
- // these both are for saving. we don't support saving
- STDMETHODIMP
- CAVIFile::CAVIFileImpl::DeleteStream(DWORD fccType, LONG lParam)
- {
- return ResultFromScode(E_FAIL);
- }
- STDMETHODIMP
- CAVIFile::CAVIStreamImpl::SetInfo(
- AVISTREAMINFOW FAR * lpInfo,
- LONG cbInfo
- )
- {
- return ResultFromScode(E_FAIL);
- }
- STDMETHODIMP CAVIFile::CAVIStreamImpl::Delete(
- LONG lStart,
- LONG lSamples)
- {
- CAVIFile FAR * p = m_pAVIFile;
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- // Should these just map to Read/WriteData? !!!
- STDMETHODIMP CAVIFile::CAVIStreamImpl::ReadData(
- DWORD fcc,
- LPVOID lp,
- LONG FAR *lpcb)
- {
- CAVIFile FAR * p = m_pAVIFile;
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- STDMETHODIMP CAVIFile::CAVIStreamImpl::WriteData(
- DWORD fcc,
- LPVOID lp,
- LONG cb)
- {
- CAVIFile FAR * p = m_pAVIFile;
- return ResultFromScode(AVIERR_UNSUPPORTED);
- }
- #ifdef CUSTOMMARSHAL
- // The code below supports custom marshalling.
- // !!! Need good explanation here!
- CAVIFile::CMarshalImpl::CMarshalImpl(
- CAVIFile FAR* pAVIFile)
- {
- m_pAVIFile = pAVIFile;
- }
- /* - - - - - - - - */
- STDMETHODIMP CAVIFile::CMarshalImpl::QueryInterface(
- const IID FAR& iid,
- void FAR* FAR* ppv)
- {
- return m_pAVIFile->m_pUnknownOuter->QueryInterface(iid, ppv);
- }
- /* - - - - - - - - */
- STDMETHODIMP_(ULONG) CAVIFile::CMarshalImpl::AddRef()
- {
- return m_pAVIFile->m_pUnknownOuter->AddRef();
- }
- /* - - - - - - - - */
- STDMETHODIMP_(ULONG) CAVIFile::CMarshalImpl::Release()
- {
- return m_pAVIFile->m_pUnknownOuter->Release();
- }
- // *** IMarshal methods ***
- STDMETHODIMP CAVIFile::CMarshalImpl::GetUnmarshalClass (
- THIS_ REFIID riid, LPVOID pv,
- DWORD dwDestContext, LPVOID pvDestContext,
- DWORD mshlflags, LPCLSID pCid)
- {
- HRESULT hr = NOERROR;
- DPF("UnMarshalClass calledn");
- if (dwDestContext != MSHCTX_LOCAL) {
- LPMARSHAL pMarshal;
- DPF("Marshal context is %lu: delegating...n", dwDestContext);
- hr = CoGetStandardMarshal(riid, NULL, dwDestContext, pvDestContext, mshlflags,
- &pMarshal);
- if (hr != NOERROR)
- return hr;
- hr = pMarshal->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext,
- mshlflags, pCid);
- pMarshal->Release();
- return hr;
- }
- *pCid = CLSID_AVISimpleUnMarshal;
- return hr;
- }
- STDMETHODIMP CAVIFile::CMarshalImpl::GetMarshalSizeMax (
- THIS_ REFIID riid, LPVOID pv,
- DWORD dwDestContext, LPVOID pvDestContext,
- DWORD mshlflags, LPDWORD pSize)
- {
- HRESULT hr = NOERROR;
- IUnknown FAR * pUnk = &m_pAVIFile->m_Unknown;
- if (dwDestContext != MSHCTX_LOCAL) {
- LPMARSHAL pMarshal;
- hr = CoGetStandardMarshal(riid, NULL, dwDestContext, pvDestContext, mshlflags,
- &pMarshal);
- if (hr != NOERROR)
- return hr;
- hr = pMarshal->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext,
- mshlflags, pSize);
- pMarshal->Release();
- return hr;
- }
- *pSize = sizeof(pUnk);
- return hr;
- }
- STDMETHODIMP CAVIFile::CMarshalImpl::MarshalInterface (
- THIS_ LPSTREAM pStm, REFIID riid,
- LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
- DWORD mshlflags)
- {
- HRESULT hr = NOERROR;
- IUnknown FAR * pUnk = &m_pAVIFile->m_Unknown;
- DPF("MarshalInterface calledn");
- if (dwDestContext != MSHCTX_LOCAL) {
- LPMARSHAL pMarshal;
- DPF("Marshal context is %lu: delegating...n", dwDestContext);
- hr = CoGetStandardMarshal(riid, NULL, dwDestContext, pvDestContext, mshlflags,
- &pMarshal);
- if (hr != NOERROR)
- return hr;
- hr = pMarshal->MarshalInterface(pStm, riid, pv, dwDestContext, pvDestContext,
- mshlflags);
- pMarshal->Release();
- return hr;
- }
- if ((riid != IID_IAVIStream && riid != IID_IAVIFile && riid != IID_IUnknown))
- return ResultFromScode(E_INVALIDARG);
- if ((hr = pStm->Write(&pUnk, sizeof(pUnk), NULL)) == NOERROR)
- AddRef();
- DPF("Returns %lxn", (DWORD) (LPVOID) hr);
- return hr;
- }
- STDMETHODIMP CAVIFile::CMarshalImpl::UnmarshalInterface (
- THIS_ LPSTREAM pStm, REFIID riid,
- LPVOID FAR* ppv)
- {
- HRESULT hr = ResultFromScode(E_FAIL);
- DPF("UnMarshalInterface called!!!n");
- return hr;
- }
- STDMETHODIMP CAVIFile::CMarshalImpl::ReleaseMarshalData (
- THIS_ LPSTREAM pStm)
- {
- HRESULT hr = NOERROR;
- IUnknown FAR * pUnk;
- hr = pStm->Read(&pUnk,sizeof(pUnk),NULL);
- if (hr == NOERROR)
- pUnk->Release();
- return hr;
- }
- STDMETHODIMP CAVIFile::CMarshalImpl::DisconnectObject (
- THIS_ DWORD dwReserved)
- {
- HRESULT hr = NOERROR;
- return hr;
- }
- #endif
- /*****************************************************************************
- *
- * dprintf() is called by the DPF macro if DEBUG is defined at compile time.
- *
- * The messages will be send to COM1: like any debug message. To
- * enable debug output, add the following to WIN.INI :
- *
- * [debug]
- * ICSAMPLE=1
- *
- ****************************************************************************/
- #ifdef DEBUG
- #define MODNAME "DSEQFILE"
- static BOOL fDebug = -1;
- static void cdecl dprintf(
- LPSTR szFormat, ...)
- {
- char ach[128];
- va_list va;
- if (fDebug == -1)
- fDebug = GetProfileIntA("Debug",MODNAME, FALSE);
- if (!fDebug)
- return;
- va_start(va, szFormat);
- if (szFormat[0] == '!')
- ach[0]=0, szFormat++;
- else
- lstrcpyA(ach, MODNAME ": ");
- wvsprintfA(ach+lstrlenA(ach),szFormat,(LPSTR)va);
- va_end(va);
- // lstrcatA(ach, "rrn");
- OutputDebugStringA(ach);
- }
- #endif