Commit c814a6ce authored by Hidenori Takeshima's avatar Hidenori Takeshima Committed by Alexandre Julliard

Implemented some part of AVIFIL32.

parent 6562310d
......@@ -10,7 +10,13 @@ LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
avifile.c
api.c \
comentry.c \
iafile.c \
iastream.c \
igframe.c \
main.c \
string.c
@MAKE_DLL_RULES@
......
/*
* Copyright 1999 Marcus Meissner
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "ole2.h"
#include "vfw.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(avifile);
#include "avifile_private.h"
/***********************************************************************
* AVIFileInit (AVIFIL32.@)
*/
void WINAPI AVIFileInit(void)
{
TRACE("()\n");
if ( AVIFILE_data.dwAVIFileRef == 0 )
{
if ( FAILED(CoInitialize(NULL)) )
AVIFILE_data.fInitCOM = FALSE;
else
AVIFILE_data.fInitCOM = TRUE;
}
AVIFILE_data.dwAVIFileRef ++;
}
/***********************************************************************
* AVIFileExit (AVIFIL32.@)
*/
void WINAPI AVIFileExit(void)
{
TRACE("()\n");
if ( AVIFILE_data.dwAVIFileRef == 0 )
{
ERR( "unexpected AVIFileExit()\n" );
return;
}
AVIFILE_data.dwAVIFileRef --;
if ( AVIFILE_data.dwAVIFileRef == 0 )
{
if ( AVIFILE_data.fInitCOM )
{
CoUninitialize();
AVIFILE_data.fInitCOM = FALSE;
}
}
}
/***********************************************************************
* AVIFileAddRef (AVIFIL32.@)
*/
ULONG WINAPI AVIFileAddRef(PAVIFILE pfile)
{
return IAVIFile_AddRef( pfile );
}
/***********************************************************************
* AVIFileRelease (AVIFIL32.@)
*/
ULONG WINAPI AVIFileRelease(PAVIFILE pfile)
{
return IAVIFile_Release( pfile );
}
/***********************************************************************
* AVIFileOpenA (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileOpenA(
PAVIFILE* ppfile,LPCSTR szFile,UINT uMode,LPCLSID lpHandler )
{
WCHAR* pwsz;
HRESULT hr;
TRACE("(%p,%p,%u,%p)\n",ppfile,szFile,uMode,lpHandler);
pwsz = AVIFILE_strdupAtoW( szFile );
if ( pwsz == NULL )
return AVIERR_MEMORY;
hr = AVIFileOpenW(ppfile,pwsz,uMode,lpHandler);
HeapFree( AVIFILE_data.hHeap, 0, pwsz );
return hr;
}
/***********************************************************************
* AVIFileOpenW (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileOpenW(
PAVIFILE* ppfile,LPCWSTR szFile,UINT uMode,LPCLSID lpHandler )
{
HRESULT hr;
IClassFactory* pcf;
CLSID clsRIFF;
TRACE("(%p,%p,%u,%p)\n",ppfile,szFile,uMode,lpHandler);
*ppfile = (PAVIFILE)NULL;
if ( lpHandler == NULL )
{
/* FIXME - check RIFF type and get a handler from registry
* if IAVIFile::Open is worked...
*/
memcpy( &clsRIFF, &CLSID_AVIFile, sizeof(CLSID) );
lpHandler = &clsRIFF;
}
/*
* FIXME - MS says IAVIFile::Open will be called,
* but no such method in vfw.h... why????
*/
if ( !IsEqualGUID( lpHandler, &CLSID_AVIFile ) )
return REGDB_E_CLASSNOTREG;
hr = AVIFILE_DllGetClassObject(&CLSID_AVIFile,
&IID_IClassFactory,(void**)&pcf);
if ( hr != S_OK )
return hr;
hr = IClassFactory_CreateInstance( pcf, NULL, &IID_IAVIFile,
(void**)ppfile );
IClassFactory_Release( pcf );
if ( hr == S_OK )
{
/* FIXME??? */
hr = AVIFILE_IAVIFile_Open( *ppfile, szFile, uMode );
if ( hr != S_OK )
{
IAVIFile_Release( (*ppfile) );
*ppfile = NULL;
}
}
return hr;
}
/***********************************************************************
* AVIFileInfoW (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileInfoW(PAVIFILE pfile,AVIFILEINFOW* pfi,LONG lSize)
{
return IAVIFile_Info( pfile, pfi, lSize );
}
/***********************************************************************
* AVIFileInfoA (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileInfoA(PAVIFILE pfile,AVIFILEINFOA* pfi,LONG lSize)
{
AVIFILEINFOW fiw;
HRESULT hr;
if ( lSize < sizeof(AVIFILEINFOA) )
return AVIERR_BADSIZE;
hr = AVIFileInfoW( pfile, &fiw, sizeof(AVIFILEINFOW) );
if ( hr != S_OK )
return hr;
memcpy( pfi,&fiw,sizeof(AVIFILEINFOA) );
AVIFILE_strncpyWtoA( pfi->szFileType, fiw.szFileType,
sizeof(pfi->szFileType) );
pfi->szFileType[sizeof(pfi->szFileType)-1] = 0;
return S_OK;
}
/***********************************************************************
* AVIFileGetStream (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileGetStream(PAVIFILE pfile,PAVISTREAM* pas,DWORD fccType,LONG lParam)
{
return IAVIFile_GetStream(pfile,pas,fccType,lParam);
}
/***********************************************************************
* AVIFileCreateStreamW (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileCreateStreamW(PAVIFILE pfile,PAVISTREAM* ppas,AVISTREAMINFOW* pasi)
{
return IAVIFile_CreateStream(pfile,ppas,pasi);
}
/***********************************************************************
* AVIFileCreateStreamA (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE pfile,PAVISTREAM* ppas,AVISTREAMINFOA* pasi)
{
AVISTREAMINFOW siw;
HRESULT hr;
memcpy( &siw,pasi,sizeof(AVISTREAMINFOA) );
AVIFILE_strncpyAtoW( siw.szName, pasi->szName,
sizeof(siw.szName)/sizeof(siw.szName[0]) );
siw.szName[sizeof(siw.szName)/sizeof(siw.szName[0])-1] = 0;
hr = AVIFileCreateStreamW(pfile,ppas,&siw);
return hr;
}
/***********************************************************************
* AVIFileWriteData (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileWriteData(
PAVIFILE pfile,DWORD dwChunkId,LPVOID lpvData,LONG cbData )
{
return IAVIFile_WriteData( pfile,dwChunkId,lpvData,cbData );
}
/***********************************************************************
* AVIFileReadData (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileReadData(
PAVIFILE pfile,DWORD dwChunkId,LPVOID lpvData,LPLONG pcbData )
{
return IAVIFile_ReadData( pfile,dwChunkId,lpvData,pcbData );
}
/***********************************************************************
* AVIFileEndRecord (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileEndRecord( PAVIFILE pfile )
{
return IAVIFile_EndRecord( pfile );
}
/***********************************************************************
* AVIStreamAddRef (AVIFIL32.@)
*/
ULONG WINAPI AVIStreamAddRef(PAVISTREAM pas)
{
return IAVIStream_Release(pas);
}
/***********************************************************************
* AVIStreamRelease (AVIFIL32.@)
*/
ULONG WINAPI AVIStreamRelease(PAVISTREAM pas)
{
return IAVIStream_Release(pas);
}
/***********************************************************************
* AVIStreamInfoW (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamInfoW(PAVISTREAM pas,AVISTREAMINFOW* psi,LONG lSize)
{
return IAVIStream_Info(pas,psi,lSize);
}
/***********************************************************************
* AVIStreamInfoA (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamInfoA(PAVISTREAM pas,AVISTREAMINFOA* psi,LONG lSize)
{
AVISTREAMINFOW siw;
HRESULT hr;
if (lSize < sizeof(AVISTREAMINFOA))
return AVIERR_BADSIZE;
hr = AVIStreamInfoW(pas,&siw,sizeof(AVISTREAMINFOW));
if ( hr != S_OK )
return hr;
memcpy( psi,&siw,sizeof(AVIFILEINFOA) );
AVIFILE_strncpyWtoA( psi->szName, siw.szName, sizeof(psi->szName) );
psi->szName[sizeof(psi->szName)-1] = 0;
return hr;
}
/***********************************************************************
* AVIStreamFindSample (AVIFIL32.@)
*/
LONG WINAPI AVIStreamFindSample(PAVISTREAM pas,LONG lPos,LONG lFlags)
{
return IAVIStream_FindSample(pas,lPos,lFlags);
}
/***********************************************************************
* AVIStreamReadFormat (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM pas,LONG pos,LPVOID format,LONG *formatsize) {
return IAVIStream_ReadFormat(pas,pos,format,formatsize);
}
/***********************************************************************
* AVIStreamSetFormat (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM pas,LONG pos,LPVOID format,LONG formatsize) {
return IAVIStream_SetFormat(pas,pos,format,formatsize);
}
/***********************************************************************
* AVIStreamReadData (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamReadData(PAVISTREAM pas,DWORD fcc,LPVOID lp,LONG *lpread) {
return IAVIStream_ReadData(pas,fcc,lp,lpread);
}
/***********************************************************************
* AVIStreamWriteData (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamWriteData(PAVISTREAM pas,DWORD fcc,LPVOID lp,LONG size) {
return IAVIStream_WriteData(pas,fcc,lp,size);
}
/***********************************************************************
* AVIStreamRead (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamRead(PAVISTREAM pas,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread)
{
return IAVIStream_Read(pas,start,samples,buffer,buffersize,bytesread,samplesread);
}
/***********************************************************************
* AVIStreamWrite (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamWrite(PAVISTREAM pas,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
return IAVIStream_Write(pas,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
}
/***********************************************************************
* AVIStreamStart (AVIFIL32.@)
*/
LONG WINAPI AVIStreamStart(PAVISTREAM pas)
{
AVISTREAMINFOW si;
HRESULT hr;
hr = IAVIStream_Info(pas,&si,sizeof(si));
if (hr != S_OK)
return -1;
return (LONG)si.dwStart;
}
/***********************************************************************
* AVIStreamLength (AVIFIL32.@)
*/
LONG WINAPI AVIStreamLength(PAVISTREAM pas)
{
AVISTREAMINFOW si;
HRESULT hr;
hr = IAVIStream_Info(pas,&si,sizeof(si));
if (hr != S_OK)
return -1;
return (LONG)si.dwLength;
}
/***********************************************************************
* AVIStreamTimeToSample (AVIFIL32.@)
*/
LONG WINAPI AVIStreamTimeToSample(PAVISTREAM pas,LONG lTime)
{
AVISTREAMINFOW si;
HRESULT hr;
hr = IAVIStream_Info(pas,&si,sizeof(si));
if (hr != S_OK)
return -1;
/* I am too lazy... */
FIXME("(%p,%ld)",pas,lTime);
return (LONG)-1L;
}
/***********************************************************************
* AVIStreamSampleToTime (AVIFIL32.@)
*/
LONG WINAPI AVIStreamSampleToTime(PAVISTREAM pas,LONG lSample)
{
AVISTREAMINFOW si;
HRESULT hr;
hr = IAVIStream_Info(pas,&si,sizeof(si));
if (hr != S_OK)
return -1;
/* I am too lazy... */
FIXME("(%p,%ld)",pas,lSample);
return (LONG)-1L;
}
/***********************************************************************
* AVIStreamBeginStreaming (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamBeginStreaming(PAVISTREAM pas,LONG lStart,LONG lEnd,LONG lRate)
{
FIXME("(%p)->(%ld,%ld,%ld),stub!\n",pas,lStart,lEnd,lRate);
return E_FAIL;
}
/***********************************************************************
* AVIStreamEndStreaming (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamEndStreaming(PAVISTREAM pas)
{
FIXME("(%p)->(),stub!\n",pas);
return E_FAIL;
}
/***********************************************************************
* AVIStreamGetFrameOpen (AVIFIL32.@)
*/
PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM pas,LPBITMAPINFOHEADER pbi)
{
IGetFrame* pgf;
HRESULT hr;
AVISTREAMINFOW si;
FIXME("(%p,%p)\n",pas,pbi);
hr = IAVIStream_Info(pas,&si,sizeof(si));
if (hr != S_OK)
return NULL;
hr = AVIFILE_CreateIGetFrame((void**)&pgf,pas,pbi);
if ( hr != S_OK )
return NULL;
hr = IGetFrame_Begin( pgf, si.dwStart, si.dwLength, 1000 );
if ( hr != S_OK )
{
IGetFrame_Release( pgf );
return NULL;
}
return pgf;
}
/***********************************************************************
* AVIStreamGetFrame (AVIFIL32.@)
*/
LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pgf, LONG lPos)
{
return IGetFrame_GetFrame(pgf,lPos);
}
/***********************************************************************
* AVIStreamGetFrameClose (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pgf)
{
return IGetFrame_End(pgf);
}
/***********************************************************************
* AVIStreamOpenFromFileA (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamOpenFromFileA(PAVISTREAM* ppas, LPCSTR szFile, DWORD fccType, LONG lParam, UINT uMode, CLSID* lpHandler)
{
WCHAR* pwsz;
HRESULT hr;
pwsz = AVIFILE_strdupAtoW( szFile );
if ( pwsz == NULL )
return AVIERR_MEMORY;
hr = AVIStreamOpenFromFileW(ppas,pwsz,fccType,lParam,uMode,lpHandler);
HeapFree( AVIFILE_data.hHeap, 0, pwsz );
return hr;
}
/***********************************************************************
* AVIStreamOpenFromFileW (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamOpenFromFileW(PAVISTREAM* ppas, LPCWSTR szFile, DWORD fccType, LONG lParam, UINT uMode, CLSID* lpHandler)
{
HRESULT hr;
PAVIFILE paf;
AVIFILEINFOW fi;
*ppas = NULL;
hr = AVIFileOpenW(&paf,szFile,uMode,lpHandler);
if ( hr != S_OK )
return hr;
hr = AVIFileInfoW(paf,&fi,sizeof(AVIFILEINFOW));
if ( hr == S_OK )
hr = AVIFileGetStream(paf,ppas,fccType,lParam);
IAVIFile_Release(paf);
return hr;
}
/***********************************************************************
* AVIStreamCreate (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamCreate(PAVISTREAM* ppas, LONG lParam1, LONG lParam2, CLSID* lpHandler)
{
HRESULT hr;
IClassFactory* pcf;
*ppas = NULL;
if ( lpHandler == NULL )
{
hr = AVIFILE_DllGetClassObject(&CLSID_AVIFile,
&IID_IClassFactory,(void**)&pcf);
}
else
{
if ( !AVIFILE_data.fInitCOM )
return E_UNEXPECTED;
hr = CoGetClassObject(lpHandler,CLSCTX_INPROC_SERVER,
NULL,&IID_IClassFactory,(void**)&pcf);
}
if ( hr != S_OK )
return hr;
hr = IClassFactory_CreateInstance( pcf, NULL, &IID_IAVIStream,
(void**)ppas );
IClassFactory_Release( pcf );
if ( hr == S_OK )
{
hr = IAVIStream_Create((*ppas),lParam1,lParam2);
if ( hr != S_OK )
{
IAVIStream_Release((*ppas));
*ppas = NULL;
}
}
return hr;
}
/***********************************************************************
* AVIMakeCompressedStream (AVIFIL32.@)
*/
HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,PAVISTREAM ppsSource,AVICOMPRESSOPTIONS *aco,CLSID *pclsidHandler)
{
FIXME("(%p,%p,%p,%p)\n",ppsCompressed,ppsSource,aco,pclsidHandler);
return E_FAIL;
}
name avifil32
type win32
init AVIFILE_DllMain
import msvfw32.dll
import ole32.dll
import kernel32.dll
import ntdll.dll
......@@ -43,7 +45,7 @@ debug_channels (avifile)
@ stub AVISaveW
@ stub AVIStreamAddRef
@ stub AVIStreamBeginStreaming
@ stub AVIStreamCreate
@ stdcall AVIStreamCreate(ptr long long ptr) AVIStreamCreate
@ stub AVIStreamEndStreaming
@ stub AVIStreamFindSample
@ stdcall AVIStreamGetFrame(ptr long) AVIStreamGetFrame
......
/*
* Copyright 1999 Marcus Meissner
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "vfw.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(avifile);
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface);
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface);
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface);
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
struct ICOM_VTABLE(IAVIFile) iavift = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IAVIFile_fnQueryInterface,
IAVIFile_fnAddRef,
IAVIFile_fnRelease,
IAVIFile_fnInfo,
IAVIFile_fnGetStream,
IAVIFile_fnCreateStream,
IAVIFile_fnWriteData,
IAVIFile_fnReadData,
IAVIFile_fnEndRecord,
IAVIFile_fnDeleteStream
};
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface);
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface);
static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
struct ICOM_VTABLE(IAVIStream) iavist = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
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
};
typedef struct IAVIStreamImpl {
/* IUnknown stuff */
ICOM_VFIELD(IAVIStream);
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;
/***********************************************************************
* AVIFileInit (AVIFIL32.@)
* AVIFileInit (AVIFILE.100)
*/
void WINAPI
AVIFileInit(void) {
FIXME("(),stub!\n");
}
typedef struct IAVIFileImpl {
/* IUnknown stuff */
ICOM_VFIELD(IAVIFile);
DWORD ref;
/* IAVIFile stuff... */
} IAVIFileImpl;
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIFileImpl,iface);
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),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("(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%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("(%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("(%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("(%p,%p,%p)\n",This,avis,asi);
istream = (IAVIStreamImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIStreamImpl));
istream->ref = 1;
ICOM_VTBL(istream) = &iavist;
fcc[4]='\0';
memcpy(fcc,(char*)&(asi->fccType),4);
FIXME("\tfccType '%s'\n",fcc);
memcpy(fcc,(char*)&(asi->fccHandler),4);
FIXME("\tfccHandler '%s'\n",fcc);
FIXME("\tdwFlags 0x%08lx\n",asi->dwFlags);
FIXME("\tdwCaps 0x%08lx\n",asi->dwCaps);
FIXME("\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("(%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("(%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("(%p)->EndRecord()\n",iface);
/* FIXME: end record? */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam) {
FIXME("(%p)->DeleteStream(0x%08lx,%ld)\n",iface,fccType,lParam);
/* FIXME: delete stream? */
return E_FAIL;
}
/***********************************************************************
* AVIFileOpenA (AVIFIL32.@)
* AVIFileOpenA (AVIFILE.102)
*/
HRESULT WINAPI AVIFileOpenA(
PAVIFILE * ppfile,LPCSTR szFile,UINT uMode,LPCLSID lpHandler
) {
IAVIFileImpl *iavi;
FIXME("(%p,%s,0x%08lx,%s),stub!\n",ppfile,szFile,(DWORD)uMode,debugstr_guid(lpHandler));
iavi = (IAVIFileImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIFileImpl));
iavi->ref = 1;
ICOM_VTBL(iavi) = &iavift;
*ppfile = (LPVOID)iavi;
return S_OK;
}
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIStreamImpl,iface);
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),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("(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->Release()\n",iface);
if (!--(This->ref)) {
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2) {
FIXME("(%p)->Create(0x%08lx,0x%08lx)\n",iface,lParam1,lParam2);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size) {
FIXME("(%p)->Info(%p,%ld)\n",iface,psi,size);
return E_FAIL;
}
static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags) {
FIXME("(%p)->FindSample(%ld,0x%08lx)\n",iface,pos,flags);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize) {
FIXME("(%p)->ReadFormat(%ld,%p,%p)\n",iface,pos,format,formatsize);
return E_FAIL;
}
/***********************************************************************
* IAVIStream::SetFormat
*/
static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize) {
IAVIStreamImpl *as = (IAVIStreamImpl*)iface;
FIXME("(%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;
}
static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
FIXME("(%p)->Read(%ld,%ld,%p,%ld,%p,%p)\n",iface,start,samples,buffer,buffersize,bytesread,samplesread);
return E_FAIL;
}
static 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("(%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;
}
static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples) {
FIXME("(%p)->Delete(%ld,%ld)\n",iface,start,samples);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread) {
FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",iface,fcc,lp,lpread);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size) {
FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,fcc,lp,size);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen) {
FIXME("(%p)->SetInfo(%p,%ld)\n",iface,info,infolen);
return E_FAIL;
}
/***********************************************************************
* AVIFileCreateStreamA (AVIFIL32.@)
*/
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));
MultiByteToWideChar( CP_ACP, 0, psi->szName, -1,
psiw.szName, sizeof(psiw.szName) / sizeof(WCHAR) );
return IAVIFile_CreateStream(iface,ppavi,&psiw);
}
/***********************************************************************
* AVIFileCreateStreamW (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileCreateStreamW(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
return IAVIFile_CreateStream(iface,avis,asi);
}
/***********************************************************************
* AVIFileGetStream (AVIFIL32.@)
* AVIFileGetStream (AVIFILE.143)
*/
HRESULT WINAPI AVIFileGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
return IAVIFile_GetStream(iface,avis,fccType,lParam);
}
/***********************************************************************
* AVIFileInfoA (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileInfoA(PAVIFILE iface,LPAVIFILEINFOA afi,LONG size) {
AVIFILEINFOW afiw;
HRESULT hres;
if (size < sizeof(AVIFILEINFOA))
return AVIERR_BADSIZE;
hres = IAVIFile_Info(iface,&afiw,sizeof(afiw));
memcpy(afi,&afiw,sizeof(*afi)-sizeof(afi->szFileType));
WideCharToMultiByte( CP_ACP, 0, afiw.szFileType, -1,
afi->szFileType, sizeof(afi->szFileType), NULL, NULL );
afi->szFileType[sizeof(afi->szFileType)-1] = 0;
return hres;
}
/***********************************************************************
* AVIStreamInfoW (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamInfoW(PAVISTREAM iface,AVISTREAMINFOW *asi,LONG
size) {
return IAVIFile_Info(iface,asi,size);
}
/***********************************************************************
* AVIStreamInfoA (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamInfoA(PAVISTREAM iface,AVISTREAMINFOA *asi,LONG
size) {
AVISTREAMINFOW asiw;
HRESULT hres;
if (size<sizeof(AVISTREAMINFOA))
return AVIERR_BADSIZE;
hres = IAVIFile_Info(iface,&asiw,sizeof(asiw));
memcpy(asi,&asiw,sizeof(asiw)-sizeof(asiw.szName));
WideCharToMultiByte( CP_ACP, 0, asiw.szName, -1,
asi->szName, sizeof(asi->szName), NULL, NULL );
asi->szName[sizeof(asi->szName)-1] = 0;
return hres;
}
/***********************************************************************
* AVIFileInfoW (AVIFIL32.@)
*/
HRESULT WINAPI AVIFileInfoW(PAVIFILE iface,LPAVIFILEINFOW afi,LONG size) {
return IAVIFile_Info(iface,afi,size);
}
/***********************************************************************
* AVIMakeCompressedStream (AVIFIL32.@)
*/
HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,PAVISTREAM ppsSource,AVICOMPRESSOPTIONS *aco,CLSID *pclsidHandler) {
char fcc[5];
IAVIStreamImpl *as;
FIXME("(%p,%p,%p,%p)\n",ppsCompressed,ppsSource,aco,pclsidHandler);
fcc[4]='\0';
memcpy(fcc,&(aco->fccType),4);
FIXME("\tfccType: '%s'\n",fcc);
memcpy(fcc,&(aco->fccHandler),4);
FIXME("\tfccHandler: '%s'\n",fcc);
FIXME("\tdwFlags: 0x%08lx\n",aco->dwFlags);
/* we just create a duplicate for now */
IAVIStream_AddRef(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("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 = (void *)0xdead4242;
icf.PutData = (void *)0xdead4243;
ICSendMessage(as->hic,ICM_COMPRESS_FRAMES_INFO,(LPARAM)&icf,sizeof(icf));
}
return S_OK;
}
/***********************************************************************
* AVIStreamSetFormat (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG formatsize) {
return IAVIStream_SetFormat(iface,pos,format,formatsize);
}
/***********************************************************************
* AVIStreamReadFormat (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG *formatsize) {
return IAVIStream_ReadFormat(iface,pos,format,formatsize);
}
/***********************************************************************
* AVIStreamWrite (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamWrite(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
return IAVIStream_Write(iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
}
/***********************************************************************
* AVIStreamRead (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamRead(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
return IAVIStream_Read(iface,start,samples,buffer,buffersize,bytesread,samplesread);
}
/***********************************************************************
* AVIStreamWriteData (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamWriteData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG size) {
return IAVIStream_WriteData(iface,fcc,lp,size);
}
/***********************************************************************
* AVIStreamReadData (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamReadData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG *lpread) {
return IAVIStream_ReadData(iface,fcc,lp,lpread);
}
/***********************************************************************
* AVIStreamStart (AVIFIL32.@)
*/
LONG WINAPI AVIStreamStart(PAVISTREAM iface) {
AVISTREAMINFOW si;
IAVIStream_Info(iface,&si,sizeof(si));
return si.dwStart;
}
/***********************************************************************
* AVIStreamLength (AVIFIL32.@)
*/
LONG WINAPI AVIStreamLength(PAVISTREAM iface) {
AVISTREAMINFOW si;
HRESULT ret;
ret = IAVIStream_Info(iface,&si,sizeof(si));
if (ret) /* error */
return 1;
return si.dwLength;
}
/***********************************************************************
* AVIStreamRelease (AVIFIL32.@)
*/
ULONG WINAPI AVIStreamRelease(PAVISTREAM iface) {
return IAVIStream_Release(iface);
}
/***********************************************************************
* AVIStreamGetFrameOpen (AVIFIL32.@)
*/
PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM iface,LPBITMAPINFOHEADER bmi) {
FIXME("(%p)->(%p),stub!\n",iface,bmi);
return NULL;
}
/***********************************************************************
* AVIStreamGetFrame (AVIFIL32.@)
*/
LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg,LONG pos) {
return IGetFrame_GetFrame(pg,pos);
}
/***********************************************************************
* AVIStreamGetFrameClose (AVIFIL32.@)
*/
HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg) {
if (pg) IGetFrame_Release(pg);
return 0;
}
/***********************************************************************
* AVIFileRelease (AVIFIL32.@)
* AVIFileRelease (AVIFILE.141)
*/
ULONG WINAPI AVIFileRelease(PAVIFILE iface) {
return IAVIFile_Release(iface);
}
/***********************************************************************
* AVIFileExit (AVIFIL32.@)
* AVIFileExit (AVIFILE.101)
*/
void WINAPI AVIFileExit(void) {
FIXME("(), stub.\n");
}
#ifndef __WINE_AVIFILE_PRIVATE_H
#define __WINE_AVIFILE_PRIVATE_H
typedef struct
{
HANDLE hHeap;
DWORD dwAVIFileRef;
DWORD dwClassObjRef;
BOOL fInitCOM;
} WINE_AVIFILE_DATA;
extern WINE_AVIFILE_DATA AVIFILE_data;
INT AVIFILE_strlenAtoW( LPCSTR lpstr );
INT AVIFILE_strlenWtoA( LPCWSTR lpwstr );
LPWSTR AVIFILE_strncpyAtoW( LPWSTR lpwstr, LPCSTR lpstr, INT wbuflen );
LPSTR AVIFILE_strncpyWtoA( LPSTR lpstr, LPCWSTR lpwstr, INT abuflen );
LPWSTR AVIFILE_strdupAtoW( LPCSTR lpstr );
LPSTR AVIFILE_strdupWtoA( LPCWSTR lpwstr );
HRESULT WINAPI AVIFILE_DllGetClassObject(const CLSID* pclsid,const IID* piid,void** ppv);
HRESULT AVIFILE_CreateIAVIFile(void** ppobj);
HRESULT AVIFILE_IAVIFile_Open( PAVIFILE paf, LPCWSTR szFile, UINT uMode );
HRESULT AVIFILE_IAVIFile_GetIndexTable( PAVIFILE paf, DWORD dwStreamIndex,
AVIINDEXENTRY** ppIndexEntry,
DWORD* pdwCountOfIndexEntry );
HRESULT AVIFILE_IAVIFile_ReadMovieData( PAVIFILE paf, DWORD dwOffset,
DWORD dwLength, LPVOID lpvBuf );
HRESULT AVIFILE_CreateIAVIStream(void** ppobj);
HRESULT AVIFILE_CreateIGetFrame(void** ppobj,
IAVIStream* pstr,LPBITMAPINFOHEADER lpbi);
typedef struct
{
DWORD dwStreamIndex;
AVIStreamHeader* pstrhdr;
BYTE* pbFmt;
DWORD dwFmtLen;
} WINE_AVISTREAM_DATA;
WINE_AVISTREAM_DATA* AVIFILE_Alloc_IAVIStreamData( DWORD dwFmtLen );
void AVIFILE_Free_IAVIStreamData( WINE_AVISTREAM_DATA* pData );
/* this should be moved to vfw.h */
#ifndef FIND_DIR
#define FIND_DIR 0x0000000FL
#define FIND_NEXT 0x00000001L
#define FIND_PREV 0x00000004L
#define FIND_FROM_START 0x00000008L
#define FIND_TYPE 0x000000F0L
#define FIND_KEY 0x00000010L
#define FIND_ANY 0x00000020L
#define FIND_FORMAT 0x00000040L
#define FIND_RET 0x0000F000L
#define FIND_POS 0x00000000L
#define FIND_LENGTH 0x00001000L
#define FIND_OFFSET 0x00002000L
#define FIND_SIZE 0x00003000L
#define FIND_INDEX 0x00004000L
#endif
#endif /* __WINE_AVIFILE_PRIVATE_H */
/*
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "ole2.h"
#include "vfw.h"
#include "debugtools.h"
#include "avifile_private.h"
DEFAULT_DEBUG_CHANNEL(avifile);
static HRESULT WINAPI
IClassFactory_fnQueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj);
static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface);
static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface);
static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj);
static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface,BOOL dolock);
static ICOM_VTABLE(IClassFactory) iclassfact =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IClassFactory_fnQueryInterface,
IClassFactory_fnAddRef,
IClassFactory_fnRelease,
IClassFactory_fnCreateInstance,
IClassFactory_fnLockServer
};
typedef struct
{
/* IUnknown fields */
ICOM_VFIELD(IClassFactory);
DWORD ref;
} IClassFactoryImpl;
static IClassFactoryImpl AVIFILE_GlobalCF = {&iclassfact, 0 };
static HRESULT WINAPI
IClassFactory_fnQueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
{
ICOM_THIS(IClassFactoryImpl,iface);
TRACE("(%p)->(%p,%p)\n",This,riid,ppobj);
if ( ( IsEqualGUID( &IID_IUnknown, riid ) ) ||
( IsEqualGUID( &IID_IClassFactory, riid ) ) )
{
*ppobj = iface;
IClassFactory_AddRef(iface);
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
{
ICOM_THIS(IClassFactoryImpl,iface);
TRACE("(%p)->()\n",This);
if ( (This->ref) == 0 )
AVIFILE_data.dwClassObjRef ++;
return ++(This->ref);
}
static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
{
ICOM_THIS(IClassFactoryImpl,iface);
TRACE("(%p)->()\n",This);
if ( (--(This->ref)) > 0 )
return This->ref;
AVIFILE_data.dwClassObjRef --;
return 0;
}
static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj)
{
/*ICOM_THIS(IClassFactoryImpl,iface);*/
*ppobj = NULL;
if ( pOuter != NULL )
return E_FAIL;
if ( IsEqualGUID( &IID_IAVIFile, riid ) )
return AVIFILE_CreateIAVIFile(ppobj);
if ( IsEqualGUID( &IID_IAVIStream, riid ) )
return AVIFILE_CreateIAVIStream(ppobj);
return E_NOINTERFACE;
}
static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface,BOOL dolock)
{
ICOM_THIS(IClassFactoryImpl,iface);
HRESULT hr;
FIXME("(%p)->(%d),stub!\n",This,dolock);
if (dolock)
hr = IClassFactory_AddRef(iface);
else
hr = IClassFactory_Release(iface);
return hr;
}
/***********************************************************************
* DllGetClassObject (AVIFIL32.@)
*/
HRESULT WINAPI AVIFILE_DllGetClassObject(const CLSID* pclsid,const IID* piid,void** ppv)
{
*ppv = NULL;
if ( IsEqualCLSID( &IID_IClassFactory, piid ) )
{
*ppv = (LPVOID)&AVIFILE_GlobalCF;
IClassFactory_AddRef((IClassFactory*)*ppv);
return S_OK;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
/*****************************************************************************
* DllCanUnloadNow (AVIFIL32.@)
*/
DWORD WINAPI AVIFILE_DllCanUnloadNow(void)
{
return ( AVIFILE_data.dwClassObjRef == 0 ) ? S_OK : S_FALSE;
}
/*
* Copyright 1999 Marcus Meissner
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
* FIXME - implements editing/writing.
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "vfw.h"
#include "debugtools.h"
#include "avifile_private.h"
DEFAULT_DEBUG_CHANNEL(avifile);
#define AVIFILE_STREAMS_MAX 4
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface);
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface);
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface);
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
struct ICOM_VTABLE(IAVIFile) iavift = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IAVIFile_fnQueryInterface,
IAVIFile_fnAddRef,
IAVIFile_fnRelease,
IAVIFile_fnInfo,
IAVIFile_fnGetStream,
IAVIFile_fnCreateStream,
IAVIFile_fnWriteData,
IAVIFile_fnReadData,
IAVIFile_fnEndRecord,
IAVIFile_fnDeleteStream,
/* IAVIFILE_fnOpen */ /* FIXME? */
};
typedef struct IAVIFileImpl
{
ICOM_VFIELD(IAVIFile);
/* IUnknown stuff */
DWORD ref;
/* IAVIFile stuff */
HANDLE hf;
DWORD dwAVIFileCaps;
DWORD dwAVIFileScale;
DWORD dwAVIFileRate;
DWORD dwAVIFileLength;
DWORD dwAVIFileEditCount;
MainAVIHeader hdr;
IAVIStream* pStreams[AVIFILE_STREAMS_MAX];
AVIStreamHeader strhdrs[AVIFILE_STREAMS_MAX];
DWORD dwMoviTop;
DWORD dwCountOfIndexEntry;
AVIINDEXENTRY* pIndexEntry;
AVIINDEXENTRY* pStreamIndexEntry[AVIFILE_STREAMS_MAX+1];
} IAVIFileImpl;
/****************************************************************************
* AVI file parser.
*/
static HRESULT AVIFILE_IAVIFile_ReadNextChunkHeader(
IAVIFileImpl* This, FOURCC* pfcc, DWORD* pdwSize )
{
BYTE buf[8];
DWORD dwRead;
if ( ( !ReadFile( This->hf, buf, 8, &dwRead, NULL ) ) ||
( 8 != dwRead ) )
return AVIERR_FILEREAD;
*pfcc = mmioFOURCC(buf[0],buf[1],buf[2],buf[3]);
*pdwSize = ( ((DWORD)buf[4]) ) |
( ((DWORD)buf[5]) << 8 ) |
( ((DWORD)buf[6]) << 16 ) |
( ((DWORD)buf[7]) << 24 );
return S_OK;
}
static HRESULT AVIFILE_IAVIFile_SkipChunkData(
IAVIFileImpl* This, DWORD dwChunkSize )
{
LONG lHigh = 0;
DWORD dwRes;
if ( dwChunkSize == 0 )
return S_OK;
SetLastError(NO_ERROR);
dwRes = SetFilePointer( This->hf, (LONG)dwChunkSize,
&lHigh, FILE_CURRENT );
if ( dwRes == (DWORD)0xffffffff && GetLastError() != NO_ERROR )
return AVIERR_FILEREAD;
return S_OK;
}
static HRESULT AVIFILE_IAVIFile_ReadChunkData(
IAVIFileImpl* This, DWORD dwChunkSize,
LPVOID lpvBuf, DWORD dwBufSize, LPDWORD lpdwRead )
{
if ( dwBufSize > dwChunkSize )
dwBufSize = dwChunkSize;
if ( ( !ReadFile( This->hf, lpvBuf, dwBufSize, lpdwRead, NULL ) ) ||
( dwBufSize != *lpdwRead ) )
return AVIERR_FILEREAD;
return AVIFILE_IAVIFile_SkipChunkData( This, dwChunkSize - dwBufSize );
}
static HRESULT AVIFILE_IAVIFile_SeekToSpecifiedChunk(
IAVIFileImpl* This, FOURCC fccType, DWORD* pdwLen )
{
HRESULT hr;
FOURCC fcc;
BYTE buf[4];
DWORD dwRead;
while ( 1 )
{
hr = AVIFILE_IAVIFile_ReadNextChunkHeader(
This, &fcc, pdwLen );
if ( hr != S_OK )
return hr;
if ( fcc == fccType )
return S_OK;
if ( fcc == FOURCC_LIST )
{
if ( ( !ReadFile( This->hf, buf, 4, &dwRead, NULL ) ) ||
( 4 != dwRead ) )
return AVIERR_FILEREAD;
}
else
{
hr = AVIFILE_IAVIFile_SkipChunkData(
This, *pdwLen );
if ( hr != S_OK )
return hr;
}
}
}
WINE_AVISTREAM_DATA* AVIFILE_Alloc_IAVIStreamData( DWORD dwFmtLen )
{
WINE_AVISTREAM_DATA* pData;
pData = (WINE_AVISTREAM_DATA*)
HeapAlloc( AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(WINE_AVISTREAM_DATA) );
if ( pData == NULL )
return NULL;
if ( dwFmtLen > 0 )
{
pData->pbFmt = (BYTE*)
HeapAlloc( AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(BYTE)*dwFmtLen );
if ( pData->pbFmt == NULL )
{
AVIFILE_Free_IAVIStreamData( pData );
return NULL;
}
}
pData->dwFmtLen = dwFmtLen;
return pData;
}
void AVIFILE_Free_IAVIStreamData( WINE_AVISTREAM_DATA* pData )
{
if ( pData != NULL )
{
if ( pData->pbFmt != NULL )
HeapFree( AVIFILE_data.hHeap,0,pData->pbFmt );
HeapFree( AVIFILE_data.hHeap,0,pData );
}
}
static void AVIFILE_IAVIFile_InitIndexTable(
IAVIFileImpl* This,
AVIINDEXENTRY* pIndexBuf,
AVIINDEXENTRY* pIndexData,
DWORD dwCountOfIndexEntry )
{
DWORD dwStreamIndex;
DWORD dwIndex;
FOURCC ckid;
dwStreamIndex = 0;
for ( ; dwStreamIndex < (AVIFILE_STREAMS_MAX+1); dwStreamIndex ++ )
This->pStreamIndexEntry[dwStreamIndex] = NULL;
dwStreamIndex = 0;
for ( ; dwStreamIndex < This->hdr.dwStreams; dwStreamIndex ++ )
{
ckid = mmioFOURCC('0','0'+dwStreamIndex,0,0);
TRACE( "testing ckid %c%c%c%c\n",
(int)(ckid>> 0)&0xff,
(int)(ckid>> 8)&0xff,
(int)(ckid>>16)&0xff,
(int)(ckid>>24)&0xff );
This->pStreamIndexEntry[dwStreamIndex] = pIndexBuf;
FIXME( "pIndexBuf = %p\n", pIndexBuf );
for ( dwIndex = 0; dwIndex < dwCountOfIndexEntry; dwIndex++ )
{
TRACE( "ckid %c%c%c%c\n",
(int)(pIndexData[dwIndex].ckid>> 0)&0xff,
(int)(pIndexData[dwIndex].ckid>> 8)&0xff,
(int)(pIndexData[dwIndex].ckid>>16)&0xff,
(int)(pIndexData[dwIndex].ckid>>24)&0xff );
if ( (pIndexData[dwIndex].ckid & mmioFOURCC(0xff,0xff,0,0))
== ckid )
{
memcpy( pIndexBuf, &pIndexData[dwIndex],
sizeof(AVIINDEXENTRY) );
pIndexBuf ++;
}
}
FIXME( "pIndexBuf = %p\n", pIndexBuf );
}
This->pStreamIndexEntry[This->hdr.dwStreams] = pIndexBuf;
}
/****************************************************************************
* Create an IAVIFile object.
*/
static HRESULT AVIFILE_IAVIFile_Construct( IAVIFileImpl* This );
static void AVIFILE_IAVIFile_Destruct( IAVIFileImpl* This );
HRESULT AVIFILE_CreateIAVIFile(void** ppobj)
{
IAVIFileImpl *This;
HRESULT hr;
TRACE("(%p)\n",ppobj);
*ppobj = NULL;
This = (IAVIFileImpl*)HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(IAVIFileImpl));
if ( This == NULL )
return AVIERR_MEMORY;
This->ref = 1;
ICOM_VTBL(This) = &iavift;
hr = AVIFILE_IAVIFile_Construct( This );
if ( hr != S_OK )
{
AVIFILE_IAVIFile_Destruct( This );
return hr;
}
TRACE("new -> %p\n",This);
*ppobj = (LPVOID)This;
return S_OK;
}
/****************************************************************************
* IUnknown interface
*/
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIFileImpl,iface);
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
if ( IsEqualGUID(&IID_IUnknown,refiid) ||
IsEqualGUID(&IID_IAVIFile,refiid) )
{
*obj = iface;
IAVIFile_AddRef(iface);
return S_OK;
}
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
TRACE("(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
TRACE("(%p)->Release()\n",iface);
if ( (--(This->ref)) > 0 )
return This->ref;
AVIFILE_IAVIFile_Destruct(This);
HeapFree(AVIFILE_data.hHeap,0,iface);
return 0;
}
/****************************************************************************
* IAVIFile interface
*/
static HRESULT AVIFILE_IAVIFile_Construct( IAVIFileImpl* This )
{
DWORD dwIndex;
This->hf = INVALID_HANDLE_VALUE;
This->dwAVIFileCaps = 0;
This->dwAVIFileScale = 0;
This->dwAVIFileRate = 0;
This->dwAVIFileLength = 0;
This->dwAVIFileEditCount = 0;
for ( dwIndex = 0; dwIndex < AVIFILE_STREAMS_MAX; dwIndex++ )
This->pStreams[dwIndex] = NULL;
This->dwCountOfIndexEntry = 0;
This->pIndexEntry = NULL;
AVIFILE_data.dwClassObjRef ++;
return S_OK;
}
static void AVIFILE_IAVIFile_Destruct( IAVIFileImpl* This )
{
DWORD dwIndex;
if ( This->pIndexEntry != NULL )
{
HeapFree(AVIFILE_data.hHeap,0,This->pIndexEntry);
This->pIndexEntry = NULL;
}
for ( dwIndex = 0; dwIndex < AVIFILE_STREAMS_MAX; dwIndex++ )
{
if ( This->pStreams[dwIndex] != NULL )
{
IAVIStream_Release( This->pStreams[dwIndex] );
This->pStreams[dwIndex] = NULL;
}
}
if ( This->hf != INVALID_HANDLE_VALUE )
CloseHandle( This->hf );
AVIFILE_data.dwClassObjRef --;
}
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size)
{
ICOM_THIS(IAVIFileImpl,iface);
AVIFILEINFOW fiw;
FIXME("(%p)->Info(%p,%ld)\n",iface,afi,size);
memset( &fiw, 0, sizeof(fiw) );
fiw.dwMaxBytesPerSec = This->hdr.dwMaxBytesPerSec;
fiw.dwFlags = This->hdr.dwFlags;
fiw.dwCaps = This->dwAVIFileCaps;
fiw.dwStreams = This->hdr.dwStreams;
fiw.dwSuggestedBufferSize = This->hdr.dwSuggestedBufferSize;
fiw.dwWidth = This->hdr.dwWidth;
fiw.dwHeight = This->hdr.dwHeight;
fiw.dwScale = This->dwAVIFileScale; /* FIXME */
fiw.dwRate = This->dwAVIFileRate; /* FIXME */
fiw.dwLength = This->dwAVIFileLength; /* FIXME */
fiw.dwEditCount = This->dwAVIFileEditCount; /* FIXME */
/* fiw.szFileType[64]; */
if ( size > sizeof(AVIFILEINFOW) )
size = sizeof(AVIFILEINFOW);
memcpy( afi, &fiw, size );
return S_OK;
}
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->GetStream(%p,0x%08lx,%ld)\n",iface,avis,fccType,lParam);
if ( fccType != 0 )
return E_FAIL;
if ( lParam < 0 || lParam >= This->hdr.dwStreams )
return E_FAIL;
*avis = This->pStreams[lParam];
IAVIStream_AddRef( *avis );
return S_OK;
}
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p,%p,%p)\n",This,avis,asi);
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",This,ckid,lpData,size);
/* FIXME: write data to file */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",This,ckid,lpData,size);
/* FIXME: read at most size bytes from file */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->EndRecord()\n",This);
/* FIXME: end record? */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->DeleteStream(0x%08lx,%ld)\n",This,fccType,lParam);
/* FIXME: delete stream? */
return E_FAIL;
}
/*****************************************************************************
* AVIFILE_IAVIFile_Open (internal)
*/
HRESULT AVIFILE_IAVIFile_Open( PAVIFILE paf, LPCWSTR szFile, UINT uMode )
{
ICOM_THIS(IAVIFileImpl,paf);
HRESULT hr;
DWORD dwAcc;
DWORD dwShared;
DWORD dwCreate;
BYTE buf[12];
DWORD dwRead;
FOURCC fccFileType;
DWORD dwLen;
DWORD dwIndex;
FIXME("(%p)->Open(%p,%u)\n",This,szFile,uMode);
if ( This->hf != INVALID_HANDLE_VALUE )
{
CloseHandle( This->hf );
This->hf = INVALID_HANDLE_VALUE;
}
switch ( uMode & 0x3 )
{
case OF_READ: /* 0x0 */
dwAcc = GENERIC_READ;
dwCreate = OPEN_EXISTING;
This->dwAVIFileCaps = AVIFILECAPS_CANREAD;
break;
case OF_WRITE: /* 0x1 */
dwAcc = GENERIC_WRITE;
dwCreate = OPEN_ALWAYS;
This->dwAVIFileCaps = AVIFILECAPS_CANWRITE;
break;
case OF_READWRITE: /* 0x2 */
dwAcc = GENERIC_READ|GENERIC_WRITE;
dwCreate = OPEN_ALWAYS;
This->dwAVIFileCaps = AVIFILECAPS_CANREAD|AVIFILECAPS_CANWRITE;
break;
default:
return E_FAIL;
}
if ( This->dwAVIFileCaps & AVIFILECAPS_CANWRITE )
{
FIXME( "editing AVI is currently not supported!\n" );
return E_FAIL;
}
switch ( uMode & 0x70 )
{
case OF_SHARE_COMPAT: /* 0x00 */
dwShared = FILE_SHARE_READ|FILE_SHARE_WRITE;
break;
case OF_SHARE_EXCLUSIVE: /* 0x10 */
dwShared = 0;
break;
case OF_SHARE_DENY_WRITE: /* 0x20 */
dwShared = FILE_SHARE_READ;
break;
case OF_SHARE_DENY_READ: /* 0x30 */
dwShared = FILE_SHARE_WRITE;
break;
case OF_SHARE_DENY_NONE: /* 0x40 */
dwShared = FILE_SHARE_READ|FILE_SHARE_WRITE;
break;
default:
return E_FAIL;
}
if ( uMode & OF_CREATE )
dwCreate = CREATE_ALWAYS;
This->hf = CreateFileW( szFile, dwAcc, dwShared, NULL,
dwCreate, FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL );
if ( This->hf == INVALID_HANDLE_VALUE )
return AVIERR_FILEOPEN;
if ( dwAcc & GENERIC_READ )
{
if ( !ReadFile( This->hf, buf, 12, &dwRead, NULL ) )
return AVIERR_FILEREAD;
if ( dwRead == 12 )
{
if ( mmioFOURCC(buf[0],buf[1],buf[2],buf[3]) != FOURCC_RIFF )
return AVIERR_BADFORMAT;
fccFileType = mmioFOURCC(buf[8],buf[9],buf[10],buf[11]);
if ( fccFileType != formtypeAVI )
return AVIERR_BADFORMAT;
/* get AVI main header. */
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, ckidAVIMAINHDR, &dwLen );
if ( hr != S_OK )
return hr;
if ( dwLen < (sizeof(DWORD)*10) )
return AVIERR_BADFORMAT;
hr = AVIFILE_IAVIFile_ReadChunkData(
This, dwLen,
&(This->hdr), sizeof(MainAVIHeader), &dwLen );
if ( This->hdr.dwStreams == 0 ||
This->hdr.dwStreams > AVIFILE_STREAMS_MAX )
return AVIERR_BADFORMAT;
/* get stream headers. */
dwIndex = 0;
while ( dwIndex < This->hdr.dwStreams )
{
WINE_AVISTREAM_DATA* pData;
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, ckidSTREAMHEADER, &dwLen );
if ( hr != S_OK )
return hr;
if ( dwLen < (sizeof(DWORD)*12) )
return AVIERR_BADFORMAT;
hr = AVIFILE_IAVIFile_ReadChunkData(
This, dwLen,
&This->strhdrs[dwIndex],
sizeof(AVIStreamHeader), &dwLen );
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, ckidSTREAMFORMAT, &dwLen );
if ( hr != S_OK )
return hr;
pData = AVIFILE_Alloc_IAVIStreamData( dwLen );
if ( pData == NULL )
return AVIERR_MEMORY;
hr = AVIFILE_IAVIFile_ReadChunkData(
This, dwLen,
pData->pbFmt, dwLen, &dwLen );
if ( hr != S_OK )
{
AVIFILE_Free_IAVIStreamData( pData );
return hr;
}
pData->dwStreamIndex = dwIndex;
pData->pstrhdr = &This->strhdrs[dwIndex];
hr = AVIStreamCreate(&This->pStreams[dwIndex],
(LONG)paf, (LONG)(pData), NULL );
if ( hr != S_OK )
{
AVIFILE_Free_IAVIStreamData( pData );
return hr;
}
if ( (This->strhdrs[dwIndex].fccType
== mmioFOURCC('v','i','d','s')) ||
(This->strhdrs[dwIndex].fccType
== mmioFOURCC('V','I','D','S')) )
{
This->dwAVIFileScale =
This->strhdrs[dwIndex].dwScale;
This->dwAVIFileRate =
This->strhdrs[dwIndex].dwRate;
This->dwAVIFileLength =
This->strhdrs[dwIndex].dwLength;
}
else
if ( This->dwAVIFileScale == 0 )
{
This->dwAVIFileScale =
This->strhdrs[dwIndex].dwScale;
This->dwAVIFileRate =
This->strhdrs[dwIndex].dwRate;
This->dwAVIFileLength =
This->strhdrs[dwIndex].dwLength;
}
dwIndex ++;
}
/* skip movi. */
while ( 1 )
{
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, FOURCC_LIST, &dwLen );
if ( hr != S_OK )
return hr;
if ( dwLen < 4 )
return AVIERR_BADFORMAT;
This->dwMoviTop = SetFilePointer( This->hf,0,NULL,FILE_CURRENT );
if ( This->dwMoviTop == 0xffffffff )
return AVIERR_BADFORMAT;
if ( ( !ReadFile(This->hf, buf, 4, &dwRead, NULL) ) ||
( dwRead != 4 ) )
return AVIERR_FILEREAD;
hr = AVIFILE_IAVIFile_SkipChunkData(
This, dwLen - 4 );
if ( hr != S_OK )
return hr;
if ( mmioFOURCC(buf[0],buf[1],buf[2],buf[3])
== mmioFOURCC('m', 'o', 'v', 'i') )
break;
}
/* get idx1. */
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, ckidAVINEWINDEX, &dwLen );
if ( hr != S_OK )
return hr;
This->dwCountOfIndexEntry = dwLen / sizeof(AVIINDEXENTRY);
This->pIndexEntry = (AVIINDEXENTRY*)
HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(AVIINDEXENTRY) *
This->dwCountOfIndexEntry * 2 );
if ( This->pIndexEntry == NULL )
return AVIERR_MEMORY;
hr = AVIFILE_IAVIFile_ReadChunkData(
This, dwLen,
This->pIndexEntry + This->dwCountOfIndexEntry,
sizeof(AVIINDEXENTRY) *
This->dwCountOfIndexEntry, &dwLen );
if ( hr != S_OK )
return hr;
AVIFILE_IAVIFile_InitIndexTable(
This, This->pIndexEntry,
This->pIndexEntry + This->dwCountOfIndexEntry,
This->dwCountOfIndexEntry );
}
else
{
/* FIXME - create the handle has GENERIC_WRITE access. */
return AVIERR_FILEREAD;
}
}
else
{
return AVIERR_FILEOPEN; /* FIXME */
}
return S_OK;
}
/*****************************************************************************
* AVIFILE_IAVIFile_GetIndexTable (internal)
*/
HRESULT AVIFILE_IAVIFile_GetIndexTable( PAVIFILE paf, DWORD dwStreamIndex,
AVIINDEXENTRY** ppIndexEntry,
DWORD* pdwCountOfIndexEntry )
{
ICOM_THIS(IAVIFileImpl,paf);
if ( dwStreamIndex < 0 || dwStreamIndex >= This->hdr.dwStreams )
{
FIXME( "invalid stream index %lu\n", dwStreamIndex );
return E_FAIL;
}
FIXME( "cur %p, next %p\n",
This->pStreamIndexEntry[dwStreamIndex],
This->pStreamIndexEntry[dwStreamIndex+1] );
*ppIndexEntry = This->pStreamIndexEntry[dwStreamIndex];
*pdwCountOfIndexEntry =
This->pStreamIndexEntry[dwStreamIndex+1] -
This->pStreamIndexEntry[dwStreamIndex];
return S_OK;
}
/*****************************************************************************
* AVIFILE_IAVIFile_ReadMovieData (internal)
*/
HRESULT AVIFILE_IAVIFile_ReadMovieData( PAVIFILE paf, DWORD dwOffset,
DWORD dwLength, LPVOID lpvBuf )
{
ICOM_THIS(IAVIFileImpl,paf);
LONG lHigh = 0;
DWORD dwRes;
if ( dwLength == 0 )
return S_OK;
SetLastError(NO_ERROR);
dwRes = SetFilePointer( This->hf, (LONG)(dwOffset+This->dwMoviTop),
&lHigh, FILE_BEGIN );
if ( dwRes == (DWORD)0xffffffff && GetLastError() != NO_ERROR )
return AVIERR_FILEREAD;
if ( ( !ReadFile(This->hf, lpvBuf, dwLength, &dwRes, NULL) ) ||
( dwLength != dwRes ) )
{
FIXME( "error in ReadFile()\n" );
return AVIERR_FILEREAD;
}
return S_OK;
}
/*
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "vfw.h"
#include "debugtools.h"
#include "avifile_private.h"
DEFAULT_DEBUG_CHANNEL(avifile);
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface);
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface);
static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
struct ICOM_VTABLE(IAVIStream) iavist = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
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
};
typedef struct IAVIStreamImpl
{
ICOM_VFIELD(IAVIStream);
/* IUnknown stuff */
DWORD ref;
/* IAVIStream stuff */
IAVIFile* paf;
WINE_AVISTREAM_DATA* pData;
} IAVIStreamImpl;
static HRESULT IAVIStream_Construct( IAVIStreamImpl* This );
static void IAVIStream_Destruct( IAVIStreamImpl* This );
HRESULT AVIFILE_CreateIAVIStream(void** ppobj)
{
IAVIStreamImpl *This;
HRESULT hr;
*ppobj = NULL;
This = (IAVIStreamImpl*)HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(IAVIStreamImpl));
This->ref = 1;
ICOM_VTBL(This) = &iavist;
hr = IAVIStream_Construct( This );
if ( hr != S_OK )
{
IAVIStream_Destruct( This );
return hr;
}
*ppobj = (LPVOID)This;
return S_OK;
}
/****************************************************************************
* IUnknown interface
*/
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIStreamImpl,iface);
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
if ( IsEqualGUID(&IID_IUnknown,refiid) ||
IsEqualGUID(&IID_IAVIStream,refiid) )
{
IAVIStream_AddRef(iface);
*obj = iface;
return S_OK;
}
/* can return IGetFrame interface too */
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface) {
ICOM_THIS(IAVIStreamImpl,iface);
TRACE("(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) {
ICOM_THIS(IAVIStreamImpl,iface);
TRACE("(%p)->Release()\n",iface);
if ((--(This->ref)) > 0 )
return This->ref;
IAVIStream_Destruct(This);
HeapFree(AVIFILE_data.hHeap,0,iface);
return 0;
}
/****************************************************************************
* IAVIStream interface
*/
static HRESULT IAVIStream_Construct( IAVIStreamImpl* This )
{
This->paf = NULL;
This->pData = NULL;
AVIFILE_data.dwClassObjRef ++;
return S_OK;
}
static void IAVIStream_Destruct( IAVIStreamImpl* This )
{
AVIFILE_data.dwClassObjRef --;
}
static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2)
{
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->Create(%ld,%ld)\n",iface,lParam1,lParam2);
This->paf = (IAVIFile*)lParam1;
This->pData = (WINE_AVISTREAM_DATA*)lParam2;
return S_OK;
}
static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size)
{
ICOM_THIS(IAVIStreamImpl,iface);
AVISTREAMINFOW siw;
FIXME("(%p)->Info(%p,%ld)\n",iface,psi,size);
if ( This->pData == NULL )
return E_UNEXPECTED;
memset( &siw, 0, sizeof(AVISTREAMINFOW) );
siw.fccType = This->pData->pstrhdr->fccType;
siw.fccHandler = This->pData->pstrhdr->fccHandler;
siw.dwFlags = This->pData->pstrhdr->dwFlags;
siw.dwCaps = 0; /* FIXME */
siw.wPriority = This->pData->pstrhdr->wPriority;
siw.wLanguage = This->pData->pstrhdr->wLanguage;
siw.dwScale = This->pData->pstrhdr->dwScale;
siw.dwRate = This->pData->pstrhdr->dwRate;
siw.dwStart = This->pData->pstrhdr->dwStart;
siw.dwLength = This->pData->pstrhdr->dwLength;
siw.dwInitialFrames = This->pData->pstrhdr->dwInitialFrames;
siw.dwSuggestedBufferSize = This->pData->pstrhdr->dwSuggestedBufferSize;
siw.dwQuality = This->pData->pstrhdr->dwQuality;
siw.dwSampleSize = This->pData->pstrhdr->dwSampleSize;
siw.rcFrame.left = This->pData->pstrhdr->rcFrame.left;
siw.rcFrame.top = This->pData->pstrhdr->rcFrame.top;
siw.rcFrame.right = This->pData->pstrhdr->rcFrame.right;
siw.rcFrame.bottom = This->pData->pstrhdr->rcFrame.bottom;
siw.dwEditCount = 0; /* FIXME */
siw.dwFormatChangeCount = 0; /* FIXME */
/* siw.szName[64] */
if ( size > sizeof(AVISTREAMINFOW) )
size = sizeof(AVISTREAMINFOW);
memcpy( psi, &siw, size );
return S_OK;
}
static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags)
{
ICOM_THIS(IAVIStreamImpl,iface);
HRESULT hr;
AVIINDEXENTRY* pIndexEntry;
DWORD dwCountOfIndexEntry;
LONG lCur, lAdd, lEnd;
FIXME("(%p)->FindSample(%ld,0x%08lx)\n",This,pos,flags);
hr = AVIFILE_IAVIFile_GetIndexTable(
This->paf, This->pData->dwStreamIndex,
&pIndexEntry, &dwCountOfIndexEntry );
if ( hr != S_OK )
return -1L;
if ( flags & (~(FIND_DIR|FIND_TYPE|FIND_RET)) )
{
FIXME( "unknown flag %08lx\n", flags );
return -1L;
}
switch ( flags & FIND_DIR )
{
case FIND_NEXT:
lCur = pos;
lAdd = 1;
lEnd = dwCountOfIndexEntry;
if ( lCur > dwCountOfIndexEntry )
return -1L;
break;
case FIND_PREV:
lCur = pos;
if ( lCur > dwCountOfIndexEntry )
lCur = dwCountOfIndexEntry;
lAdd = -1;
lEnd = 0;
break;
case FIND_FROM_START:
lCur = 0;
lAdd = 1;
lEnd = dwCountOfIndexEntry;
break;
default:
FIXME( "unknown direction flag %08lx\n", (flags & FIND_DIR) );
return -1L;
}
switch ( flags & FIND_TYPE )
{
case FIND_KEY:
while ( 1 )
{
if ( pIndexEntry[lCur].dwFlags & AVIIF_KEYFRAME )
break;
if ( lCur == lEnd )
return -1L;
lCur += lAdd;
}
break;
case FIND_ANY:
while ( 1 )
{
if ( !(pIndexEntry[lCur].dwFlags & AVIIF_NOTIME) )
break;
if ( lCur == lEnd )
return -1L;
lCur += lAdd;
}
break;
case FIND_FORMAT:
FIXME( "FIND_FORMAT is not implemented.\n" );
return -1L;
default:
FIXME( "unknown type flag %08lx\n", (flags & FIND_TYPE) );
return -1L;
}
switch ( flags & FIND_RET )
{
case FIND_POS:
return lCur;
case FIND_LENGTH:
FIXME( "FIND_LENGTH is not implemented.\n" );
return -1L;
case FIND_OFFSET:
return pIndexEntry[lCur].dwChunkOffset;
case FIND_SIZE:
return pIndexEntry[lCur].dwChunkLength;
case FIND_INDEX:
FIXME( "FIND_INDEX is not implemented.\n" );
return -1L;
default:
FIXME( "unknown return type flag %08lx\n", (flags & FIND_RET) );
break;
}
return -1L;
}
static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize) {
ICOM_THIS(IAVIStreamImpl,iface);
TRACE("(%p)->ReadFormat(%ld,%p,%p)\n",This,pos,format,formatsize);
if ( This->pData == NULL )
return E_UNEXPECTED;
/* FIXME - check pos. */
if ( format == NULL )
{
*formatsize = This->pData->dwFmtLen;
return S_OK;
}
if ( (*formatsize) < This->pData->dwFmtLen )
return AVIERR_BUFFERTOOSMALL;
memcpy( format, This->pData->pbFmt, This->pData->dwFmtLen );
*formatsize = This->pData->dwFmtLen;
return S_OK;
}
static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->SetFormat(%ld,%p,%ld)\n",This,pos,format,formatsize);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
ICOM_THIS(IAVIStreamImpl,iface);
HRESULT hr;
AVIINDEXENTRY* pIndexEntry;
DWORD dwCountOfIndexEntry;
DWORD dwFrameLength;
FIXME("(%p)->Read(%ld,%ld,%p,%ld,%p,%p)\n",This,start,samples,buffer,buffersize,bytesread,samplesread);
*bytesread = 0;
*samplesread = 0;
hr = AVIFILE_IAVIFile_GetIndexTable(
This->paf, This->pData->dwStreamIndex,
&pIndexEntry, &dwCountOfIndexEntry );
if ( hr != S_OK )
return hr;
if ( start < 0 )
return E_FAIL;
if ( start >= dwCountOfIndexEntry || samples <= 0 )
{
FIXME("start %ld,samples %ld,total %ld\n",start,samples,dwCountOfIndexEntry);
return S_OK;
}
/* FIXME - is this data valid??? */
dwFrameLength = pIndexEntry[start].dwChunkLength + sizeof(DWORD)*2;
if ( buffer == NULL )
{
*bytesread = dwFrameLength;
*samplesread = 1;
return S_OK;
}
if ( buffersize < dwFrameLength )
{
FIXME( "buffer is too small!\n" );
return AVIERR_BUFFERTOOSMALL;
}
hr = AVIFILE_IAVIFile_ReadMovieData(
This->paf,
pIndexEntry[start].dwChunkOffset,
dwFrameLength, buffer );
if ( hr != S_OK )
{
FIXME( "ReadMovieData failed!\n");
return hr;
}
*bytesread = dwFrameLength;
*samplesread = 1;
return S_OK;
}
static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->Write(%ld,%ld,%p,%ld,0x%08lx,%p,%p)\n",This,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->Delete(%ld,%ld)\n",This,start,samples);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",This,fcc,lp,lpread);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",This,fcc,lp,size);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->SetInfo(%p,%ld)\n",This,info,infolen);
return E_FAIL;
}
/*
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
* FIXME - implements color space(depth) converter.
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "vfw.h"
#include "debugtools.h"
#include "avifile_private.h"
DEFAULT_DEBUG_CHANNEL(avifile);
static HRESULT WINAPI IGetFrame_fnQueryInterface(IGetFrame* iface,REFIID refiid,LPVOID *obj);
static ULONG WINAPI IGetFrame_fnAddRef(IGetFrame* iface);
static ULONG WINAPI IGetFrame_fnRelease(IGetFrame* iface);
static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame* iface,LONG lPos);
static HRESULT WINAPI IGetFrame_fnBegin(IGetFrame* iface,LONG lStart,LONG lEnd,LONG lRate);
static HRESULT WINAPI IGetFrame_fnEnd(IGetFrame* iface);
static HRESULT WINAPI IGetFrame_fnSetFormat(IGetFrame* iface,LPBITMAPINFOHEADER lpbi,LPVOID lpBits,INT x,INT y,INT dx,INT dy);
struct ICOM_VTABLE(IGetFrame) igetfrm = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IGetFrame_fnQueryInterface,
IGetFrame_fnAddRef,
IGetFrame_fnRelease,
IGetFrame_fnGetFrame,
IGetFrame_fnBegin,
IGetFrame_fnEnd,
IGetFrame_fnSetFormat,
};
typedef struct IGetFrameImpl
{
ICOM_VFIELD(IGetFrame);
/* IUnknown stuff */
DWORD ref;
/* IGetFrame stuff */
IAVIStream* pas;
HIC hIC;
LONG lCachedFrame;
BITMAPINFO* pbiICIn;
BITMAPINFO* pbiICOut;
LPVOID pvICOutBits;
LPVOID pvICInFmtBuf;
DWORD dwICInDataBufSize;
LPVOID pvICInDataBuf;
LPVOID pvICOutBuf;
} IGetFrameImpl;
static HRESULT IGetFrame_Construct( IGetFrameImpl* This,
IAVIStream* pstr,
LPBITMAPINFOHEADER lpbi );
static void IGetFrame_Destruct( IGetFrameImpl* This );
static LPVOID AVIFILE_IGetFrame_DecodeFrame(IGetFrameImpl* This,LONG lPos)
{
HRESULT hr;
DWORD dwRes;
LONG lFrameLength;
LONG lSampleCount;
ICDECOMPRESS icd;
if ( This->hIC == (HIC)NULL )
return NULL;
hr = IAVIStream_Read(This->pas,lPos,1,NULL,0,
&lFrameLength,&lSampleCount);
if ( hr != S_OK || lSampleCount <= 0 )
{
FIXME( "IAVIStream_Read failed! res = %08lx\n", hr );
return NULL;
}
TRACE( "frame length = %ld\n", lFrameLength );
if ( This->dwICInDataBufSize < lFrameLength )
{
LPVOID lpv;
if ( This->pvICInDataBuf == NULL )
{
lpv = HeapAlloc(
AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
lFrameLength );
}
else
{
lpv = HeapReAlloc(
AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
This->pvICInDataBuf,lFrameLength );
}
if ( lpv == NULL )
{
ERR( "out of memory!\n" );
return NULL;
}
This->pvICInDataBuf = lpv;
This->dwICInDataBufSize = lFrameLength;
}
hr = IAVIStream_Read(This->pas,lPos,1,
This->pvICInDataBuf,This->dwICInDataBufSize,
&lFrameLength,&lSampleCount);
if ( hr != S_OK || lSampleCount <= 0 )
{
FIXME( "IAVIStream_Read to buffer failed! res = %08lx\n", hr );
return NULL;
}
This->pbiICIn->bmiHeader.biSizeImage = lFrameLength;
TRACE( "call ICM_DECOMPRESS\n" );
icd.dwFlags = (*(BYTE*)This->pvICInDataBuf) == 'c' ?
ICDECOMPRESS_NOTKEYFRAME : 0;
icd.lpbiInput = &This->pbiICIn->bmiHeader;
icd.lpInput = (BYTE*)This->pvICInDataBuf + 8;
icd.lpbiOutput = &This->pbiICOut->bmiHeader;
icd.lpOutput = This->pvICOutBits;
icd.ckid = *((DWORD*)This->pvICInDataBuf);
dwRes = ICSendMessage(This->hIC,ICM_DECOMPRESS,
(DWORD)(&icd),sizeof(ICDECOMPRESS) );
TRACE( "returned from ICM_DECOMPRESS\n" );
if ( dwRes != ICERR_OK )
{
ERR( "ICDecompress failed!\n" );
return NULL;
}
This->lCachedFrame = lPos;
return This->pvICOutBits;
}
/****************************************************************************/
HRESULT AVIFILE_CreateIGetFrame(void** ppobj,
IAVIStream* pstr,LPBITMAPINFOHEADER lpbi)
{
IGetFrameImpl *This;
HRESULT hr;
*ppobj = NULL;
This = (IGetFrameImpl*)HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(IGetFrameImpl));
This->ref = 1;
ICOM_VTBL(This) = &igetfrm;
hr = IGetFrame_Construct( This, pstr, lpbi );
if ( hr != S_OK )
{
IGetFrame_Destruct( This );
return hr;
}
*ppobj = (LPVOID)This;
return S_OK;
}
/****************************************************************************
* IUnknown interface
*/
static HRESULT WINAPI IGetFrame_fnQueryInterface(IGetFrame* iface,REFIID refiid,LPVOID *obj)
{
ICOM_THIS(IGetFrameImpl,iface);
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
if ( IsEqualGUID(&IID_IUnknown,refiid) ||
IsEqualGUID(&IID_IGetFrame,refiid) )
{
IGetFrame_AddRef(iface);
*obj = iface;
return S_OK;
}
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IGetFrame_fnAddRef(IGetFrame* iface)
{
ICOM_THIS(IGetFrameImpl,iface);
TRACE("(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IGetFrame_fnRelease(IGetFrame* iface)
{
ICOM_THIS(IGetFrameImpl,iface);
TRACE("(%p)->Release()\n",iface);
if ((--(This->ref)) > 0 )
return This->ref;
IGetFrame_Destruct(This);
if ( This->pas != NULL )
IAVIStream_Release( This->pas );
HeapFree(AVIFILE_data.hHeap,0,iface);
return 0;
}
/****************************************************************************
* IGetFrrame interface
*/
static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame* iface,LONG lPos)
{
ICOM_THIS(IGetFrameImpl,iface);
LPVOID lpv;
LONG lKeyFrame;
TRACE( "(%p)->(%ld)\n", This, lPos );
if ( lPos < 0 )
return NULL;
if ( This->lCachedFrame == lPos )
return This->pvICOutBits;
if ( (This->lCachedFrame+1) != lPos )
{
lKeyFrame = IAVIStream_FindSample( This->pas, lPos,
FIND_KEY | FIND_PREV );
if ( lKeyFrame < 0 || lKeyFrame > lPos )
return NULL;
while ( ++lKeyFrame < lPos )
{
lpv = AVIFILE_IGetFrame_DecodeFrame(This, lKeyFrame);
if ( lpv == NULL )
return NULL;
}
}
lpv = AVIFILE_IGetFrame_DecodeFrame(This, lPos);
TRACE( "lpv = %p\n",lpv );
if ( lpv == NULL )
return NULL;
return lpv;
}
static HRESULT WINAPI IGetFrame_fnBegin(IGetFrame* iface,LONG lStart,LONG lEnd,LONG lRate)
{
ICOM_THIS(IGetFrameImpl,iface);
TRACE( "(%p)->(%ld,%ld,%ld)\n", This, lStart, lEnd, lRate );
if ( This->hIC == (HIC)NULL )
return E_UNEXPECTED;
if ( ICDecompressBegin( This->hIC,
This->pbiICIn,
This->pbiICOut ) != ICERR_OK )
return E_FAIL;
return S_OK;
}
static HRESULT WINAPI IGetFrame_fnEnd(IGetFrame* iface)
{
ICOM_THIS(IGetFrameImpl,iface);
TRACE( "(%p)->()\n", This );
if ( This->hIC == (HIC)NULL )
return E_UNEXPECTED;
if ( ICDecompressEnd( This->hIC ) != ICERR_OK )
return E_FAIL;
return S_OK;
}
static HRESULT WINAPI IGetFrame_fnSetFormat(IGetFrame* iface,LPBITMAPINFOHEADER lpbi,LPVOID lpBits,INT x,INT y,INT dx,INT dy)
{
ICOM_THIS(IGetFrameImpl,iface);
HRESULT hr;
LONG fmtlen;
BITMAPINFOHEADER biTemp;
DWORD dwSizeImage;
FIXME( "(%p)->(%p,%p,%d,%d,%d,%d)\n",This,lpbi,lpBits,x,y,dx,dy );
IGetFrame_Destruct(This);
hr = IAVIStream_ReadFormat(This->pas,0,NULL,&fmtlen);
if ( hr != S_OK )
return hr;
This->pvICInFmtBuf = HeapAlloc(
AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,fmtlen);
if ( This->pvICInFmtBuf == NULL )
return AVIERR_MEMORY;
hr = IAVIStream_ReadFormat(This->pas,0,This->pvICInFmtBuf,&fmtlen);
if ( hr != S_OK )
return hr;
This->pbiICIn = (LPBITMAPINFO)This->pvICInFmtBuf;
This->hIC = (HIC)ICOpen( ICTYPE_VIDEO,
This->pbiICIn->bmiHeader.biCompression,
ICMODE_DECOMPRESS );
if ( This->hIC == (HIC)NULL )
{
ERR( "no AVI decompressor for %c%c%c%c.\n",
(int)(This->pbiICIn->bmiHeader.biCompression>> 0)&0xff,
(int)(This->pbiICIn->bmiHeader.biCompression>> 8)&0xff,
(int)(This->pbiICIn->bmiHeader.biCompression>>16)&0xff,
(int)(This->pbiICIn->bmiHeader.biCompression>>24)&0xff );
return E_FAIL;
}
if ( lpbi == NULL || lpbi == ((LPBITMAPINFOHEADER)1) )
{
memset( &biTemp, 0, sizeof(biTemp) );
biTemp.biSize = sizeof(BITMAPINFOHEADER);
biTemp.biWidth = This->pbiICIn->bmiHeader.biWidth;
biTemp.biHeight = This->pbiICIn->bmiHeader.biHeight;
biTemp.biPlanes = 1;
biTemp.biBitCount = 24;
biTemp.biCompression = 0;
lpbi = &biTemp;
}
if ( lpbi->biPlanes != 1 || lpbi->biCompression != 0 )
return E_FAIL;
dwSizeImage =
((This->pbiICIn->bmiHeader.biWidth*lpbi->biBitCount+7)/8)*
This->pbiICIn->bmiHeader.biHeight;
This->pvICOutBuf = HeapAlloc(
AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
(sizeof(BITMAPINFO)+sizeof(RGBQUAD)*256)*2+
dwSizeImage );
if ( This->pvICOutBuf == NULL )
return AVIERR_MEMORY;
This->pbiICOut = (BITMAPINFO*)This->pvICOutBuf;
This->pvICOutBits = (LPVOID)( (BYTE*)This->pvICOutBuf +
sizeof(BITMAPINFO) + sizeof(RGBQUAD)*256 );
This->pbiICOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
This->pbiICOut->bmiHeader.biWidth = This->pbiICIn->bmiHeader.biWidth;
This->pbiICOut->bmiHeader.biHeight = This->pbiICIn->bmiHeader.biHeight;
This->pbiICOut->bmiHeader.biPlanes = 1;
This->pbiICOut->bmiHeader.biBitCount = lpbi->biBitCount;
This->pbiICOut->bmiHeader.biSizeImage = dwSizeImage;
memcpy( This->pvICOutBits, This->pbiICOut, sizeof(BITMAPINFOHEADER) );
return S_OK;
}
static HRESULT IGetFrame_Construct( IGetFrameImpl* This,
IAVIStream* pstr,
LPBITMAPINFOHEADER lpbi )
{
HRESULT hr;
TRACE( "(%p)->(%p,%p)\n",This,pstr,lpbi );
IAVIStream_AddRef( pstr );
This->pas = pstr;
This->hIC = (HIC)NULL;
This->lCachedFrame = -1L;
This->pbiICIn = NULL;
This->pbiICOut = NULL;
This->pvICInFmtBuf = NULL;
This->pvICInDataBuf = NULL;
This->dwICInDataBufSize = 0;
This->pvICOutBuf = NULL;
hr = IGetFrame_SetFormat((IGetFrame*)This,lpbi,NULL,0,0,0,0);
if ( hr != S_OK )
return hr;
return S_OK;
}
static void IGetFrame_Destruct( IGetFrameImpl* This )
{
if ( This->hIC != (HIC)NULL )
{
ICClose( This->hIC );
This->hIC = (HIC)NULL;
}
if ( This->pvICInFmtBuf != NULL )
{
HeapFree( AVIFILE_data.hHeap, 0, This->pvICInFmtBuf );
This->pvICInFmtBuf = NULL;
}
if ( This->pvICInDataBuf != NULL )
{
HeapFree( AVIFILE_data.hHeap, 0, This->pvICInDataBuf );
This->pvICInDataBuf = NULL;
}
if ( This->pvICOutBuf != NULL )
{
HeapFree( AVIFILE_data.hHeap, 0, This->pvICOutBuf );
This->pvICOutBuf = NULL;
}
This->lCachedFrame = -1L;
This->pbiICIn = NULL;
This->pbiICOut = NULL;
This->dwICInDataBufSize = 0;
}
/*
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "vfw.h"
#include "debugtools.h"
#include "avifile_private.h"
DEFAULT_DEBUG_CHANNEL(avifile);
WINE_AVIFILE_DATA AVIFILE_data;
/***********************************************************************
* AVIFILE_InitProcess (internal)
*/
static BOOL AVIFILE_InitProcess( void )
{
TRACE("()\n");
AVIFILE_data.dwAVIFileRef = 0;
AVIFILE_data.dwClassObjRef = 0;
AVIFILE_data.hHeap = (HANDLE)NULL;
AVIFILE_data.hHeap = HeapCreate( 0, 0x10000, 0 );
if ( AVIFILE_data.hHeap == (HANDLE)NULL )
{
ERR( "cannot allocate heap for AVIFILE.\n" );
return FALSE;
}
return TRUE;
}
/***********************************************************************
* AVIFILE_UninitProcess (internal)
*/
static void AVIFILE_UninitProcess( void )
{
TRACE("()\n");
if ( AVIFILE_data.dwAVIFileRef != 0 )
ERR( "you must call AVIFileExit()\n" );
if ( AVIFILE_data.dwClassObjRef != 0 )
ERR( "you must release some objects allocated from AVIFile.\n" );
if ( AVIFILE_data.hHeap != (HANDLE)NULL )
{
HeapDestroy( AVIFILE_data.hHeap );
AVIFILE_data.hHeap = (HANDLE)NULL;
}
}
/***********************************************************************
* AVIFILE_DllMain
*/
BOOL WINAPI AVIFILE_DllMain(
HINSTANCE hInstDLL,
DWORD fdwReason,
LPVOID lpvReserved )
{
switch ( fdwReason )
{
case DLL_PROCESS_ATTACH:
if ( !AVIFILE_InitProcess() )
return FALSE;
break;
case DLL_PROCESS_DETACH:
AVIFILE_UninitProcess();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
/*
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "vfw.h"
#include "debugtools.h"
#include "avifile_private.h"
DEFAULT_DEBUG_CHANNEL(avifile);
/****************************************************************************
* string APIs (internal) - Copied from wine/dlls/imm32/string.c
*/
INT AVIFILE_strlenAtoW( LPCSTR lpstr )
{
INT len;
len = MultiByteToWideChar( CP_ACP, 0, lpstr, -1, NULL, 0 );
return ( len > 0 ) ? (len-1) : 0;
}
INT AVIFILE_strlenWtoA( LPCWSTR lpwstr )
{
INT len;
len = WideCharToMultiByte( CP_ACP, 0, lpwstr, -1,
NULL, 0, NULL, NULL );
return ( len > 0 ) ? (len-1) : 0;
}
LPWSTR AVIFILE_strncpyAtoW( LPWSTR lpwstr, LPCSTR lpstr, INT wbuflen )
{
INT len;
len = MultiByteToWideChar( CP_ACP, 0, lpstr, -1, lpwstr, wbuflen );
if ( len == 0 )
*lpwstr = 0;
return lpwstr;
}
LPSTR AVIFILE_strncpyWtoA( LPSTR lpstr, LPCWSTR lpwstr, INT abuflen )
{
INT len;
len = WideCharToMultiByte( CP_ACP, 0, lpwstr, -1,
lpstr, abuflen, NULL, NULL );
if ( len == 0 )
*lpstr = 0;
return lpstr;
}
LPWSTR AVIFILE_strdupAtoW( LPCSTR lpstr )
{
INT len;
LPWSTR lpwstr = NULL;
len = AVIFILE_strlenAtoW( lpstr );
if ( len > 0 )
{
lpwstr = (LPWSTR)HeapAlloc( AVIFILE_data.hHeap, 0, sizeof(WCHAR)*(len+1) );
if ( lpwstr != NULL )
(void)AVIFILE_strncpyAtoW( lpwstr, lpstr, len+1 );
}
return lpwstr;
}
LPSTR AVIFILE_strdupWtoA( LPCWSTR lpwstr )
{
INT len;
LPSTR lpstr = NULL;
len = AVIFILE_strlenWtoA( lpwstr );
if ( len > 0 )
{
lpstr = (LPSTR)HeapAlloc( AVIFILE_data.hHeap, 0, sizeof(CHAR)*(len+1) );
if ( lpstr != NULL )
(void)AVIFILE_strncpyWtoA( lpstr, lpwstr, len+1 );
}
return lpstr;
}
......@@ -1004,6 +1004,7 @@ ICOM_DEFINE(IAVIStream, IUnknown)
HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM*ppsCompressed,PAVISTREAM ppsSource,AVICOMPRESSOPTIONS *lpOptions,CLSID*pclsidHandler);
HRESULT WINAPI AVIStreamCreate(PAVISTREAM*,LONG,LONG,CLSID*);
HRESULT WINAPI AVIStreamInfoA(PAVISTREAM iface,AVISTREAMINFOA *asi,LONG size);
HRESULT WINAPI AVIStreamInfoW(PAVISTREAM iface,AVISTREAMINFOW *asi,LONG size);
#define AVIStreamInfo WINELIB_NAME_AW(AVIStreamInfo)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment