bool BitBltFromI420ToI420(int w, int h, BYTE* dsty, BYTE* dstu, BYTE* dstv, int dstpitch, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch) { VDPixmap srcbm = {0}; srcbm.data = srcy; srcbm.pitch = srcpitch; srcbm.w = w; srcbm.h = h; srcbm.format = nsVDPixmap::kPixFormat_YUV420_Planar; srcbm.data2 = srcu; srcbm.pitch2 = srcpitch / 2; srcbm.data3 = srcv; srcbm.pitch3 = srcpitch / 2; VDPixmap dstpxm = {0}; dstpxm.data = dsty; dstpxm.pitch = dstpitch; dstpxm.w = w; dstpxm.h = h; dstpxm.format = nsVDPixmap::kPixFormat_YUV420_Planar; dstpxm.data2 = dstu; dstpxm.pitch2 = dstpitch / 2; dstpxm.data3 = dstv; dstpxm.pitch3 = dstpitch / 2; return VDPixmapBlt(dstpxm, srcbm); }
sint32 VDVideoFilterInput::Run() { mpSource->getFrame(mpContext->mpOutput->mFrameNum); mpContext->AllocFrame(); VDPixmapBlt(*mpContext->mpDstFrame->mpPixmap, mpSource->getTargetFormat()); return kVFVRun_OK; }
bool BitBltFromRGBToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* src, int srcpitch, int sbpp) { VDPixmap srcbm = { (char *)src + srcpitch * (h - 1), NULL, w, h, -srcpitch }; switch(sbpp) { case 8: srcbm.format = nsVDPixmap::kPixFormat_Pal8; break; case 16: srcbm.format = nsVDPixmap::kPixFormat_RGB565; break; case 24: srcbm.format = nsVDPixmap::kPixFormat_RGB888; break; case 32: srcbm.format = nsVDPixmap::kPixFormat_XRGB8888; break; default: VDASSERT(false); } VDPixmap dstpxm = { (char *)dst + dstpitch * (h - 1), NULL, w, h, -dstpitch }; switch(dbpp) { case 8: dstpxm.format = nsVDPixmap::kPixFormat_Pal8; break; case 16: dstpxm.format = nsVDPixmap::kPixFormat_RGB565; break; case 24: dstpxm.format = nsVDPixmap::kPixFormat_RGB888; break; case 32: dstpxm.format = nsVDPixmap::kPixFormat_XRGB8888; break; default: VDASSERT(false); } return VDPixmapBlt(dstpxm, srcbm); }
const void *VDVideoSourceFLM::streamGetFrame(const void *inputBuffer, uint32 data_len, bool is_preroll, VDPosition frame_num, VDPosition target_sample) { VDPixmap srcbm = {0}; srcbm.data = (void *)inputBuffer; srcbm.pitch = mWidth * 4; srcbm.w = mWidth; srcbm.h = mHeight; srcbm.format = nsVDPixmap::kPixFormat_XRGB8888; VDPixmapBlt(mTargetFormat, srcbm); mCachedFrame = frame_num; return getFrameBuffer(); }
void VDVideoDecompressorHuffyuv::DecompressFrame(void *dst, const void *src, uint32 srcSize, bool keyframe, bool preroll) { if (!mFormat) throw MyError("Cannot find compatible target format for video decompression."); mpDecoder->DecompressFrame(src, srcSize); // blit time! VDPixmap pxsrc(mpDecoder->GetFrameBuffer()); VDPixmapLayout dstlayout; VDMakeBitmapCompatiblePixmapLayout(dstlayout, mWidth, mHeight, mFormat, 0); VDPixmap pxdst(VDPixmapFromLayout(dstlayout, dst)); VDPixmapBlt(pxdst, pxsrc); }
LRESULT Frameserver::SessionFrame(LPARAM lParam, WPARAM original_frame) { FrameserverSession *fs = SessionLookup(lParam); if (!fs) return VDSRVERR_BADSESSION; try { const VDPixmapLayout& output = filters.GetOutputLayout(); if (fs->arena_size < ((output.w*3+3)&-4)*output.h) return VDSRVERR_TOOBIG; VDPosition pos = mVideoFrameMap[original_frame].mSourceFrame; if (pos < 0) return VDSRVERR_FAILED; vdrefptr<IVDFilterFrameClientRequest> creq; filters.RequestFrame(pos, 0, ~creq); while(!creq->IsCompleted()) { if (filters.Run(NULL, false) == FilterSystem::kRunResult_Running) continue; switch(mpVideoFrameSource->RunRequests(NULL)) { case IVDFilterFrameSource::kRunResult_Running: case IVDFilterFrameSource::kRunResult_IdleWasActive: case IVDFilterFrameSource::kRunResult_BlockedWasActive: continue; } filters.Block(); } VDPixmap pxdst(VDPixmapFromLayout(mFrameLayout, fs->arena)); VDFilterFrameBuffer *buf = creq->GetResultBuffer(); VDPixmapBlt(pxdst, VDPixmapFromLayout(filters.GetOutputLayout(), (void *)buf->LockRead())); buf->Unlock(); } catch(const MyError&) { return VDSRVERR_FAILED; } return VDSRVERR_OK; }
bool BitBltFromI420ToYUY2(int w, int h, BYTE* dst, int dstpitch, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch) { if (srcpitch == 0) srcpitch = w; #ifndef _WIN64 if ((g_cpuid.m_flags & CCpuID::sse2) && !((DWORD_PTR)srcy&15) && !((DWORD_PTR)srcu&15) && !((DWORD_PTR)srcv&15) && !(srcpitch&31) && !((DWORD_PTR)dst&15) && !(dstpitch&15)) { if (w<=0 || h<=0 || (w&1) || (h&1)) return false; yv12_yuy2_sse2(srcy, srcu, srcv, srcpitch/2, w/2, h, dst, dstpitch); return true; } #endif VDPixmap srcbm = {0}; srcbm.data = srcy; srcbm.pitch = srcpitch; srcbm.w = w; srcbm.h = h; srcbm.format = nsVDPixmap::kPixFormat_YUV420_Planar; srcbm.data2 = srcu; srcbm.pitch2 = srcpitch/2; srcbm.data3 = srcv; srcbm.pitch3 = srcpitch/2; VDPixmap dstpxm = { dst, NULL, w, h, dstpitch }; dstpxm.format = nsVDPixmap::kPixFormat_YUV422_YUYV; return VDPixmapBlt(dstpxm, srcbm); }
bool BitBltFromYUY2ToYUY2(int w, int h, BYTE* dst, int dstpitch, BYTE* src, int srcpitch) { VDPixmap srcbm = {0}; srcbm.data = src; srcbm.pitch = srcpitch; srcbm.w = w; srcbm.h = h; srcbm.format = nsVDPixmap::kPixFormat_YUV422_YUYV; VDPixmap dstpxm = { dst, NULL, w, h, dstpitch }; dstpxm.format = nsVDPixmap::kPixFormat_YUV422_YUYV; return VDPixmapBlt(dstpxm, srcbm); }
bool BitBltFromI420ToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch) { VDPixmap srcbm = {0}; srcbm.data = srcy; srcbm.pitch = srcpitch; srcbm.w = w; srcbm.h = h; srcbm.format = nsVDPixmap::kPixFormat_YUV420_Planar; srcbm.data2 = srcu; srcbm.pitch2 = srcpitch/2; srcbm.data3 = srcv; srcbm.pitch3 = srcpitch/2; VDPixmap dstpxm = { (char *)dst + dstpitch * (h - 1), NULL, w, h, -dstpitch }; switch(dbpp) { case 16: dstpxm.format = nsVDPixmap::kPixFormat_RGB565; break; case 24: dstpxm.format = nsVDPixmap::kPixFormat_RGB888; break; case 32: dstpxm.format = nsVDPixmap::kPixFormat_XRGB8888; break; default: VDASSERT(false); } return VDPixmapBlt(dstpxm, srcbm); }
bool BitBltFromYUY2ToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* src, int srcpitch) { if (srcpitch == 0) srcpitch = w; VDPixmap srcbm = {0}; srcbm.data = src; srcbm.pitch = srcpitch; srcbm.w = w; srcbm.h = h; srcbm.format = nsVDPixmap::kPixFormat_YUV422_YUYV; VDPixmap dstpxm = { (char *)dst + dstpitch * (h - 1), NULL, w, h, -dstpitch }; switch(dbpp) { case 16: dstpxm.format = nsVDPixmap::kPixFormat_RGB565; break; case 24: dstpxm.format = nsVDPixmap::kPixFormat_RGB888; break; case 32: dstpxm.format = nsVDPixmap::kPixFormat_XRGB8888; break; default: VDASSERT(false); } return VDPixmapBlt(dstpxm, srcbm); }
LRESULT Frameserver::SessionFrame(LPARAM lParam, WPARAM original_frame) { FrameserverSession *fs = SessionLookup(lParam); if (!fs) return VDSRVERR_BADSESSION; try { const void *ptr = vSrc->getFrameBuffer(); const BITMAPINFOHEADER *bmih = vSrc->getDecompressedFormat(); VDPosition sample; bool is_preroll; if (fs->arena_size < ((filters.LastBitmap()->w*3+3)&-4)*filters.LastBitmap()->h) return VDSRVERR_TOOBIG; sample = mVideoFrameMap[original_frame].mDisplayFrame; if (sample < 0) return VDSRVERR_FAILED; vSrc->streamSetDesiredFrame(sample); VDPosition targetSample = vSrc->displayToStreamOrder(sample); VDPosition frame = vSrc->streamGetNextRequiredFrame(is_preroll); if (frame >= 0) { do { uint32 lSize; int hr; // _RPT1(0,"feeding frame %ld\n", frame); hr = vSrc->read(frame, 1, NULL, 0x7FFFFFFF, &lSize, NULL); if (hr) return VDSRVERR_FAILED; uint32 bufSize = (lSize + 65535 + vSrc->streamGetDecodePadding()) & ~65535; if (mInputBuffer.size() < bufSize) mInputBuffer.resize(bufSize); hr = vSrc->read(frame, 1, mInputBuffer.data(), lSize, &lSize, NULL); if (hr) return VDSRVERR_FAILED; vSrc->streamFillDecodePadding(mInputBuffer.data(), lSize); ptr = vSrc->streamGetFrame(mInputBuffer.data(), lSize, is_preroll, frame, targetSample); } while(-1 != (frame = vSrc->streamGetNextRequiredFrame(is_preroll))); } else ptr = vSrc->streamGetFrame(NULL, 0, FALSE, targetSample, targetSample); VDPixmap pxdst(VDPixmapFromLayout(mFrameLayout, fs->arena)); if (!g_listFA.IsEmpty()) { VDPixmapBlt(VDAsPixmap(*filters.InputBitmap()), vSrc->getTargetFormat()); fsi.lCurrentFrame = original_frame; fsi.lCurrentSourceFrame = sample; fsi.lSourceFrameMS = MulDiv(fsi.lCurrentSourceFrame, fsi.lMicrosecsPerSrcFrame, 1000); fsi.lDestFrameMS = MulDiv(fsi.lCurrentFrame, fsi.lMicrosecsPerFrame, 1000); filters.RunFilters(fsi); VDPixmapBlt(pxdst, VDAsPixmap(*filters.LastBitmap())); } else VDPixmapBlt(pxdst, vSrc->getTargetFormat()); } catch(const MyError&) { return VDSRVERR_FAILED; } return VDSRVERR_OK; }
const void *VideoSourceImages::streamGetFrame(const void *inputBuffer, uint32 data_len, bool is_preroll, VDPosition frame_num, VDPosition target_sample) { // We may get a zero-byte frame if we already have the image. if (!data_len) return getFrameBuffer(); int w, h; bool bHasAlpha; bool bIsPNG = false; bool bIsJPG = false; bool bIsBMP = false; bool bIsIFF = false; bool bIsTGA = false; bIsPNG = VDDecodePNGHeader(inputBuffer, data_len, w, h, bHasAlpha); if (!bIsPNG) { bIsJPG = VDIsJPEGHeader(inputBuffer, data_len); if (!bIsJPG) { bIsBMP = DecodeBMPHeader(inputBuffer, data_len, w, h, bHasAlpha); if (!bIsBMP) { bIsIFF = VDIsMayaIFFHeader(inputBuffer, data_len); if (!bIsIFF) bIsTGA = DecodeTGAHeader(inputBuffer, data_len, w, h, bHasAlpha); } } } if (!bIsBMP && !bIsTGA && !bIsJPG && !bIsPNG && !bIsIFF) throw MyError("Image file must be in PNG, Windows BMP, truecolor TARGA format, MayaIFF, or sequential JPEG format."); if (bIsJPG) { if (!mpJPEGDecoder) mpJPEGDecoder = VDCreateJPEGDecoder(); mpJPEGDecoder->Begin(inputBuffer, data_len); mpJPEGDecoder->DecodeHeader(w, h); } VDPixmap pxIFF; if (bIsIFF) { if (!mpIFFDecoder) mpIFFDecoder = VDCreateImageDecoderIFF(); pxIFF = mpIFFDecoder->Decode(inputBuffer, data_len); w = pxIFF.w; h = pxIFF.h; } // Check image header. VDAVIBitmapInfoHeader *pFormat = getImageFormat(); if (getFrameBuffer()) { if (w != pFormat->biWidth || h != pFormat->biHeight) { vdfastvector<wchar_t> errBuf; throw MyError("Image \"%ls\" (%dx%d) doesn't match the image dimensions of the first image (%dx%d)." , mpParent->ComputeFilename(errBuf, frame_num), w, h, pFormat->biWidth, pFormat->biHeight); } } else { if (!AllocFrameBuffer(w * h * 4)) throw MyMemoryError(); pFormat->biSize = sizeof(BITMAPINFOHEADER); pFormat->biWidth = w; pFormat->biHeight = h; pFormat->biPlanes = 1; pFormat->biCompression = 0xFFFFFFFFUL; pFormat->biBitCount = 0; pFormat->biSizeImage = 0; pFormat->biXPelsPerMeter = 0; pFormat->biYPelsPerMeter = 0; pFormat->biClrUsed = 0; pFormat->biClrImportant = 0; // special case for initial read in constructor return NULL; } if (bIsJPG) { int format; switch(mvbFrameBuffer.depth) { case 16: format = IVDJPEGDecoder::kFormatXRGB1555; break; case 24: format = IVDJPEGDecoder::kFormatRGB888; break; case 32: format = IVDJPEGDecoder::kFormatXRGB8888; break; } mpJPEGDecoder->DecodeImage((char *)mvbFrameBuffer.data + mvbFrameBuffer.pitch * (mvbFrameBuffer.h - 1), -mvbFrameBuffer.pitch, format); mpJPEGDecoder->End(); } if (bIsIFF) VDPixmapBlt(getTargetFormat(), pxIFF); if (bIsBMP) DecodeBMP(inputBuffer, data_len, mvbFrameBuffer); if (bIsTGA) DecodeTGA(inputBuffer, data_len, mvbFrameBuffer); if (bIsPNG) { if (!mpPNGDecoder) mpPNGDecoder = VDCreateImageDecoderPNG(); PNGDecodeError err = mpPNGDecoder->Decode(inputBuffer, data_len); if (err) { if (err == kPNGDecodeOutOfMemory) throw MyMemoryError(); vdfastvector<wchar_t> errBuf; throw MyError("Error decoding \"%ls\": %ls\n", mpParent->ComputeFilename(errBuf, frame_num), VDLoadString(0, kVDST_PNGDecodeErrors, err)); } VDPixmapBlt(VDAsPixmap(mvbFrameBuffer), mpPNGDecoder->GetFrameBuffer()); } mCachedFrame = frame_num; return mpFrameBuffer; }
void VDTestPixmaps() { CPUEnableExtensions(CPUCheckForExtensions()); VDFastMemcpyAutodetect(); VDRegisterVideoDisplayControl(); HWND hwndDisp = CreateWindow(VIDEODISPLAYCONTROLCLASS, "Kasumi onee-sama", WS_VISIBLE|WS_POPUP, 0, 0, 1024, 768, NULL, NULL, GetModuleHandle(NULL), NULL); IVDVideoDisplay *pDisp = VDGetIVideoDisplay(hwndDisp); const int srcw = 80; const int srch = 60; VDPixmapBuffer image(srcw, srch, nsVDPixmap::kPixFormat_XRGB8888); for(int y=0; y<srch; ++y) { for(int x=0; x<srcw; ++x) { int x2 = x - (srcw>>1); int y2 = y - (srch>>1); uint32 v = (int)((1.0 + sin((x2*x2 + y2*y2) / 50.0)) * 255.0 / 2.0 + 0.5); uint32 r = (255-v)<<16; if ((x^y)&1) v = r = 0; ((uint32 *)((char *)image.data + image.pitch * y))[x] = (v*x/srcw) + (((v*y)/srch)<<8) + r; } } VDPixmapBuffer sprite(srcw, srch, nsVDPixmap::kPixFormat_XRGB8888); VDPixmapBuffer buffer(1024, 768, nsVDPixmap::kPixFormat_XRGB8888); VDPixmapBlt(sprite, image); pDisp->SetSourcePersistent(true, buffer); bouncer p1(-64, -48, 1024+64, 768+48, 1.0); bouncer p2(-64, -48, 1024+64, 768+48, 0.5); sint64 freq; QueryPerformanceFrequency((LARGE_INTEGER *)&freq); sint64 start; QueryPerformanceCounter((LARGE_INTEGER *)&start); int blits = 0; double th = 0; VDPixmapTextureMipmapChain mipchain(sprite); vdautoptr<IVDPixmapResampler> pResampler(VDCreatePixmapResampler()); while(pump()) { int x1 = p1.xposf(); int y1 = p1.yposf(); int x2 = p2.xposf(); int y2 = p2.yposf(); // VDPixmapBlt(buffer, xp, yp, image, 0, 0, 320, 240); // VDPixmapStretchBltNearest(buffer, x1, y1, x2, y2, sprite, -32<<16, -32<<16, (srcw+32)<<16, (srch+32)<<16); // VDPixmapStretchBltBilinear(buffer, x1, y1, x2, y2, sprite, 0, 0, srcw<<16, srch<<16); double fx1 = x1 / 65536.0; double fy1 = y1 / 65536.0; double fx2 = x2 / 65536.0; double fy2 = y2 / 65536.0; if (fx2 < fx1) std::swap(fx1, fx2); if (fy2 < fy1) std::swap(fy1, fy2); pResampler->Init(fx2-fx1, fy2-fy1, buffer.format, sprite.w, sprite.h, sprite.format, IVDPixmapResampler::kFilterLanczos3, IVDPixmapResampler::kFilterLanczos3, false); pResampler->Process(&buffer, fx1, fy1, fx2, fy2, &sprite, 0, 0); #if 0 float mx[16]={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; mx[0] = cos(th) / 512.0f; mx[1] = sin(th) / 512.0f; mx[5] = cos(th) / 384.0f; mx[4] = -sin(th) / 384.0f; mx[13] = -6.0f / 384.0f; mx[15] = 1.0f; VDTriBltVertex vx[4]={ { -100, -100, 0, 0, 0 }, { +100, -100, 0, 0, 60 }, { +100, +100, 0, 80, 60 }, { -100, +100, 0, 80, 0 }, }; const int idx[6]={0,1,2,0,2,3}; VDPixmap buffer_cropped(VDPixmapOffset(buffer, 160, 120)); buffer_cropped.w -= 320; buffer_cropped.h -= 240; VDPixmapTriBlt(buffer_cropped, mipchain.Mips(), mipchain.Levels(), vx, 4, idx, 6, kTriBltFilterTrilinear, 0.0f, mx); th += 0.01; #endif pDisp->Update(); ++blits; p1.advance(); p2.advance(); sint64 last; QueryPerformanceCounter((LARGE_INTEGER *)&last); if (last-start >= freq) { start += freq; VDDEBUG2("%d blits/sec\n", blits); blits = 0; } } }