📄 timgfilteravisynth.cpp
字号:
buffersFilled++;
curInFrameNo++;
if ((buffersFilled < buffersNeeded) && !passFirstThrough && !passLastThrough)
// Not enough has been buffered, so don't return frames yet
return;
if (debugPrint)
{
if (passFirstThrough)
DPRINTF(_l("TimgFilterAvisynth: Passing through first frame"));
if (sequenceStart)
DPRINTF(_l("TimgFilterAvisynth: Start of MPEG2 sequence"));
if (sequenceEnd)
DPRINTF(_l("TimgFilterAvisynth: End of MPEG2 sequence, flushing buffers"));
}
int minBuffers=(passFirstThrough || passLastThrough ? 0 : bufferAhead);
while (buffers && buffersFilled > minBuffers)
{
int lastOutScaledFrameNo=(int)(REFERENCE_TIME(curOutFrameNo)*frameScaleNum/frameScaleDen);
int targetOutScaledFrameNo=(int)(REFERENCE_TIME(curOutFrameNo+1)*frameScaleNum/frameScaleDen);
int lastOutScaledFrameRem=(int)(REFERENCE_TIME(curOutFrameNo)*frameScaleNum%frameScaleDen);
if (lastOutScaledFrameNo < targetOutScaledFrameNo)
buffersFilled--;
bool finalBuffer=(passLastThrough && buffersFilled == 0 && numBuffers > 1);
if (curOutScaledFrameNo < targetOutScaledFrameNo)
curOutScaledFrameNo++;
if (curOutScaledFrameNo == targetOutScaledFrameNo || finalBuffer)
{
if (finalBuffer)
{
skipAhead(false,false);
passFirstThrough=false;
passLastThrough=false;
ignoreAheadValue=true;
}
int requestedFrame=curOutFrameNo;
// Set up request statistics
input->numAccessedFrames=0;
input->minAccessedFrame=INT_MAX;
input->maxAccessedFrame=INT_MIN;
input->curFrame=lastOutScaledFrameNo;
input->backLimit=backLimit;
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Requesting frame %i from Avisynth"),requestedFrame);
// Request frame from AviSynth script
PVideoFrame frame=(*input->clip)->GetFrame(requestedFrame);
// Evaluate request statistics
if (input->numAccessedFrames > 0 && !sequenceStart && !passFirstThrough)
{
if (minAccessedFrame > input->minAccessedFrame)
minAccessedFrame=input->minAccessedFrame;
if (ignoreAheadValue)
ignoreAheadValue=false;
else if (maxAccessedFrame < input->maxAccessedFrame)
maxAccessedFrame=input->maxAccessedFrame;
}
char* bufPos=infoBuf;
maxBufferBack=(minAccessedFrame < 0 ? -minAccessedFrame : 0);
maxBufferAhead=(maxAccessedFrame > 0 ? maxAccessedFrame : 0);
bufPos+=sprintf(
bufPos,
"Frame %6i: %3i back, %3i ahead; ",
lastOutScaledFrameNo,
maxBufferBack,
maxBufferAhead);
if (hasPulldown)
bufPos+=sprintf(bufPos,"applying pulldown; ");
bufPos+=sprintf(bufPos,"requested ");
int frameCount=input->numAccessedFrames;
if (frameCount > 100)
frameCount=100;
if (frameCount == 0)
bufPos+=sprintf(bufPos,"none");
else
for (int framePos=0; framePos < frameCount; framePos++)
bufPos+=sprintf(bufPos,"%i ",lastOutScaledFrameNo+input->accessedFrames[framePos]);
*bufPos=0;
if (debugPrint)
DPRINTFA("TimgFilterAvisynth: %s", infoBuf);
if (pict.diff[0] || outputRect!=self->pictRect)
{
// Copy resulting frame into current TffPict
unsigned char *data[4];
if (outputRect==self->pictRect)
self->getNext(self->outcsp,pict,cfg->full,data);
else
self->getNext(self->outcsp,pict,cfg->full,data,&outputRect);
if (outputRect != pict.rectFull)
self->parent->dirtyBorder=1;
if (isYV12)
{
TffPict::copy(data[0],self->stride2[0],frame->GetReadPtr(PLANAR_Y),frame->GetPitch(PLANAR_Y),frame->GetRowSize(PLANAR_Y),frame->GetHeight(PLANAR_Y));
TffPict::copy(data[1],self->stride2[1],frame->GetReadPtr(PLANAR_U),frame->GetPitch(PLANAR_U),frame->GetRowSize(PLANAR_U),frame->GetHeight(PLANAR_U));
TffPict::copy(data[2],self->stride2[2],frame->GetReadPtr(PLANAR_V),frame->GetPitch(PLANAR_V),frame->GetRowSize(PLANAR_V),frame->GetHeight(PLANAR_V));
}
else
TffPict::copy(data[0],self->stride2[0],frame->GetReadPtr(),frame->GetPitch(),frame->GetRowSize(),frame->GetHeight());
}
else
{
// Reference the resulting frame's data in current TffPict
pict.csp=self->outcsp;
if (isYV12)
{
pict.data[0]=(unsigned char*)frame->GetReadPtr(PLANAR_Y);pict.ro[0]=true;pict.stride[0]=frame->GetPitch(PLANAR_Y);
pict.data[1]=(unsigned char*)frame->GetReadPtr(PLANAR_U);pict.ro[1]=true;pict.stride[1]=frame->GetPitch(PLANAR_U);
pict.data[2]=(unsigned char*)frame->GetReadPtr(PLANAR_V);pict.ro[2]=true;pict.stride[2]=frame->GetPitch(PLANAR_V);
pict.data[3]=NULL;pict.stride[3]=0;
}
else
{
pict.data[0]=(unsigned char*)frame->GetReadPtr();pict.ro[0]=true;pict.stride[0]=frame->GetPitch();
pict.data[1]=pict.data[2]=pict.data[3]=NULL;
}
pict.calcDiff();
}
// Calculate the new frame's timestamps
TframeBuffer& lastOutFrameBuffer=buffers[findBuffer(buffers,numBuffers,lastOutScaledFrameNo)];
REFERENCE_TIME lastDuration=lastOutFrameBuffer.stop-lastOutFrameBuffer.start;
pict.fieldtype=lastOutFrameBuffer.fieldType;
if (frameScaleNum == frameScaleDen)
{
// Use original timestamps if no frames are added or removed
pict.rtStart=lastOutFrameBuffer.start;
pict.rtStop=lastOutFrameBuffer.stop;
}
else
{
// Interpolate new timestamps
pict.rtStart=lastOutFrameBuffer.start+lastDuration*(lastOutScaledFrameRem)/frameScaleDen;
pict.rtStop=pict.rtStart+lastDuration*frameScaleNum/frameScaleDen;
REFERENCE_TIME difference=pict.rtStart-lastOutStopTime;
if (difference < 0)
difference=-difference;
if (difference < lastDuration/4)
// Fill small gaps between consecutive frames
pict.rtStart=lastOutStopTime;
if ((passFirstThrough || finalBuffer) && pict.rtStart < lastOutStopTime)
{
// Make sure that a frame gets delivered when passFirstThrough or finalBuffer is true
pict.rtStart=lastOutStopTime;
if (pict.rtStop < pict.rtStart)
pict.rtStop=pict.rtStart+lastDuration*frameScaleNum/(frameScaleDen*2);
}
}
if ((frameScaleNum == frameScaleDen) ||
pict.rtStart >= lastOutStopTime && pict.rtStop > pict.rtStart)
{
// Only deliver frames with strictly increasing timestamps
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Delivering frame %i; %10.6f - %10.6f = %10.6f"),curOutFrameNo,pict.rtStart/10000.0,pict.rtStop/10000.0,(pict.rtStop-pict.rtStart)/10000.0);
if (input->outputDar)
pict.setDar(input->outputDar);
else if (input->outputSar)
pict.setSar(input->outputSar);
if (csp_isRGB_RGB(pict.csp))
pict.csp^=FF_CSP_FLAGS_VFLIP;
if (buffersFilled > minBuffers)
{
TffPict tempPict=pict;
++it;
self->parent->deliverSample(it,tempPict);
--it;
}
else
{
++it;
self->parent->deliverSample(it,pict);
--it;
}
}
curOutFrameNo++;
lastOutStopTime=pict.rtStop;
}
if (passFirstThrough)
skipAhead(false,false);
}
if (sequenceEnd)
skipAhead(false,false);
}
//===================================== TimgFilterAvisynth =====================================
TimgFilterAvisynth::TimgFilterAvisynth(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
avisynth=0;
input=0;
outFmtInput=0;
outcsp=FF_CSP_NULL;
oldcfg.script[0]='\0';
}
TimgFilterAvisynth::~TimgFilterAvisynth()
{
if (avisynth) delete avisynth;
if (input) delete input;
if (outFmtInput) delete outFmtInput;
}
void TimgFilterAvisynth::done(void)
{
if (avisynth) delete avisynth; avisynth=0;
if (input) delete input; input=0;
if (outFmtInput) delete outFmtInput; outFmtInput=0;
}
void TimgFilterAvisynth::onSizeChange(void)
{
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: onSizeChange"));
oldcfg.script[0]='\0';
}
void TimgFilterAvisynth::onSeek(void)
{
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: onSeek"));
if (avisynth) avisynth->skipAhead(false,true);
}
void TimgFilterAvisynth::onFlush(void)
{
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: onFlush"));
if (avisynth) avisynth->skipAhead(false,true);
}
void TimgFilterAvisynth::onStop(void)
{
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: onStop"));
if (avisynth) avisynth->skipAhead(false,true);
}
void TimgFilterAvisynth::reset(void)
{
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: reset"));
oldcfg.script[0]='\0';
}
/*
If this method returns false when the script is empty there won't be no video at all...
-- Leak
bool TimgFilterAvisynth::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TavisynthSettings *cfg=(const TavisynthSettings*)cfg0;
return super::is(pict,cfg) && cfg->script[0];
}
*/
int TimgFilterAvisynth::getWantedCsp(const TavisynthSettings *cfg) const
{
return (cfg->inYV12?FF_CSP_420P:0)|(cfg->inYUY2?FF_CSP_YUY2:0)|(cfg->inRGB24?FF_CSP_RGB24:0)|(cfg->inRGB32?FF_CSP_RGB32:0);
}
int TimgFilterAvisynth::getSupportedInputColorspaces(const TfilterSettingsVideo *cfg0) const
{
const TavisynthSettings *cfg=(const TavisynthSettings*)cfg0;
return getWantedCsp(cfg);
}
int TimgFilterAvisynth::getSupportedOutputColorspaces(const TfilterSettingsVideo *cfg) const
{
return outcsp?outcsp:FF_CSP_420P|FF_CSP_YUY2|FF_CSP_RGB24|FF_CSP_RGB32;
}
bool TimgFilterAvisynth::getOutputFmt(TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TavisynthSettings *cfg=(const TavisynthSettings*)cfg0;
try
{
Trect r=pict.getRect(cfg->full,cfg->half);
if (!outFmtInput)
outFmtInput=new Tinput();
outFmtInput->numBuffers=0;
outFmtInput->buffers=0;
outFmtInput->numAccessedFrames=0;
outFmtInput->minAccessedFrame=INT_MAX;
outFmtInput->maxAccessedFrame=INT_MIN;
outFmtInput->curFrame=0;
outFmtInput->backLimit=0;
outFmtInput->dx=r.dx;
outFmtInput->dy=r.dy;
outFmtInput->csp=getWantedCsp(cfg);
outFmtInput->cspBpp=(outFmtInput->csp ? csp_getInfo(outFmtInput->csp)->Bpp : 0);
outFmtInput->src[0]=NULL;
lavc_reduce(&outFmtInput->fpsnum,&outFmtInput->fpsden,deciV->getAVIfps1000_2(),1000,65000);
if (!avisynth) avisynth=new Tavisynth;
avisynth->setOutFmt(cfg,outFmtInput,pict);
}
catch (Tavisynth::AvisynthError &err)
{
DPRINTFA("%s",err.msg);
}
return true;
}
else
return false;
}
const char* TimgFilterAvisynth::getInfoBuffer(void)
{
if (avisynth && oldcfg.is && oldcfg.show)
return avisynth->infoBuf;
else
return "unavailable";
}
HRESULT TimgFilterAvisynth::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TavisynthSettings *cfg=(const TavisynthSettings*)cfg0;
init(pict,cfg->full,cfg->half);
int wantedcsp=getWantedCsp(cfg);
if (wantedcsp!=0)
{
bool reset=!cfg->equal(oldcfg);
if (reset)
done();
if (!input)
input=new Tinput();
getCur(wantedcsp,pict,cfg->full,input->src);
input->stride1=stride1;
if (reset)
{
oldcfg=*cfg;
try
{
debugPrint=(strnicmp(cfg->script,_l("#DEBUG"),6) == 0);
input->numBuffers=0;
input->buffers=0;
input->numAccessedFrames=0;
input->minAccessedFrame=INT_MAX;
input->maxAccessedFrame=INT_MIN;
input->curFrame=0;
input->backLimit=0;
input->dx=dx1[0];
input->dy=dy1[0];
input->csp=csp1;
input->cspBpp=csp_getInfo(csp1)->Bpp;
lavc_reduce(&input->fpsnum,&input->fpsden,deciV->getAVIfps1000_2(),1000,65000);
if (!avisynth) avisynth=new Tavisynth;
avisynth->init(oldcfg,input,&outcsp,pict);
deciV->drawOSD(0,50,_l(""));
}
catch (Tavisynth::AvisynthError &err)
{
deciV->drawOSD(0,50,text<char_t>(err.msg));
DPRINTFA("%s",err.msg);
}
}
if (avisynth && input && input->clip)
avisynth->process(this,it,pict,cfg);
}
}
return S_OK;
}
int TimgFilterAvisynth::getMaxBufferAhead() { return maxBufferAhead; }
int TimgFilterAvisynth::getMaxBufferBack() { return maxBufferBack; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -