tffdecoder.cpp.svn-base
来自「ffshow源码」· SVN-BASE 代码 · 共 1,162 行 · 第 1/3 页
SVN-BASE
1,162 行
/* * Copyright (c) 2002-2006 Milan Cutka * based on CXvidDecoder.cpp from XviD DirectShow filter * * 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 *//* * Modified to support multi-thread related features * by Haruhiko Yamagata <h.yamagata@nifty.com> in 2006. * * This modification 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. * * Original version is available from * http://svn.sourceforge.net/viewcvs.cgi/ffdshow/ */#include "stdafx.h"#include "TffDecoderVideo.h"#include "Tconfig.h"#include "TglobalSettings.h"#include "Tpresets.h"#include "TpresetSettingsVideo.h"#include "ToutputVideoSettings.h"#include "TdialogSettings.h"#include "ffdebug.h"#include "ffdshow_mediaguids.h"#include "ffcodecs.h"#include "TtrayIcon.h"#include "TcpuUsage.h"#include "TffPict.h"#include "TimgFilters.h"#include "TffdshowVideoInputPin.h"#include "TtextInputPin.h"#include "Tlibmplayer.h"#include "TfontManager.h"#include "TvideoCodec.h"#include "dsutil.h"#include "TkeyboardDirect.h"#include "ffdshowRemoteAPIimpl.h"#include "IffdshowEnc.h"#include "ThwOverlayControlOverlay.h"#include "ThwOverlayControlVMR9.h"void TffdshowDecVideo::getMinMax(int id,int &min,int &max){ if (id==IDFF_subCurLang) { min=0; max=getSubtitleLanguagesCount2()-1; }}// constructorTffdshowDecVideo::TffdshowDecVideo(CLSID Iclsid,const char_t *className,const CLSID &Iproppageid,int IcfgDlgCaptionId,int IiconId,LPUNKNOWN punk,HRESULT *phr,int Imode,int IdefaultMerit,TintStrColl *Ioptions): TffdshowVideo(this,m_pOutput,this,this), TffdshowDec(Ioptions, className,punk,Iclsid, globalSettings=new TglobalSettingsDecVideo(&config,Imode,Ioptions), dialogSettings=new TdialogSettingsDecVideo(Imode&IDFF_FILTERMODE_VFW?true:false,Ioptions), presets=Imode&IDFF_FILTERMODE_PROC?(TpresetsVideo*)new TpresetsVideoProc:(Imode&IDFF_FILTERMODE_VFW?(TpresetsVideo*)new TpresetsVideoVFW:(TpresetsVideo*)new TpresetsVideoPlayer), (Tpreset*&)presetSettings, this, (TinputPin*&)inpin, m_pOutput, m_pGraph, (Tfilters*&)imgFilters, Iproppageid,IcfgDlgCaptionId,IiconId, defaultMerit), decVideo_char(punk,this), outOldRenderer(false){ DPRINTF(_l("TffdshowDecVideo::Constructor")); hVideoThread= NULL; hReceiveThread= NULL; hVideoSemaphore= CreateSemaphore(NULL, 0 , 1, NULL);#ifdef OSDTIMETABALE OSDtimeMax= 0;#endif ASSERT(phr); setThreadName(DWORD(-1),"decVideo"); static const TintOptionT<TffdshowDecVideo> iopts[]= { IDFF_currentFrame ,&TffdshowDecVideo::currentFrame , 1, 1,_l("Current frame"),0,NULL,0, IDFF_decodingFps ,&TffdshowDecVideo::decodingFps ,-1,-1,_l("Decoding Fps"),0,NULL,0, IDFF_AVIcolorspace ,&TffdshowDecVideo::decodingCsp ,-1,-1,_l("Input colorspace"),0,NULL,0, IDFF_dvdproc ,&TffdshowDecVideo::dvdproc ,-1,-1,_l(""),0,NULL,0, IDFF_currentq ,&TffdshowDecVideo::currentq ,0,6,_l(""),0,NULL,0, IDFF_subShowEmbedded ,&TffdshowDecVideo::subShowEmbedded ,0,40,_l(""),0,NULL,0, //IDFF_subFoundEmbedded ,&TffdshowDecVideo::foundEmbedded ,0,0,_l(""),0,NULL,0, IDFF_subCurLang ,&TffdshowDecVideo::subCurLang ,-3,-3,_l(""),0,NULL,0, 0 }; addOptions(iopts); trayIconStart=&TtrayIconBase::start<TtrayIconDecVideo>; inpin=new TffdshowVideoInputPin(NAME("TffdshowVideoInputPin"),this,phr); if (!inpin) *phr=E_OUTOFMEMORY; else inpin->SetLockm_csReceiveRequired(false); // We don't want the input pin lock m_csReceive. We lock it in deliverProcessedSample. m_pInput=inpin; if (FAILED(*phr)) return; //textpin=new TtextInputPin(this,phr); 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; } subShowEmbedded=0; imgFilters=NULL; wasSubtitleResetTime=false;fontManager=NULL; m_frame.dstColorspace=0; currentFrame=-1;decodingFps=0;decodingCsp=FF_CSP_NULL; segmentStart=-1;segmentFrameCnt=0; videoWindow=NULL;wasVideoWindow=false; basicVideo=NULL;wasBasicVideo=false; currentq=0; subCurLang=0; dvdproc=0; hwDeinterlace=false; waitForKeyframe=0;}TffdshowDecVideoRaw::TffdshowDecVideoRaw(LPUNKNOWN punk,HRESULT *phr):TffdshowDecVideo(CLSID_FFDSHOWRAW,NAME("TffdshowDecVideoRaw"),CLSID_TFFDSHOWPAGERAW,IDS_FFDSHOWDECVIDEORAW,IDI_FFDSHOW,punk,phr,IDFF_FILTERMODE_PLAYER|IDFF_FILTERMODE_VIDEORAW,defaultMerit,new TintStrColl){}// destructorTffdshowDecVideo::~TffdshowDecVideo(){ DPRINTF(_l("TffdshowDecVideo::Destructor")); m_csReceive.Unlock(); m_csReceiveProtector.Unlock(); waitForVideoThread(); waitForReceiveThread(); CloseHandle(hVideoSemaphore); for (size_t i=0;i<textpins.size();i++) delete textpins[i]; if (fontManager) delete fontManager;}HRESULT TffdshowDecVideo::CheckConnect(PIN_DIRECTION dir,IPin *pPin){ HRESULT res; switch (dir) { case PINDIR_INPUT: dvdproc=searchPrevNextFilter(PINDIR_INPUT,pPin,CLSID_DVDNavigator); return S_OK; case PINDIR_OUTPUT: { if (!presetSettings) initPreset(); CLSID clsid=GetCLSID(pPin); outOldRenderer=!!(clsid==CLSID_VideoRenderer); if (presetSettings->output->allowOutChange3 || dvdproc) { bool filterOk=clsid==CLSID_OverlayMixer || clsid==CLSID_VideoMixingRenderer || clsid==CLSID_VideoMixingRenderer9 || clsid==CLSID_DirectVobSubFilter || clsid==CLSID_DirectVobSubFilter2 || clsid==CLSID_FFDSHOW || clsid==CLSID_FFDSHOWRAW; allowOutChange=dvdproc || presetSettings->output->allowOutChange3==1 || (presetSettings->output->allowOutChange3==2 && filterOk); if (presetSettings->output->allowOutChange3==1 && presetSettings->output->outChangeCompatOnly) res=filterOk?S_OK:E_FAIL; else res=S_OK; } else { allowOutChange=false; res=S_OK; } break; } default: return E_UNEXPECTED; } return res==S_OK?CTransformFilter::CheckConnect(dir,pPin):res;}HRESULT TffdshowDecVideo::CheckInputType(const CMediaType *mtIn){ return S_OK;}// get list of supported output colorspacesHRESULT TffdshowDecVideo::GetMediaType(int iPosition, CMediaType *mtOut){ DPRINTF(_l("TffdshowDecVideo::GetMediaType")); if (m_pInput->IsConnected()==FALSE) return E_UNEXPECTED; if (!presetSettings) initPreset(); int hwOverlay=presetSettings->output->hwOverlay; if (hwOverlay==2 && m_pOutput->IsConnected()) { const CLSID &ref=GetCLSID(m_pOutput->GetConnected()); if (ref==CLSID_VideoMixingRenderer || ref==CLSID_VideoMixingRenderer9) hwOverlay=1; } bool isVIH2=!outdv && (hwOverlay==1 || (hwOverlay==2 && (iPosition&1)==0)); if (hwOverlay==2) iPosition/=2; if (iPosition<0) return E_INVALIDARG; TcspInfos ocsps;size_t osize; if (outdv) osize=1; else { presetSettings->output->getOutputColorspaces(ocsps); osize=ocsps.size(); } if ((size_t)iPosition>=osize) return VFW_S_NO_MORE_ITEMS; TffPictBase pictOut=inpin->pictIn; calcNewSize(pictOut); if (presetSettings->output->closest && !outdv) ocsps.sort(pictOut.csp); oldRect=pictOut.rectFull; static const TcspInfo dv= { 0,_l("DVSD"), 3,24, //Bpp 1, //numplanes {0,0,0,0}, //shiftX {0,0,0,0}, //shiftY {0,0,0,0}, //black, FOURCC_DVSD, FOURCC_YV12, &MEDIASUBTYPE_DVSD }; const TcspInfo *c=outdv?&dv:ocsps[iPosition]; BITMAPINFOHEADER bih;memset(&bih,0,sizeof(bih)); bih.biSize =sizeof(BITMAPINFOHEADER); bih.biWidth =pictOut.rectFull.dx; bih.biHeight=pictOut.rectFull.dy; bih.biPlanes=WORD(c->numPlanes); bih.biCompression=c->fcc; bih.biBitCount=WORD(c->bpp); bih.biSizeImage=DIBSIZE(bih);// bih.biWidth*bih.biHeight*bih.biBitCount>>3; mtOut->majortype=MEDIATYPE_Video; mtOut->subtype=*c->subtype; mtOut->formattype=isVIH2?FORMAT_VideoInfo2:FORMAT_VideoInfo; mtOut->SetTemporalCompression(FALSE); mtOut->SetSampleSize(bih.biSizeImage); if (!isVIH2) { VIDEOINFOHEADER *vih=(VIDEOINFOHEADER*)mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER)); if (!vih) return E_OUTOFMEMORY; ZeroMemory(vih,sizeof(VIDEOINFOHEADER)); vih->rcSource.left=0;vih->rcSource.right=bih.biWidth;vih->rcSource.top=0;vih->rcSource.bottom=bih.biHeight; vih->rcTarget=vih->rcSource; vih->AvgTimePerFrame=inpin->avgTimePerFrame; vih->bmiHeader=bih; } else { VIDEOINFOHEADER2 *vih2=(VIDEOINFOHEADER2*)mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER2)); if (!vih2) return E_OUTOFMEMORY; ZeroMemory(vih2,sizeof(VIDEOINFOHEADER2)); setVIH2aspect(vih2,pictOut.rectFull,presetSettings->output->hwOverlayAspect); vih2->rcSource.left=0;vih2->rcSource.right=bih.biWidth;vih2->rcSource.top=0;vih2->rcSource.bottom=bih.biHeight; vih2->rcTarget=vih2->rcSource; vih2->AvgTimePerFrame=inpin->avgTimePerFrame; vih2->bmiHeader=bih; hwDeinterlace=presetSettings->output->hwDeinterlace; if (hwDeinterlace) vih2->dwInterlaceFlags=AMINTERLACE_IsInterlaced|AMINTERLACE_DisplayModeBobOrWeave; } return S_OK;}HRESULT TffdshowDecVideo::setOutputMediaType(const CMediaType &mt){ DPRINTF(_l("TffdshowDecVideo::setOutputMediaType"));/* enable this to strictly require selected output colorspaces bool ok=false; TcspInfos ocsps;presetSettings->output->getOutputColorspaces(ocsps); for (TcspInfos::const_iterator oc=ocsps.begin();oc!=ocsps.end();oc++) if (mt.subtype==*(*oc)->subtype) { ok=true; break; } if (!ok) return S_FALSE;*/ for (int i=0;cspFccs[i].name;i++) { const TcspInfo *cspInfo; if (*(cspInfo=csp_getInfo(cspFccs[i].csp))->subtype==mt.subtype) { m_frame.dstColorspace=cspFccs[i].csp; if (m_frame.dstColorspace==FF_CSP_NV12) m_frame.dstColorspace=FF_CSP_NV12|FF_CSP_FLAGS_YUV_ORDER; // HACK int biWidth,outDy; BITMAPINFOHEADER *bih; if (mt.formattype==FORMAT_VideoInfo) { VIDEOINFOHEADER *vih=(VIDEOINFOHEADER*)mt.pbFormat; m_frame.dstStride=calcBIstride(biWidth=vih->bmiHeader.biWidth,cspInfo->Bpp*8); outDy=vih->bmiHeader.biHeight; bih=&vih->bmiHeader; } else if (mt.formattype==FORMAT_VideoInfo2) { VIDEOINFOHEADER2 *vih2=(VIDEOINFOHEADER2*)mt.pbFormat; m_frame.dstStride=calcBIstride(biWidth=vih2->bmiHeader.biWidth,cspInfo->Bpp*8); outDy=vih2->bmiHeader.biHeight; bih=&vih2->bmiHeader; } else return S_FALSE; m_frame.dstSize=DIBSIZE(*bih); char_t s[256]; DPRINTF(_l("TffdshowDecVideo::setOutputMediaType: colorspace:%s, biWidth:%i, dstStride:%i, Bpp:%i, dstSize:%i"),csp_getName(m_frame.dstColorspace,s,256),biWidth,m_frame.dstStride,cspInfo->Bpp,m_frame.dstSize); if (csp_isRGB(m_frame.dstColorspace) && outDy>0) m_frame.dstColorspace|=FF_CSP_FLAGS_VFLIP; //else if (biheight<0) // m_frame.colorspace|=FF_CSP_FLAGS_VFLIP; return S_OK; } } m_frame.dstColorspace=FF_CSP_NULL; return S_FALSE; }// set output colorspaceHRESULT TffdshowDecVideo::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt){ DPRINTF(_l("TffdshowDecVideo::SetMediaType")); switch (direction) { case PINDIR_INPUT: return S_OK; case PINDIR_OUTPUT: return setOutputMediaType(*pmt); default: return E_UNEXPECTED; } }// check input<->output compatibilityHRESULT TffdshowDecVideo::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut){ DPRINTF(_l("TffdshowDecVideo::CheckTransform")); if (!outOldRenderer) return S_OK; else { BITMAPINFOHEADER biOut; ExtractBIH(*mtOut,&biOut); if ((unsigned int)ff_abs(biOut.biWidth)>=oldRect.dx && (unsigned int)ff_abs(biOut.biHeight)==oldRect.dy) return S_OK; else return VFW_E_TYPE_NOT_ACCEPTED; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?