/*
 * Copyright 2002 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
 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <assert.h>
#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "vfw.h"

#include "avifile_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(avifile);

#define MAX_FRAMESIZE       (16 * 1024 * 1024)
#define MAX_FRAMESIZE_DIFF  512

/***********************************************************************/

typedef struct _IAVIStreamImpl {
  /* IUnknown stuff */
  IAVIStream         IAVIStream_iface;
  LONG               ref;

  /* IAVIStream stuff */
  PAVISTREAM         pStream;
  AVISTREAMINFOW     sInfo;

  PGETFRAME          pg;
  HIC                hic;
  DWORD              dwICMFlags;

  LONG               lCurrent;
  LONG               lLastKey;
  LONG               lKeyFrameEvery;
  DWORD              dwLastQuality;
  DWORD              dwBytesPerFrame;
  DWORD              dwUnusedBytes;

  LPBITMAPINFOHEADER lpbiCur;  /* current frame */
  LPVOID             lpCur;
  LPBITMAPINFOHEADER lpbiPrev; /* previous frame */
  LPVOID             lpPrev;

  LPBITMAPINFOHEADER lpbiOutput; /* output format of codec */
  LONG               cbOutput;
  LPBITMAPINFOHEADER lpbiInput;  /* input format for codec */
  LONG               cbInput;
} IAVIStreamImpl;

/***********************************************************************/

static HRESULT AVIFILE_EncodeFrame(IAVIStreamImpl *This,
				   LPBITMAPINFOHEADER lpbi, LPVOID lpBits);
static HRESULT AVIFILE_OpenGetFrame(IAVIStreamImpl *This);

static inline IAVIStreamImpl *impl_from_IAVIStream(IAVIStream *iface)
{
  return CONTAINING_RECORD(iface, IAVIStreamImpl, IAVIStream_iface);
}

static inline void AVIFILE_Reset(IAVIStreamImpl *This)
{
  This->lCurrent      = -1;
  This->lLastKey      = 0;
  This->dwLastQuality = ICQUALITY_HIGH;
  This->dwUnusedBytes = 0;
}

static HRESULT WINAPI ICMStream_fnQueryInterface(IAVIStream *iface,
						  REFIID refiid, LPVOID *obj)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);

  if (IsEqualGUID(&IID_IUnknown, refiid) ||
      IsEqualGUID(&IID_IAVIStream, refiid)) {
    *obj = &This->IAVIStream_iface;
    IAVIStream_AddRef(iface);

    return S_OK;
  }

  return OLE_E_ENUM_NOMORE;
}

static ULONG WINAPI ICMStream_fnAddRef(IAVIStream *iface)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);
  ULONG ref = InterlockedIncrement(&This->ref);

  TRACE("(%p) -> %d\n", iface, ref);

  /* also add reference to the nested stream */
  if (This->pStream != NULL)
    IAVIStream_AddRef(This->pStream);

  return ref;
}

static ULONG WINAPI ICMStream_fnRelease(IAVIStream* iface)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);
  ULONG ref = InterlockedDecrement(&This->ref);

  TRACE("(%p) -> %d\n", iface, ref);

  if (ref == 0) {
    /* destruct */
    if (This->pg != NULL) {
      AVIStreamGetFrameClose(This->pg);
      This->pg = NULL;
    }
    if (This->pStream != NULL) {
      IAVIStream_Release(This->pStream);
      This->pStream = NULL;
    }
    if (This->hic != NULL) {
      if (This->lpbiPrev != NULL) {
	ICDecompressEnd(This->hic);
	HeapFree(GetProcessHeap(), 0, This->lpbiPrev);
	This->lpbiPrev = NULL;
	This->lpPrev   = NULL;
      }
      ICCompressEnd(This->hic);
      This->hic = NULL;
    }
    if (This->lpbiCur != NULL) {
      HeapFree(GetProcessHeap(), 0, This->lpbiCur);
      This->lpbiCur = NULL;
      This->lpCur   = NULL;
    }
    if (This->lpbiOutput != NULL) {
      HeapFree(GetProcessHeap(), 0, This->lpbiOutput);
      This->lpbiOutput = NULL;
      This->cbOutput   = 0;
    }
    if (This->lpbiInput != NULL) {
      HeapFree(GetProcessHeap(), 0, This->lpbiInput);
      This->lpbiInput = NULL;
      This->cbInput   = 0;
    }

    HeapFree(GetProcessHeap(), 0, This);

    return 0;
  }

  /* also release reference to the nested stream */
  if (This->pStream != NULL)
    IAVIStream_Release(This->pStream);

  return ref;
}

