/*
* Copyright 1999 Marcus Meissner
- * Copyright 2002-2003 Michael Günnewig
+ * Copyright 2002-2003 Michael Günnewig
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
static HRESULT AVIFILE_ParseIndex(const IAVIFileImpl *This, AVIINDEXENTRY *lp,
LONG count, DWORD pos, BOOL *bAbsolute);
static HRESULT AVIFILE_ReadBlock(IAVIStreamImpl *This, DWORD start,
- LPVOID buffer, LONG size);
+ LPVOID buffer, DWORD size);
static void AVIFILE_SamplesToBlock(const IAVIStreamImpl *This, LPLONG pos,
LPLONG offset);
static HRESULT AVIFILE_SaveFile(IAVIFileImpl *This);
LONG lSkip);
static void AVIFILE_UpdateInfo(IAVIFileImpl *This);
static HRESULT AVIFILE_WriteBlock(IAVIStreamImpl *This, DWORD block,
- FOURCC ckid, DWORD flags, LPVOID buffer,
+ FOURCC ckid, DWORD flags, LPCVOID buffer,
LONG size);
HRESULT AVIFILE_CreateAVIFile(REFIID riid, LPVOID *ppv)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
- LPBITMAPINFOHEADER lpbiNew = (LPBITMAPINFOHEADER)format;
+ LPBITMAPINFOHEADER lpbiNew = format;
TRACE("(%p,%d,%p,%d)\n", iface, pos, format, formatsize);
return AVIERR_OK;
} else {
MMCKINFO ck;
- LPBITMAPINFOHEADER lpbiOld = (LPBITMAPINFOHEADER)This->lpFormat;
+ LPBITMAPINFOHEADER lpbiOld = This->lpFormat;
RGBQUAD *rgbNew = (RGBQUAD*)((LPBYTE)lpbiNew + lpbiNew->biSize);
AVIPALCHANGE *lppc = NULL;
UINT n;
LONG block = start;
LONG offset = 0;
+ if (!buffer)
+ {
+ if (bytesread)
+ *bytesread = samples*This->sInfo.dwSampleSize;
+ if (samplesread)
+ *samplesread = samples;
+ return AVIERR_OK;
+ }
+
/* convert start sample to block,offset pair */
AVIFILE_SamplesToBlock(This, &block, &offset);
samples *= This->sInfo.dwSampleSize;
while (samples > 0 && buffersize > 0) {
+ LONG blocksize;
if (block != This->dwCurrentFrame) {
hr = AVIFILE_ReadBlock(This, block, NULL, 0);
if (FAILED(hr))
}
size = min((DWORD)samples, (DWORD)buffersize);
- size = min(size, This->cbBuffer - offset);
+ blocksize = This->lpBuffer[1];
+ TRACE("blocksize = %u\n",blocksize);
+ size = min(size, blocksize - offset);
memcpy(buffer, ((BYTE*)&This->lpBuffer[2]) + offset, size);
block++;
static HRESULT AVIFILE_AddFrame(IAVIStreamImpl *This, DWORD ckid, DWORD size, DWORD offset, DWORD flags)
{
+ UINT n;
+
/* pre-conditions */
assert(This != NULL);
ERR(": found palette change in non-video stream!\n");
return AVIERR_BADFORMAT;
}
- This->sInfo.dwFlags |= AVISTREAMINFO_FORMATCHANGES;
- This->sInfo.dwFormatChangeCount++;
- if (This->idxFmtChanges == NULL || This->sInfo.dwFormatChangeCount < This->nIdxFmtChanges) {
- UINT n = This->sInfo.dwFormatChangeCount;
+ if (This->idxFmtChanges == NULL || This->nIdxFmtChanges <= This->sInfo.dwFormatChangeCount) {
+ DWORD new_count = This->nIdxFmtChanges + 16;
+ void *new_buffer;
- This->nIdxFmtChanges += 16;
- if (This->idxFmtChanges == NULL)
+ if (This->idxFmtChanges == NULL) {
This->idxFmtChanges =
- HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->nIdxFmtChanges * sizeof(AVIINDEXENTRY));
- else
- This->idxFmtChanges =
- HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->idxFmtChanges,
- This->nIdxFmtChanges * sizeof(AVIINDEXENTRY));
- if (This->idxFmtChanges == NULL)
- return AVIERR_MEMORY;
+ HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(AVIINDEXENTRY));
+ if (!This->idxFmtChanges) return AVIERR_MEMORY;
+ } else {
+ new_buffer = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->idxFmtChanges,
+ new_count * sizeof(AVIINDEXENTRY));
+ if (!new_buffer) return AVIERR_MEMORY;
+ This->idxFmtChanges = new_buffer;
+ }
+ This->nIdxFmtChanges = new_count;
+ }
- This->idxFmtChanges[n].ckid = This->lLastFrame;
- This->idxFmtChanges[n].dwFlags = 0;
- This->idxFmtChanges[n].dwChunkOffset = offset;
- This->idxFmtChanges[n].dwChunkLength = size;
+ This->sInfo.dwFlags |= AVISTREAMINFO_FORMATCHANGES;
+ n = ++This->sInfo.dwFormatChangeCount;
+ This->idxFmtChanges[n].ckid = This->lLastFrame;
+ This->idxFmtChanges[n].dwFlags = 0;
+ This->idxFmtChanges[n].dwChunkOffset = offset;
+ This->idxFmtChanges[n].dwChunkLength = size;
- return AVIERR_OK;
- }
- break;
+ return AVIERR_OK;
case cktypeWAVEbytes:
if (This->paf->fInfo.dwFlags & AVIFILEINFO_TRUSTCKTYPE)
flags |= AVIIF_KEYFRAME;
This->fInfo.dwCaps = AVIFILECAPS_CANREAD|AVIFILECAPS_CANWRITE;
This->fInfo.dwLength = MainAVIHdr.dwTotalFrames;
This->fInfo.dwStreams = MainAVIHdr.dwStreams;
- This->fInfo.dwSuggestedBufferSize = MainAVIHdr.dwSuggestedBufferSize;
+ This->fInfo.dwSuggestedBufferSize = 0;
This->fInfo.dwWidth = MainAVIHdr.dwWidth;
This->fInfo.dwHeight = MainAVIHdr.dwHeight;
LoadStringW(AVIFILE_hModule, IDS_AVIFILETYPE, This->fInfo.szFileType,
return AVIERR_MEMORY;
pStream->cbHandlerData = ck.cksize;
- if (mmioRead(This->hmmio, (HPSTR)pStream->lpHandlerData, ck.cksize) != ck.cksize)
+ if (mmioRead(This->hmmio, pStream->lpHandlerData, ck.cksize) != ck.cksize)
return AVIERR_FILEREAD;
break;
case ckidSTREAMFORMAT:
return AVIERR_MEMORY;
pStream->cbFormat = ck.cksize;
- if (mmioRead(This->hmmio, (HPSTR)pStream->lpFormat, ck.cksize) != ck.cksize)
+ if (mmioRead(This->hmmio, pStream->lpFormat, ck.cksize) != ck.cksize)
return AVIERR_FILEREAD;
if (pStream->sInfo.fccType == streamtypeVIDEO) {
- LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)pStream->lpFormat;
+ LPBITMAPINFOHEADER lpbi = pStream->lpFormat;
/* some corrections to the video format */
if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8)
pStream->sInfo.dwRate = streamHdr.dwRate;
pStream->sInfo.dwStart = streamHdr.dwStart;
pStream->sInfo.dwLength = streamHdr.dwLength;
- pStream->sInfo.dwSuggestedBufferSize =
- streamHdr.dwSuggestedBufferSize;
+ pStream->sInfo.dwSuggestedBufferSize = 0;
pStream->sInfo.dwQuality = streamHdr.dwQuality;
pStream->sInfo.dwSampleSize = streamHdr.dwSampleSize;
pStream->sInfo.rcFrame.left = streamHdr.rcFrame.left;
if (FAILED(hr))
return hr;
};
-
+ if (pStream->lpFormat != NULL && pStream->sInfo.fccType == streamtypeAUDIO)
+ {
+ WAVEFORMATEX *wfx = pStream->lpFormat; /* wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8; could be added */
+ pStream->sInfo.dwSampleSize = wfx->nBlockAlign; /* to deal with corrupt wfx->nBlockAlign but Windows doesn't do this */
+ TRACE("Block size reset to %u, chan=%u bpp=%u\n", wfx->nBlockAlign, wfx->nChannels, wfx->wBitsPerSample);
+ pStream->sInfo.dwScale = 1;
+ pStream->sInfo.dwRate = wfx->nSamplesPerSec;
+ }
if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
return AVIERR_FILEREAD;
}
}
}
+ for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++)
+ {
+ DWORD sugbuf = This->ppStreams[nStream]->sInfo.dwSuggestedBufferSize;
+ if (This->fInfo.dwSuggestedBufferSize < sugbuf)
+ This->fInfo.dwSuggestedBufferSize = sugbuf;
+ }
+
/* find other chunks */
FindChunkAndKeepExtras(&This->fileextra, This->hmmio, &ck, &ckRIFF, 0);
}
static HRESULT AVIFILE_ReadBlock(IAVIStreamImpl *This, DWORD pos,
- LPVOID buffer, LONG size)
+ LPVOID buffer, DWORD size)
{
/* pre-conditions */
assert(This != NULL);
size += 2 * sizeof(DWORD);
/* check that buffer is big enough -- don't trust dwSuggestedBufferSize */
- if (This->lpBuffer == NULL || size < This->cbBuffer) {
+ if (This->lpBuffer == NULL || This->cbBuffer < size) {
DWORD maxSize = max(size, This->sInfo.dwSuggestedBufferSize);
- if (This->lpBuffer == NULL)
+ if (This->lpBuffer == NULL) {
This->lpBuffer = HeapAlloc(GetProcessHeap(), 0, maxSize);
- else
- This->lpBuffer = HeapReAlloc(GetProcessHeap(), 0, This->lpBuffer, maxSize);
- if (This->lpBuffer == NULL)
- return AVIERR_MEMORY;
- This->cbBuffer = max(size, This->sInfo.dwSuggestedBufferSize);
+ if (!This->lpBuffer) return AVIERR_MEMORY;
+ } else {
+ void *new_buffer = HeapReAlloc(GetProcessHeap(), 0, This->lpBuffer, maxSize);
+ if (!new_buffer) return AVIERR_MEMORY;
+ This->lpBuffer = new_buffer;
+ }
+ This->cbBuffer = maxSize;
}
/* now read the complete chunk into our buffer */
} else {
if (mmioSeek(This->paf->hmmio, This->idxFrames[pos].dwChunkOffset + 2 * sizeof(DWORD), SEEK_SET) == -1)
return AVIERR_FILEREAD;
- if (mmioRead(This->paf->hmmio, (HPSTR)buffer, size) != size)
+ if (mmioRead(This->paf->hmmio, buffer, size) != size)
return AVIERR_FILEREAD;
}
if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
return AVIERR_FILEWRITE;
if (pStream->lpFormat != NULL && ck.cksize > 0) {
- if (mmioWrite(This->hmmio, (HPSTR)pStream->lpFormat, ck.cksize) != ck.cksize)
+ if (mmioWrite(This->hmmio, pStream->lpFormat, ck.cksize) != ck.cksize)
return AVIERR_FILEWRITE;
}
if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
ck.cksize = pStream->cbHandlerData;
if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
return AVIERR_FILEWRITE;
- if (mmioWrite(This->hmmio, (HPSTR)pStream->lpHandlerData, ck.cksize) != ck.cksize)
+ if (mmioWrite(This->hmmio, pStream->lpHandlerData, ck.cksize) != ck.cksize)
return AVIERR_FILEWRITE;
if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
return AVIERR_FILEWRITE;
/* ... some optional additional extra chunk for this stream ... */
if (pStream->extra.lp != NULL && pStream->extra.cb > 0) {
/* the chunk header(s) are already in the structure */
- if (mmioWrite(This->hmmio, (HPSTR)pStream->extra.lp, pStream->extra.cb) != pStream->extra.cb)
+ if (mmioWrite(This->hmmio, pStream->extra.lp, pStream->extra.cb) != pStream->extra.cb)
return AVIERR_FILEWRITE;
}
/* write optional extra file chunks */
if (This->fileextra.lp != NULL && This->fileextra.cb > 0) {
/* as for the streams, are the chunk header(s) in the structure */
- if (mmioWrite(This->hmmio, (HPSTR)This->fileextra.lp, This->fileextra.cb) != This->fileextra.cb)
+ if (mmioWrite(This->hmmio, This->fileextra.lp, This->fileextra.cb) != This->fileextra.cb)
return AVIERR_FILEWRITE;
}
}
static HRESULT AVIFILE_WriteBlock(IAVIStreamImpl *This, DWORD block,
- FOURCC ckid, DWORD flags, LPVOID buffer,
+ FOURCC ckid, DWORD flags, LPCVOID buffer,
LONG size)
{
MMCKINFO ck;
if (mmioCreateChunk(This->paf->hmmio, &ck, 0) != S_OK)
return AVIERR_FILEWRITE;
if (buffer != NULL && size > 0) {
- if (mmioWrite(This->paf->hmmio, (HPSTR)buffer, size) != size)
+ if (mmioWrite(This->paf->hmmio, buffer, size) != size)
return AVIERR_FILEWRITE;
}
if (mmioAscend(This->paf->hmmio, &ck, 0) != S_OK)