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

340 lines
7.8 KiB
C++

/****************************************************************************
*
* AVIMEM.C
*
* routine for putting a stream interface on top of data in memory
*
* Copyright (c) 1992 - 1995 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 <win32.h>
#include <vfw.h>
#include "avifilei.h"
#include "avimem.h"
#define WIDTHBYTES(i) ((UINT)((i+31)&(~31))/8)
#define DIBWIDTHBYTES(lpbi) (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth * (UINT)(lpbi)->biBitCount)
STDAPI AVIMakeStreamFromClipboard(UINT cfFormat, HANDLE hGlobal, PAVISTREAM FAR *ppstream)
{
CAVIMemStream FAR* pAVIStream;
HRESULT hr;
LPVOID lp;
if (cfFormat != CF_DIB && cfFormat != CF_WAVE)
return ResultFromScode(AVIERR_UNSUPPORTED);
pAVIStream = new FAR CAVIMemStream();
if (!pAVIStream)
return ResultFromScode(E_OUTOFMEMORY);
lp = GlobalAllocPtr(GMEM_MOVEABLE, GlobalSize(hGlobal));
if (!lp)
return ResultFromScode(E_OUTOFMEMORY);
hmemcpy(lp, GlobalLock(hGlobal), GlobalSize(hGlobal));
pAVIStream->Create((LPARAM) cfFormat, (LPARAM) lp);
GlobalUnlock(hGlobal);
hr = pAVIStream->QueryInterface(IID_IAVIStream, (LPVOID FAR *) ppstream);
if (FAILED(GetScode(hr)))
delete pAVIStream;
return hr;
}
/* - - - - - - - - */
CAVIMemStream::CAVIMemStream()
{
m_lpData = NULL;
m_lpMemory = NULL;
m_lpFormat = NULL;
m_refs = 0;
}
/* - - - - - - - - */
STDMETHODIMP CAVIMemStream::QueryInterface(
const IID FAR& iid,
void FAR* FAR* ppv)
{
if (iid == IID_IUnknown)
*ppv = this;
else if (iid == IID_IAVIStream)
*ppv = this;
else {
*ppv = NULL;
return ResultFromScode(E_NOINTERFACE);
}
AddRef();
return AVIERR_OK;
}
/* - - - - - - - - */
STDMETHODIMP_(ULONG) CAVIMemStream::AddRef()
{
uUseCount++;
return ++m_refs;
}
/* - - - - - - - - */
STDMETHODIMP CAVIMemStream::Create(LPARAM lParam1, LPARAM lParam2)
{
UINT cfFormat = (UINT) lParam1;
m_lpMemory = (LPVOID) lParam2;
if (cfFormat == CF_DIB) {
LPBITMAPINFOHEADER lpbi;
m_lpFormat = m_lpMemory;
lpbi = (LPBITMAPINFOHEADER) m_lpFormat;
if (lpbi->biSizeImage == 0) {
if (lpbi->biCompression = BI_RGB) {
lpbi->biSizeImage = DIBWIDTHBYTES(lpbi) *
lpbi->biHeight;
}
}
_fmemset(&m_avistream, 0, sizeof(m_avistream));
m_avistream.fccType = streamtypeVIDEO;
m_avistream.fccHandler = 0;
m_avistream.dwStart = 0;
m_avistream.dwLength = 1;
m_avistream.dwScale = 1;
m_avistream.dwRate = 15;
m_avistream.dwSampleSize = 0;
SetRect(&m_avistream.rcFrame, 0, 0,
(int) lpbi->biWidth,
(int) lpbi->biHeight);
m_cbFormat = lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
m_lpData = (LPBYTE) m_lpMemory + m_cbFormat;
m_cbData = lpbi->biSizeImage;
} else if (cfFormat == CF_WAVE) {
DWORD _huge * lpdw;
LPWAVEFORMAT lpwf;
#define ckidWAVEFORMAT mmioFOURCC('f', 'm', 't', ' ')
#define ckidWAVEDATA mmioFOURCC('d', 'a', 't', 'a')
lpdw = (DWORD _huge *) ((LPBYTE) m_lpMemory + 12);
while (*lpdw != ckidWAVEFORMAT)
lpdw = (DWORD _huge *)
(((BYTE _huge *) lpdw) + lpdw[1] + sizeof(DWORD) * 2);
m_lpFormat = (LPBYTE) (lpdw + 2);
m_cbFormat = lpdw[1];
do {
lpdw = (DWORD _huge *)
(((BYTE _huge *) lpdw) + lpdw[1] + sizeof(DWORD) * 2);
} while (*lpdw != ckidWAVEDATA);
m_lpData = (LPBYTE) (lpdw + 2);
m_cbData = lpdw[1];
lpwf = (LPWAVEFORMAT) m_lpFormat;
_fmemset(&m_avistream, 0, sizeof(m_avistream));
m_avistream.fccType = streamtypeAUDIO;
m_avistream.fccHandler = 0;
m_avistream.dwStart = 0;
m_avistream.dwSampleSize = lpwf->nBlockAlign;
m_avistream.dwLength = m_cbData / m_avistream.dwSampleSize;
m_avistream.dwScale = lpwf->nBlockAlign;
m_avistream.dwRate = lpwf->nAvgBytesPerSec;
}
return 0;
}
STDMETHODIMP_(ULONG) CAVIMemStream::Release()
{
uUseCount--;
if (!--m_refs) {
if (m_lpMemory) {
GlobalFreePtr(m_lpMemory);
}
delete this;
return 0;
}
return m_refs;
}
STDMETHODIMP CAVIMemStream::Info(AVISTREAMINFOW FAR * psi, LONG lSize)
{
hmemcpy(psi, &m_avistream, min(lSize, sizeof(m_avistream)));
// return sizeof(m_avistream);
return ResultFromScode(0);
}
STDMETHODIMP CAVIMemStream::ReadFormat(LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat)
{
if (lpFormat) {
hmemcpy(lpFormat, m_lpFormat, min(*lpcbFormat, (LONG) m_cbFormat));
}
*lpcbFormat = m_cbFormat;
return AVIERR_OK;
}
STDMETHODIMP CAVIMemStream::Read(
LONG lStart,
LONG lSamples,
LPVOID lpBuffer,
LONG cbBuffer,
LONG FAR * plBytes,
LONG FAR * plSamples)
{
// !!! CONVENIENT?
if (lStart + lSamples > (LONG) m_avistream.dwLength)
lSamples = (LONG) m_avistream.dwLength - lStart;
if (lSamples == 0 || lStart >= (LONG) m_avistream.dwLength) {
if (plBytes)
*plBytes = 0;
if (plSamples)
*plSamples = 0;
}
if (m_avistream.dwSampleSize) {
if (lSamples > 0)
lSamples = min(lSamples, cbBuffer / (LONG) m_avistream.dwSampleSize);
else
lSamples = cbBuffer / m_avistream.dwSampleSize;
if (plBytes)
*plBytes = lSamples * m_avistream.dwSampleSize;
if (plSamples)
*plSamples = lSamples;
if (lpBuffer) {
hmemcpy(lpBuffer,
(BYTE _huge *) m_lpData + lStart * m_avistream.dwSampleSize,
lSamples * m_avistream.dwSampleSize);
if (cbBuffer < (LONG) m_avistream.dwSampleSize)
return ResultFromScode(AVIERR_BUFFERTOOSMALL);
}
} else {
if (plBytes)
*plBytes = m_cbData;
if (plSamples)
*plSamples = 1;
if (lpBuffer) {
hmemcpy(lpBuffer, m_lpData, min(cbBuffer, m_cbData));
if (cbBuffer < m_cbData)
return ResultFromScode(AVIERR_BUFFERTOOSMALL);
}
}
return AVIERR_OK;
}
STDMETHODIMP_(LONG) CAVIMemStream::FindSample(LONG lPos, LONG lFlags)
{
if (lFlags & FIND_FORMAT) {
if (lFlags & FIND_PREV)
return 0;
else {
if (lPos > 0)
return -1;
else
return 0;
}
}
return lPos;
}
STDMETHODIMP CAVIMemStream::SetFormat(LONG lPos,LPVOID lpFormat,LONG cbFormat)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
STDMETHODIMP CAVIMemStream::Write(LONG lStart,
LONG lSamples,
LPVOID lpBuffer,
LONG cbBuffer,
DWORD dwFlags,
LONG FAR *plSampWritten,
LONG FAR *plBytesWritten)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
STDMETHODIMP CAVIMemStream::Delete(LONG lStart,LONG lSamples)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
STDMETHODIMP CAVIMemStream::ReadData(DWORD fcc, LPVOID lp, LONG FAR *lpcb)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
STDMETHODIMP CAVIMemStream::WriteData(DWORD fcc, LPVOID lp, LONG cb)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
#if 0
STDMETHODIMP CAVIMemStream::Clone(PAVISTREAM FAR * ppaviNew)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
#endif
#ifdef _WIN32
STDMETHODIMP CAVIMemStream::SetInfo(AVISTREAMINFOW FAR *lpInfo, LONG cbInfo)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
#else
STDMETHODIMP CAVIMemStream::Reserved1(void)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
STDMETHODIMP CAVIMemStream::Reserved2(void)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
STDMETHODIMP CAVIMemStream::Reserved3(void)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
STDMETHODIMP CAVIMemStream::Reserved4(void)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
STDMETHODIMP CAVIMemStream::Reserved5(void)
{
return ResultFromScode(AVIERR_UNSUPPORTED);
}
#endif