/* lParam1: PAVISTREAM
 * lParam2: LPAVICOMPRESSOPTIONS
 */
static HRESULT WINAPI ICMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
					  LPARAM lParam2)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  ICINFO               icinfo;
  ICCOMPRESSFRAMES     icFrames;
  LPAVICOMPRESSOPTIONS pco = (LPAVICOMPRESSOPTIONS)lParam2;

  TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);

  /* check parameter */
  if ((LPVOID)lParam1 == NULL)
    return AVIERR_BADPARAM;

  /* get infos from stream */
  IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
  if (This->sInfo.fccType != streamtypeVIDEO)
    return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */

  /* add reference to the stream */
  This->pStream = (PAVISTREAM)lParam1;
  IAVIStream_AddRef(This->pStream);

  AVIFILE_Reset(This);

  if (pco != NULL && pco->fccHandler != comptypeDIB) {
    /* we should compress */
    This->sInfo.fccHandler = pco->fccHandler;

    This->hic = ICOpen(ICTYPE_VIDEO, pco->fccHandler, ICMODE_COMPRESS);
    if (This->hic == NULL)
      return AVIERR_NOCOMPRESSOR;

    /* restore saved state of codec */
    if (pco->cbParms > 0 && pco->lpParms != NULL) {
      ICSetState(This->hic, pco->lpParms, pco->cbParms);
    }

    /* set quality -- resolve default quality */
    This->sInfo.dwQuality = pco->dwQuality;
    if (pco->dwQuality == ICQUALITY_DEFAULT)
      This->sInfo.dwQuality = ICGetDefaultQuality(This->hic);

    /* get capabilities of codec */
    ICGetInfo(This->hic, &icinfo, sizeof(icinfo));
    This->dwICMFlags = icinfo.dwFlags;

    /* use keyframes? */
    if ((pco->dwFlags & AVICOMPRESSF_KEYFRAMES) &&
	(icinfo.dwFlags & (VIDCF_TEMPORAL|VIDCF_FASTTEMPORALC))) {
      This->lKeyFrameEvery = pco->dwKeyFrameEvery;
    } else
      This->lKeyFrameEvery = 1;

    /* use datarate? */
    if ((pco->dwFlags & AVICOMPRESSF_DATARATE)) {
      /* Do we have a chance to reduce size to desired one? */
      if ((icinfo.dwFlags & (VIDCF_CRUNCH|VIDCF_QUALITY)) == 0)
	return AVIERR_NOCOMPRESSOR;

      assert(This->sInfo.dwRate != 0);

      This->dwBytesPerFrame = MulDiv(pco->dwBytesPerSecond,
				     This->sInfo.dwScale, This->sInfo.dwRate);
    } else {
      pco->dwBytesPerSecond = 0;
      This->dwBytesPerFrame = 0;
    }

    if (icinfo.dwFlags & VIDCF_COMPRESSFRAMES) {
      memset(&icFrames, 0, sizeof(icFrames));
      icFrames.lpbiOutput  = This->lpbiOutput;
      icFrames.lpbiInput   = This->lpbiInput;
      icFrames.lFrameCount = This->sInfo.dwLength;
      icFrames.lQuality    = This->sInfo.dwQuality;
      icFrames.lDataRate   = pco->dwBytesPerSecond;
      icFrames.lKeyRate    = This->lKeyFrameEvery;
      icFrames.dwRate      = This->sInfo.dwRate;
      icFrames.dwScale     = This->sInfo.dwScale;
      ICSendMessage(This->hic, ICM_COMPRESS_FRAMES_INFO,
		    (LPARAM)&icFrames, (LPARAM)sizeof(icFrames));
    }
  } else
    This->sInfo.fccHandler = comptypeDIB;

  return AVIERR_OK;
}

