double MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) { void* pBitmapData; LPBITMAPINFO pBitmapInfo; if (!hDC || !wma->inbih) return 0; TRACE("Painting frame %u (cached %u)\n", wma->dwCurrVideoFrame, wma->dwCachedFrame); if (wma->dwCurrVideoFrame != wma->dwCachedFrame) { if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset) return 0; if (wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize) { mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET); mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize); wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize; if (wma->hic && ICDecompress(wma->hic, 0, wma->inbih, wma->indata, wma->outbih, wma->outdata) != ICERR_OK) { WARN("Decompression error\n"); return 0; } } wma->dwCachedFrame = wma->dwCurrVideoFrame; } if (wma->hic) { pBitmapData = wma->outdata; pBitmapInfo = (LPBITMAPINFO)wma->outbih; } else { pBitmapData = wma->indata; pBitmapInfo = (LPBITMAPINFO)wma->inbih; } StretchDIBits(hDC, wma->dest.left, wma->dest.top, wma->dest.right - wma->dest.left, wma->dest.bottom - wma->dest.top, wma->source.left, wma->source.top, wma->source.right - wma->source.left, wma->source.bottom - wma->source.top, pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY); return (wma->ash_video.dwScale / (double)wma->ash_video.dwRate) * 1000000; }
// decode a frame static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ vd_vfw_ctx *priv = sh->context; mp_image_t* mpi; HRESULT ret; if(len<=0) return NULL; // skipped frame mpi=mpcodecs_get_image(sh, (sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_STATIC) ? MP_IMGTYPE_STATIC : MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_WIDTH, sh->disp_w, sh->disp_h); if(!mpi){ // temporary! mp_msg(MSGT_DECVIDEO,MSGL_WARN,MSGTR_MPCODECS_CouldntAllocateImageForCinepakCodec); return NULL; } // set stride: (trick discovered by Andreas Ackermann - thanx!) sh->bih->biWidth=mpi->width; //mpi->stride[0]/(mpi->bpp/8); priv->o_bih->biWidth=mpi->width; //mpi->stride[0]/(mpi->bpp/8); sh->bih->biSizeImage = len; #ifdef BUILD_VFWEX ret = ICDecompressEx(priv->handle, #else ret = ICDecompress(priv->handle, #endif ( (sh->ds->flags&1) ? 0 : ICDECOMPRESS_NOTKEYFRAME ) | ( ((flags&3)==2 && !(sh->ds->flags&1))?(ICDECOMPRESS_HURRYUP|ICDECOMPRESS_PREROL):0 ), sh->bih, data, priv->o_bih, (flags&3) ? 0 : mpi->planes[0]); if ((int)ret){ mp_msg(MSGT_DECVIDEO,MSGL_WARN,"Error decompressing frame, err=%ld\n",ret); return NULL; } // export palette: if(mpi->imgfmt==IMGFMT_RGB8 || mpi->imgfmt==IMGFMT_BGR8){ if (priv->palette) { mpi->planes[1] = priv->palette; mpi->flags |= MP_IMGFLAG_RGB_PALETTE; mp_dbg(MSGT_DECVIDEO, MSGL_DBG2, "Found and copied palette\n"); } else mpi->planes[1]=NULL; } return mpi; }
void decodeFrame() { LONG a,b; HRESULT hr; hr = AVIStreamRead(stream,lastSample,1,indata,bihEncoded.biSizeImage,&a,&b); if(hr != 0) err("error in AVIStreamRead: hresult: %d",hr); if(b != 1) err("error in AVIStreamRead: did not read 1 frame, as instructed"); hr = ICDecompress(hIC,0,&bihEncoded,indata,&bihDecoded,outdata); if(hr != 0) err("error in ICDecompress: hresult: %d",hr); bDirty = true; }
// Function name : PASCAL VideoCallbackProc // Description : Encode the captured frame // Return type : LRESULT FAR // Argument : HWND hWnd // Argument : LPVIDEOHDR lpVHdr LRESULT FAR PASCAL VideoCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr) { unsigned char *bufi, *buf; int type=0; int quant=0; int declen=0; int enclen=0; bufi = new unsigned char[lpVHdr->dwBytesUsed+40]; //original image buf = new unsigned char[lpVHdr->dwBytesUsed]; //coded stream memcpy((void *)(bufi), lpVHdr->lpData, lpVHdr->dwBytesUsed); unsigned char *buf1; buf1 = buf; if (m_vfwState==ENCDEC) { //Encode buf1 = (unsigned char*)ICSeqCompressFrame(&pc,0,bufi, &IsKeyFrame,&FrameSize); //enc_main(bufi, buf, (int *)&FrameSize, &IsKeyFrame, -1); //////////////////////////////// if (bSaveAVI){ AVIStreamSetFormat(pMainFrame->ps,pMainFrame->m_Frame++,lpbiTmp,sizeof(BITMAPINFO)); AVIStreamWrite(pMainFrame->ps,pMainFrame->m_Frame, 1, (LPBYTE)buf1, lpbiTmp->bmiHeader.biSizeImage,AVIIF_KEYFRAME,NULL,NULL); } //////////////////////////////// //Decode ICDecompress(hic2,0,&lpbiTmp->bmiHeader,buf1,&lpbiOut->bmiHeader,&bufo[40]); } else { enc_main(bufi,buf, &IsKeyFrame,&type,&quant,&enclen); declen = dec_main(buf, bufi, enclen,lpbiIn->bmiHeader.biWidth); pMainFrame->conv.YV12_to_RGB24(bufi, bufi+(lpbiIn->bmiHeader.biWidth*lpbiIn->bmiHeader.biHeight), bufi+(lpbiIn->bmiHeader.biWidth*lpbiIn->bmiHeader.biHeight*5/4), &bufo[40], lpbiIn->bmiHeader.biWidth, lpbiIn->bmiHeader.biHeight); } pMainFrame->GetActiveView()->InvalidateRect(NULL,FALSE); delete bufi; delete buf; return (LRESULT) TRUE; }
static HRESULT WINAPI AVIDec_Receive(TransformFilter *tf, IMediaSample *pSample) { AVIDecImpl* This = (AVIDecImpl *)tf; AM_MEDIA_TYPE amt; HRESULT hr; DWORD res; IMediaSample* pOutSample = NULL; DWORD cbDstStream; LPBYTE pbDstStream; DWORD cbSrcStream; LPBYTE pbSrcStream; LONGLONG tStart, tStop; DWORD flags = 0; EnterCriticalSection(&This->tf.csReceive); hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); goto error; } cbSrcStream = IMediaSample_GetActualDataLength(pSample); TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); goto error; } /* Update input size to match sample size */ This->pBihIn->biSizeImage = cbSrcStream; hr = BaseOutputPinImpl_GetDeliveryBuffer((BaseOutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%x)\n", hr); goto error; } hr = IMediaSample_SetActualDataLength(pOutSample, 0); assert(hr == S_OK); hr = IMediaSample_GetPointer(pOutSample, &pbDstStream); if (FAILED(hr)) { ERR("Unable to get pointer to buffer (%x)\n", hr); goto error; } cbDstStream = IMediaSample_GetSize(pOutSample); if (cbDstStream < This->pBihOut->biSizeImage) { ERR("Sample size is too small %d < %d\n", cbDstStream, This->pBihOut->biSizeImage); hr = E_FAIL; goto error; } if (IMediaSample_IsPreroll(pSample) == S_OK) flags |= ICDECOMPRESS_PREROLL; if (IMediaSample_IsSyncPoint(pSample) != S_OK) flags |= ICDECOMPRESS_NOTKEYFRAME; hr = IMediaSample_GetTime(pSample, &tStart, &tStop); if (hr == S_OK && AVIDec_DropSample(This, tStart)) flags |= ICDECOMPRESS_HURRYUP; res = ICDecompress(This->hvid, flags, This->pBihIn, pbSrcStream, This->pBihOut, pbDstStream); if (res != ICERR_OK) ERR("Error occurred during the decompression (%x)\n", res); /* Drop sample if its intended to be dropped */ if (flags & ICDECOMPRESS_HURRYUP) { hr = S_OK; goto error; } IMediaSample_SetActualDataLength(pOutSample, This->pBihOut->biSizeImage); IMediaSample_SetPreroll(pOutSample, (IMediaSample_IsPreroll(pSample) == S_OK)); IMediaSample_SetDiscontinuity(pOutSample, (IMediaSample_IsDiscontinuity(pSample) == S_OK)); IMediaSample_SetSyncPoint(pOutSample, (IMediaSample_IsSyncPoint(pSample) == S_OK)); if (hr == S_OK) IMediaSample_SetTime(pOutSample, &tStart, &tStop); else if (hr == VFW_S_NO_STOP_TIME) IMediaSample_SetTime(pOutSample, &tStart, NULL); else IMediaSample_SetTime(pOutSample, NULL, NULL); if (IMediaSample_GetMediaTime(pSample, &tStart, &tStop) == S_OK) IMediaSample_SetMediaTime(pOutSample, &tStart, &tStop); else IMediaSample_SetMediaTime(pOutSample, NULL, NULL); LeaveCriticalSection(&This->tf.csReceive); hr = BaseOutputPinImpl_Deliver((BaseOutputPin*)This->tf.ppPins[1], pOutSample); EnterCriticalSection(&This->tf.csReceive); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) ERR("Error sending sample (%x)\n", hr); error: if (pOutSample) IMediaSample_Release(pOutSample); LeaveCriticalSection(&This->tf.csReceive); return hr; }
static int vfw_decompress_frame(LBXGL_VidCodecCTX *ctx, void *src, void *dst, int ssz, int dsz) { vfw_ctxinfo *info; int err, i, j, k, ib, ob; byte *sbuf, *tbuf; info=ctx->data; info->ihead->biSizeImage=ssz; info->ohead->biSizeImage=dsz; // memset(dst, 255, info->ohead->biWidth*info->ohead->biHeight*4); #ifdef CATCH_BLOCK_SEH __try { #endif i=(!dst)?ICDECOMPRESS_PREROLL:0; //frame skip // i=ICDECOMPRESS_NOTKEYFRAME; // err=ICDecompress(info->hicd, 0, info->ihead, src, info->ohead, dst); err=ICDecompress(info->hicd, i, info->ihead, src, info->ohead, info->buffer); #ifdef CATCH_BLOCK_SEH } __except(EXCEPTION_EXECUTE_HANDLER) { printf("RECAUGHT VFW\n"); return(-1); } #endif if(dst) { sbuf=info->buffer; tbuf=dst; j=info->ohead->biHeight; if(j<0)j=-j; j=info->ohead->biWidth*j; k=info->ohead->biBitCount/8; if(k==3)LBXGL_ConvBGR2RGB(sbuf, tbuf, j); if(k==4)LBXGL_ConvBGRA2RGBA(sbuf, tbuf, j); } #if 0 j=info->ohead->biHeight; if(j<0)j=-j; j=info->ohead->biWidth*j; k=info->ohead->biBitCount/8; for(i=0; i<j; i++) { tbuf[0]=sbuf[2]; tbuf[1]=sbuf[1]; tbuf[2]=sbuf[0]; tbuf[3]=255; sbuf+=k; tbuf+=k; } #endif #if 0 k=info->ohead->biBitCount/8; for(i=0; i<info->ohead->biHeight; i++) { ib=((info->ohead->biHeight-i-1)*info->ohead->biWidth)*k; ob=(i*info->ohead->biWidth)*k; for(j=0; j<info->ohead->biWidth; j++) { tbuf[ob+0]=sbuf[ib+2]; tbuf[ob+1]=sbuf[ib+1]; tbuf[ob+2]=sbuf[ib+0]; if(k==4)tbuf[ob+3]=255; ib+=k; ob+=k; } } #endif if(err!=ICERR_OK)printf("VFW: decompress %d\n", err); if(err!=ICERR_OK)return(-1); return(0); }
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 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); }
LRESULT CALLBACK cap_stream_cb(HWND hwnd, VIDEOHDR *pframe) { cap_cx *cx; void *temp = NULL; int iskeyframe; size_t datalen; void *pdata; size_t outdatalen; void *poutdata; int width; int height; size_t rgblen; void *prgb; int quein; char message[256]; DWORD decodetime; if(!(cx = cap_assoc_get(hwnd))) return TRUE; if(cx->started) { /* * Get captured frame */ pdata = pframe->lpData; datalen = (size_t)(pframe->dwBytesUsed); iskeyframe = pframe->dwFlags & VHDR_KEYFRAME; width = cx->pfmt->bmiHeader.biWidth; height = cx->pfmt->bmiHeader.biHeight; //start decoding frame time decodetime = GetTickCount(); /* * Use VCM decompressor */ if(cx->mode == CAP_USE_IC) { // alloc buffer for decompressed frame outdatalen = cx->poutfmt->bmiHeader.biSizeImage; if(!(poutdata = malloc(outdatalen))) { return TRUE; } // decompress frame if(ICDecompress( cx->ic, iskeyframe ? 0 : ICDECOMPRESS_NOTKEYFRAME, &(cx->pfmt->bmiHeader), pdata, &(cx->poutfmt->bmiHeader), poutdata) != ICERR_OK) { free(poutdata); return TRUE; } // to dealloc temp = poutdata; // get decompressed frame pdata = poutdata; datalen = outdatalen; width = cx->poutfmt->bmiHeader.biWidth; height = cx->poutfmt->bmiHeader.biHeight; } /* * Use pixel decoder */ if( (cx->mode == CAP_USE_PIXDEC) || (cx->mode == CAP_USE_IC) ) { // alloc buffer rgblen = width*height*3; if(!(prgb = malloc(rgblen))) { free(temp); return TRUE; } // decode frame if(!cx->pix_func(prgb, pdata, width, height)) { free(prgb); free(temp); return TRUE; } // dealloc encoded frame buffer free(temp); } /* * Use JPEG decompressor */ if(cx->mode == CAP_USE_JPEG) { if(!(prgb = jpeg_decompress(pdata, datalen, &width, &height))) { return TRUE; } } //output statistics decodetime = GetTickCount() - decodetime; sprintf(message, "Frame decode time = %d ms, input length = %d, output length = %d\n", decodetime, pframe->dwBytesUsed, rgblen); OutputDebugString(message); /* * Put frame in buffer */ // check buffer have free slot if((quein = (cx->que_in + 1) % CAP_QUE) == cx->que_out) { OutputDebugString("Capture buffer overflow\n"); free(prgb); return TRUE; } // put frame to free slot cx->que[cx->que_in].rgb = prgb; cx->que[cx->que_in].width = width; cx->que[cx->que_in].height = height; cx->que[cx->que_in].length = rgblen; cx->que_in = quein; } return TRUE; }
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; }
/********************************************************************** * DrawDibDraw [MSVFW32.@] */ BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc, INT xDst, INT yDst, INT dxDst, INT dyDst, LPBITMAPINFOHEADER lpbi, LPVOID lpBits, INT xSrc, INT ySrc, INT dxSrc, INT dySrc, UINT wFlags) { WINE_HDD *whdd; BOOL ret = TRUE; TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08x)\n", hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags); whdd = MSVIDEO_GetHddPtr(hdd); if (!whdd) return FALSE; TRACE("whdd=%p\n", whdd); if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW | DDF_BACKGROUNDPAL)) FIXME("wFlags == 0x%08x not handled\n", wFlags); if (!lpBits) { /* Undocumented? */ lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD)); } #define CHANGED(x) (whdd->x != x) if ((!whdd->begun) || (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) || (!(wFlags & DDF_SAME_DRAW) && (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst)))) { TRACE("Something changed!\n"); ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0); if (!ret) return ret; } #undef CHANGED if ((dxDst == -1) && (dyDst == -1)) { dxDst = dxSrc; dyDst = dySrc; } if (!(wFlags & DDF_UPDATE)) { if (lpbi->biCompression) { DWORD flags = 0; TRACE("Compression == 0x%08x\n", lpbi->biCompression); if (wFlags & DDF_NOTKEYFRAME) flags |= ICDECOMPRESS_NOTKEYFRAME; ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits); } else { /* BI_RGB: lpbi->biSizeImage isn't reliable */ DWORD biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight; memcpy(whdd->lpvbits, lpBits, biSizeImage); } } if (!(wFlags & DDF_DONTDRAW) && whdd->hpal) { if ((wFlags & DDF_BACKGROUNDPAL) && ! (wFlags & DDF_SAME_HDC)) SelectPalette(hdc, whdd->hpal, TRUE); else SelectPalette(hdc, whdd->hpal, FALSE); } if (!(StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY))) ret = FALSE; return ret; }
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 AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) { AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; AM_MEDIA_TYPE amt; HRESULT hr; DWORD res; IMediaSample* pOutSample = NULL; DWORD cbDstStream; LPBYTE pbDstStream; DWORD cbSrcStream; LPBYTE pbSrcStream; LONGLONG tStart, tStop; EnterCriticalSection(&This->tf.csFilter); if (This->tf.state == State_Stopped) { LeaveCriticalSection(&This->tf.csFilter); return VFW_E_WRONG_STATE; } if (pin->end_of_stream || pin->flushing) { LeaveCriticalSection(&This->tf.csFilter); return S_FALSE; } hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); goto error; } cbSrcStream = IMediaSample_GetActualDataLength(pSample); TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); goto error; } /* Update input size to match sample size */ This->pBihIn->biSizeImage = cbSrcStream; hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%x)\n", hr); goto error; } hr = IMediaSample_SetActualDataLength(pOutSample, 0); assert(hr == S_OK); hr = IMediaSample_GetPointer(pOutSample, &pbDstStream); if (FAILED(hr)) { ERR("Unable to get pointer to buffer (%x)\n", hr); goto error; } cbDstStream = IMediaSample_GetSize(pOutSample); if (cbDstStream < This->pBihOut->biSizeImage) { ERR("Sample size is too small %d < %d\n", cbDstStream, This->pBihOut->biSizeImage); hr = E_FAIL; goto error; } res = ICDecompress(This->hvid, 0, This->pBihIn, pbSrcStream, This->pBihOut, pbDstStream); if (res != ICERR_OK) ERR("Error occurred during the decompression (%x)\n", res); IMediaSample_SetActualDataLength(pOutSample, This->pBihOut->biSizeImage); IMediaSample_SetPreroll(pOutSample, (IMediaSample_IsPreroll(pSample) == S_OK)); IMediaSample_SetDiscontinuity(pOutSample, (IMediaSample_IsDiscontinuity(pSample) == S_OK)); IMediaSample_SetSyncPoint(pOutSample, (IMediaSample_IsSyncPoint(pSample) == S_OK)); if (IMediaSample_GetTime(pSample, &tStart, &tStop) == S_OK) IMediaSample_SetTime(pOutSample, &tStart, &tStop); else IMediaSample_SetTime(pOutSample, NULL, NULL); LeaveCriticalSection(&This->tf.csFilter); hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) ERR("Error sending sample (%x)\n", hr); IMediaSample_Release(pOutSample); return hr; error: if (pOutSample) IMediaSample_Release(pOutSample); LeaveCriticalSection(&This->tf.csFilter); return hr; }
/********************************************************************** * DrawDibDraw [MSVFW32.@] */ BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc, INT xDst, INT yDst, INT dxDst, INT dyDst, LPBITMAPINFOHEADER lpbi, LPVOID lpBits, INT xSrc, INT ySrc, INT dxSrc, INT dySrc, UINT wFlags) { WINE_HDD *whdd; BOOL ret; int reopen = 0; TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08x)\n", hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags); whdd = MSVIDEO_GetHddPtr(hdd); if (!whdd) return FALSE; TRACE("whdd=%p\n", whdd); if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW | DDF_BACKGROUNDPAL)) FIXME("wFlags == 0x%08x not handled\n", wFlags); if (!lpBits) { /* Undocumented? */ lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD)); } #define CHANGED(x) (whdd->x != x) /* Check if anything changed from the parameters passed and our struct. * If anything changed we need to run DrawDibBegin again to ensure we * can support the changes. */ if (!whdd->begun) reopen = 1; else if (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) reopen = 2; else if (!(wFlags & DDF_SAME_DRAW)) { if (CHANGED(lpbi) && memcmp(lpbi, whdd->lpbi, sizeof(*lpbi))) reopen = 3; else if (CHANGED(dxSrc)) reopen = 4; else if (CHANGED(dySrc)) reopen = 5; else if (CHANGED(dxDst)) reopen = 6; else if (CHANGED(dyDst)) reopen = 7; } if (reopen) { TRACE("Something changed (reason %d)!\n", reopen); ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0); if (!ret) return ret; } #undef CHANGED /* If source dimensions are not specified derive them from bitmap header */ if (dxSrc == -1 && dySrc == -1) { dxSrc = lpbi->biWidth; dySrc = lpbi->biHeight; } /* If destination dimensions are not specified derive them from source */ if (dxDst == -1 && dyDst == -1) { dxDst = dxSrc; dyDst = dySrc; } if (!(wFlags & DDF_UPDATE)) { if (lpbi->biCompression) { DWORD flags = 0; TRACE("Compression == 0x%08x\n", lpbi->biCompression); if (wFlags & DDF_NOTKEYFRAME) flags |= ICDECOMPRESS_NOTKEYFRAME; ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits); } else { /* BI_RGB: lpbi->biSizeImage isn't reliable */ DWORD biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight; memcpy(whdd->lpvbits, lpBits, biSizeImage); } } if (!(wFlags & DDF_DONTDRAW) && whdd->hpal) { if ((wFlags & DDF_BACKGROUNDPAL) && ! (wFlags & DDF_SAME_HDC)) SelectPalette(hdc, whdd->hpal, TRUE); else SelectPalette(hdc, whdd->hpal, FALSE); } ret = StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY); TRACE("Painting %dx%d at %d,%d from %dx%d at %d,%d -> %d\n", dxDst, dyDst, xDst, yDst, dxSrc, dySrc, xSrc, ySrc, ret); return ret; }
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; }
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; }
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; }