Esempio n. 1
0
static HRESULT WINAPI IGetFrame_fnSetFormat(IGetFrame *iface,
					    LPBITMAPINFOHEADER lpbiWanted,
					    LPVOID lpBits, INT x, INT y,
					    INT dx, INT dy)
{
  IGetFrameImpl *This = impl_from_IGetFrame(iface);

  AVISTREAMINFOW     sInfo;
  LPBITMAPINFOHEADER lpbi         = lpbiWanted;
  BOOL               bBestDisplay = FALSE;

  TRACE("(%p,%p,%p,%d,%d,%d,%d)\n", iface, lpbiWanted, lpBits,
	x, y, dx, dy);

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

  if (lpbiWanted == (LPBITMAPINFOHEADER)AVIGETFRAMEF_BESTDISPLAYFMT) {
    lpbi = NULL;
    bBestDisplay = TRUE;
  }

  IAVIStream_Info(This->pStream, &sInfo, sizeof(sInfo));
  if (sInfo.fccType != streamtypeVIDEO)
    return AVIERR_UNSUPPORTED;

  This->bFormatChanges = (sInfo.dwFlags & AVISTREAMINFO_FORMATCHANGES) != 0;
  This->dwFormatChangeCount = sInfo.dwFormatChangeCount;
  This->dwEditCount         = sInfo.dwEditCount;
  This->lCurrentFrame       = -1;

  /* get input format from stream */
  if (This->lpInFormat == NULL) {
    HRESULT hr;

    This->cbInBuffer = (LONG)sInfo.dwSuggestedBufferSize;
    if (This->cbInBuffer == 0)
      This->cbInBuffer = 1024;

    IAVIStream_ReadFormat(This->pStream, sInfo.dwStart,
			  NULL, &This->cbInFormat);

    This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat + This->cbInBuffer);
    if (This->lpInFormat == NULL) {
      AVIFILE_CloseCompressor(This);
      return AVIERR_MEMORY;
    }

    hr = IAVIStream_ReadFormat(This->pStream, sInfo.dwStart, This->lpInFormat, &This->cbInFormat);
    if (FAILED(hr)) {
      AVIFILE_CloseCompressor(This);
      return hr;
    }

    This->lpInBuffer = ((LPBYTE)This->lpInFormat) + This->cbInFormat;
  }

  /* check input format */
  if (This->lpInFormat->biClrUsed == 0 && This->lpInFormat->biBitCount <= 8)
    This->lpInFormat->biClrUsed = 1u << This->lpInFormat->biBitCount;
  if (This->lpInFormat->biSizeImage == 0 &&
      This->lpInFormat->biCompression == BI_RGB) {
    This->lpInFormat->biSizeImage =
      DIBWIDTHBYTES(*This->lpInFormat) * This->lpInFormat->biHeight;
  }

  /* only to pass through? */
  if (This->lpInFormat->biCompression == BI_RGB && lpBits == NULL) {
    if (lpbi == NULL || 
	(lpbi->biCompression == BI_RGB &&
	 lpbi->biWidth == This->lpInFormat->biWidth &&
	 lpbi->biHeight == This->lpInFormat->biHeight &&
	 lpbi->biBitCount == This->lpInFormat->biBitCount)) {
      This->lpOutFormat = This->lpInFormat;
      This->lpOutBuffer = DIBPTR(This->lpInFormat);
      return AVIERR_OK;
    }
  }

  /* need memory for output format? */
  if (This->lpOutFormat == NULL) {
    This->lpOutFormat =
      HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
    if (This->lpOutFormat == NULL) {
      AVIFILE_CloseCompressor(This);
      return AVIERR_MEMORY;
    }
  }

  /* need handle to video compressor */
  if (This->hic == NULL) {
    FOURCC fccHandler;

    if (This->lpInFormat->biCompression == BI_RGB)
      fccHandler = comptypeDIB;
    else if (This->lpInFormat->biCompression == BI_RLE8)
      fccHandler = mmioFOURCC('R','L','E',' ');
    else
      fccHandler = sInfo.fccHandler;

    if (lpbi != NULL) {
      if (lpbi->biWidth == 0)
	lpbi->biWidth = This->lpInFormat->biWidth;
      if (lpbi->biHeight == 0)
	lpbi->biHeight = This->lpInFormat->biHeight;
    }

    This->hic = ICLocate(ICTYPE_VIDEO, fccHandler, This->lpInFormat, lpbi, ICMODE_DECOMPRESS);
    if (This->hic == NULL) {
      AVIFILE_CloseCompressor(This);
      return AVIERR_NOCOMPRESSOR;
    }
  }

  /* output format given? */
  if (lpbi != NULL) {
    /* check the given output format ... */
    if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8)
      lpbi->biClrUsed = 1u << lpbi->biBitCount;

    /* ... and remember it */
    memcpy(This->lpOutFormat, lpbi,
	   lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD));
    if (lpbi->biBitCount <= 8)
      ICDecompressGetPalette(This->hic, This->lpInFormat, This->lpOutFormat);

    return AVIERR_OK;
  } else {
    if (bBestDisplay) {
      ICGetDisplayFormat(This->hic, This->lpInFormat,
			 This->lpOutFormat, 0, dx, dy);
    } else if (ICDecompressGetFormat(This->hic, This->lpInFormat,
				     This->lpOutFormat) < 0) {
      AVIFILE_CloseCompressor(This);
      return AVIERR_NOCOMPRESSOR;
    }

    /* check output format */
    if (This->lpOutFormat->biClrUsed == 0 &&
	This->lpOutFormat->biBitCount <= 8)
      This->lpOutFormat->biClrUsed = 1u << This->lpOutFormat->biBitCount;
    if (This->lpOutFormat->biSizeImage == 0 &&
	This->lpOutFormat->biCompression == BI_RGB) {
      This->lpOutFormat->biSizeImage =
	DIBWIDTHBYTES(*This->lpOutFormat) * This->lpOutFormat->biHeight;
    }

    if (lpBits == NULL) {
      DWORD size = This->lpOutFormat->biClrUsed * sizeof(RGBQUAD);

      size += This->lpOutFormat->biSize + This->lpOutFormat->biSizeImage;
      This->lpOutFormat = HeapReAlloc(GetProcessHeap(), 0, This->lpOutFormat, size);
      if (This->lpOutFormat == NULL) {
	AVIFILE_CloseCompressor(This);
	return AVIERR_MEMORY;
      }
      This->lpOutBuffer = DIBPTR(This->lpOutFormat);
    } else
      This->lpOutBuffer = lpBits;

    /* for user size was irrelevant */
    if (dx == -1)
      dx = This->lpOutFormat->biWidth;
    if (dy == -1)
      dy = This->lpOutFormat->biHeight;

    /* need to resize? */
    if (x != 0 || y != 0) {
      if (dy == This->lpOutFormat->biHeight &&
	  dx == This->lpOutFormat->biWidth)
	This->bResize = FALSE;
      else
	This->bResize = TRUE;
    }

    if (This->bResize) {
      This->x  = x;
      This->y  = y;
      This->dx = dx;
      This->dy = dy;

      if (ICDecompressExBegin(This->hic,0,This->lpInFormat,This->lpInBuffer,0,
			      0,This->lpInFormat->biWidth,
			      This->lpInFormat->biHeight,This->lpOutFormat,
			      This->lpOutBuffer, x, y, dx, dy) == ICERR_OK)
	return AVIERR_OK;
    } else if (ICDecompressBegin(This->hic, This->lpInFormat,
				 This->lpOutFormat) == ICERR_OK)
      return AVIERR_OK;

    AVIFILE_CloseCompressor(This);

    return AVIERR_COMPRESSOR;
  }
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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);
}