⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tffpict.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2002-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 "TffRect.h"
#include "TffPict.h"
#include "Tconvert.h"
#include "Tconfig.h"
#include "ffImgfmt.h"
#include "Tlibavcodec.h"
#include "IffdshowBase.h"
#include "simd.h"
#include "md5sum.h"

int FRAME_TYPE::fromSample(IMediaSample *pIn)
{
 return (!pIn || pIn->IsSyncPoint()==S_OK)?I:P;
}
int FIELD_TYPE::fromSample(IMediaSample *pIn,bool isInterlacedRawVideo)
{
 if (pIn && isInterlacedRawVideo)
  if (comptrQ<IMediaSample2> pIn2=pIn)
   {
    AM_SAMPLE2_PROPERTIES inProp2;
    if (SUCCEEDED(pIn2->GetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES,tStart),(PBYTE)&inProp2)))
     {
      // Set interlace information (every sample)
      if (!(inProp2.dwTypeSpecificFlags&AM_VIDEO_FLAG_WEAVE))
       if (inProp2.dwTypeSpecificFlags&AM_VIDEO_FLAG_FIELD1FIRST)
        return INT_TFF;
       else
        return INT_BFF;
     }
   }
 return PROGRESSIVE_FRAME;
}

//===================================== Tpalette ====================================
Tpalette::Tpalette(const AVPaletteControl *palctrl)
{
 pal=palctrl?(const unsigned char*)palctrl->palette:NULL;
 numcolors=palctrl?256:0;
}

//=================================== TffPictBase ===================================
TffPictBase::TffPictBase(unsigned int Idx,unsigned int Idy)
{
 setSize(Idx,Idy);
}
void TffPictBase::setSize(unsigned int Idx,unsigned int Idy)
{
 rectFull=rectClip=Trect(0,0,Idx,Idy);
 memset(diff,0,sizeof(diff));
}
void TffPictBase::setDar(const Rational &dar)
{
 rectFull.setDar(dar);
 rectClip.setDar(dar);
}
void TffPictBase::setSar(const Rational &sar)
{
 rectFull.sar=sar;
 rectClip.sar=sar;
}

Trect TffPictBase::getRect(int full,int half) const
{
 Trect rect=full?rectFull:rectClip;
 if (half) {rect.dx/=2;rect.x+=rect.dx;}
 return rect;
}

//===================================== TffPict =====================================
TffPict::Tcopy* TffPict::copy=TffPict::asm_BitBlt_C;
extern "C" void asm_BitBlt_ISSE(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height);
void TffPict::initCopy(int cpu_flags)
{
 #ifndef WIN64
 if (cpu_flags&FF_CPU_MMXEXT)
  copy=::asm_BitBlt_ISSE;
 else
 #endif
 if (cpu_flags&FF_CPU_MMX)
  copy=asm_BitBlt_MMX;
 else
  copy=asm_BitBlt_C;
}

