static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This) { HRESULT hr; /* pre-conditions */ assert(This != NULL); assert(This->pStream != NULL); if (This->has != NULL) return AVIERR_OK; if (This->lpInFormat == NULL) { /* decode or encode the data from pStream */ hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat); if (FAILED(hr)) return hr; This->lpInFormat = HeapAlloc(GetProcessHeap(), 0, This->cbInFormat); if (This->lpInFormat == NULL) return AVIERR_MEMORY; hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart, This->lpInFormat, &This->cbInFormat); if (FAILED(hr)) return hr; if (This->lpOutFormat == NULL) { /* we must decode to default format */ This->cbOutFormat = sizeof(PCMWAVEFORMAT); This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat); if (This->lpOutFormat == NULL) return AVIERR_MEMORY; This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM; if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat, This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK) return AVIERR_NOCOMPRESSOR; } } else if (This->lpOutFormat == NULL) return AVIERR_ERROR; /* To what should I encode? */ if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK) return AVIERR_NOCOMPRESSOR; /* update AVISTREAMINFO structure */ This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign; This->sInfo.dwScale = This->lpOutFormat->nBlockAlign; This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec; This->sInfo.dwQuality = (DWORD)ICQUALITY_DEFAULT; SetRectEmpty(&This->sInfo.rcFrame); /* convert positions and sizes to output format */ CONVERT_STREAM_to_THIS(&This->sInfo.dwStart); CONVERT_STREAM_to_THIS(&This->sInfo.dwLength); CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize); return AVIERR_OK; }
static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos, LPVOID format,LONG*fmtsize) { IAVIEditStreamImpl *This = impl_from_IAVIStream( iface ); LPBITMAPINFOHEADER lp; PAVISTREAM stream; DWORD n; HRESULT hr; TRACE("(%p,%d,%p,%p)\n",iface,pos,format,fmtsize); if (fmtsize == NULL || pos < This->sInfo.dwStart || This->sInfo.dwStart + This->sInfo.dwLength <= pos) return AVIERR_BADPARAM; /* find stream corresponding to position */ hr = AVIFILE_FindStreamInTable(This, pos, &stream, &n, NULL, FALSE); if (FAILED(hr)) return hr; if (! This->bDecompress) return IAVIStream_ReadFormat(stream, n, format, fmtsize); lp = AVIFILE_ReadFrame(This, stream, n); if (lp == NULL) return AVIERR_ERROR; if (lp->biBitCount <= 8) { n = (lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount); n *= sizeof(RGBQUAD); } else n = 0; n += lp->biSize; memcpy(format, lp, min((LONG)n, *fmtsize)); hr = ((LONG)n > *fmtsize ? AVIERR_BUFFERTOOSMALL : AVIERR_OK); *fmtsize = n; return hr; }
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; } }
static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame *iface, LONG lPos) { IGetFrameImpl *This = impl_from_IGetFrame(iface); LONG readBytes; LONG readSamples; TRACE("(%p,%d)\n", iface, lPos); /* We don't want negative start values! -- marks invalid buffer content */ if (lPos < 0) return NULL; /* check state */ if (This->pStream == NULL) return NULL; if (This->lpInFormat == NULL) return NULL; /* Could stream have changed? */ if (! This->bFixedStream) { AVISTREAMINFOW sInfo; IAVIStream_Info(This->pStream, &sInfo, sizeof(sInfo)); if (sInfo.dwEditCount != This->dwEditCount) { This->dwEditCount = sInfo.dwEditCount; This->lCurrentFrame = -1; } if (sInfo.dwFormatChangeCount != This->dwFormatChangeCount) { /* stream has changed */ if (This->lpOutFormat != NULL) { BITMAPINFOHEADER bi; bi = *This->lpOutFormat; AVIFILE_CloseCompressor(This); if (FAILED(IGetFrame_SetFormat(iface, &bi, NULL, 0, 0, -1, -1))) { if (FAILED(IGetFrame_SetFormat(iface, NULL, NULL, 0, 0, -1, -1))) return NULL; } } else if (FAILED(IGetFrame_SetFormat(iface, NULL, NULL, 0, 0, -1, -1))) return NULL; } } if (lPos != This->lCurrentFrame) { LONG lNext = IAVIStream_FindSample(This->pStream,lPos,FIND_KEY|FIND_PREV); if (lNext == -1) return NULL; /* frame doesn't exist */ if (lNext <= This->lCurrentFrame && This->lCurrentFrame < lPos) lNext = This->lCurrentFrame + 1; for (; lNext <= lPos; lNext++) { /* new format for this frame? */ if (This->bFormatChanges) { IAVIStream_ReadFormat(This->pStream, lNext, This->lpInFormat, &This->cbInFormat); if (This->lpOutFormat != NULL) { if (This->lpOutFormat->biBitCount <= 8) ICDecompressGetPalette(This->hic, This->lpInFormat, This->lpOutFormat); } } /* read input frame */ while (FAILED(AVIStreamRead(This->pStream, lNext, 1, This->lpInBuffer, This->cbInBuffer, &readBytes, &readSamples))) { /* not enough memory for input buffer? */ readBytes = 0; if (FAILED(AVIStreamSampleSize(This->pStream, lNext, &readBytes))) return NULL; /* bad thing, but bad things will happen */ if (readBytes <= 0) { ERR(": IAVIStream::Read doesn't return needed bytes!\n"); return NULL; } /* IAVIStream::Read failed because of other reasons not buffersize? */ if (This->cbInBuffer >= readBytes) break; This->cbInBuffer = This->cbInFormat + readBytes; This->lpInFormat = HeapReAlloc(GetProcessHeap(), 0, This->lpInFormat, This->cbInBuffer); if (This->lpInFormat == NULL) return NULL; /* out of memory */ This->lpInBuffer = (BYTE*)This->lpInFormat + This->cbInFormat; } if (readSamples != 1) { ERR(": no frames read\n"); return NULL; } if (readBytes != 0) { This->lpInFormat->biSizeImage = readBytes; /* nothing to decompress? */ if (This->hic == NULL) { This->lCurrentFrame = lPos; return This->lpInFormat; } if (This->bResize) { ICDecompressEx(This->hic,0,This->lpInFormat,This->lpInBuffer,0,0, This->lpInFormat->biWidth,This->lpInFormat->biHeight, This->lpOutFormat,This->lpOutBuffer,This->x,This->y, This->dx,This->dy); } else { ICDecompress(This->hic, 0, This->lpInFormat, This->lpInBuffer, This->lpOutFormat, This->lpOutBuffer); } } } /* for (lNext < lPos) */ } /* if (This->lCurrentFrame != lPos) */ return (This->hic == NULL ? This->lpInFormat : This->lpOutFormat); }