434 lines
12 KiB
C
434 lines
12 KiB
C
/*
|
|
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#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 "wine/debug.h"
|
|
#include "avifile_private.h"
|
|
|
|
WINE_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 - no audio support. */
|
|
dwFrameLength = pIndexEntry[start].dwChunkLength;
|
|
|
|
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 + sizeof(DWORD)*2,
|
|
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;
|
|
}
|
|
|