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