int cap_ic_start(cap_cx *cx, char *err) { char format[32]; char message[80]; if((cx->ic = ICDecompressOpen( ICTYPE_VIDEO, 0, &(cx->pfmt->bmiHeader), NULL))) { cx->outfmtlen = ICDecompressGetFormatSize(cx->ic, cx->pfmt); if((cx->poutfmt = malloc(cx->outfmtlen))) { if(ICDecompressGetFormat(cx->ic, cx->pfmt, cx->poutfmt) == ICERR_OK) { if(ICDecompressBegin(cx->ic, cx->pfmt, cx->poutfmt) == ICERR_OK) { cx->mode = CAP_USE_IC; return 1; } } free(cx->poutfmt); } ICClose(cx->ic); } sprintf(message, "Can't open decompressor for format \"%s\"", reverse_fourcc(format, cx->pfmt->bmiHeader.biCompression)); set_err(message); return 0; }
/* 对捕获的视频做编码、解码处理 */ void CMainFrame::OnVfwCodec() { // TODO: 在此添加命令处理程序代码 DWORD fsize; /* VCM initialization */ hic1 = ICOpen(mmioFOURCC('v','i','d','c'), mmioFOURCC('X','V','I','D'), ICMODE_COMPRESS); if (hic1 == 0) AfxMessageBox(_T("打开编码器失败!")); hic2 = ICOpen(mmioFOURCC('v','i','d','c'), mmioFOURCC('X','V','I','D'), ICMODE_DECOMPRESS); if (hic2 == 0) AfxMessageBox(_T("打开解码器失败!")); fsize = capGetVideoFormatSize(m_hWndCap); capGetVideoFormat(m_hWndCap, lpbiIn, fsize); InitAVIWriteOpt(); lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); lpbiOut->bmiHeader.biWidth = lpbiIn->bmiHeader.biWidth; lpbiOut->bmiHeader.biHeight = lpbiIn->bmiHeader.biHeight; lpbiOut->bmiHeader.biPlanes = 1; lpbiOut->bmiHeader.biBitCount = 24; lpbiOut->bmiHeader.biCompression = BI_RGB; lpbiOut->bmiHeader.biSizeImage = lpbiIn->bmiHeader.biWidth*lpbiIn->bmiHeader.biHeight*3; lpbiOut->bmiHeader.biXPelsPerMeter = 0; lpbiOut->bmiHeader.biYPelsPerMeter = 0; lpbiOut->bmiHeader.biClrUsed = 0; lpbiOut->bmiHeader.biClrImportant = 0; // get the format of the input video if (ICCompressGetFormat(hic1,lpbiIn,lpbiTmp)!=ICERR_OK) AfxMessageBox(_T("编码器不能读取输出格式!")); if (ICCompressQuery(hic1,lpbiIn,lpbiTmp) != ICERR_OK) AfxMessageBox(_T("不能处理编码器输入输出格式!")); // set the parameters of the CODEC pc.cbSize = sizeof(COMPVARS); //结构体大小 pc.dwFlags = ICMF_COMPVARS_VALID; pc.hic = hic1; //编码器句柄 pc.fccType = mmioFOURCC('v','i','d','c'); pc.fccHandler = mmioFOURCC('X','V','I','D'); pc.lpbiOut = lpbiTmp; //输出格式 pc.lKey = 100; //key帧频率 pc.lQ = 10000; //图像质量 if(!ICSeqCompressFrameStart(&pc, lpbiIn)) return; ICDecompressBegin(hic2,lpbiTmp,lpbiOut); m_vfwState = ENCDEC; }
static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter) { AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; DWORD result; TRACE("(%p)->()\n", This); result = ICDecompressBegin(This->hvid, This->pBihIn, This->pBihOut); if (result != ICERR_OK) { ERR("Cannot start processing (%d)\n", result); return E_FAIL; } return S_OK; }
static HRESULT WINAPI AVIDec_StartStreaming(TransformFilter* pTransformFilter) { AVIDecImpl* This = impl_from_TransformFilter(pTransformFilter); DWORD result; TRACE("(%p)->()\n", This); This->late = -1; result = ICDecompressBegin(This->hvid, This->pBihIn, This->pBihOut); if (result != ICERR_OK) { ERR("Cannot start processing (%d)\n", result); return E_FAIL; } return S_OK; }
IplImage* CvCaptureCAM_VFW::retrieveFrame(int) { BITMAPINFO vfmt; memset( &vfmt, 0, sizeof(vfmt)); BITMAPINFOHEADER& vfmt0 = vfmt.bmiHeader; if( !capWnd ) return 0; const DWORD sz = capGetVideoFormat( capWnd, &vfmt, sizeof(vfmt)); const int prevWidth = frame ? frame->width : 0; const int prevHeight = frame ? frame->height : 0; if( !hdr || hdr->lpData == 0 || sz == 0 ) return 0; if( !frame || frame->width != vfmt0.biWidth || frame->height != vfmt0.biHeight ) { cvReleaseImage( &frame ); frame = cvCreateImage( cvSize( vfmt0.biWidth, vfmt0.biHeight ), 8, 3 ); } if ( vfmt0.biCompression == MAKEFOURCC('N','V','1','2') ) { // Frame is in YUV 4:2:0 NV12 format, convert to BGR color space // See https://msdn.microsoft.com/en-us/library/windows/desktop/dd206750(v=vs.85).aspx#nv12) IplImage src; cvInitImageHeader( &src, cvSize( vfmt0.biWidth, vfmt0.biHeight * 3 / 2 ), IPL_DEPTH_8U, 1, IPL_ORIGIN_BL, 4 ); cvSetData( &src, hdr->lpData, src.widthStep ); cvCvtColor( &src, frame, CV_YUV2BGR_NV12 ); } else if( vfmt0.biCompression != BI_RGB || vfmt0.biBitCount != 24 ) { BITMAPINFOHEADER vfmt1 = icvBitmapHeader( vfmt0.biWidth, vfmt0.biHeight, 24 ); if( hic == 0 || fourcc != vfmt0.biCompression || prevWidth != vfmt0.biWidth || prevHeight != vfmt0.biHeight ) { closeHIC(); hic = ICOpen( MAKEFOURCC('V','I','D','C'), vfmt0.biCompression, ICMODE_DECOMPRESS ); if( hic ) { if( ICDecompressBegin( hic, &vfmt0, &vfmt1 ) != ICERR_OK ) { closeHIC(); return 0; } } } if( !hic || ICDecompress( hic, 0, &vfmt0, hdr->lpData, &vfmt1, frame->imageData ) != ICERR_OK ) { closeHIC(); return 0; } cvFlip( frame, frame, 0 ); } else { IplImage src; cvInitImageHeader( &src, cvSize(vfmt0.biWidth, vfmt0.biHeight), IPL_DEPTH_8U, 3, IPL_ORIGIN_BL, 4 ); cvSetData( &src, hdr->lpData, src.widthStep ); cvFlip( &src, frame, 0 ); } return frame; }
/*********************************************************************** * DrawDibBegin [MSVFW32.@] */ BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd, HDC hdc, INT dxDst, INT dyDst, LPBITMAPINFOHEADER lpbi, INT dxSrc, INT dySrc, UINT wFlags) { BOOL ret = TRUE; WINE_HDD *whdd; TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08x)\n", hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, wFlags); TRACE("lpbi: %d,%d/%d,%d,%d,%d,%d,%d,%d,%d,%d\n", lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes, lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage, lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed, lpbi->biClrImportant); if (wFlags & ~(DDF_BUFFER)) FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER)); whdd = MSVIDEO_GetHddPtr(hdd); if (!whdd) return FALSE; if (whdd->begun) DrawDibEnd(hdd); if (lpbi->biCompression) { DWORD size = 0; whdd->hic = ICOpen(ICTYPE_VIDEO, lpbi->biCompression, ICMODE_DECOMPRESS); if (!whdd->hic) { WARN("Could not open IC. biCompression == 0x%08x\n", lpbi->biCompression); ret = FALSE; } if (ret) { size = ICDecompressGetFormat(whdd->hic, lpbi, NULL); if (size == ICERR_UNSUPPORTED) { WARN("Codec doesn't support GetFormat, giving up.\n"); ret = FALSE; } } if (ret) { whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, size); if (ICDecompressGetFormat(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK) ret = FALSE; } if (ret) { /* FIXME: Use Ex functions if available? */ if (ICDecompressBegin(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK) ret = FALSE; TRACE("biSizeImage == %d\n", whdd->lpbiOut->biSizeImage); TRACE("biCompression == %d\n", whdd->lpbiOut->biCompression); TRACE("biBitCount == %d\n", whdd->lpbiOut->biBitCount); } } else { DWORD dwSize; /* No compression */ TRACE("Not compressed!\n"); if (lpbi->biHeight <= 0) { /* we don't draw inverted DIBs */ TRACE("detected inverted DIB\n"); ret = FALSE; } else { dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD); whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, dwSize); memcpy(whdd->lpbiOut, lpbi, dwSize); } } if (ret) { /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/ whdd->hMemDC = CreateCompatibleDC(hdc); TRACE("Creating: %d, %p\n", whdd->lpbiOut->biSize, whdd->lpvbits); whdd->hDib = CreateDIBSection(whdd->hMemDC, (BITMAPINFO *)whdd->lpbiOut, DIB_RGB_COLORS, &(whdd->lpvbits), 0, 0); if (whdd->hDib) { TRACE("Created: %p,%p\n", whdd->hDib, whdd->lpvbits); } else { ret = FALSE; TRACE("Error: %d\n", GetLastError()); } whdd->hOldDib = SelectObject(whdd->hMemDC, whdd->hDib); } if (ret) { whdd->hdc = hdc; whdd->dxDst = dxDst; whdd->dyDst = dyDst; whdd->lpbi = HeapAlloc(GetProcessHeap(), 0, lpbi->biSize); memcpy(whdd->lpbi, lpbi, lpbi->biSize); whdd->dxSrc = dxSrc; whdd->dySrc = dySrc; whdd->begun = TRUE; whdd->hpal = 0; } else { if (whdd->hic) ICClose(whdd->hic); HeapFree(GetProcessHeap(), 0, whdd->lpbiOut); whdd->lpbiOut = NULL; } return ret; }
// init driver static int init(sh_video_t *sh){ HRESULT ret; // unsigned int outfmt=sh->codec->outfmt[sh->outfmtidx]; int i, o_bih_len; vd_vfw_ctx *priv; const char *dll = codec_idx2str(sh->codec->dll_idx); /* Hack for VSSH codec: new dll can't decode old files * In my samples old files have no extradata, so use that info * to decide what dll should be used (here and in vd_dshow). */ if (!strcmp(dll, "vssh264.dll") && (sh->bih->biSize > 40)) return 0; priv = malloc(sizeof(vd_vfw_ctx)); if (!priv) return 0; memset(priv, 0, sizeof(vd_vfw_ctx)); sh->context = priv; mp_msg(MSGT_WIN32,MSGL_V,"======= Win32 (VFW) VIDEO Codec init =======\n"); // win32_codec_name = dll; // sh->hic = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_FASTDECOMPRESS); // priv->handle = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_DECOMPRESS); priv->handle = ICOpen( (long)(dll), sh->bih->biCompression, ICMODE_DECOMPRESS); if(!priv->handle){ mp_msg(MSGT_WIN32,MSGL_ERR,"ICOpen failed! unknown codec / wrong parameters?\n"); return 0; } // sh->bih->biBitCount=32; o_bih_len = ICDecompressGetFormatSize(priv->handle, sh->bih); if(o_bih_len < sizeof(BITMAPINFOHEADER)){ mp_msg(MSGT_WIN32,MSGL_ERR,"ICDecompressGetFormatSize returned a bogus value: %d\n", o_bih_len); return 0; } priv->o_bih = malloc(o_bih_len); memset(priv->o_bih, 0, o_bih_len); mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetFormatSize ret: %d\n", o_bih_len); ret = ICDecompressGetFormat(priv->handle, sh->bih, priv->o_bih); if(ret < 0){ mp_msg(MSGT_WIN32,MSGL_ERR,"ICDecompressGetFormat failed: Error %d\n", (int)ret); for (i=0; i < o_bih_len; i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02x ", priv->o_bih[i]); return 0; } mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetFormat OK\n"); #if 0 // workaround for pegasus MJPEG: if(!sh_video->o_bih.biWidth) sh_video->o_bih.biWidth=sh_video->bih->biWidth; if(!sh_video->o_bih.biHeight) sh_video->o_bih.biHeight=sh_video->bih->biHeight; if(!sh_video->o_bih.biPlanes) sh_video->o_bih.biPlanes=sh_video->bih->biPlanes; #endif // ok let libvo and vd core to handshake and decide the optimal csp: if(!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YUY2)) return 0; if (!(sh->codec->outflags[sh->outfmtidx]&CODECS_FLAG_FLIP)) { priv->o_bih->biHeight=-sh->bih->biHeight; // flip image! } // ok, let's set the choosen colorspace: set_csp(priv->o_bih,sh->codec->outfmt[sh->outfmtidx]); // fake it to RGB for broken DLLs (divx3) if(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK) priv->o_bih->biCompression = 0; // sanity check: #ifdef BUILD_VFWEX ret = ICDecompressQueryEx(priv->handle, sh->bih, priv->o_bih); #else ret = ICDecompressQuery(priv->handle, sh->bih, priv->o_bih); #endif if (ret) { mp_msg(MSGT_WIN32,MSGL_WARN,"ICDecompressQuery failed: Error %d\n", (int)ret); // return 0; } else mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressQuery OK\n"); #ifdef BUILD_VFWEX ret = ICDecompressBeginEx(priv->handle, sh->bih, priv->o_bih); #else ret = ICDecompressBegin(priv->handle, sh->bih, priv->o_bih); #endif if (ret) { mp_msg(MSGT_WIN32,MSGL_WARN,"ICDecompressBegin failed: Error %d\n", (int)ret); // return 0; } // for broken codecs set it again: if(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK) set_csp(priv->o_bih,sh->codec->outfmt[sh->outfmtidx]); mp_msg(MSGT_WIN32, MSGL_V, "Input format:\n"); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh->bih,MSGL_V); mp_msg(MSGT_WIN32, MSGL_V, "Output format:\n"); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(priv->o_bih,MSGL_V); // set postprocessing level in xvid/divx4 .dll ICSendMessage(priv->handle, ICM_USER+80, (long)(&divx_quality), 0); // don't do this palette mess always, it makes div3 dll crashing... if(sh->codec->outfmt[sh->outfmtidx]==IMGFMT_BGR8){ if(ICDecompressGetPalette(priv->handle, sh->bih, priv->o_bih)){ priv->palette = (unsigned char*)(priv->o_bih+1); mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetPalette OK\n"); } else { if(sh->bih->biSize>=40+4*4) priv->palette = (unsigned char*)(sh->bih+1); } } mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: Win32 video codec init OK!\n"); return 1; }
static LBXGL_VidCodecCTX *vfw_begin_decompress(int fcc, PDGL_BMPInfoHeader *in, PDGL_BMPInfoHeader *out) { LBXGL_VidCodecCTX *ctx; vfw_ctxinfo *info; int err; ctx=LBXGL_VidCodecCTX_New(); info=gcalloc(sizeof(vfw_ctxinfo)); ctx->data=info; info->ihead=malloc(sizeof(BITMAPINFOHEADER)); memset(info->ihead, 0, sizeof(BITMAPINFOHEADER)); info->ihead->biSize = sizeof(BITMAPINFOHEADER); info->ihead->biWidth = in->biWidth; info->ihead->biHeight = in->biHeight; info->ihead->biPlanes = in->biPlanes; info->ihead->biBitCount = in->biBitCount; info->ihead->biCompression = in->biCompression; info->ihead->biSizeImage = in->biWidth*in->biHeight*in->biBitCount/8; info->ohead=malloc(sizeof(BITMAPINFOHEADER)); memset(info->ohead, 0, sizeof(BITMAPINFOHEADER)); info->ohead->biSize = sizeof(BITMAPINFOHEADER); info->ohead->biWidth = out->biWidth; // info->ohead->biHeight = -out->biHeight; info->ohead->biHeight = out->biHeight; info->ohead->biPlanes = out->biPlanes; info->ohead->biBitCount = out->biBitCount; info->ohead->biCompression = out->biCompression; info->ihead->biSizeImage = out->biWidth*out->biHeight*out->biBitCount/8; info->buffer=malloc(out->biWidth*out->biHeight*out->biBitCount/8); // info->hicd = ICOpen(ICTYPE_VIDEO, fcc, ICMODE_FASTDECOMPRESS); info->hicd = ICLocate(ICTYPE_VIDEO, fcc, info->ihead, info->ohead, ICMODE_FASTDECOMPRESS); if(!info->hicd) { printf("VFW: decompress %0.4s %0.4s: fail\n", &fcc, &in->biCompression); return(NULL); } printf("VFW: decompress %0.4s %0.4s: ok\n", &fcc, &in->biCompression); err=ICDecompressBegin(info->hicd, info->ihead, info->ohead); if(err) { printf("VFW: err %d, %0.4s %0.4s: fail\n", err, &fcc, &in->biCompression); return(NULL); } vfw_hicd[vfw_n_hicd++]=info->hicd; ctx->decompress_frame=&vfw_decompress_frame; return(ctx); }
std::shared_ptr<WatermarkSearchResult> WatermarkSearchWorker::findWatermark(int width, int height) { std::shared_ptr<WatermarkSearchResult> r = std::make_shared<WatermarkSearchResult>(); r->size_.width_ = width; r->size_.height_ = height; int const bytesPerPixel = 4; int const scanlineSizeInBytes = width * bytesPerPixel; BITMAPINFOHEADER inputFormat; ZeroMemory(&inputFormat, sizeof(inputFormat)); inputFormat.biSize = sizeof(inputFormat); inputFormat.biWidth = width; inputFormat.biHeight = height; inputFormat.biPlanes = 1; inputFormat.biBitCount = 8 * bytesPerPixel; inputFormat.biCompression = BI_RGB; inputFormat.biSizeImage = scanlineSizeInBytes * height; DWORD const size = ICCompressGetFormatSize(compressor_, &inputFormat); if (size == 0 || (size & 0xFFFF0000) == 0xFFFF0000) { return r; } std::vector<uint8_t> outputFormatStorage(size); LPBITMAPINFOHEADER outputFormat = (LPBITMAPINFOHEADER)(BITMAPINFO*)outputFormatStorage.data(); if (ICCompressGetFormat(compressor_, &inputFormat, outputFormat) != ICERR_OK) { return r; } DWORD const outputSize = ICCompressGetSize(compressor_, &inputFormat, outputFormat); if (outputSize < 0) { return r; } if (outputBuffer_.size() < outputSize) { outputBuffer_.resize(outputSize); } if (inputBuffer_.size() < inputFormat.biSizeImage) { inputBuffer_.resize(inputFormat.biSizeImage); } std::fill(inputBuffer_.begin(), inputBuffer_.begin() + inputFormat.biSizeImage, (uint8_t)0xff); if (ICCompressBegin(compressor_, &inputFormat, outputFormat) != ICERR_OK) { return r; } DWORD flags = 0; DWORD dwckid = 0; DWORD result = ICCompress(compressor_, 0, // dwFlags outputFormat, outputBuffer_.data(), &inputFormat, inputBuffer_.data(), &dwckid, &flags, 0, // lpFrameNum 0, // dwFrameSize 0, // dwQuality nullptr, // lpbiPrev nullptr); // lpPrev if (result != ICERR_OK) { return r; } if (ICCompressEnd(compressor_) != ICERR_OK) { return r; } if (ICDecompressBegin(decompressor_, outputFormat, &inputFormat) != ICERR_OK) { return r; } std::fill(inputBuffer_.begin(), inputBuffer_.begin() + inputFormat.biSizeImage, (uint8_t)0xff); if (ICDecompress(decompressor_, 0, outputFormat, outputBuffer_.data(), &inputFormat, inputBuffer_.data()) != ICERR_OK) { return r; } if (ICDecompressEnd(decompressor_) != ICERR_OK) { return r; } // Search left edge of watermark int left = -1; for (int x = 0; x < width; ++x) { bool found = false; for (int y = 0; y < height; ++y) { for (int j = 0; j < bytesPerPixel; ++j) { int index = scanlineSizeInBytes * y + x * bytesPerPixel + j; if (inputBuffer_[index] != (uint8_t)0xff) { found = true; left = x; break; } } if (found) { break; } } if (found) { break; } } if (left < 0) { return r; } // Search right edge of watermark int right = -1; for (int x = width - 1; x >= 0; --x) { bool found = false; for (int y = 0; y < height; ++y) { for (int j = 0; j < bytesPerPixel; ++j) { int index = scanlineSizeInBytes * y + x * bytesPerPixel + j; if (inputBuffer_[index] != (uint8_t)0xff) { found = true; right = x; break; } } if (found) { break; } } if (found) { break; } } if (right < 0) { return r; } // Search top edge of watermark int top = -1; for (int y = 0; y < height; ++y) { bool found = false; for (int x = 0; x < width; ++x) { for (int j = 0; j < bytesPerPixel; ++j) { int index = scanlineSizeInBytes * y + x * bytesPerPixel + j; if (inputBuffer_[index] != (uint8_t)0xff) { found = true; top = y; break; } } if (found) { break; } } if (found) { break; } } if (top < 0) { return r; } // Search bottom edge of watermark int bottom = -1; for (int y = height - 1; y >= 0; --y) { bool found = false; for (int x = 0; x < width; ++x) { for (int j = 0; j < bytesPerPixel; ++j) { int index = scanlineSizeInBytes * y + x * bytesPerPixel + j; if (inputBuffer_[index] != (uint8_t)0xff) { found = true; bottom = y; break; } } if (found) { break; } } if (found) { break; } } if (top < 0) { return r; } r->x_ = left; r->y_ = top; int const watermarkWidth = right - left + 1; int const watermarkHeight = bottom - top + 1; r->width_ = watermarkWidth; r->height_ = watermarkHeight; r->watermark_ = std::make_shared<Bitmap>(watermarkWidth, watermarkHeight); for (int y = 0; y < watermarkHeight; ++y) { for (int x = 0; x < watermarkWidth; ++x) { int index = scanlineSizeInBytes * (y + top) + (x + left) * bytesPerPixel; uint8_t red = inputBuffer_[index]; uint8_t green = inputBuffer_[index + 1]; uint8_t blue = inputBuffer_[index + 2]; r->watermark_->setPixel(x, watermarkHeight - y - 1, Color{ red, green, blue }); } } return r; }
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; } }
IplImage* CvCaptureCAM_VFW::retrieveFrame(int) { BITMAPINFO vfmt; memset( &vfmt, 0, sizeof(vfmt)); BITMAPINFOHEADER& vfmt0 = vfmt.bmiHeader; if( !capWnd ) return 0; const DWORD sz = capGetVideoFormat( capWnd, &vfmt, sizeof(vfmt)); const int prevWidth = frame ? frame->width : 0; const int prevHeight = frame ? frame->height : 0; if( !hdr || hdr->lpData == 0 || sz == 0 ) return 0; if( !frame || frame->width != vfmt0.biWidth || frame->height != vfmt0.biHeight ) { cvReleaseImage( &frame ); frame = cvCreateImage( cvSize( vfmt0.biWidth, vfmt0.biHeight ), 8, 3 ); } if( vfmt0.biCompression != BI_RGB || vfmt0.biBitCount != 24 ) { BITMAPINFOHEADER vfmt1 = icvBitmapHeader( vfmt0.biWidth, vfmt0.biHeight, 24 ); if( hic == 0 || fourcc != vfmt0.biCompression || prevWidth != vfmt0.biWidth || prevHeight != vfmt0.biHeight ) { closeHIC(); hic = ICOpen( MAKEFOURCC('V','I','D','C'), vfmt0.biCompression, ICMODE_DECOMPRESS ); if( hic ) { if( ICDecompressBegin( hic, &vfmt0, &vfmt1 ) != ICERR_OK ) { closeHIC(); return 0; } } } if( !hic || ICDecompress( hic, 0, &vfmt0, hdr->lpData, &vfmt1, frame->imageData ) != ICERR_OK ) { closeHIC(); return 0; } cvFlip( frame, frame, 0 ); } else { IplImage src; cvInitImageHeader( &src, cvSize(vfmt0.biWidth, vfmt0.biHeight), IPL_DEPTH_8U, 3, IPL_ORIGIN_BL, 4 ); cvSetData( &src, hdr->lpData, src.widthStep ); cvFlip( &src, frame, 0 ); } return frame; }
HANDLE VFWAPI ICImageDecompress( HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn, LPVOID lpBits, LPBITMAPINFO lpbiOut) { HGLOBAL hMem = NULL; BYTE* pMem = NULL; BOOL bReleaseIC = FALSE; BYTE* pHdr = NULL; ULONG cbHdr = 0; BOOL bSucceeded = FALSE; BOOL bInDecompress = FALSE; DWORD biSizeImage; TRACE("(%p,%08x,%p,%p,%p)\n", hic, uiFlags, lpbiIn, lpBits, lpbiOut); if ( hic == NULL ) { hic = ICDecompressOpen( ICTYPE_VIDEO, 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL ); if ( hic == NULL ) { WARN("no handler\n" ); goto err; } bReleaseIC = TRUE; } if ( uiFlags != 0 ) { FIXME( "unknown flag %08x\n", uiFlags ); goto err; } if ( lpbiIn == NULL || lpBits == NULL ) { WARN("invalid argument\n"); goto err; } if ( lpbiOut != NULL ) { if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ) goto err; cbHdr = sizeof(BITMAPINFOHEADER); if ( lpbiOut->bmiHeader.biCompression == 3 ) cbHdr += sizeof(DWORD)*3; else if ( lpbiOut->bmiHeader.biBitCount <= 8 ) { if ( lpbiOut->bmiHeader.biClrUsed == 0 ) cbHdr += sizeof(RGBQUAD) * (1<<lpbiOut->bmiHeader.biBitCount); else cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed; } } else { TRACE( "get format\n" ); cbHdr = ICDecompressGetFormatSize(hic,lpbiIn); if ( cbHdr < sizeof(BITMAPINFOHEADER) ) goto err; pHdr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,cbHdr+sizeof(RGBQUAD)*256); if ( pHdr == NULL ) goto err; if ( ICDecompressGetFormat( hic, lpbiIn, pHdr ) != ICERR_OK ) goto err; lpbiOut = (BITMAPINFO*)pHdr; if ( lpbiOut->bmiHeader.biBitCount <= 8 && ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK && lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount ) { if ( lpbiIn->bmiHeader.biClrUsed == 0 ) memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<<lpbiOut->bmiHeader.biBitCount) ); else memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed ); } if ( lpbiOut->bmiHeader.biBitCount <= 8 && lpbiOut->bmiHeader.biClrUsed == 0 ) lpbiOut->bmiHeader.biClrUsed = 1<<lpbiOut->bmiHeader.biBitCount; lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed; } biSizeImage = lpbiOut->bmiHeader.biSizeImage; if ( biSizeImage == 0 ) biSizeImage = ((((lpbiOut->bmiHeader.biWidth * lpbiOut->bmiHeader.biBitCount + 7) >> 3) + 3) & (~3)) * abs(lpbiOut->bmiHeader.biHeight); TRACE( "call ICDecompressBegin\n" ); if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK ) goto err; bInDecompress = TRUE; TRACE( "cbHdr %d, biSizeImage %d\n", cbHdr, biSizeImage ); hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage ); if ( hMem == NULL ) { WARN( "out of memory\n" ); goto err; } pMem = GlobalLock( hMem ); if ( pMem == NULL ) goto err; memcpy( pMem, lpbiOut, cbHdr ); TRACE( "call ICDecompress\n" ); if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK ) goto err; bSucceeded = TRUE; err: if ( bInDecompress ) ICDecompressEnd( hic ); if ( bReleaseIC ) ICClose(hic); HeapFree(GetProcessHeap(),0,pHdr); if ( pMem != NULL ) GlobalUnlock( hMem ); if ( !bSucceeded && hMem != NULL ) { GlobalFree(hMem); hMem = NULL; } return hMem; }
BOOST_DATA_TEST_CASE(vcm_encdec, make_data_from_tuple_container(vecEncDecClips), src, dst, fmt, config, tolerance) { VideoClip srcClip(src); VideoClip dstClip(dst); DWORD fccCodec = FCC(fmt); BOOST_REQUIRE(srcClip.GetWidth() == dstClip.GetWidth()); BOOST_REQUIRE(srcClip.GetHeight() == dstClip.GetHeight()); DWORD fccSrc = srcClip.GetFourCC(); DWORD fccDst = dstClip.GetFourCC(); unsigned int nWidth = srcClip.GetWidth(); unsigned int nHeight = srcClip.GetHeight(); size_t cbSrcData; size_t cbDstData; size_t cbCompressedData; HIC hicEncode, hicDecode; LRESULT lr; union { BITMAPINFOHEADER bihCompressed; char bihCompressedBuf[128]; }; BITMAPINFOHEADER bihSrc; BITMAPINFOHEADER bihDst; hicEncode = ICOpen(ICTYPE_VIDEO, fccCodec, ICMODE_COMPRESS); BOOST_REQUIRE(hicEncode != NULL); ICCloser iccloserEnc(hicEncode); lr = ICSetState(hicEncode, &config.front(), config.size()); BOOST_REQUIRE(lr == config.size()); hicDecode = ICOpen(ICTYPE_VIDEO, fccCodec, ICMODE_DECOMPRESS); BOOST_REQUIRE(hicDecode != NULL); ICCloser iccloserDec(hicDecode); memset(&bihSrc, 0, sizeof(BITMAPINFOHEADER)); bihSrc.biSize = sizeof(BITMAPINFOHEADER); bihSrc.biWidth = nWidth; bihSrc.biHeight = nHeight; bihSrc.biPlanes = 1; bihSrc.biBitCount = FCC2BitCount(fccSrc); bihSrc.biCompression = FCC2Compression(fccSrc); bihSrc.biSizeImage = 10000000; memset(&bihDst, 0, sizeof(BITMAPINFOHEADER)); bihDst.biSize = sizeof(BITMAPINFOHEADER); bihDst.biWidth = nWidth; bihDst.biHeight = nHeight; bihDst.biPlanes = 1; bihDst.biBitCount = FCC2BitCount(fccDst); bihDst.biCompression = FCC2Compression(fccDst); bihDst.biSizeImage = 10000000; lr = ICCompressGetFormat(hicEncode, &bihSrc, &bihCompressed); BOOST_REQUIRE_EQUAL(lr, ICERR_OK); cbCompressedData = ICCompressGetSize(hicEncode, &bihSrc, &bihCompressed); lr = ICCompressBegin(hicEncode, &bihSrc, &bihCompressed); BOOST_REQUIRE_EQUAL(lr, ICERR_OK); lr = ICDecompressBegin(hicDecode, &bihCompressed, &bihDst); BOOST_REQUIRE_EQUAL(lr, ICERR_OK); void *pSrcData; void *pDstData; void *pEncoderOut = malloc(cbCompressedData); void *pDecoderOut = NULL; int retSrc, retDst; LONG lFrameNum = 0; while ((retSrc = srcClip.GetNextFrame(&pSrcData, &cbSrcData, NULL)) == 0 && (retDst = dstClip.GetNextFrame(&pDstData, &cbDstData, NULL) == 0)) { DWORD dwFlags = 0; lr = ICCompress(hicEncode, 0, &bihCompressed, pEncoderOut, &bihSrc, pSrcData, NULL, &dwFlags, lFrameNum++, 0, 0, &bihSrc, NULL); BOOST_REQUIRE(lr == ICERR_OK); if (pDecoderOut == NULL) pDecoderOut = malloc(cbDstData); lr = ICDecompress(hicDecode, (dwFlags & AVIIF_KEYFRAME) ? 0 : ICDECOMPRESS_NOTKEYFRAME, &bihCompressed, pEncoderOut, &bihDst, pDecoderOut); BOOST_REQUIRE(lr == ICERR_OK); BOOST_CHECK(bihDst.biSizeImage == cbDstData); BOOST_CHECK(CompareFrame(pDstData, pDecoderOut, nWidth, cbDstData, fccDst, tolerance) == 0); } BOOST_CHECK(retSrc != 0 && retDst != 0); if (pDecoderOut != NULL) free(pDecoderOut); free(pEncoderOut); lr = ICDecompressEnd(hicDecode); BOOST_CHECK(lr == ICERR_OK); lr = ICCompressEnd(hicEncode); BOOST_CHECK(lr == ICERR_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; }
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); }