static HRESULT WINAPI ICMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
					LONG size)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  TRACE("(%p,%p,%d)\n", iface, psi, size);

  if (psi == NULL)
    return AVIERR_BADPARAM;
  if (size < 0)
    return AVIERR_BADSIZE;

  memcpy(psi, &This->sInfo, min((DWORD)size, sizeof(This->sInfo)));

  if ((DWORD)size < sizeof(This->sInfo))
    return AVIERR_BUFFERTOOSMALL;
  return AVIERR_OK;
}

static LONG WINAPI ICMStream_fnFindSample(IAVIStream *iface, LONG pos,
					   LONG flags)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  TRACE("(%p,%d,0x%08X)\n",iface,pos,flags);

  if (flags & FIND_FROM_START) {
    pos = This->sInfo.dwStart;
    flags &= ~(FIND_FROM_START|FIND_PREV);
    flags |= FIND_NEXT;
  }

  if (flags & FIND_RET)
    WARN(": FIND_RET flags will be ignored!\n");

  if (flags & FIND_KEY) {
    if (This->hic == NULL)
      return pos; /* we decompress so every frame is a keyframe */

    if (flags & FIND_PREV) {
      /* need to read old or new frames? */
      if (This->lLastKey <= pos || pos < This->lCurrent)
	IAVIStream_Read(iface, pos, 1, NULL, 0, NULL, NULL);

      return This->lLastKey;
    }
  } else if (flags & FIND_ANY) {
    return pos; /* We really don't know, reread is too expensive, so guess. */
  } else if (flags & FIND_FORMAT) {
    if (flags & FIND_PREV)
      return 0;
  }

  return -1;
}

static HRESULT WINAPI ICMStream_fnReadFormat(IAVIStream *iface, LONG pos,
					      LPVOID format, LONG *formatsize)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  LPBITMAPINFOHEADER lpbi;
  HRESULT            hr;

  TRACE("(%p,%d,%p,%p)\n", iface, pos, format, formatsize);

  if (formatsize == NULL)
    return AVIERR_BADPARAM;

  if (This->pg == NULL) {
    hr = AVIFILE_OpenGetFrame(This);

    if (FAILED(hr))
      return hr;
  }

  lpbi = AVIStreamGetFrame(This->pg, pos);
  if (lpbi == NULL)
    return AVIERR_MEMORY;

  if (This->hic == NULL) {
    LONG size = lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);

    if (size > 0) {
      if (This->sInfo.dwSuggestedBufferSize < lpbi->biSizeImage)
	This->sInfo.dwSuggestedBufferSize = lpbi->biSizeImage;

      This->cbOutput = size;
      if (format != NULL) {
	if (This->lpbiOutput != NULL)
	  memcpy(format, This->lpbiOutput, min(*formatsize, This->cbOutput));
	else
	  memcpy(format, lpbi, min(*formatsize, size));
      }
    }
  } else if (format != NULL)
    memcpy(format, This->lpbiOutput, min(*formatsize, This->cbOutput));

  if (*formatsize < This->cbOutput)
    hr = AVIERR_BUFFERTOOSMALL;
  else
    hr = AVIERR_OK;

  *formatsize = This->cbOutput;
  return hr;
}

static HRESULT WINAPI ICMStream_fnSetFormat(IAVIStream *iface, LONG pos,
					     LPVOID format, LONG formatsize)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  TRACE("(%p,%d,%p,%d)\n", iface, pos, format, formatsize);

  /* check parameters */
  if (format == NULL || formatsize <= 0)
    return AVIERR_BADPARAM;

  /* We can only accept RGB data for writing */
  if (((LPBITMAPINFOHEADER)format)->biCompression != BI_RGB) {
    WARN(": need RGB data as input\n");
    return AVIERR_UNSUPPORTED;
  }

  /* Input format already known?
   * Changing of palette is supported, but be quiet if it's the same */
  if (This->lpbiInput != NULL) {
    if (This->cbInput != formatsize)
      return AVIERR_UNSUPPORTED;

    if (memcmp(format, This->lpbiInput, formatsize) == 0)
      return AVIERR_OK;
  }

  /* Does the nested stream support writing? */
  if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
    return AVIERR_READONLY;

  /* check if frame is already written */
  if (This->sInfo.dwLength + This->sInfo.dwStart > pos)
    return AVIERR_UNSUPPORTED;

  /* check if we should compress */
  if (This->sInfo.fccHandler == 0 ||
      This->sInfo.fccHandler == mmioFOURCC('N','O','N','E'))
    This->sInfo.fccHandler = comptypeDIB;

  /* only pass through? */
  if (This->sInfo.fccHandler == comptypeDIB)
    return IAVIStream_SetFormat(This->pStream, pos, format, formatsize);

  /* initial format setting? */
  if (This->lpbiInput == NULL) {
    ULONG size;

    assert(This->hic != NULL);

    /* get memory for input format */
    This->lpbiInput = HeapAlloc(GetProcessHeap(), 0, formatsize);
    if (This->lpbiInput == NULL)
      return AVIERR_MEMORY;
    This->cbInput = formatsize;
    memcpy(This->lpbiInput, format, formatsize);

    /* get output format */
    size = ICCompressGetFormatSize(This->hic, This->lpbiInput);
    if (size < sizeof(BITMAPINFOHEADER))
      return AVIERR_COMPRESSOR;
    This->lpbiOutput = HeapAlloc(GetProcessHeap(), 0, size);
    if (This->lpbiOutput == NULL)
      return AVIERR_MEMORY;
    This->cbOutput = size;
    if (ICCompressGetFormat(This->hic,This->lpbiInput,This->lpbiOutput) < S_OK)
      return AVIERR_COMPRESSOR;

    /* update AVISTREAMINFO structure */
    This->sInfo.rcFrame.right  =
      This->sInfo.rcFrame.left + This->lpbiOutput->biWidth;
    This->sInfo.rcFrame.bottom =
      This->sInfo.rcFrame.top  + This->lpbiOutput->biHeight;

    /* prepare codec for compression */
    if (ICCompressBegin(This->hic, This->lpbiInput, This->lpbiOutput) != S_OK)
      return AVIERR_COMPRESSOR;

    /* allocate memory for compressed frame */
    size = ICCompressGetSize(This->hic, This->lpbiInput, This->lpbiOutput);
    This->lpbiCur = HeapAlloc(GetProcessHeap(), 0, This->cbOutput + size);
    if (This->lpbiCur == NULL)
      return AVIERR_MEMORY;
    memcpy(This->lpbiCur, This->lpbiOutput, This->cbOutput);
    This->lpCur = DIBPTR(This->lpbiCur);

    /* allocate memory for last frame if needed */
    if (This->lKeyFrameEvery != 1 &&
	(This->dwICMFlags & VIDCF_FASTTEMPORALC) == 0) {
      size = ICDecompressGetFormatSize(This->hic, This->lpbiOutput);
      This->lpbiPrev = HeapAlloc(GetProcessHeap(), 0, size);
      if (This->lpbiPrev == NULL)
	return AVIERR_MEMORY;
      if (ICDecompressGetFormat(This->hic, This->lpbiOutput, This->lpbiPrev) < S_OK)
	return AVIERR_COMPRESSOR;

      if (This->lpbiPrev->biSizeImage == 0) {
	This->lpbiPrev->biSizeImage =
	  DIBWIDTHBYTES(*This->lpbiPrev) * This->lpbiPrev->biHeight;
      }

      /* get memory for format and picture */
      size += This->lpbiPrev->biSizeImage;
      This->lpbiPrev = HeapReAlloc(GetProcessHeap(), 0, This->lpbiPrev, size);
      if (This->lpbiPrev == NULL)
	return AVIERR_MEMORY;
      This->lpPrev = DIBPTR(This->lpbiPrev);

      /* prepare codec also for decompression */
      if (ICDecompressBegin(This->hic,This->lpbiOutput,This->lpbiPrev) != S_OK)
	return AVIERR_COMPRESSOR;
    }
  } else {
    /* format change -- check that's only the palette */
    LPBITMAPINFOHEADER lpbi = format;

    if (lpbi->biSize != This->lpbiInput->biSize ||
	lpbi->biWidth != This->lpbiInput->biWidth ||
	lpbi->biHeight != This->lpbiInput->biHeight ||
	lpbi->biBitCount != This->lpbiInput->biBitCount ||
	lpbi->biPlanes != This->lpbiInput->biPlanes ||
	lpbi->biCompression != This->lpbiInput->biCompression ||
	lpbi->biClrUsed != This->lpbiInput->biClrUsed)
      return AVIERR_UNSUPPORTED;

    /* get new output format */
    if (ICCompressGetFormat(This->hic, lpbi, This->lpbiOutput) < S_OK)
      return AVIERR_BADFORMAT;

    /* restart compression */
    ICCompressEnd(This->hic);
    if (ICCompressBegin(This->hic, lpbi, This->lpbiOutput) != S_OK)
      return AVIERR_COMPRESSOR;

    /* check if we need to restart decompression also */
    if (This->lKeyFrameEvery != 1 &&
	(This->dwICMFlags & VIDCF_FASTTEMPORALC) == 0) {
      ICDecompressEnd(This->hic);
      if (ICDecompressGetFormat(This->hic,This->lpbiOutput,This->lpbiPrev) < S_OK)
	return AVIERR_COMPRESSOR;
      if (ICDecompressBegin(This->hic,This->lpbiOutput,This->lpbiPrev) != S_OK)
	return AVIERR_COMPRESSOR;
    }
  }

  /* tell nested stream the new format */
  return IAVIStream_SetFormat(This->pStream, pos,
			      This->lpbiOutput, This->cbOutput);
}

static HRESULT WINAPI ICMStream_fnRead(IAVIStream *iface, LONG start,
					LONG samples, LPVOID buffer,
					LONG buffersize, LPLONG bytesread,
					LPLONG samplesread)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  LPBITMAPINFOHEADER lpbi;

  TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer,
 	buffersize, bytesread, samplesread);

  /* clear return parameters if given */
  if (bytesread != NULL)
    *bytesread = 0;
  if (samplesread != NULL)
    *samplesread = 0;

  if (samples == 0)
    return AVIERR_OK;

  /* check parameters */
  if (samples != 1 && (bytesread == NULL && samplesread == NULL))
    return AVIERR_BADPARAM;
  if (samples == -1) /* read as much as we could */
    samples = 1;

  if (This->pg == NULL) {
    HRESULT hr = AVIFILE_OpenGetFrame(This);

    if (FAILED(hr))
      return hr;
  }

  /* compress or decompress? */
  if (This->hic == NULL) {
    /* decompress */
    lpbi = AVIStreamGetFrame(This->pg, start);
    if (lpbi == NULL)
      return AVIERR_MEMORY;

    if (buffer != NULL && buffersize > 0) {
      /* check buffersize */
      if (buffersize < lpbi->biSizeImage)
	return AVIERR_BUFFERTOOSMALL;

      memcpy(buffer, DIBPTR(lpbi), lpbi->biSizeImage);
    }

    /* fill out return parameters if given */
    if (bytesread != NULL)
      *bytesread = lpbi->biSizeImage;
  } else {
    /* compress */
    if (This->lCurrent > start)
      AVIFILE_Reset(This);

    while (start > This->lCurrent) {
      HRESULT hr;

      lpbi = AVIStreamGetFrame(This->pg, ++This->lCurrent);
      if (lpbi == NULL) {
	AVIFILE_Reset(This);
	return AVIERR_MEMORY;
      }

      hr = AVIFILE_EncodeFrame(This, lpbi, DIBPTR(lpbi));
      if (FAILED(hr)) {
	AVIFILE_Reset(This);
	return hr;
      }
    }

    if (buffer != NULL && buffersize > 0) {
      /* check buffersize */
      if (This->lpbiCur->biSizeImage > buffersize)
	return AVIERR_BUFFERTOOSMALL;

      memcpy(buffer, This->lpCur, This->lpbiCur->biSizeImage);
    }

    /* fill out return parameters if given */
    if (bytesread != NULL)
      *bytesread = This->lpbiCur->biSizeImage;
  }

  /* fill out return parameters if given */
  if (samplesread != NULL)
    *samplesread = 1;

  return AVIERR_OK;
}

