tffdshowenc.cpp.svn-base
来自「ffshow源码」· SVN-BASE 代码 · 共 1,074 行 · 第 1/2 页
SVN-BASE
1,074 行
if (coSettings->storeExt && !ownStoreExt && coSettings->storeExtFlnm[0]) mux=Tmuxer::getMuxer(coSettings->muxer,this); else mux=NULL; switch (cfgcomode) { case ENC_MODE::PASS2_1: pass=new T2passFirst(*coSettings); break; case ENC_MODE::PASS2_2_EXT: pass=new T2passSecond(this); case ENC_MODE::PASS2_2_INT: pass=new T2passSecond(this); break; } dx=inhdr->biWidth;dy=inhdr->biHeight; totalsize=keyspacing=0; if (coSettings->isProc && ffproc) ffproc->begin(dx,dy,fpsRate,fpsScale); if (mux) mux->writeHeader(extradata.data,extradata.size,1,biOutput.bmiHeader); memset(¶ms,0,sizeof(params)); encStats.init(outDx,outDy,enccsp); outputdebug=globalSettings->outputdebug;outputdebugfile=globalSettings->outputdebugfile; working=true;firstrun=true; return ICERR_OK;}HRESULT TffdshowEnc::EndOfStream(void){ HRESULT hr=compress(&inpin->biIn.bmiHeader,NULL,0,_I64_MIN,_I64_MIN); return FAILED(hr)?hr:CTransformFilter::EndOfStream();}STDMETHODIMP_(LRESULT) TffdshowEnc::end(void){ if (working && (outputdebug || outputdebugfile) && encStats.count>0) { if (int(encStats.sumQuants)>0) dbgWrite(_l("Average quantizer: %-5.2f\n"),float(encStats.sumQuants)/encStats.count); if (coSettings->mode!=ENC_MODE::VBR_QUANT) { dbgWrite(_l("Quantizer distribution:")); for (int i=1;i<countof(encStats.quantCount);i++) if (encStats.quantCount[i]) dbgWrite(_l("Q:%i:%i"),i,encStats.quantCount[i]); } dbgWrite(_l("Bitrate: %i kbps"),int((8ULL*encStats.sumFramesize*fpsRate)/(1000ULL*encStats.count*fpsScale))); if (globalSettings->psnr) { double psnrY,psnrU,psnrV;encStats.calcPSNR(&psnrY,&psnrU,&psnrV); if (psnrY!=-1) dbgWrite(_l("Average PSNR: %6.2f,%6.2f,%6.2f\n"),psnrY,psnrU,psnrV); } } working=false; if (h_graph) PostMessage(h_graph,TencStats::MSG_FF_CLEAR,0,0); hideTrayIcon(); if (coSettings->isProc && ffproc) ffproc->end(); if (pass) delete pass;pass=NULL; if (enc) enc->end(); if (mux) delete mux;mux=NULL; if (convert) delete convert;convert=NULL; if (ownpictbuf.size()) {ownpictbuf.clear();memset(&ownpict,0,sizeof(ownpict));} enccsps.clear(); dbgDone(); return ICERR_OK;}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::PASS2_1: params.quant=getQuantFirst(); break; case ENC_MODE::PASS2_2_EXT: case ENC_MODE::PASS2_2_INT: if (!pass->getQuantSecond(params)) return ICERR_ERROR; if (params.quant!=-1) params.quant&=Txvid_2pass::NNSTATS_QUANTMASK; break; case ENC_MODE::UNKNOWN: break; default: DPRINTF(_l("Invalid encoding mode")); return ICERR_ERROR; } params.quanttype=coSettings->getQuantType(params.quant); params.gray=coSettings->gray || (coSettings->graycredits && coSettings->isInCredits(params.framenum)); if (keyspacing<coSettings->min_key_interval && params.framenum) params.frametype=FRAME_TYPE::P; //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 (csp_isPAL(pict.csp)) { pict.palette.pal=(unsigned char*)(inhdr+1); pict.palette.numcolors=inhdr->biClrUsed; } 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) return ffproc->processPict(params.framenum,pict,enccsp); else return src?enc->compress(pict,params):enc->flushEnc(pict,params);}STDMETHODIMP TffdshowEnc::TffProcVideoEnc::deliverProcessedSample(TffPict &pict){ return self->enc->compress(pict,self->params);}STDMETHODIMP TffdshowEnc::deliverEncodedSample(const TmediaSample &sample,TencFrameParams ¶ms){ _mm_empty(); params.outlength=coSettings->storeAVI?params.length:0; if (mux) mux->writeFrame(sample,params.length,params); if (params.keyframe) keyspacing=0; totalsize+=params.length; if (outputdebug || outputdebugfile) if (cfgcomode==ENC_MODE::PASS2_2_INT || cfgcomode==ENC_MODE::PASS2_2_EXT) pass->writeInfo(params); else dbgWrite(_l("1st-pass: size:%d total-kbytes:%d %s quant:%d %s kblocks:%d mblocks:%d\n"),params.length,int(totalsize/1024),FRAME_TYPE::name(params.frametype),params.quant,encQuantTypes[params.quanttype],params.kblks,params.mblks); if (pass) if (pass->update(params)==false) return ICERR_ERROR; params.framenum++;keyspacing++; encStats.add(params); if (h_graph) PostMessage(h_graph,TencStats::MSG_FF_FRAME,params.length,(params.quant<<20)|params.frametype); return ICERR_OK;}STDMETHODIMP TffdshowEnc::JoinFilterGraph(IFilterGraph *pGraph,LPCWSTR pName){ return onJoinFilterGraph(pGraph,pName);}HRESULT TffdshowEnc::onGraphRemove(void){ _release(); return TffdshowBase::onGraphRemove();}void TffdshowEnc::sendOnChange(int paramID,int val){ if (paramID!=IDFF_enc_fpsRate && paramID!=IDFF_enc_fpsScale && paramID!=IDFF_enc_fpsScale ) TffdshowBase::sendOnChange(paramID,val);}STDMETHODIMP TffdshowEnc::setCoSettingsPtr(TcoSettings *coSettingsPtr){ if (!coSettingsPtr) return E_POINTER; coSettings=coSettingsPtr; new(coSettings)TcoSettings(options); notifyParamsChanged(); return S_OK;}STDMETHODIMP TffdshowEnc::getCoSettingsPtr(const TcoSettings* *coSettingsPtr){ if (!coSettingsPtr) return E_POINTER; *coSettingsPtr=coSettings; return S_OK;}STDMETHODIMP TffdshowEnc::loadEncodingSettings(void){ initCo(); return S_OK;}STDMETHODIMP TffdshowEnc::saveEncodingSettings(void){ initCo(); if (!notreg) coSettings->saveReg(); return S_OK;}HRESULT TffdshowEnc::onInitDialog(void){ loadEncodingSettings(); return S_OK;}void TffdshowEnc::onTrayIconChange(int id,int newval){ if (working) TffdshowBase::onTrayIconChange(id,newval);}void TffdshowEnc::lockReceive(void){ m_csReceive.Lock();}void TffdshowEnc::unlockReceive(void){ m_csReceive.Unlock();}void TffdshowEnc::getColls(TintStrColls &colls){ if (coSettings) colls.push_back(coSettings->options); TffdshowBase::getColls(colls); }TinfoBase* TffdshowEnc::createInfo(void){ return new TinfoBase(this);}HRESULT TffdshowEnc::muxHeader(const void *data,size_t datalen,int flush){ if (!mux) return E_UNEXPECTED; return mux->writeHeader(data,datalen,!!flush,biOutput.bmiHeader)==0?S_FALSE:S_OK;}STDMETHODIMP TffdshowEnc::getEncStats(TencStats* *encStatsPtr){ if (!encStatsPtr) return E_POINTER; *encStatsPtr=&encStats; return S_OK;}STDMETHODIMP TffdshowEnc::isLAVCadaptiveQuant(void){ return coSettings->isLAVCadaptiveQuant();}STDMETHODIMP TffdshowEnc::isQuantControlActive(void){ return coSettings->isQuantControlActive();}STDMETHODIMP_(int) TffdshowEnc::getQuantType2(int quant){ return coSettings->getQuantType(quant);}STDMETHODIMP TffdshowEnc::getCustomQuantMatrixes(unsigned char* *intra8,unsigned char* *inter8,unsigned char* *intra4Y,unsigned char* *inter4Y,unsigned char* *intra4C,unsigned char* *inter4C){ if (intra8) *intra8=(unsigned char*)&coSettings->qmatrix_intra_custom0; if (inter8) *inter8=(unsigned char*)&coSettings->qmatrix_inter_custom0; if (intra4Y) *intra4Y=(unsigned char*)&coSettings->qmatrix_intra4x4Y_custom0; if (inter4Y) *inter4Y=(unsigned char*)&coSettings->qmatrix_inter4x4Y_custom0; if (intra4C) *intra4C=(unsigned char*)&coSettings->qmatrix_intra4x4C_custom0; if (inter4C) *inter4C=(unsigned char*)&coSettings->qmatrix_inter4x4C_custom0; return S_OK;}STDMETHODIMP TffdshowEnc::getEncoder(int codecId,const Tencoder* *encPtr){ if (!encPtr) return E_POINTER; *encPtr=enclibs.getEncoder(codecId); return S_OK;}STDMETHODIMP TffdshowEnc::getVideoCodecs(const TvideoCodecs* *codecs){ if (!codecs) return E_POINTER; *codecs=&enclibs; return S_OK;}void TffdshowEnc::getFFproc(void){ if (!ffproc) { HRESULT hr; ffproc=new TffProcVideoEnc(NULL,&hr,this); ffproc->setTempPreset("ffdshowenc temporary preset"); ffproc->loadPreset("ffdshowenc"); }}STDMETHODIMP TffdshowEnc::getFFproc(TffProcVideo* *procPtr){ if (!procPtr) return E_POINTER; getFFproc(); *procPtr=ffproc; return S_OK;}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_(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 TffdshowEnc::getInCodecString(char_t *buf,size_t buflen){ if (!buf) return E_POINTER; if (inColorspace==0) buf[0]='\0'; else csp_getName(inColorspace,buf,buflen); return S_OK;}STDMETHODIMP TffdshowEnc::getOutCodecString(char_t *buf,size_t buflen){ if (!buf) return E_POINTER; if (!enc) return E_UNEXPECTED; strncpy(buf,enc->getName(),buflen); buf[buflen-1]='\0'; return S_OK;}//================================== DirectShow ====================================STDMETHODIMP_(LRESULT) TffdshowEncDshow::begin(const BITMAPINFOHEADER *inhdr){ HRESULT hr=TffdshowEnc::begin(inhdr); if (SUCCEEDED(hr)) times.clear(); return hr; }HRESULT TffdshowEncDshow::Receive(IMediaSample *pIn){ if (!started) if (!start()) return E_FAIL; BYTE *src=NULL; if (pIn->GetPointer(&src)!=S_OK) return S_FALSE; size_t srcLen=pIn->GetActualDataLength(); REFERENCE_TIME rtStart,rtStop; if (FAILED(pIn->GetTime(&rtStart,&rtStop))) rtStart=rtStop=REFTIME_INVALID; return (HRESULT)compress(&inpin->biIn.bmiHeader,src,srcLen,rtStart,rtStop);}STDMETHODIMP TffdshowEncDshow::getDstBuffer(IMediaSample* *pOut,const TffPict &pict){ *pOut=NULL;BYTE *data; HRESULT hr; if (FAILED(hr=getDeliveryBuffer(pOut,&data))) return hr; if (coSettings->isFPSoverride || pict.rtStart==REFTIME_INVALID || pict.rtStop==REFTIME_INVALID) { REFERENCE_TIME tStart=(params.framenum )*inpin->avgTimePerFrame; REFERENCE_TIME tStop =(params.framenum+1)*inpin->avgTimePerFrame; setPropsTime(*pOut,tStart,tStop,m_pInput->SampleProps(),&m_bSampleSkipped); //DPRINTF("tStart:%i, tStop:%i, AVIfps:%i",int(tStart),int(tStop),timePerFrame); } else (*pOut)->SetTime((REFERENCE_TIME*)&pict.rtStart,(REFERENCE_TIME*)&pict.rtStop); AM_MEDIA_TYPE *mtOut; (*pOut)->GetMediaType(&mtOut); if (mtOut!=NULL) { HRESULT result=S_OK; DeleteMediaType(mtOut); if (result!=S_OK) return result; } return S_OK;}STDMETHODIMP TffdshowEncDshow::deliverError(void){ return E_FAIL;}STDMETHODIMP TffdshowEncDshow::deliverEncodedSample(const TmediaSample &sample,TencFrameParams ¶ms){ REFERENCE_TIME rtStart,rtStop; if (sample->GetTime(&rtStart,&rtStop)==S_OK) times.push_back(std::make_pair(rtStart,rtStop)); if (params.frametype==FRAME_TYPE::DELAY) { sample->Release(); return S_OK; } HRESULT hr; if (FAILED(hr=TffdshowEnc::deliverEncodedSample(sample,params))) return hr; if (!times.empty()) { rtStart=times.front().first; rtStop=times.front().second; sample->SetTime(&rtStart,&rtStop); times.pop_front(); } sample->SetSyncPoint(params.keyframe?TRUE:FALSE); sample->SetActualDataLength(params.outlength); if (fileout) { ft2+=params.outlength; sample->SetTime(&ft1,&ft2); ft1+=params.outlength; } IMediaSample **s=(IMediaSample**)&sample; return m_pOutput->Deliver(*s);}//===================================== VFW ========================================STDMETHODIMP TffdshowEncVFW::getDstBuffer(IMediaSample* *samplePtr,const TffPict &pict){ if (!samplePtr) return E_POINTER; struct TfakeEncMediaSample : TfakeMediaSample,CUnknown { private: void *buf;long bufsize; public: TfakeEncMediaSample(void *Ibuf,long Ibufsize):buf(Ibuf),bufsize(Ibufsize),CUnknown("TfakeEncMediaSample",NULL) {} DECLARE_IUNKNOWN virtual HRESULT STDMETHODCALLTYPE GetPointer(BYTE **ppBuffer) { if (!ppBuffer) return E_POINTER; return (*ppBuffer=(uint8_t*)buf)!=NULL?S_OK:E_FAIL; } virtual long STDMETHODCALLTYPE GetSize(void) {return bufsize;} }; *samplePtr=new TfakeEncMediaSample(icc->lpOutput,icc->lpbiOutput->biSizeImage); (*samplePtr)->AddRef(); return S_OK;}STDMETHODIMP TffdshowEncVFW::deliverError(void){ return ICERR_ERROR;}STDMETHODIMP TffdshowEncVFW::deliverEncodedSample(const TmediaSample &sample,TencFrameParams ¶ms){ HRESULT hr; if (FAILED(hr=TffdshowEnc::deliverEncodedSample(sample,params))) return hr; icc->lpbiOutput->biSizeImage=params.outlength; if (icc->lpdwFlags) *icc->lpdwFlags=params.keyframe?AVIIF_KEYFRAME:0; return hr;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?