Sweden-Number/dlls/avifil32/avifile.c

510 lines
15 KiB
C

/*
* Copyright 1999 Marcus Meissner
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "vfw.h"
#include "winbase.h"
#include "wine/winestring.h"
#include "driver.h"
#include "mmsystem.h"
#include "winerror.h"
#include "debugstr.h"
#include "debug.h"
DECLARE_DEBUG_CHANNEL(avifile)
DECLARE_DEBUG_CHANNEL(msvideo)
DECLARE_DEBUG_CHANNEL(relay)
typedef struct IAVIStreamImpl {
/* IUnknown stuff */
ICOM_VTABLE(IAVIStream)* lpvtbl;
DWORD ref;
/* IAVIStream stuff */
LPVOID lpInputFormat;
DWORD inputformatsize;
BOOL iscompressing;
DWORD curframe;
/* Compressor stuff */
HIC hic;
LPVOID lpCompressFormat;
ICINFO icinfo;
DWORD compbufsize;
LPVOID compbuffer;
DWORD decompbufsize;
LPVOID decompbuffer;
LPVOID decompformat;
AVICOMPRESSOPTIONS aco;
LPVOID lpPrev; /* pointer to decompressed frame later */
LPVOID lpPrevFormat; /* pointer to decompressed info later */
} IAVIStreamImpl;
void WINAPI
AVIFileInit(void) {
FIXME(avifile,"(),stub!\n");
}
typedef struct IAVIFileImpl {
/* IUnknown stuff */
ICOM_VTABLE(IAVIFile)* lpvtbl;
DWORD ref;
/* IAVIFile stuff... */
} IAVIFileImpl;
struct ICOM_VTABLE(IAVIStream) iavist;
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIFileImpl,iface);
char xrefiid[50];
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
TRACE(relay,"(%p)->QueryInterface(%s,%p)\n",This,xrefiid,obj);
if ( !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
!memcmp(&IID_IAVIFile,refiid,sizeof(IID_IAVIFile))
) {
*obj = iface;
return S_OK;
}
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
FIXME(relay,"(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
FIXME(relay,"(%p)->Release()\n",iface);
if (!--(This->ref)) {
HeapFree(GetProcessHeap(),0,iface);
return 0;
}
return This->ref;
}
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size) {
FIXME(avifile,"(%p)->Info(%p,%ld)\n",iface,afi,size);
/* FIXME: fill out struct? */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
FIXME(avifile,"(%p)->GetStream(%p,0x%08lx,%ld)\n",iface,avis,fccType,lParam);
/* FIXME: create interface etc. */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
ICOM_THIS(IAVIStreamImpl,iface);
char fcc[5];
IAVIStreamImpl *istream;
FIXME(avifile,"(%p,%p,%p)\n",This,avis,asi);
istream = (IAVIStreamImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIStreamImpl));
istream->ref = 1;
istream->lpvtbl = &iavist;
fcc[4]='\0';
memcpy(fcc,(char*)&(asi->fccType),4);
FIXME(avifile,"\tfccType '%s'\n",fcc);
memcpy(fcc,(char*)&(asi->fccHandler),4);
FIXME(avifile,"\tfccHandler '%s'\n",fcc);
FIXME(avifile,"\tdwFlags 0x%08lx\n",asi->dwFlags);
FIXME(avifile,"\tdwCaps 0x%08lx\n",asi->dwCaps);
FIXME(avifile,"\tname '%s'\n",debugstr_w(asi->szName));
istream->curframe = 0;
*avis = (PAVISTREAM)istream;
return S_OK;
}
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size) {
FIXME(avifile,"(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,ckid,lpData,size);
/* FIXME: write data to file */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size) {
FIXME(avifile,"(%p)->ReadData(0x%08lx,%p,%p)\n",iface,ckid,lpData,size);
/* FIXME: read at most size bytes from file */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface) {
FIXME(avifile,"(%p)->EndRecord()\n",iface);
/* FIXME: end record? */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam) {
FIXME(avifile,"(%p)->DeleteStream(0x%08lx,%ld)\n",iface,fccType,lParam);
/* FIXME: delete stream? */
return E_FAIL;
}
struct ICOM_VTABLE(IAVIFile) iavift = {
IAVIFile_fnQueryInterface,
IAVIFile_fnAddRef,
IAVIFile_fnRelease,
IAVIFile_fnInfo,
IAVIFile_fnGetStream,
IAVIFile_fnCreateStream,
IAVIFile_fnWriteData,
IAVIFile_fnReadData,
IAVIFile_fnEndRecord,
IAVIFile_fnDeleteStream
};
HRESULT WINAPI AVIFileOpenA(
PAVIFILE * ppfile,LPCSTR szFile,UINT uMode,LPCLSID lpHandler
) {
char buf[80];
IAVIFileImpl *iavi;
if (HIWORD(lpHandler))
WINE_StringFromCLSID(lpHandler,buf);
else
sprintf(buf,"<clsid-0x%04lx>",(DWORD)lpHandler);
FIXME(avifile,"(%p,%s,0x%08lx,%s),stub!\n",ppfile,szFile,(DWORD)uMode,buf);
iavi = (IAVIFileImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIFileImpl));
iavi->ref = 1;
iavi->lpvtbl = &iavift;
*ppfile = (LPVOID)iavi;
return S_OK;
}
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIStreamImpl,iface);
char xrefiid[50];
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
TRACE(relay,"(%p)->QueryInterface(%s,%p)\n",This,xrefiid,obj);
if ( !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
!memcmp(&IID_IAVIStream,refiid,sizeof(IID_IAVIStream))
) {
*obj = This;
return S_OK;
}
/* can return IGetFrame interface too */
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME(relay,"(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME(relay,"(%p)->Release()\n",iface);
if (!--(This->ref)) {
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2) {
FIXME(avifile,"(%p)->Create(0x%08lx,0x%08lx)\n",iface,lParam1,lParam2);
return E_FAIL;
}
HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size) {
FIXME(avifile,"(%p)->Info(%p,%ld)\n",iface,psi,size);
return E_FAIL;
}
LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags) {
FIXME(avifile,"(%p)->FindSample(%ld,0x%08lx)\n",iface,pos,flags);
return E_FAIL;
}
HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize) {
FIXME(avifile,"(%p)->ReadFormat(%ld,%p,%p)\n",iface,pos,format,formatsize);
return E_FAIL;
}
/*****************************************************************************
* [IAVIStream::SetFormat]
*/
HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize) {
IAVIStreamImpl *as = (IAVIStreamImpl*)iface;
FIXME(avifile,"(%p)->SetFormat(%ld,%p,%ld)\n",iface,pos,format,formatsize);
if (as->lpInputFormat) HeapFree(GetProcessHeap(),0,as->lpInputFormat);
as->inputformatsize = formatsize;
as->lpInputFormat = HeapAlloc(GetProcessHeap(),0,formatsize);
memcpy(as->lpInputFormat,format,formatsize);
if (as->iscompressing) {
int xsize;
/* Set up the Compressor part */
xsize = ICCompressGetFormatSize(as->hic,as->lpInputFormat);
as->lpCompressFormat = HeapAlloc(GetProcessHeap(),0,xsize);
ICCompressGetFormat(as->hic,as->lpInputFormat,as->lpCompressFormat);
ICCompressBegin(as->hic,as->lpInputFormat,as->lpCompressFormat);
as->compbufsize = ICCompressGetSize(as->hic,as->lpInputFormat,as->lpCompressFormat);
as->compbuffer = HeapAlloc(GetProcessHeap(),0,as->compbufsize);
/* Set up the Decompressor part (for prev frames?) */
xsize=ICDecompressGetFormatSize(as->hic,as->lpCompressFormat);
as->decompformat = HeapAlloc(GetProcessHeap(),0,xsize);
ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
as->decompbufsize=((LPBITMAPINFOHEADER)as->decompbuffer)->biSizeImage;
as->decompbuffer = HeapReAlloc(GetProcessHeap(),0,as->decompbuffer,as->decompbufsize);
memset(as->decompbuffer,0xff,as->decompbufsize);
assert(HeapValidate(GetProcessHeap(),0,NULL));
ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
ICDecompressBegin(as->hic,as->lpCompressFormat,as->decompformat);
as->lpPrev = as->lpPrevFormat = NULL;
}
return S_OK;
}
HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
FIXME(avifile,"(%p)->Read(%ld,%ld,%p,%ld,%p,%p)\n",iface,start,samples,buffer,buffersize,bytesread,samplesread);
return E_FAIL;
}
HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
IAVIStreamImpl *as = (IAVIStreamImpl*)iface;
DWORD ckid,xflags;
FIXME(avifile,"(%p)->Write(%ld,%ld,%p,%ld,0x%08lx,%p,%p)\n",iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
ICCompress(
as->hic,flags,
as->lpCompressFormat,
as->compbuffer,
as->lpInputFormat,buffer,
&ckid,&xflags,
as->curframe,0xffffff/*framesize*/,as->aco.dwQuality,
as->lpPrevFormat,as->lpPrev
);
ICDecompress(
as->hic,
flags, /* FIXME: check */
as->lpCompressFormat,
as->compbuffer,
as->decompformat,
as->decompbuffer
);
/* We now have a prev format for the next compress ... */
as->lpPrevFormat = as->decompformat;
as->lpPrev = as->decompbuffer;
return S_OK;
}
HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples) {
FIXME(avifile,"(%p)->Delete(%ld,%ld)\n",iface,start,samples);
return E_FAIL;
}
HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread) {
FIXME(avifile,"(%p)->ReadData(0x%08lx,%p,%p)\n",iface,fcc,lp,lpread);
return E_FAIL;
}
HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size) {
FIXME(avifile,"(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,fcc,lp,size);
return E_FAIL;
}
HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen) {
FIXME(avifile,"(%p)->SetInfo(%p,%ld)\n",iface,info,infolen);
return E_FAIL;
}
struct ICOM_VTABLE(IAVIStream) iavist = {
IAVIStream_fnQueryInterface,
IAVIStream_fnAddRef,
IAVIStream_fnRelease,
IAVIStream_fnCreate,
IAVIStream_fnInfo,
IAVIStream_fnFindSample,
IAVIStream_fnReadFormat,
IAVIStream_fnSetFormat,
IAVIStream_fnRead,
IAVIStream_fnWrite,
IAVIStream_fnDelete,
IAVIStream_fnReadData,
IAVIStream_fnWriteData,
IAVIStream_fnSetInfo
};
HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE iface,PAVISTREAM *ppavi,AVISTREAMINFOA * psi) {
AVISTREAMINFOW psiw;
/* Only the szName at the end is different */
memcpy(&psiw,psi,sizeof(*psi)-sizeof(psi->szName));
lstrcpynAtoW(psiw.szName,psi->szName,sizeof(psi->szName));
return iface->lpvtbl->fnCreateStream(iface,ppavi,&psiw);
}
HRESULT WINAPI AVIFileCreateStreamW(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
return iface->lpvtbl->fnCreateStream(iface,avis,asi);
}
HRESULT WINAPI AVIFileGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
return iface->lpvtbl->fnGetStream(iface,avis,fccType,lParam);
}
HRESULT WINAPI AVIFileInfoA(PAVIFILE iface,LPAVIFILEINFOA afi,LONG size) {
AVIFILEINFOW afiw;
HRESULT hres;
if (size < sizeof(AVIFILEINFOA))
return AVIERR_BADSIZE;
hres = iface->lpvtbl->fnInfo(iface,&afiw,sizeof(afiw));
memcpy(afi,&afiw,sizeof(*afi)-sizeof(afi->szFileType));
lstrcpynWtoA(afi->szFileType,afiw.szFileType,sizeof(afi->szFileType));
return hres;
}
HRESULT WINAPI AVIStreamInfoW(PAVISTREAM iface,AVISTREAMINFOW *asi,LONG
size) {
return iface->lpvtbl->fnInfo(iface,asi,size);
}
HRESULT WINAPI AVIStreamInfoA(PAVISTREAM iface,AVISTREAMINFOA *asi,LONG
size) {
AVISTREAMINFOW asiw;
HRESULT hres;
if (size<sizeof(AVISTREAMINFOA))
return AVIERR_BADSIZE;
hres = iface->lpvtbl->fnInfo(iface,&asiw,sizeof(asiw));
memcpy(asi,&asiw,sizeof(asiw)-sizeof(asiw.szName));
lstrcpynWtoA(asi->szName,asiw.szName,sizeof(asi->szName));
return hres;
}
HRESULT WINAPI AVIFileInfoW(PAVIFILE iface,LPAVIFILEINFOW afi,LONG size) {
return iface->lpvtbl->fnInfo(iface,afi,size);
}
HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,PAVISTREAM ppsSource,AVICOMPRESSOPTIONS *aco,CLSID *pclsidHandler) {
char fcc[5];
IAVIStreamImpl *as;
FIXME(avifile,"(%p,%p,%p,%p)\n",ppsCompressed,ppsSource,aco,pclsidHandler);
fcc[4]='\0';
memcpy(fcc,&(aco->fccType),4);
FIXME(avifile,"\tfccType: '%s'\n",fcc);
memcpy(fcc,&(aco->fccHandler),4);
FIXME(avifile,"\tfccHandler: '%s'\n",fcc);
FIXME(avifile,"\tdwFlags: 0x%08lx\n",aco->dwFlags);
/* we just create a duplicate for now */
((IUnknown*)ppsSource)->lpvtbl->fnAddRef((IUnknown*)ppsSource);
*ppsCompressed = ppsSource;
as = (IAVIStreamImpl*)ppsSource;
/* this is where the fun begins. Open a compressor and prepare it. */
as->hic = ICOpen(aco->fccType,aco->fccHandler,ICMODE_COMPRESS);
/* May happen. for instance if the codec is not able to compress */
if (!as->hic)
return AVIERR_UNSUPPORTED;
ICGetInfo(as->hic,&(as->icinfo),sizeof(ICINFO));
FIXME(avifile,"Opened compressor: '%s' '%s'\n",debugstr_w(as->icinfo.szName),debugstr_w(as->icinfo.szDescription));
as->iscompressing = TRUE;
memcpy(&(as->aco),aco,sizeof(*aco));
if (as->icinfo.dwFlags & VIDCF_COMPRESSFRAMES) {
ICCOMPRESSFRAMES icf;
/* now what to fill in there ... Hmm */
memset(&icf,0,sizeof(icf));
icf.lDataRate = aco->dwBytesPerSecond;
icf.lQuality = aco->dwQuality;
icf.lKeyRate = aco->dwKeyFrameEvery;
icf.GetData = (LONG (*)(LPARAM,LONG,LPVOID,LONG)) 0xdead4242;
icf.PutData = (LONG (*)(LPARAM,LONG,LPVOID,LONG)) 0xdead4243;
ICSendMessage(as->hic,ICM_COMPRESS_FRAMES_INFO,(LPARAM)&icf,sizeof(icf));
}
return S_OK;
}
HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG formatsize) {
return iface->lpvtbl->fnSetFormat(iface,pos,format,formatsize);
}
HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG *formatsize) {
return iface->lpvtbl->fnReadFormat(iface,pos,format,formatsize);
}
HRESULT WINAPI AVIStreamWrite(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
return iface->lpvtbl->fnWrite(iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
}
HRESULT WINAPI AVIStreamRead(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
return iface->lpvtbl->fnRead(iface,start,samples,buffer,buffersize,bytesread,samplesread);
}
HRESULT WINAPI AVIStreamWriteData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG size) {
return iface->lpvtbl->fnWriteData(iface,fcc,lp,size);
}
HRESULT WINAPI AVIStreamReadData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG *lpread) {
return iface->lpvtbl->fnReadData(iface,fcc,lp,lpread);
}
LONG WINAPI AVIStreamStart(PAVISTREAM iface) {
AVISTREAMINFOW si;
iface->lpvtbl->fnInfo(iface,&si,sizeof(si));
return si.dwStart;
}
LONG WINAPI AVIStreamLength(PAVISTREAM iface) {
AVISTREAMINFOW si;
HRESULT ret;
ret = iface->lpvtbl->fnInfo(iface,&si,sizeof(si));
if (ret) /* error */
return 1;
return si.dwLength;
}
ULONG WINAPI AVIStreamRelease(PAVISTREAM iface) {
return ((LPUNKNOWN)iface)->lpvtbl->fnRelease((LPUNKNOWN)iface);
}
PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM iface,LPBITMAPINFOHEADER bmi) {
FIXME(msvideo,"(%p)->(%p),stub!\n",iface,bmi);
return NULL;
}
LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg,LONG pos) {
return pg->lpvtbl->fnGetFrame(pg,pos);
}
HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg) {
if (pg) ((LPUNKNOWN)pg)->lpvtbl->fnRelease((LPUNKNOWN)pg);
return 0;
}
ULONG WINAPI AVIFileRelease(PAVIFILE iface) {
return ((LPUNKNOWN)iface)->lpvtbl->fnRelease((LPUNKNOWN)iface);
}
void WINAPI AVIFileExit(void) {
FIXME(avifile,"(), stub.\n");
}