TffPict::TffPict(void)
{
 init();
}
void TffPict::init(void)
{
 csp=FF_CSP_NULL;memset(&cspInfo,0,sizeof(cspInfo));
 memset(data,0,sizeof(data));memset(stride,0,sizeof(stride));memset(ro,0,sizeof(ro));memset(diff,0,sizeof(diff));
 frametype=FRAME_TYPE::UNKNOWN;fieldtype=FIELD_TYPE::PROGRESSIVE_FRAME;
 rtStart=rtStop=mediatimeStart=mediatimeStop=REFTIME_INVALID;
 gmcWarpingPoints=gmcWarpingPointsReal=0;
 edge=0;
}
void TffPict::init(int Icsp,unsigned char *Idata[4],const stride_t Istride[4],const Trect &r,bool Iro,int Iframetype,int Ifieldtype,size_t IsrcSize,const Tpalette &Ipalette)
{
 cspInfo=*csp_getInfo(csp=Icsp);
 frametype=Iframetype;fieldtype=Ifieldtype;
 unsigned int i;
 for (i=0;i<cspInfo.numPlanes;i++)
  {
   data[i]=Idata[i];
   stride[i]=Istride[i];
   ro[i]=Iro;
   diff[i]=0;
  }
 for (;i<4;i++)
  {
   data[i]=NULL;
   stride[i]=diff[i]=0;
   ro[i]=false;
  }
 palette=Ipalette;
 rectFull=rectClip=r;
 rtStart=rtStop=mediatimeStart=mediatimeStop=REFTIME_INVALID;
 gmcWarpingPoints=gmcWarpingPointsReal=0;
 srcSize=IsrcSize;
 edge=0;
}
TffPict::TffPict(int Icsp,unsigned char *Idata[4],const stride_t Istride[4],const Trect &r,bool Iro,int Iframetype,int Ifieldtype,size_t IsrcSize,IMediaSample *pIn,const Tpalette &Ipalette)
{
 init(Icsp,Idata,Istride,r,Iro,Iframetype,Ifieldtype,IsrcSize,Ipalette);
 if (pIn) setTimestamps(pIn);
}
TffPict::TffPict(int Icsp,unsigned char *data[4],const stride_t stride[4],const Trect &r,bool ro,IMediaSample *pIn,const Tpalette &Ipalette,bool isInterlacedRawVideo)
{
 init(Icsp,data,stride,r,ro,FRAME_TYPE::fromSample(pIn),FIELD_TYPE::fromSample(pIn,isInterlacedRawVideo),pIn?pIn->GetSize():0,Ipalette);
 if (pIn) setTimestamps(pIn);
}
void TffPict::setTimestamps(IMediaSample *pIn)
{
 if (FAILED(pIn->GetTime(&rtStart,&rtStop)))
  rtStart=rtStop=REFTIME_INVALID;
 if (FAILED(pIn->GetMediaTime(&mediatimeStart,&mediatimeStop)))
  mediatimeStart=mediatimeStop=REFTIME_INVALID;
}

void TffPict::readLibavcodec(int Icsp,const char_t *flnm,const char_t *ext,Tbuffer &buf,IffdshowBase *deci)
{
 Tlibavcodec *libavcodec;
 if (FAILED(deci->getLibavcodec(&libavcodec))) return;
 AVCodec *avcodec=libavcodec->avcodec_find_decoder(stricmp(ext,_l(".png"))==0?CODEC_ID_PNG:CODEC_ID_MJPEG);
 if (!avcodec) return;
 AVCodecContext *avctx=libavcodec->avcodec_alloc_context();
 avctx->flags|=CODEC_FLAG_TRUNCATED;
 if (libavcodec->avcodec_open(avctx,avcodec)>=0)
  {
   FILE *f=fopen(flnm,_l("rb"));if (!f) return;
   int srclen=_filelength(fileno(f));
   uint8_t *src=(uint8_t*)calloc(srclen,2);
   fread(src,1,srclen,f);
   fclose(f);
   AVFrame *frame=libavcodec->avcodec_alloc_frame();
   int got_picture=0;
   int ret=libavcodec->avcodec_decode_video(avctx,frame,&got_picture,src,srclen);
   if (got_picture && frame->data[0])
    {
     const stride_t linesize[4]={frame->linesize[0],frame->linesize[1],frame->linesize[2],frame->linesize[3]};
     init(csp_lavc2ffdshow(avctx->pix_fmt),frame->data,linesize,Trect(0,0,avctx->width,avctx->height),true,frametype,fieldtype,srclen,avctx->palctrl);
     Tconvert *convert=new Tconvert(deci,avctx->width,avctx->height);
     convertCSP(csp_bestMatch(csp,Icsp),buf,convert);
     delete convert;
    }
   else
    readOle(Icsp,flnm,ext,buf,deci);
   free(src);
   libavcodec->av_free(frame);
  }
 libavcodec->avcodec_close(avctx);
 libavcodec->av_free(avctx);
 libavcodec->Release();
}
void TffPict::readOle(int Icsp,const char_t *flnm,const char_t *ext,Tbuffer &buf,IffdshowBase *deci)
{
 //wchar_t flnmL[MAX_PATH];memset(flnmL,0,sizeof(flnmL));nCopyAnsiToWideChar(flnmL,flnm);
 comptr<IPicture> ip;
 if (OleLoadPicturePath((LPOLESTR)(const wchar_t*)text<wchar_t>(flnm),NULL,0,0,IID_IPicture,(void**)&ip)==S_OK)
  {
   long dxm,dym;
   ip->get_Width(&dxm);ip->get_Height(&dym);
   static const int HIMETRIC_PER_INCH=2540;
   const HDC hDCScreen=GetDC(NULL);
   const int nPixelsPerInchX=GetDeviceCaps(hDCScreen,LOGPIXELSX);
   const int nPixelsPerInchY=GetDeviceCaps(hDCScreen,LOGPIXELSY);
   ReleaseDC(NULL,hDCScreen);
   Tbuffer bufRGB;
   int pdx=(nPixelsPerInchX*dxm+HIMETRIC_PER_INCH/2)/HIMETRIC_PER_INCH,pdy=(nPixelsPerInchY*dym+HIMETRIC_PER_INCH/2)/HIMETRIC_PER_INCH;
   int pdx4=pdx;if (pdx4&3) pdx4=(pdx/4+1)*4;
   alloc(pdx4,pdy,FF_CSP_RGB24,bufRGB);
   HDC cdc=CreateCompatibleDC(NULL);
   HRESULT hr=ip->SelectPicture(cdc,NULL,NULL);
   BITMAPINFO bmi;
   bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader);
   bmi.bmiHeader.biWidth=pdx4;
   bmi.bmiHeader.biHeight=-pdy;
   bmi.bmiHeader.biPlanes=1;
   bmi.bmiHeader.biBitCount=24;
   bmi.bmiHeader.biCompression=BI_RGB;
   bmi.bmiHeader.biSizeImage=3*rectFull.dx*rectFull.dy;
   bmi.bmiHeader.biXPelsPerMeter=75;
   bmi.bmiHeader.biYPelsPerMeter=75;
   bmi.bmiHeader.biClrUsed=0;
   bmi.bmiHeader.biClrImportant=0;
   HBITMAP hbmp;ip->get_Handle((OLE_HANDLE*)&hbmp);
   int lines=GetDIBits(cdc,hbmp,0,pdy,bufRGB,&bmi,DIB_RGB_COLORS);
   DeleteDC(cdc);
   Tconvert *convert=new Tconvert(deci,rectFull.dx,rectFull.dy);
   convertCSP(csp_bestMatch(csp,Icsp),buf,convert);
   delete convert;
   rectFull.dx=rectClip.dx=pdx;
  }
}

