STDMETHODIMP_(void) Tffvfw::aboutDlg(HWND hParent) { if (initCo()) { deciEB->putParam(IDFF_dlgEncAbout,1); deciEB->showCfgDlg(hParent); } }
HRESULT TffdshowEnc::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt) { DPRINTF(_l("TffdshowEnc::SetMediaType")); if (direction == PINDIR_INPUT) { initCo(); } return S_OK; }
STDMETHODIMP_(LRESULT) Tffvfw::coGetSize(BITMAPINFO *lpbiInput,BITMAPINFO*) { if (initCo()) { return deciE_VFW->getSize(lpbiInput); } else { return VFW_E_RUNTIME_ERROR; } }
STDMETHODIMP_(LRESULT) Tffvfw::coGetFormat(BITMAPINFO *lpbiInput,BITMAPINFO *lpbiOutput) { if (initCo()) { return deciE_VFW->getFormat(&lpbiInput->bmiHeader,lpbiOutput); } else { return VFW_E_RUNTIME_ERROR; } }
//------------------------------ encoding ------------------------------ STDMETHODIMP_(LRESULT) Tffvfw::coQuery(BITMAPINFO *lpbiInput,BITMAPINFO *lpbiOutput) { if (initCo()) { return deciE_VFW->query(&lpbiInput->bmiHeader,lpbiOutput?&lpbiOutput->bmiHeader:NULL); } else { return VFW_E_RUNTIME_ERROR; } }
STDMETHODIMP TffdshowEnc::saveEncodingSettings(void) { initCo(); if (!notreg) { coSettings->saveReg(); } return S_OK; }
STDMETHODIMP_(int) Tffvfw::loadMem(const void *buf,int len) { if (initCo()) { return deciE->loadEncodingSettingsMem(buf,len); } else { return 0; } }
STDMETHODIMP_(int) Tffvfw::saveMem(void *buf,int len) { if (initCo()) { return deciE->saveEncodingSettingsMem(buf,len); } else { return 0; } }
STDMETHODIMP_(LRESULT) Tffvfw::coBegin(BITMAPINFO *lpbiInput,BITMAPINFO *lpbiOutput) { if (initCo()) { previous_out_biSizeImage = 0; previouts_lpOutput = NULL; return deciE_VFW->begin(&lpbiInput->bmiHeader); } else { return VFW_E_RUNTIME_ERROR; } }
STDMETHODIMP_(LRESULT) Tffvfw::coEnd(void) { if (initCo()) { previous_out_biSizeImage = 0; previouts_lpOutput = NULL; return deciE_VFW->end(); } else { return VFW_E_RUNTIME_ERROR; } }
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; }
void TffdshowEnc::getOut(unsigned int AVIdx, unsigned int AVIdy, unsigned int *outDx, unsigned int *outDy) { initCo(); if (!ffproc) { getFFproc(); } if (coSettings->isProc && ffproc) { ffproc->getNewSize(AVIdx, AVIdy, outDx, outDy); } else { *outDx = AVIdx; *outDy = AVIdy; } }
STDMETHODIMP_(LRESULT) Tffvfw::coFramesInfo(ICCOMPRESSFRAMES *icf) { if (initCo()) { int r=icf->dwRate; int s=icf->dwScale; if (r==1000000) { switch (s) { case 41708: // 23.976 fps r=24000; s=1001; break; case 33367: // 29.97 fps r=30000; s=1001; break; case 41667: // 24 fps r=24; s=1; break; case 33333: // 30 fps r=30; s=1; break; case 16683: // 59.941 fps r=60000; s=1001; break; case 16667: // 60 fps r=60; s=1; break; case 66667: // 15 fps r=15; s=1; break; case 83333: // 12 fps r=12; s=1; break; } } deciEB->putParam(IDFF_enc_fpsRate ,r); deciEB->putParam(IDFF_enc_fpsScale,s); icf->dwRate=r; icf->dwScale=s; return ICERR_OK; } else { return VFW_E_RUNTIME_ERROR; } }
STDMETHODIMP_(int) TffdshowEnc::saveEncodingSettingsMem(void *buf, int len) { initCo(); TregOpIDstreamWrite t; coSettings->reg_op(t); getFFproc(); if (ffproc) { ffproc->saveConfig(t); } lzo_uint lenC = (lzo_uint)t.size() * 2; unsigned char *bufC = (unsigned char*)malloc(lenC); unsigned char work[LZO1X_MEM_COMPRESS]; lzo1x_1_compress(&*t.begin(), (lzo_uint)t.size(), bufC, &lenC, work); if (buf) { memcpy(buf, bufC, lenC); } free(bufC); return (int)lenC; }
STDMETHODIMP_(int) TffdshowEnc::loadEncodingSettingsMem(const void *buf, int len) { initCo(); lzo_uint lenD = len * 10; unsigned char *bufD = (unsigned char*)malloc(lenD); if (lzo1x_decompress((unsigned char*)buf, len, bufD, &lenD, NULL) < 0) { return 0; } const unsigned char *last; TregOpIDstreamRead t(bufD, lenD, (const void**)&last); coSettings->reg_op(t); getFFproc(); if (ffproc && last != bufD + lenD && *(short*)last == 0) { last += 3; ffproc->loadConfig(!!notreg, last, lenD - (last - bufD)); } free(bufD); coSettings->fillIncsps(); return len; }
STDMETHODIMP_(LRESULT) Tffvfw::coRun(void *icc0) { if (initCo()) { ICCOMPRESS *icc=(ICCOMPRESS*)icc0; // Work around applications' bugs // Because Microsoft's document is incomplete, many applications are buggy in my opinion. // lpbiOutput->biSizeImage is used to return value, the applications should update lpbiOutput->biSizeImage on every call. // But some applications doesn't do this, thus lpbiOutput->biSizeImage smaller and smaller. // The size of the buffer isn't likely to change during encoding. if (previouts_lpOutput == icc->lpOutput) { icc->lpbiOutput->biSizeImage = std::max(icc->lpbiOutput->biSizeImage, previous_out_biSizeImage); // looks like very bad code, but I have no choice. Not one application need this. } previous_out_biSizeImage = icc->lpbiOutput->biSizeImage; previouts_lpOutput = icc->lpOutput; // End of work around applications' bugs. deciE_VFW->setICC(icc0); return deciE_VFW->compress(icc->lpbiInput,(const uint8_t*)icc->lpInput,icc->lpbiInput->biSizeImage,0,0); } else { return VFW_E_RUNTIME_ERROR; } }
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_(void) Tffvfw::loadReg(void) { if (initCo()) { deciE->loadEncodingSettings(); } }
STDMETHODIMP TffdshowEnc::loadEncodingSettings(void) { initCo(); return S_OK; }
int TffdshowEnc::getVideoCodecId(const BITMAPINFOHEADER *hdr, const GUID *subtype, FOURCC *AVIfourcc) { initCo(); return query(hdr, NULL) == ICERR_OK ? CODEC_ID_RAW : CODEC_ID_NONE; }
STDMETHODIMP_(void) Tffvfw::configDlg(HWND hParent) { if (initCo() && initDec()) { TSpecifyPropertyPagesVE::show2configPages(IID_IffdshowEnc,deciE,getGUID<IffdshowDecVideo>(),(IffdshowDecVideo*)decVFW,IDS_FFDSHOWENC,IDI_FFVFW,IDFF_dlgEncCurrentPage); } }