static HRESULT WINAPI ICMStream_fnWrite(IAVIStream *iface, LONG start,
					 LONG samples, LPVOID buffer,
					 LONG buffersize, DWORD flags,
					 LPLONG sampwritten,
					 LPLONG byteswritten)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  HRESULT hr;

  TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface, start, samples,
	buffer, buffersize, flags, sampwritten, byteswritten);

  /* clear return parameters if given */
  if (sampwritten != NULL)
    *sampwritten = 0;
  if (byteswritten != NULL)
    *byteswritten = 0;

  /* check parameters */
  if (buffer == NULL && (buffersize > 0 || samples > 0))
    return AVIERR_BADPARAM;

  if (This->sInfo.fccHandler == comptypeDIB) {
    /* only pass through */
    flags |= AVIIF_KEYFRAME;

    return IAVIStream_Write(This->pStream, start, samples, buffer, buffersize,
			    flags, sampwritten, byteswritten);
  } else {
    /* compress data before writing to pStream */
    if (samples != 1 && (sampwritten == NULL && byteswritten == NULL))
      return AVIERR_UNSUPPORTED;

    This->lCurrent = start;
    hr = AVIFILE_EncodeFrame(This, This->lpbiInput, buffer);
    if (FAILED(hr))
      return hr;

    if (This->lLastKey == start)
      flags |= AVIIF_KEYFRAME;

    return IAVIStream_Write(This->pStream, start, samples, This->lpCur,
			    This->lpbiCur->biSizeImage, flags, byteswritten,
			    sampwritten);
  }
}

static HRESULT WINAPI ICMStream_fnDelete(IAVIStream *iface, LONG start,
					  LONG samples)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  TRACE("(%p,%d,%d)\n", iface, start, samples);

  return IAVIStream_Delete(This->pStream, start, samples);
}

static HRESULT WINAPI ICMStream_fnReadData(IAVIStream *iface, DWORD fcc,
					    LPVOID lp, LPLONG lpread)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  TRACE("(%p,0x%08X,%p,%p)\n", iface, fcc, lp, lpread);

  assert(This->pStream != NULL);

  return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
}

static HRESULT WINAPI ICMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
					     LPVOID lp, LONG size)
{
  IAVIStreamImpl *This = impl_from_IAVIStream(iface);

  TRACE("(%p,0x%08x,%p,%d)\n", iface, fcc, lp, size);

  assert(This->pStream != NULL);

  return IAVIStream_WriteData(This->pStream, fcc, lp, size);
}

static HRESULT WINAPI ICMStream_fnSetInfo(IAVIStream *iface,
					   LPAVISTREAMINFOW info, LONG infolen)
{
  FIXME("(%p,%p,%d): stub\n", iface, info, infolen);

  return E_FAIL;
}

static const struct IAVIStreamVtbl iicmst = {
  ICMStream_fnQueryInterface,
  ICMStream_fnAddRef,
  ICMStream_fnRelease,
  ICMStream_fnCreate,
  ICMStream_fnInfo,
  ICMStream_fnFindSample,
  ICMStream_fnReadFormat,
  ICMStream_fnSetFormat,
  ICMStream_fnRead,
  ICMStream_fnWrite,
  ICMStream_fnDelete,
  ICMStream_fnReadData,
  ICMStream_fnWriteData,
  ICMStream_fnSetInfo
};

HRESULT AVIFILE_CreateICMStream(REFIID riid, LPVOID *ppv)
{
  IAVIStreamImpl *pstream;
  HRESULT         hr;

  assert(riid != NULL && ppv != NULL);

  *ppv = NULL;

  pstream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAVIStreamImpl));
  if (pstream == NULL)
    return AVIERR_MEMORY;

  pstream->IAVIStream_iface.lpVtbl = &iicmst;
  AVIFILE_Reset(pstream);

  hr = IAVIStream_QueryInterface(&pstream->IAVIStream_iface, riid, ppv);
  if (FAILED(hr))
    HeapFree(GetProcessHeap(), 0, pstream);

  return hr;
}

/***********************************************************************/

static HRESULT AVIFILE_EncodeFrame(IAVIStreamImpl *This,
				   LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
{
  DWORD dwMinQual, dwMaxQual, dwCurQual;
  DWORD dwRequest;
  DWORD icmFlags = 0;
  DWORD idxFlags = 0;
  BOOL  bDecreasedQual = FALSE;
  BOOL  doSizeCheck;
  BOOL  noPrev;

  /* make lKeyFrameEvery and at start a keyframe */
  if ((This->lKeyFrameEvery != 0 &&
       (This->lCurrent - This->lLastKey) >= This->lKeyFrameEvery) ||
      This->lCurrent == This->sInfo.dwStart) {
    idxFlags = AVIIF_KEYFRAME;
    icmFlags = ICCOMPRESS_KEYFRAME;
  }

  if (This->lKeyFrameEvery != 0) {
    if (This->lCurrent == This->sInfo.dwStart) {
      if (idxFlags & AVIIF_KEYFRAME) {
	/* for keyframes allow to consume all unused bytes */
	dwRequest = This->dwBytesPerFrame + This->dwUnusedBytes;
	This->dwUnusedBytes = 0;
      } else {
	/* for non-keyframes only allow something of the unused bytes to be consumed */
	DWORD tmp1 = 0;
	DWORD tmp2;

	if (This->dwBytesPerFrame >= This->dwUnusedBytes)
	  tmp1 = This->dwBytesPerFrame / This->lKeyFrameEvery;
	tmp2 = (This->dwUnusedBytes + tmp1) / This->lKeyFrameEvery;

	dwRequest = This->dwBytesPerFrame - tmp1 + tmp2;
	This->dwUnusedBytes -= tmp2;
      }
    } else
      dwRequest = MAX_FRAMESIZE;
  } else {
    /* only one keyframe at start desired */
    if (This->lCurrent == This->sInfo.dwStart) {
      dwRequest = This->dwBytesPerFrame + This->dwUnusedBytes;
      This->dwUnusedBytes = 0;
    } else
      dwRequest = MAX_FRAMESIZE;
  }

  /* must we check for framesize to gain requested
   * datarate or could we trust codec? */
  doSizeCheck = (dwRequest != 0 && ((This->dwICMFlags & (VIDCF_CRUNCH|VIDCF_QUALITY)) == 0));

  dwMaxQual = dwCurQual = This->sInfo.dwQuality;
  dwMinQual = ICQUALITY_LOW;

  noPrev = TRUE;
  if ((icmFlags & ICCOMPRESS_KEYFRAME) == 0 && 
      (This->dwICMFlags & VIDCF_FASTTEMPORALC) == 0)
    noPrev = FALSE;

  do {
    DWORD   idxCkid = 0;
    DWORD   res;

    res = ICCompress(This->hic,icmFlags,This->lpbiCur,This->lpCur,lpbi,lpBits,
		     &idxCkid, &idxFlags, This->lCurrent, dwRequest, dwCurQual,
		     noPrev ? NULL:This->lpbiPrev, noPrev ? NULL:This->lpPrev);
    if (res == ICERR_NEWPALETTE) {
      FIXME(": codec has changed palette -- unhandled!\n");
    } else if (res != ICERR_OK)
      return AVIERR_COMPRESSOR;

    /* need to check for framesize */
    if (! doSizeCheck)
      break;

    if (dwRequest >= This->lpbiCur->biSizeImage) {
      /* frame is smaller -- try to maximize quality */
      if (dwMaxQual - dwCurQual > 10) {
	DWORD tmp = dwRequest / 8;

	if (tmp < MAX_FRAMESIZE_DIFF)
	  tmp = MAX_FRAMESIZE_DIFF;

	if (tmp < dwRequest - This->lpbiCur->biSizeImage && bDecreasedQual) {
	  tmp = dwCurQual;
	  dwCurQual = (dwMinQual + dwMaxQual) / 2;
	  dwMinQual = tmp;
	  continue;
	}
      } else
	break;
    } else if (dwMaxQual - dwMinQual <= 1) {
      break;
    } else {
      dwMaxQual = dwCurQual;

      if (bDecreasedQual || dwCurQual == This->dwLastQuality)
	dwCurQual = (dwMinQual + dwMaxQual) / 2;
      else
	FIXME(": no new quality computed min=%u cur=%u max=%u last=%u\n",
	      dwMinQual, dwCurQual, dwMaxQual, This->dwLastQuality);

      bDecreasedQual = TRUE;
    }
  } while (TRUE);

  /* remember some values */
  This->dwLastQuality = dwCurQual;
  This->dwUnusedBytes = dwRequest - This->lpbiCur->biSizeImage;
  if (icmFlags & ICCOMPRESS_KEYFRAME)
    This->lLastKey = This->lCurrent;

  /* Does we manage previous frame? */
  if (This->lpPrev != NULL && This->lKeyFrameEvery != 1)
    ICDecompress(This->hic, 0, This->lpbiCur, This->lpCur,
		 This->lpbiPrev, This->lpPrev);

  return AVIERR_OK;
}

static HRESULT AVIFILE_OpenGetFrame(IAVIStreamImpl *This)
{
  LPBITMAPINFOHEADER lpbi;
  DWORD              size;

  /* pre-conditions */
  assert(This != NULL);
  assert(This->pStream != NULL);
  assert(This->pg == NULL);

  This->pg = AVIStreamGetFrameOpen(This->pStream, NULL);
  if (This->pg == NULL)
    return AVIERR_ERROR;

  /* When we only decompress this is enough */
  if (This->sInfo.fccHandler == comptypeDIB)
    return AVIERR_OK;

  assert(This->hic != NULL);
  assert(This->lpbiOutput == NULL);

  /* get input format */
  lpbi = AVIStreamGetFrame(This->pg, This->sInfo.dwStart);
  if (lpbi == NULL)
    return AVIERR_MEMORY;

  /* get memory for output format */
  size = ICCompressGetFormatSize(This->hic, lpbi);
  if ((LONG)size < (LONG)sizeof(BITMAPINFOHEADER))
    return AVIERR_COMPRESSOR;
  This->lpbiOutput = HeapAlloc(GetProcessHeap(), 0, size);
  if (This->lpbiOutput == NULL)
    return AVIERR_MEMORY;
  This->cbOutput = size;

  if (ICCompressGetFormat(This->hic, lpbi, This->lpbiOutput) < S_OK)
    return AVIERR_BADFORMAT;

  /* update AVISTREAMINFO structure */
  This->sInfo.rcFrame.right  =
    This->sInfo.rcFrame.left + This->lpbiOutput->biWidth;
  This->sInfo.rcFrame.bottom =
    This->sInfo.rcFrame.top  + This->lpbiOutput->biHeight;
  This->sInfo.dwSuggestedBufferSize =
    ICCompressGetSize(This->hic, lpbi, This->lpbiOutput);

  /* prepare codec for compression */
  if (ICCompressBegin(This->hic, lpbi, This->lpbiOutput) != S_OK)
    return AVIERR_COMPRESSOR;

  /* allocate memory for current frame */
  size += This->sInfo.dwSuggestedBufferSize;
  This->lpbiCur = HeapAlloc(GetProcessHeap(), 0, size);
  if (This->lpbiCur == NULL)
    return AVIERR_MEMORY;
  memcpy(This->lpbiCur, This->lpbiOutput, This->cbOutput);
  This->lpCur = DIBPTR(This->lpbiCur);

  /* allocate memory for last frame if needed */
  if (This->lKeyFrameEvery != 1 &&
      (This->dwICMFlags & VIDCF_FASTTEMPORALC) == 0) {
    size = ICDecompressGetFormatSize(This->hic, This->lpbiOutput);
    This->lpbiPrev = HeapAlloc(GetProcessHeap(), 0, size);
    if (This->lpbiPrev == NULL)
      return AVIERR_MEMORY;
    if (ICDecompressGetFormat(This->hic, This->lpbiOutput, This->lpbiPrev) < S_OK)
      return AVIERR_COMPRESSOR;

    if (This->lpbiPrev->biSizeImage == 0) {
      This->lpbiPrev->biSizeImage =
	DIBWIDTHBYTES(*This->lpbiPrev) * This->lpbiPrev->biHeight;
    }

    /* get memory for format and picture */
    size += This->lpbiPrev->biSizeImage;
    This->lpbiPrev = HeapReAlloc(GetProcessHeap(), 0, This->lpbiPrev, size );
    if (This->lpbiPrev == NULL)
      return AVIERR_MEMORY;
    This->lpPrev = DIBPTR(This->lpbiPrev);

    /* prepare codec also for decompression */
    if (ICDecompressBegin(This->hic,This->lpbiOutput,This->lpbiPrev) != S_OK)
      return AVIERR_COMPRESSOR;
  }

  return AVIERR_OK;
}