TffPict::TffPict(int Icsp,const char_t *flnm,Tbuffer &buf,IffdshowBase *deci)
{
 init();
 if (!fileexists(flnm)) return;
 char_t ext[MAX_PATH];
 _splitpath(flnm,NULL,NULL,NULL,ext);
 if (stricmp(ext,_l(".jpg"))==0 || stricmp(ext,_l(".jpeg"))==0 || stricmp(ext,_l(".png"))==0)
  readLibavcodec(Icsp,flnm,ext,buf,deci);
 else if (stricmp(ext,_l(".bmp"))==0 || stricmp(ext,_l(".gif"))==0)
  readOle(Icsp,flnm,ext,buf,deci);
}

void TffPict::clear(const Trect &r,unsigned int plane)
{
 if (r.dx!=0 && r.dy!=0 && !ro[plane])
  clear(cspInfo.Bpp,cspInfo.black[plane],data[plane]+r.y*stride[plane]+cspInfo.Bpp*r.x,stride[plane],cspInfo.Bpp*r.dx,r.dy);
}
void TffPict::clear(int full,unsigned int plane)
{
 const Trect &r=full?rectFull:rectClip;
 for (unsigned int i=0;i<cspInfo.numPlanes;i++)
  if (plane==PLANE_ALL || i==plane)
   clear(Trect(r.x>>cspInfo.shiftX[i],r.y>>cspInfo.shiftY[i],r.dx>>cspInfo.shiftX[i],r.dy>>cspInfo.shiftY[i]),i);
}
void TffPict::clearBorder(void)
{
 if (rectFull==rectClip) return;
 for (unsigned int i=0;i<cspInfo.numPlanes;i++)
  {
   const int rectFulldx=rectFull.dx>>cspInfo.shiftX[i],rectFulldy=rectFull.dy>>cspInfo.shiftY[i];
   const int rectClipx =rectClip.x >>cspInfo.shiftX[i],rectClipy =rectClip.y >>cspInfo.shiftY[i];
   const int rectClipdx=rectClip.dx>>cspInfo.shiftX[i],rectClipdy=rectClip.dy>>cspInfo.shiftY[i];
   clear(Trect(0,0,rectFulldx,rectClipy),i);
   clear(Trect(0,rectClipy+rectClipdy,rectFulldx,rectFulldy-(rectClipy+rectClipdy)),i);
   clear(Trect(0,rectClipy,rectClipx,rectClipdy),i);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -