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 + -
显示快捷键?