STDMETHODIMP_(LRESULT) Tffvfw::decRun(void *icd0) { if (!decVFW) { return VFW_E_RUNTIME_ERROR; } icd=(ICDECOMPRESS*)icd0; if (~((icd->dwFlags&ICDECOMPRESS_HURRYUP) | (icd->dwFlags&ICDECOMPRESS_UPDATE) | (icd->dwFlags&ICDECOMPRESS_PREROLL))) { if ((colorspace=getBMPcolorspace(icd->lpbiOutput,autoforcedcolorspaces.decGetForcedCsp(decVFW)))==FF_CSP_NULL) { return ICERR_UNSUPPORTED; } if (colorspace&FF_CSP_RGB16) { colorspace=(colorspace&~FF_CSP_RGB16)|FF_CSP_RGB15; } if (sign(icd->lpbiInput->biHeight)!=sign(icd->lpbiOutput->biHeight) && !csp_isYUVpacked(colorspace)) { colorspace^=FF_CSP_FLAGS_VFLIP; } } else { colorspace=FF_CSP_NULL; } unsigned char *inData=(unsigned char*)icd->lpInput; unsigned int inLen=icd->lpbiInput->biSizeImage; isSyncPoint=(icd->dwFlags&ICDECOMPRESS_NOTKEYFRAME)==0; return dec->decompress(inData,inLen,this); }
STDMETHODIMP_(LRESULT) TffdshowEnc::getFormat(const BITMAPINFOHEADER *inhdr, BITMAPINFO *lpbiOutput) { extraDataSize = 0; initCo(); if (getBMPcolorspace(inhdr, coSettings->incsps) == FF_CSP_NULL) { return ICERR_BADFORMAT; } unsigned int outDx, outDy; getOut(inhdr->biWidth, inhdr->biHeight, &outDx, &outDy); if (!findEncLib()) { return 0; } extradata.clear(); if (enc->supExtradata()) { if (enccsps.empty()) { enc->getCompressColorspaces(enccsps, outDx, outDy); } enccsp = enccsps[0]; enc->beginCompress(coSettings->mode, enccsp, Trect(0, 0, outDx, outDy)); const void *edata0; enc->getExtradata(&edata0, &extraDataSize); if (extraDataSize) { extradata.set(edata0, extraDataSize, 0, true); } enc->end(); } if (lpbiOutput == NULL) { return sizeof(BITMAPINFOHEADER) + extradata.size; } BITMAPINFOHEADER *outhdr = &lpbiOutput->bmiHeader; memcpy(outhdr, inhdr, sizeof(BITMAPINFOHEADER)); outhdr->biSize = DWORD(sizeof(BITMAPINFOHEADER) + extradata.size); findEncLib(); outhdr->biWidth = outDx; outhdr->biHeight = outDy; if (!enc || !enc->prepareHeader(outhdr)) { outhdr->biCompression = coSettings->fourcc; outhdr->biBitCount = 24; // or 16 outhdr->biSizeImage = outDx * outDy * 3; } //TODO: maybe encoders should be allowed to modify other outhdr properties outhdr->biPlanes = 1; outhdr->biXPelsPerMeter = 0; outhdr->biYPelsPerMeter = 0; outhdr->biClrUsed = 0; outhdr->biClrImportant = 0; if (extradata.data) { memcpy((unsigned char*)outhdr + sizeof(BITMAPINFOHEADER), extradata.data, extradata.size); } biOutput.bmiHeader = lpbiOutput->bmiHeader; return ICERR_OK; }
STDMETHODIMP_(LRESULT) TffdshowEnc::query(const BITMAPINFOHEADER *inhdr, BITMAPINFOHEADER *outhdr) { initCo(); if (getBMPcolorspace(inhdr, coSettings->incsps) == FF_CSP_NULL) { return ICERR_BADFORMAT; } if (outhdr == NULL) { unsigned int outDx, outDy; getOut(inhdr->biWidth, inhdr->biHeight, &outDx, &outDy); if (outDx & 1 || outDy & 1) { return ICERR_BADFORMAT; } return ICERR_OK; } if (inhdr->biWidth != outhdr->biWidth || inhdr->biHeight != outhdr->biHeight) { return ICERR_BADFORMAT; } if (outhdr->biCompression == coSettings->fourcc) { return ICERR_OK; //FIX ? } return ICERR_BADFORMAT; }
STDMETHODIMP_(LRESULT) TffdshowEnc::compress(const BITMAPINFOHEADER *inhdr, const uint8_t *src, size_t /*srclen*/, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop) { if (firstrun) { firstrun = false; showTrayIcon(); } _mm_empty(); inColorspace = getBMPcolorspace(inhdr, coSettings->incsps); if (inColorspace == FF_CSP_NULL) { return ICERR_BADFORMAT; } if (coSettings->flip) { inColorspace ^= FF_CSP_FLAGS_VFLIP; } if (globalSettings->isDyInterlaced && dy > (unsigned int)globalSettings->dyInterlaced) { inColorspace |= FF_CSP_FLAGS_INTERLACED; } params.quant = -1; params.frametype = FRAME_TYPE::UNKNOWN; params.keyframe = false; switch (cfgcomode) { case ENC_MODE::CBR: case ENC_MODE::VBR_QUAL: break; case ENC_MODE::VBR_QUANT: params.quant = getQuantQuant(); break; case ENC_MODE::UNKNOWN: break; default: DPRINTF(_l("Invalid encoding mode")); return ICERR_ERROR; } params.gray = !!coSettings->gray; //if (!src || !srclen) return ICERR_ERROR; if (pict.csp != inColorspace) { pict.csp = inColorspace; pict.cspInfo = *csp_getInfo(pict.csp); } pict.setSize(dx, dy); pict.data[0] = (unsigned char*)src; pict.stride[0] = dx * pict.cspInfo.Bpp; if (src) { csp_yuv_adj_to_plane(pict.csp, &pict.cspInfo, dy, pict.data, pict.stride); csp_yuv_order(pict.csp, pict.data, pict.stride); csp_vflip(pict.csp, &pict.cspInfo, pict.data, pict.stride, dy); } if (!coSettings->isProc || !ffproc) { bool directYV12 = false; for (Tcsps::const_iterator c = enccsps.begin(); c != enccsps.end(); c++) if (*c == pict.csp) { directYV12 = true; break; } if (!directYV12) { if (!convert) { convert = new Tconvert(this, dx, dy); } if (!ownpict.data[0]) { ownpict.alloc(dx, dy, enccsp, ownpictbuf); } if (src) { convert->convert(pict, ownpict.csp, ownpict.data, ownpict.stride); } //srclen=ownpict.cspInfo.bpp*ownpict.rectFull.dx*ownpict.rectFull.dy/8; pict = ownpict; if (!src) { pict.data[0] = NULL; } } } params.length = 0; params.priv = NULL; pict.rtStart = rtStart; pict.rtStop = rtStop; if (src && coSettings->isProc && ffproc) { HRESULT hr = ffproc->processPict(params.framenum, pict, enccsp); if (hr == S_OK) { hr = src ? enc->compress(pict, params) : enc->flushEnc(pict, params); } return hr; } else { return src ? enc->compress(pict, params) : enc->flushEnc(pict, params); } }
STDMETHODIMP_(LRESULT) Tffvfw::decQuery(BITMAPINFO *lpbiInput,BITMAPINFO *lpbiOutput) { if (initDec()) { if (lpbiInput==NULL) { return ICERR_ERROR; } CodecID codecId; autoptr<TvideoCodecDec> dec=initDecoder(lpbiInput,&codecId); if (codecId==CODEC_ID_NONE) { return ICERR_UNSUPPORTED; } if (lpbiOutput!=NULL) { if (!dec) { return ICERR_UNSUPPORTED; } dec->forceOutputColorspace(&lpbiInput->bmiHeader,&autoforcedilace,autoforcedcolorspaces); const BITMAPINFOHEADER *outhdr=&lpbiOutput->bmiHeader; char_t pomS[60]; DPRINTF(_l("Tffvfw::decQuery: %s"),fourcc2str(hdr2fourcc(outhdr,NULL),pomS,60)); if (lpbiInput->bmiHeader.biWidth!=outhdr->biWidth || abs(lpbiInput->bmiHeader.biHeight)!=abs(outhdr->biHeight) || getBMPcolorspace(outhdr,autoforcedcolorspaces.decGetForcedCsp(decVFW))==FF_CSP_NULL) { return ICERR_BADFORMAT; } } return ICERR_OK; } else { return VFW_E_RUNTIME_ERROR; } }