📄 tvideocodecxvid4.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 "TvideoCodecXviD4.h"
#include "xvidcore\xvid.h"
#include "xvidcore\decoder.h"
#include "Tdll.h"
#include "TcodecSettings.h"
#include "IffdshowBase.h"
#include "dsutil.h"
#include "ffdebug.h"
const TmeXviDpreset meXviDpresets[]=
{
_l("None") ,0,
_l("Very low") ,0,
_l("Low") ,0,
_l("Medium") ,0,
_l("High") ,XVID_ME::HALFPELREFINE16,
_l("Very high") ,XVID_ME::HALFPELREFINE16|XVID_ME::ADVANCEDDIAMOND16,
_l("Ultra high"),XVID_ME::HALFPELREFINE16|XVID_ME::EXTSEARCH16|XVID_ME::HALFPELREFINE8|XVID_ME::USESQUARES16,
NULL,0
};
const TmeXviDpreset vhqXviDpresets[]=
{
_l("Off") ,0,
_l("Mode decision") ,0,
_l("Limited search"),XVID_ME_RD::HALFPELREFINE16|XVID_ME_RD::QUARTERPELREFINE16,
_l("Medium search") ,XVID_ME_RD::HALFPELREFINE16|XVID_ME_RD::HALFPELREFINE8|XVID_ME_RD::QUARTERPELREFINE16|XVID_ME_RD::QUARTERPELREFINE8|XVID_ME_RD::CHECKPREDICTION,
_l("Full search") ,XVID_ME_RD::HALFPELREFINE16|XVID_ME_RD::HALFPELREFINE8|XVID_ME_RD::QUARTERPELREFINE16|XVID_ME_RD::QUARTERPELREFINE8|XVID_ME_RD::CHECKPREDICTION|XVID_ME_RD::EXTSEARCH,
NULL,0
};
const char_t* TvideoCodecXviD4::dllname=_l("xvidcore.dll");
int TvideoCodecXviD4::me_hq(int rd3)
{
int rd4=0;
if (rd3&XVID_ME_RD::HALFPELREFINE16 ) rd4|=XVID_ME_HALFPELREFINE16_RD;
if (rd3&XVID_ME_RD::HALFPELREFINE8 ) rd4|=XVID_ME_HALFPELREFINE8_RD;
if (rd3&XVID_ME_RD::QUARTERPELREFINE16) rd4|=XVID_ME_QUARTERPELREFINE16_RD;
if (rd3&XVID_ME_RD::QUARTERPELREFINE8 ) rd4|=XVID_ME_QUARTERPELREFINE8_RD;
if (rd3&XVID_ME_RD::EXTSEARCH ) rd4|=XVID_ME_EXTSEARCH_RD;
if (rd3&XVID_ME_RD::CHECKPREDICTION ) rd4|=XVID_ME_CHECKPREDICTION_RD;
return rd4;
}
int TvideoCodecXviD4::me_(int me3)
{
int me4=0;
if (me3&XVID_ME::ADVANCEDDIAMOND16) me4|=XVID_ME_ADVANCEDDIAMOND16;
if (me3&XVID_ME::HALFPELREFINE16 ) me4|=XVID_ME_HALFPELREFINE16;
if (me3&XVID_ME::EXTSEARCH16 ) me4|=XVID_ME_EXTSEARCH16;
if (me3&XVID_ME::USESQUARES16 ) me4|=XVID_ME_USESQUARES16;
if (me3&XVID_ME::ADVANCEDDIAMOND8 ) me4|=XVID_ME_ADVANCEDDIAMOND8;
if (me3&XVID_ME::HALFPELREFINE8 ) me4|=XVID_ME_HALFPELREFINE8;
if (me3&XVID_ME::EXTSEARCH8 ) me4|=XVID_ME_EXTSEARCH8;
if (me3&(int)XVID_ME::USESQUARES8 ) me4|=XVID_ME_USESQUARES8;
return me4;
}
TvideoCodecXviD4::TvideoCodecXviD4(IffdshowBase *Ideci,IdecVideoSink *IsinkD):
Tcodec(Ideci),TcodecDec(Ideci,IsinkD),
TvideoCodec(Ideci),
TvideoCodecDec(Ideci,IsinkD),
TvideoCodecEnc(Ideci,NULL)
{
create();
}
TvideoCodecXviD4::TvideoCodecXviD4(IffdshowBase *Ideci,IencVideoSink *IsinkE):
Tcodec(Ideci),TcodecDec(Ideci,NULL),
TvideoCodec(Ideci),
TvideoCodecDec(Ideci,NULL),
TvideoCodecEnc(Ideci,IsinkE)
{
create();
if (ok)
encoders.push_back(new Tencoder(_l("XviD"),CODEC_ID_XVID4));
}
void TvideoCodecXviD4::create(void)
{
frame=new xvid_enc_frame_t;
enchandle=NULL;
dechandle=NULL;
extradata=NULL;
dll=new Tdll(dllname,config);
dll->loadFunction(xvid_global,"xvid_global");
dll->loadFunction(xvid_encore,"xvid_encore");
dll->loadFunction(xvid_decore,"xvid_decore");
dll->loadFunction(xvid_plugin_single,"xvid_plugin_single");
dll->loadFunction(xvid_plugin_lumimasking,"xvid_plugin_lumimasking");
if (dll->ok)
{
xvid_gbl_init_t init;
memset(&init,0,sizeof(init));
init.version=XVID_VERSION;
init.cpu_flags=(unsigned int)(XVID_CPU_ASM|XVID_CPU_FORCE);
if (Tconfig::cpu_flags&FF_CPU_MMX ) init.cpu_flags|=XVID_CPU_MMX;
if (Tconfig::cpu_flags&FF_CPU_MMXEXT ) init.cpu_flags|=XVID_CPU_MMXEXT;
if (Tconfig::cpu_flags&FF_CPU_SSE ) init.cpu_flags|=XVID_CPU_SSE;
if (Tconfig::cpu_flags&FF_CPU_SSE2 ) init.cpu_flags|=XVID_CPU_SSE2;
if (Tconfig::cpu_flags&FF_CPU_SSE3 ) init.cpu_flags|=XVID_CPU_SSE3;
if (Tconfig::cpu_flags&FF_CPU_3DNOW ) init.cpu_flags|=XVID_CPU_3DNOW;
if (Tconfig::cpu_flags&FF_CPU_3DNOWEXT) init.cpu_flags|=XVID_CPU_3DNOWEXT;
if (xvid_global(NULL,XVID_GBL_INIT,&init,NULL)==0)
{
ok=true;
quantBytes=4;
return;
}
}
ok=false;
}
TvideoCodecXviD4::~TvideoCodecXviD4()
{
end();
if (dll)
{
delete dll;
dll=NULL;
}
delete frame;
}
bool TvideoCodecXviD4::getVersion(const Tconfig *config,ffstring &vers,ffstring &license)
{
Tdll *dl=new Tdll(dllname,config);
int (*xvid_global)(void *handle, int opt, void *param1, void *param2);
dl->loadFunction(xvid_global,"xvid_global");
bool res=false;
if (xvid_global)
{
res=true;
xvid_gbl_info_t info;
memset(&info,0,sizeof(info));
info.version=XVID_VERSION;
xvid_global(0,XVID_GBL_INFO,&info,NULL);
vers=ffstring::intToStr(XVID_VERSION_MAJOR(info.actual_version))+_l(".")+ffstring::intToStr(XVID_VERSION_MINOR(info.actual_version))+_l(".")+ffstring::intToStr(XVID_VERSION_PATCH(info.actual_version));
license.clear();
}
else
{
vers=_l("XviD: not found");
license.clear();
}
delete dl;
return res;
}
//-------------------------- decompression ----------------------------
bool TvideoCodecXviD4::beginDecompress(TffPictBase &pict,FOURCC infcc,const CMediaType &mt,int sourceFlags)
{
xvid_dec_create_t dr;
dr.version=XVID_VERSION;
dr.width=0;
dr.height=0;
extradata=new Textradata(mt,8);
int res=xvid_decore(NULL,XVID_DEC_CREATE,&dr,NULL);
if (res<0) return false;
dechandle=dr.handle;
pictbuf.clear();
quantsDx=(pict.rectFull.dx+15)>>4;quantsDy=(pict.rectFull.dy+15)>>4;
pict.csp=FF_CSP_420P;
return true;
}
HRESULT TvideoCodecXviD4::flushDec(void)
{
return decompress(NULL,0,NULL);
}
HRESULT TvideoCodecXviD4::decompress(const unsigned char *src0,size_t srcLen0,IMediaSample *pIn)
{
xvid_dec_frame_t xframe;
xframe.version=XVID_VERSION;
xframe.general=XVID_LOWDELAY;
//TODO: XVID_DISCONTINUITY
xframe.output.csp=XVID4_CSP_PLANAR;
xframe.brightness=0;
const unsigned char *src;size_t srcLen;TbyteBuffer buf;
if (extradata && extradata->size)
{
buf.append(extradata->data,extradata->size);
buf.append(src0,srcLen0);
src=&*buf.begin();
srcLen=buf.size();
delete extradata;extradata=NULL;
}
else
{
src=src0;
srcLen=srcLen0;
}
if (pIn)
if (FAILED(pIn->GetTime(&rtStart,&rtStop)))
rtStart=rtStop=_I64_MIN;
repeat:
xframe.bitstream=(void*)src;
xframe.length=src0?(int)srcLen:-1;
xframe.output.plane[0]=pict.data[0];xframe.output.plane[1]=pict.data[1];xframe.output.plane[2]=pict.data[2];
xframe.output.stride[0]=(int)pict.stride[0];xframe.output.stride[1]=(int)pict.stride[1];xframe.output.stride[2]=(int)pict.stride[2];
xvid_dec_stats_t stats;memset(&stats,0,sizeof(stats));
stats.version=XVID_VERSION;
int length=xvid_decore(dechandle,XVID_DEC_DECODE,&xframe,&stats);
if (extradata) {delete extradata;extradata=NULL;}
if (length<0 || (stats.type==XVID_TYPE_NOTHING && length>0))
return S_FALSE;
if (stats.type==XVID_TYPE_VOL)
{
pict.alloc(stats.data.vol.width,stats.data.vol.height,FF_CSP_420P,pictbuf);
if (stats.data.vol.par==XVID_PAR_EXT)
pict.rectFull.sar=pict.rectClip.sar=Rational(stats.data.vol.par_width,stats.data.vol.par_height);
else if (isMPC_matroska && stats.data.vol.par==XVID_PAR_11_VGA) // With MPC's internal matroska splitter, AR is not reliable.
pict.rectFull.sar=containerSar;
else
{
static const int pars[][2]=
{
{ 1, 1},
{12,11},
{10,11},
{16,11},
{40,33},
{ 0, 0},
};
pict.rectFull.sar=pict.rectClip.sar=Rational(pars[stats.data.vol.par-1][0],pars[stats.data.vol.par-1][1]);
}
src+=length;
srcLen-=length;
goto repeat;
}
else
{
switch (stats.type)
{
case XVID_TYPE_IVOP:pict.frametype=FRAME_TYPE::I;break;
case XVID_TYPE_PVOP:pict.frametype=FRAME_TYPE::P;break;
case XVID_TYPE_BVOP:pict.frametype=FRAME_TYPE::B;break;
case XVID_TYPE_SVOP:pict.frametype=FRAME_TYPE::GMC;break;
}
if (pIn && pIn->IsPreroll()==S_OK)
return sinkD->deliverPreroll(pict.frametype);
quants=stats.data.vop.qscale;
quantsStride=stats.data.vop.qscale_stride;
quantType=1;
TffPict p1=pict;
DECODER *dec=(DECODER *)dechandle;
p1.fieldtype=dec->interlacing?(dec->top_field_first?FIELD_TYPE::INT_TFF:FIELD_TYPE::INT_BFF):FIELD_TYPE::PROGRESSIVE_FRAME;
if (pIn)
{
p1.rtStart=rtStart;
p1.rtStop=rtStop;
}
else
{
p1.rtStart=rtStop;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -