📄 tffpict.cpp
字号:
/*
* 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 + -