tffvfw.cpp.svn-base
来自「ffshow源码」· SVN-BASE 代码 · 共 372 行
SVN-BASE
372 行
/* * Copyright (c) 2003-2006 Milan Cutka * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include "stdafx.h"#include "Tffvfw.h"#include "ffdshow_constants.h"#include "IffdshowBase.h"#include "IffdshowEnc.h"#include "Tconvert.h"#include "TpageSite.h"#include "TSpecifyPropertyPagesVE.h"#include "TpresetSettingsVideo.h"#include "ToutputVideoSettings.h"#include "TglobalSettings.h"#include "dsutil.h"#include "autoptr.h"#include "ffdebug.h"#include "TffDecoderVideo.h"class TimgFiltersVFW :public TimgFilters{public: TimgFiltersVFW(IffdshowBase *Ideci,IprocVideoSink *Isink):TimgFilters(Ideci,Isink) {}};class TffdshowDecVideoVFW :public TffdshowDecVideo{private: IprocVideoSink *procVideoSink;protected: virtual TimgFilters* createImgFilters(void) { return new TimgFiltersVFW(this,procVideoSink); }public: TffdshowDecVideoVFW(HRESULT *phr,IprocVideoSink* iprocVideoSink): TffdshowDecVideo(CLSID_FFDSHOWVFW,NAME("TffdshowDecVideoVFW"),CLSID_TFFDSHOWPAGEVFW,IDS_FFDSHOWDECVIDEOVFW,IDI_FFDSHOW,NULL,phr,IDFF_FILTERMODE_PLAYER|IDFF_FILTERMODE_VFW,MERIT_DO_NOT_USE,new TintStrColl), procVideoSink(iprocVideoSink) { AddRef(); } void release(void) { if (imgFilters) delete imgFilters; Release(); } HRESULT processPict(TffPict &pict) { if (!imgFilters) imgFilters=createImgFilters(); return imgFilters->process(pict,presetSettings); } bool getFlip(void) const { return !!presetSettings->output->flip; } };//==================================================================CUnknown* WINAPI Tffvfw::CreateInstance(LPUNKNOWN punk,HRESULT *phr){ Tffvfw *pNewObject=new Tffvfw(punk,phr); if (pNewObject==NULL) *phr=E_OUTOFMEMORY; return pNewObject;}STDMETHODIMP Tffvfw::NonDelegatingQueryInterface(REFIID riid,void **ppv){ CheckPointer(ppv, E_POINTER); if (riid==IID_Iffvfw) return GetInterface<Iffvfw>(this,ppv); else return CUnknown::NonDelegatingQueryInterface(riid,ppv);}Tffvfw::Tffvfw(LPUNKNOWN punk,HRESULT *phr): CUnknown(NAME("Tffvfw"),punk), convert(NULL), dec(NULL), graph(false){ randomize();}Tffvfw::~Tffvfw(){ if (dec) delete dec; if (deciE) deciE->_release(); if (convert) delete convert; if (decVFW) decVFW->release();}bool Tffvfw::initCo(void){ if (deciEB) return true; if (SUCCEEDED(CoCreateInstance(CLSID_FFDSHOWENCVFW,NULL,CLSCTX_INPROC_SERVER,IID_IffdshowEncVFW,(void**)&deciE_VFW))) { deciE=deciE_VFW; deciEB=deciE; } else deciEB=NULL; return !!deciEB;}bool Tffvfw::initDec(void){ if (decVFW) return true; HRESULT hr=S_OK; decVFW=new TffdshowDecVideoVFW(&hr,this); decVFW->initPresets(); decVFW->setActivePreset(FFPRESET_DEFAULT,0); return !!decVFW;}STDMETHODIMP_(void) Tffvfw::aboutDlg(HWND hParent){ if (initCo()) { deciEB->putParam(IDFF_dlgEncAbout,1); deciEB->showCfgDlg(hParent); }}STDMETHODIMP_(void) Tffvfw::configDlg(HWND hParent){ if (initCo() && initDec()) TSpecifyPropertyPagesVE::show2configPages(IID_IffdshowEnc,deciE,getGUID<IffdshowDecVideo>(),(IffdshowDecVideo*)decVFW,IDS_FFDSHOWENC,IDI_FFVFW,IDFF_dlgEncCurrentPage);}STDMETHODIMP_(int) Tffvfw::saveMem(void *buf,int len){ if (initCo()) return deciE->saveEncodingSettingsMem(buf,len); else return 0;}STDMETHODIMP_(int) Tffvfw::loadMem(const void *buf,int len){ if (initCo()) return deciE->loadEncodingSettingsMem(buf,len); else return 0;}STDMETHODIMP_(void) Tffvfw::loadReg(void){ if (initCo()) deciE->loadEncodingSettings();}//------------------------------ 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_(LRESULT) Tffvfw::coGetFormat(BITMAPINFO *lpbiInput,BITMAPINFO *lpbiOutput){ if (initCo()) return deciE_VFW->getFormat(&lpbiInput->bmiHeader,lpbiOutput); else return VFW_E_RUNTIME_ERROR;}STDMETHODIMP_(LRESULT) Tffvfw::coGetSize(BITMAPINFO *lpbiInput,BITMAPINFO*){ if (initCo()) return deciE_VFW->getSize(lpbiInput); else return VFW_E_RUNTIME_ERROR;}STDMETHODIMP_(LRESULT) Tffvfw::coFramesInfo(ICCOMPRESSFRAMES *icf){ if (initCo()) { deciEB->putParam(IDFF_enc_fpsRate ,icf->dwRate ); deciEB->putParam(IDFF_enc_fpsScale,icf->dwScale); return ICERR_OK; } else return VFW_E_RUNTIME_ERROR;}STDMETHODIMP_(LRESULT) Tffvfw::coBegin(BITMAPINFO *lpbiInput,BITMAPINFO *lpbiOutput){ if (initCo()) return deciE_VFW->begin(&lpbiInput->bmiHeader); else return VFW_E_RUNTIME_ERROR;}STDMETHODIMP_(LRESULT) Tffvfw::coEnd(void){ if (initCo()) return deciE_VFW->end(); else return VFW_E_RUNTIME_ERROR;}STDMETHODIMP_(LRESULT) Tffvfw::coRun(void *icc0){ if (initCo()) { deciE_VFW->setICC(icc0); ICCOMPRESS *icc=(ICCOMPRESS*)icc0; return deciE_VFW->compress(icc->lpbiInput,(const uint8_t*)icc->lpInput,icc->lpbiInput->biSizeImage,0,0); } else return VFW_E_RUNTIME_ERROR;}//------------------------------ decoding ------------------------------TcspInfos Tffvfw::TautoForcedCsps::decGetForcedCsp(IffdshowDec *deciD){ if (!empty()) return *this; else { TpresetVideo *presetSettings;deciD->getPresetPtr((Tpreset**)&presetSettings); TcspInfos ocsps;presetSettings->output->getOutputColorspaces(ocsps); return ocsps; }}TvideoCodecDec* Tffvfw::initDecoder(const BITMAPINFO *lpbiInput,CodecID *codecId){ BITMAPINFOHEADER inhdr=lpbiInput->bmiHeader; fixMPEGinAVI(inhdr.biCompression); FOURCC fcc; CodecID owncodecId;if (!codecId) codecId=&owncodecId; *codecId=(CodecID)decVFW->getCodecId(&inhdr,NULL,&fcc); if (*codecId==CODEC_ID_NONE) return NULL; CMediaType mt; bih2mediatype(lpbiInput->bmiHeader,&mt); return TvideoCodecDec::initDec(decVFW,this,*codecId,fcc,mt);}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;}STDMETHODIMP_(LRESULT) Tffvfw::decGetFormat(BITMAPINFO *lpbiInput,BITMAPINFO *lpbiOutput){ if (lpbiOutput==NULL) return sizeof(BITMAPINFOHEADER); BITMAPINFOHEADER *inhdr =&lpbiInput ->bmiHeader; BITMAPINFOHEADER *outhdr=&lpbiOutput->bmiHeader; memcpy(outhdr,inhdr,sizeof(BITMAPINFOHEADER)); outhdr->biSize=sizeof(BITMAPINFOHEADER); outhdr->biBitCount=24; outhdr->biCompression=BI_RGB; outhdr->biSizeImage=outhdr->biWidth*outhdr->biHeight*(outhdr->biBitCount>>3); outhdr->biXPelsPerMeter=0; outhdr->biYPelsPerMeter=0; outhdr->biClrUsed=0; outhdr->biClrImportant=0; return decQuery(lpbiInput,lpbiOutput);}STDMETHODIMP_(LRESULT) Tffvfw::decBegin(BITMAPINFO *lpbiInput,BITMAPINFO *lpbiOutput){ if (!decVFW) return VFW_E_RUNTIME_ERROR; if (dec) delete dec; dec=initDecoder(lpbiInput,NULL); FOURCC infcc=lpbiInput->bmiHeader.biCompression; fixMPEGinAVI(infcc); CMediaType mt; bih2mediatype(lpbiInput->bmiHeader,&mt); TffPictBase p(lpbiInput->bmiHeader.biWidth,lpbiInput->bmiHeader.biHeight); LRESULT res=dec->beginDecompress(p,infcc,mt,0); if (!res) return ICERR_UNSUPPORTED; decVFW->dbgInit(); return ICERR_OK;}STDMETHODIMP_(LRESULT) Tffvfw::decEnd(void){ if (!decVFW) return VFW_E_RUNTIME_ERROR; if (dec) dec->end(); decVFW->dbgDone(); return ICERR_OK;}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)) 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 Tffvfw::deliverPreroll(int frametype){ return S_FALSE;}STDMETHODIMP Tffvfw::deliverDecodedSample(TffPict &pict){ if (!pict.data[0]) return /*used_bytes==inLen?ICERR_OK:*/ICERR_ERROR; //TODO if (colorspace==FF_CSP_NULL) return ICERR_OK; if (autoforcedilace==1) pict.csp&=~FF_CSP_FLAGS_INTERLACED; else if (autoforcedilace==2) pict.csp|=FF_CSP_FLAGS_INTERLACED; return decVFW->processPict(pict);} STDMETHODIMP Tffvfw::deliverProcessedSample(TffPict &pict){ if (!convert || (LONG)convert->dx!=icd->lpbiInput->biWidth || (LONG)convert->dy!=icd->lpbiInput->biHeight) { if (convert) delete convert; convert=new Tconvert(decVFW,icd->lpbiInput->biWidth,abs(icd->lpbiInput->biHeight)); } unsigned char *dst[4]={(unsigned char*)icd->lpOutput,NULL,NULL}; stride_t dstStride[4]={icd->lpbiInput->biWidth*csp_getInfo(colorspace)->Bpp,0,0}; return convert->convert(pict,colorspace^(decVFW->getFlip()?FF_CSP_FLAGS_VFLIP:0),dst,dstStride)?ICERR_OK:ICERR_BADFORMAT;}/*void Tffvfw::dbgError(const char *msg){ initCo(); deciEB->dbgError(msg);}*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?