tffdshowenc.cpp.svn-base
来自「ffshow源码」· SVN-BASE 代码 · 共 1,074 行 · 第 1/2 页
SVN-BASE
1,074 行
/* * 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 "TffdshowEnc.h"#include "Tconfig.h"#include "TffdshowVideoInputPin.h"#include "ffcodecs.h"#include "ffdebug.h"#include "TglobalSettings.h"#include "lzo/minilzo.h"#include "TffProc.h"#include "TtrayIcon.h"#include "TdialogSettings.h"#include "reg.h"#include "dsutil.h"#include "resource.h"#include "Tmuxer.h"#include "Tinfo.h"#include "2pass.h"#include "Tconvert.h"#include <mmintrin.h>#include "TfakeImediaSample.h"STDMETHODIMP_(int) TffdshowEnc::getVersion2(void){ return VERSION;}CUnknown* WINAPI TffdshowEncDshow::CreateInstance(LPUNKNOWN punk,HRESULT *phr){ TffdshowEnc *pNewObject=new TffdshowEncDshow(punk,phr,new TintStrColl); if (pNewObject==NULL) *phr=E_OUTOFMEMORY; return pNewObject;}CUnknown* WINAPI TffdshowEncVFW::CreateInstance(LPUNKNOWN punk,HRESULT *phr){ TffdshowEncVFW *pNewObject=new TffdshowEncVFW(punk,phr,new TintStrColl); if (pNewObject==NULL) *phr=E_OUTOFMEMORY; return pNewObject;}STDMETHODIMP TffdshowEnc::NonDelegatingQueryInterface(REFIID riid,void **ppv){ CheckPointer(ppv,E_POINTER); if (riid==IID_IffdshowEnc) return GetInterface<IffdshowEnc>(this,ppv); else if (riid==IID_IffdshowBaseA) return GetInterface<IffdshowBaseA>(getBaseInterface<IffdshowBaseA>(),ppv); else if (riid==IID_IffdshowBaseW) return GetInterface<IffdshowBaseW>(getBaseInterface<IffdshowBaseW>(),ppv); else if (riid==IID_ISpecifyPropertyPages) return GetInterface<ISpecifyPropertyPages>(this,ppv); else if (riid==IID_IPersistStream) return GetInterface<IPersistStream>(this,ppv); else if (riid==IID_IffdshowParamsEnum) return GetInterface<IffdshowParamsEnum>(this,ppv); else return CTransformFilter::NonDelegatingQueryInterface(riid,ppv);}STDMETHODIMP TffdshowEncVFW::NonDelegatingQueryInterface(REFIID riid,void **ppv){ CheckPointer(ppv,E_POINTER); if (riid==IID_IffdshowEncVFW) return GetInterface<IffdshowEncVFW>(this,ppv); else return TffdshowEnc::NonDelegatingQueryInterface(riid,ppv);}TffdshowEnc::TffdshowEnc(LPUNKNOWN punk, HRESULT *phr,TintStrColl *Ioptions,const char_t *Iname,REFCLSID Iclsid,int Imode): TffdshowBase( punk, Ioptions, globalSettings=new TglobalSettingsEnc(&config,Imode,Ioptions), dialogSettings=new TdialogSettingsEnc(Ioptions), this, (TinputPin*&)inpin, m_pOutput, m_pGraph, IDS_FFDSHOWENC,IDI_FFVFW, defaultMerit ), CmyTransformFilter(Iname,punk,Iclsid), TffdshowVideo(this,m_pOutput,this,NULL), CPersistStream(punk,phr), inColorspace(FF_CSP_NULL){ DPRINTF(_l("TffdshowEnc::Constructor")); setThreadName(DWORD(-1),"enc"); SetDirty(TRUE); static const TintOptionT<TffdshowEnc> iopts[]= { IDFF_enc_fpsRate ,&TffdshowEnc::fpsRate , 1, 1,_l(""),0,NULL,0, IDFF_enc_fpsScale ,&TffdshowEnc::fpsScale , 1, 1,_l(""),0,NULL,0, IDFF_enc_ownStoreExt ,&TffdshowEnc::ownStoreExt, 0, 0,_l(""),0,NULL,0, IDFF_dlgEncGraph ,&TffdshowEnc::dlgEncGraph, 0, 0,_l(""),0,NULL,0, IDFF_dlgEncAbout ,&TffdshowEnc::dlgEncAbout, 0, 0,_l(""),0,NULL,0, IDFF_enc_working ,&TffdshowEnc::working ,-1,-1,_l(""),0,NULL,0, 0 }; addOptions(iopts); m_pInput=inpin=new TffdshowVideoEncInputPin(this,phr); if (!m_pInput) *phr=E_OUTOFMEMORY; if (FAILED(*phr)) return; m_pOutput=new CTransformOutputPin(NAME("Transform output pin"),this,phr,L"Out"); if (!m_pOutput) *phr=E_OUTOFMEMORY; if (FAILED(*phr)) { delete m_pInput;m_pInput=NULL; return; } trayIconStart=&TtrayIconBase::start<TtrayIconEnc>; started=false; coSettings=NULL; fpsRate=25;fpsScale=1; ownStoreExt=false; dlgEncGraph=dlgEncAbout=0; memset(&ownpict,0,sizeof(ownpict)); enc=NULL;mux=NULL; pass=NULL; working=false;firstrun=false; h_graph=NULL; convert=NULL; ffproc=NULL; oldCodecId=CODEC_ID_NONE; options=Ioptions;}TffdshowEnc::~TffdshowEnc(){ _release();}void TffdshowEnc::initCo(void){ if (!coSettings) { coSettings=new TcoSettings(options); enclibs.init(this,this); coSettings->loadReg(); }}STDMETHODIMP TffdshowEnc::_release(void){ for (TvideoCodecs::iterator i=enclibs.begin();i!=enclibs.end();i++) delete *i; enclibs.clear(); if (ffproc) delete ffproc;ffproc=NULL; if (coSettings) delete coSettings;coSettings=NULL; return S_OK;}STDMETHODIMP TffdshowEnc::GetPages(CAUUID * pPages){ DPRINTF(_l("TffdshowEnc::GetPages")); initDialog();loadEncodingSettings(); onTrayIconChange(0,0); pPages->cElems=1; pPages->pElems=(GUID *)CoTaskMemAlloc(pPages->cElems*sizeof(GUID)); if (pPages->pElems==NULL) return E_OUTOFMEMORY; pPages->pElems[0]=(globalSettings->filtermode&IDFF_FILTERMODE_VFW)?CLSID_TFFDSHOWENCPAGEVFW:CLSID_TFFDSHOWENCPAGE; return S_OK;}STDMETHODIMP TffdshowEnc::GetClassID(CLSID *pClsid){ return CBaseFilter::GetClassID(pClsid);}int TffdshowEnc::SizeMax(void){ return 4096;}HRESULT TffdshowEnc::WriteToStream(IStream *pStream){ int32_t len=saveEncodingSettingsMem(NULL,0); void *buf=malloc(len+4); *(int32_t*)buf=len; saveEncodingSettingsMem((char*)buf+4,len); pStream->Write(buf,len+4,NULL); free(buf); return S_OK;}HRESULT TffdshowEnc::ReadFromStream(IStream *pStream){ int32_t len; pStream->Read(&len,4,NULL); void *buf=malloc(len); pStream->Read(buf,len,NULL); notreg=true; loadEncodingSettingsMem(buf,len); free(buf); return S_OK;}HRESULT TffdshowEnc::CheckInputType(const CMediaType * mtIn){ 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;}HRESULT TffdshowEnc::CheckConnect(PIN_DIRECTION dir,IPin *pPin){ if (dir==PINDIR_INPUT) return S_OK; else return CTransformFilter::CheckConnect(dir,pPin);}HRESULT TffdshowEnc::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt){ DPRINTF(_l("TffdshowEnc::SetMediaType")); if (direction==PINDIR_INPUT) initCo(); return S_OK;}HRESULT TffdshowEnc::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut){ DPRINTF(_l("TffdshowEnc::CheckTransform")); fileout=!!(*mtOut->Type()==MEDIATYPE_Stream); return S_OK;}HRESULT TffdshowEnc::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest){ DPRINTF(_l("TffdshowEnc::DecideBufferSize")); if (m_pInput->IsConnected()==FALSE) return E_UNEXPECTED; ppropInputRequest->cBuffers=1; ppropInputRequest->cbBuffer=(long)getSize(&inpin->biIn); ppropInputRequest->cbPrefix=0; if (fileout) ppropInputRequest->cbAlign=1; ALLOCATOR_PROPERTIES ppropActual; HRESULT result=pAlloc->SetProperties(ppropInputRequest,&ppropActual); if (result!=S_OK) return result; if (ppropActual.cbBuffer<ppropInputRequest->cbBuffer) return E_FAIL; return S_OK;}HRESULT TffdshowEnc::GetMediaType(int iPosition, CMediaType *mtOut){ DPRINTF(_l("TffdshowEnc::GetMediaType")); if (m_pInput->IsConnected()==FALSE) return E_UNEXPECTED; if (iPosition<0) return E_INVALIDARG; if (iPosition>/*(mpeg_codec(ffvfw->cfg.co.codecId)?2:1)*/1) return VFW_S_NO_MORE_ITEMS; switch (iPosition) { case 0: { size_t elen=getFormat(&inpin->biIn.bmiHeader,NULL)-sizeof(BITMAPINFOHEADER); VIDEOINFOHEADER *vih=(VIDEOINFOHEADER*)mtOut->ReallocFormatBuffer(ULONG(sizeof(VIDEOINFOHEADER)+elen)); if (!vih) return E_OUTOFMEMORY; ZeroMemory(vih,sizeof(VIDEOINFOHEADER)+elen); getFormat(&inpin->biIn.bmiHeader,(BITMAPINFO*)&vih->bmiHeader); vih->rcSource.left=0;vih->rcSource.top=0;vih->rcSource.right=vih->bmiHeader.biWidth;vih->rcSource.bottom=vih->bmiHeader.biHeight; vih->rcTarget=vih->rcSource; vih->AvgTimePerFrame=inpin->avgTimePerFrame; GUID subtype=MEDIASUBTYPE_YV12; subtype.Data1=vih->bmiHeader.biCompression; mtOut->SetSubtype(&subtype); mtOut->SetType(&MEDIATYPE_Video); mtOut->SetFormatType(&FORMAT_VideoInfo); mtOut->SetTemporalCompression(TRUE); mtOut->SetSampleSize(vih->bmiHeader.biSizeImage); break; } case 1: { mtOut->SetType(&MEDIATYPE_Stream); mtOut->SetSubtype(&MEDIASUBTYPE_None); mtOut->SetFormatType(&FORMAT_None); unsigned int outdx,outdy; getOut(inpin->biIn.bmiHeader.biWidth,inpin->biIn.bmiHeader.biHeight,&outdx,&outdy); mtOut->SetSampleSize(outdx*outdy*4); mtOut->SetVariableSize(); mtOut->SetTemporalCompression(FALSE); break; } case 2: { unsigned int outdx,outdy; getOut(inpin->biIn.bmiHeader.biWidth,inpin->biIn.bmiHeader.biHeight,&outdx,&outdy); mtOut->SetType(&MEDIATYPE_Video); mtOut->SetTemporalCompression(TRUE); mtOut->SetSampleSize(outdx*outdy*4); if (coSettings->codecId==CODEC_ID_MPEG1VIDEO) //mpeg1 (including VideoCD) { mtOut->SetSubtype(&MEDIASUBTYPE_MPEG1Video); mtOut->SetFormatType(&FORMAT_MPEGVideo); MPEG1VIDEOINFO *mvi=(MPEG1VIDEOINFO*)mtOut->ReallocFormatBuffer(sizeof(MPEG1VIDEOINFO)); mvi->dwStartTimeCode=0; ZeroMemory(&mvi->hdr,sizeof(VIDEOINFOHEADER)); mvi->hdr.rcSource.left=0;mvi->hdr.rcSource.top=0;mvi->hdr.rcSource.right=outdx;mvi->hdr.rcSource.bottom=outdy; mvi->hdr.rcTarget=mvi->hdr.rcSource; mvi->hdr.AvgTimePerFrame=inpin->avgTimePerFrame; //mvi->hdr.bmiHeader=biOut.bmiHeader; } else //mpeg2 { } break; } } return S_OK;}STDMETHODIMP TffdshowEnc::Stop(void){ DPRINTF(_l("TffdshowEnc::Stop")); HRESULT res=CTransformFilter::Stop(); end(); started=false; return res;}bool TffdshowEnc::start(void){ started=true; if (coSettings->isFPSoverride) { inpin->avgTimePerFrame=REF_SECOND_MULT*coSettings->fpsOverrideDen/coSettings->fpsOverrideNum; fpsRate=coSettings->fpsOverrideNum;fpsScale=coSettings->fpsOverrideDen; } else if (inpin->avgTimePerFrame>10000) //if sane value is available lavc_reduce(&fpsRate,&fpsScale,REF_SECOND_MULT,inpin->avgTimePerFrame,32768); else // default { fpsRate=25;fpsScale=1; } if (begin(&inpin->biIn.bmiHeader)!=ICERR_OK) return false; ft1=ft2=0; return true; }int TffdshowEnc::getQuantFirst(void){ if (coSettings->credits_mode==CREDITS_MODE::QUANT && coSettings->isInCredits(params.framenum)) return coSettings->credits_quant_p; else return 2;}int TffdshowEnc::getQuantQuant(void){ if (coSettings->isInCredits(params.framenum)) switch (coSettings->credits_mode) { case CREDITS_MODE::PERCENT: return coSettings->q_p_max-((coSettings->q_p_max-coSettings->quant)*coSettings->credits_percent/100); case CREDITS_MODE::QUANT: return coSettings->credits_quant_p; default: return 0; } else return coSettings->quant;}TvideoCodecEnc* TffdshowEnc::findEncLib(void){ if (!enc || oldCodecId!=coSettings->codecId) { oldCodecId=(CodecID)coSettings->codecId; enc=enclibs.getEncLib(oldCodecId); } return enc;}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) 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::getFormat(const BITMAPINFOHEADER *inhdr,BITMAPINFO *lpbiOutput){ 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;size_t elen; enc->getExtradata(&edata0,&elen); if (elen) extradata.set(edata0,elen,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::getSize(const BITMAPINFO *lpbiInput){ findEncLib(); unsigned int outDx,outDy; getOut(lpbiInput->bmiHeader.biWidth,lpbiInput->bmiHeader.biHeight,&outDx,&outDy); BITMAPINFOHEADER outhdr; outhdr.biWidth=outDx; outhdr.biHeight=outDy; if (!enc || !enc->prepareHeader(&outhdr)) return outDx*outDy*3; else return outhdr.biSizeImage;}STDMETHODIMP_(LRESULT) TffdshowEnc::begin(const BITMAPINFOHEADER *inhdr){ if (!findEncLib()) return ICERR_ERROR; int nom,den; if (lavc_reduce(&nom,&den,fpsRate,fpsScale,10000)) { fpsRate =nom; fpsScale=den; } dbgInit(); getOut(inhdr->biWidth,inhdr->biHeight,&outDx,&outDy); ownStoreExt=false; if (enccsps.empty()) { enc->getCompressColorspaces(enccsps,outDx,outDy); if (enccsps.empty()) return ICERR_BADFORMAT; } enccsp=enccsps[0]; cfgcomode=coSettings->mode; switch (cfgcomode) { case ENC_MODE::CBR: if (!sup_CBR(coSettings->codecId)) cfgcomode=ENC_MODE::UNKNOWN; break; case ENC_MODE::VBR_QUAL: if (!sup_VBR_QUAL(coSettings->codecId)) cfgcomode=ENC_MODE::UNKNOWN; break; case ENC_MODE::VBR_QUANT: if (!sup_VBR_QUANT(coSettings->codecId)) cfgcomode=ENC_MODE::UNKNOWN; break; case ENC_MODE::PASS2_1: case ENC_MODE::PASS2_2_EXT: case ENC_MODE::PASS2_2_INT: if (!sup_XVID2PASS(coSettings->codecId)) cfgcomode=ENC_MODE::UNKNOWN; break; } enc->setCoSettings(oldCodecId); LRESULT res=enc->beginCompress(cfgcomode,enccsp,Trect(0,0,outDx,outDy)); if (res!=ICERR_OK) return res;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?