/*
 * 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_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 to 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;
}
