📄 timgfilteravisynth.cpp
字号:
pict.rectFull=pict.rectClip=outputRect=Trect(0,0,vi.width,vi.height,input->outputSar);
else if ((unsigned int)vi.width != inputRect.dx || (unsigned int)vi.height != inputRect.dy)
pict.rectFull=pict.rectClip=outputRect=Trect(0,0,vi.width,vi.height,inputSar);
else
outputRect=inputRect;
restart=true;
deleteBuffers=true;
}
}
void TimgFilterAvisynth::Tavisynth::process(TimgFilterAvisynth *self,TfilterQueue::iterator& it,TffPict &pict,const TavisynthSettings *cfg)
{
bool sequenceStart=(pict.fieldtype & FIELD_TYPE::MASK_SEQ) == FIELD_TYPE::SEQ_START;
bool sequenceEnd=(pict.fieldtype & FIELD_TYPE::MASK_SEQ) == FIELD_TYPE::SEQ_END;
bool isYV12=((pict.csp&FF_CSPS_MASK) == FF_CSP_420P);
Tinput* input=self->input;
if (sequenceStart)
passFirstThrough=true;
if (sequenceEnd)
passLastThrough=true;
if (passFirstThrough)
resetBuffers=true;
if (restart)
{
if (debugPrint)
{
DPRINTF(_l("TimgFilterAvisynth: (Re-)Starting playback"));
DPRINTF(_l("TimgFilterAvisynth: FrameScale: %lli/%lli"),frameScaleNum,frameScaleDen);
}
skipAhead(passFirstThrough,true);
restart=false;
}
if (deleteBuffers)
{
if (debugPrint && (buffers || bufferData))
DPRINTF(_l("TimgFilterAvisynth: Freeing buffers"));
if (buffers) delete buffers; buffers=0;
if (bufferData) delete bufferData; bufferData=0;
deleteBuffers=false;
resetBuffers=true;
}
if (resetBuffers)
{
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: (Re-)Initializing buffers"));
hasPulldown=false;
buffersFilled=0;
curBufferNo=0;
minAccessedFrame=INT_MAX;
maxAccessedFrame=INT_MIN;
ignoreAheadValue=true;
if (!buffers)
input->buffers=buffers=new TframeBuffer[numBuffers+(applyPulldown != 0 ? 1 : 0)];
int pitch[4];
int width[4];
int height[4];
int size[4];
if (numBuffers > 1)
{
// Storage for buffers is only needed when there's more than one buffer
// NB: pitch, width, height and size aren't initialized in that case,
// but their values will be taken from the actual frame anyway later on
int bufferSize;
if (isYV12)
{
pitch[0]=input->stride1[0];
pitch[1]=input->stride1[1];
pitch[2]=input->stride1[2];
pitch[3]=0;
width[0]=input->dx;
width[1]=width[2]=input->dx/2;
width[3]=0;
height[0]=input->dy;
height[1]=height[2]=input->dy/2;
height[3]=0;
bufferSize =(size[0]=pitch[0]*height[0]);
bufferSize+=(size[1]=pitch[1]*height[1]);
bufferSize+=(size[2]=pitch[2]*height[2]);
size[3]=0;
}
else
{
pitch[0]=input->stride1[0];
pitch[1]=pitch[2]=pitch[3]=0;
width[0]=input->dx;
width[1]=width[2]=width[3]=0;
height[0]=input->dy;
height[1]=height[2]=height[3]=0;
bufferSize=(size[0]=pitch[0]*height[0]);
size[1]=size[2]=size[3]=0;
}
if (!bufferData)
bufferData=new unsigned char[bufferSize*(numBuffers+(applyPulldown == 1 ? 1 : 0)+1)];
}
unsigned char* newBuffer=bufferData;
for (int bufNo=0; bufNo < numBuffers+(applyPulldown > 0 ? 1 : 0); bufNo++)
{
buffers[bufNo].frameNo=-1;
buffers[bufNo].bytesPerPixel=input->cspBpp;
buffers[bufNo].start=0;
buffers[bufNo].stop=0;
buffers[bufNo].fieldType=0;
if (bufNo < numBuffers ||
applyPulldown == 1)
for (int planeNo=0; planeNo < 4; planeNo++)
{
buffers[bufNo].width[planeNo]=width[planeNo];
buffers[bufNo].height[planeNo]=height[planeNo];
buffers[bufNo].pitch[planeNo]=pitch[planeNo];
buffers[bufNo].data[planeNo]=newBuffer;
newBuffer+=size[planeNo];
}
}
resetBuffers=false;
}
TframeBuffer& curBuffer=buffers[curBufferNo];
curBuffer.frameNo=curInFrameNo;
if (numBuffers == 1)
{
// "Buffer" current frame without copying data
if (isYV12)
{
curBuffer.data[0]=(unsigned char*)input->src[0];
curBuffer.data[1]=(unsigned char*)input->src[1];
curBuffer.data[2]=(unsigned char*)input->src[2];
curBuffer.data[3]=0;
curBuffer.pitch[0]=input->stride1[0];
curBuffer.pitch[1]=input->stride1[1];
curBuffer.pitch[2]=input->stride1[2];
curBuffer.pitch[3]=0;
curBuffer.width[0]=input->dx;
curBuffer.width[1]=curBuffer.width[2]=input->dx/2;
curBuffer.width[3]=0;
curBuffer.height[0]=input->dy;
curBuffer.height[1]=curBuffer.height[2]=input->dy/2;
curBuffer.height[3]=0;
}
else
{
curBuffer.data[0]=(unsigned char*)input->src[0];
curBuffer.data[1]=curBuffer.data[2]=curBuffer.data[3]=0;
curBuffer.pitch[0]=input->stride1[0];
curBuffer.pitch[1]=curBuffer.pitch[2]=curBuffer.pitch[3]=0;
curBuffer.width[0]=input->dx;
curBuffer.width[1]=curBuffer.width[2]=curBuffer.width[3]=0;
curBuffer.height[0]=input->dy;
curBuffer.height[1]=curBuffer.height[2]=curBuffer.height[3]=0;
}
curBuffer.start=pict.rtStart;
curBuffer.stop=pict.rtStop;
curBuffer.fieldType=pict.fieldtype;
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Passing through frame %i, %10.6f - %10.6f = %10.6f"),curInFrameNo,curBuffer.start/10000.0,curBuffer.stop/10000.0,(curBuffer.stop-curBuffer.start)/10000.0);
}
else if (applyPulldown != 1 || !(pict.fieldtype & FIELD_TYPE::MASK_INT))
{
// Buffer frames as-is and pass the fieldtype through
if (isYV12)
{
TffPict::copy(curBuffer.data[0],curBuffer.pitch[0],input->src[0],input->stride1[0],input->dx ,input->dy);
TffPict::copy(curBuffer.data[1],curBuffer.pitch[1],input->src[1],input->stride1[1],input->dx/2,input->dy/2);
TffPict::copy(curBuffer.data[2],curBuffer.pitch[2],input->src[2],input->stride1[2],input->dx/2,input->dy/2);
}
else
TffPict::copy(curBuffer.data[0],curBuffer.pitch[0],input->src[0],input->stride1[0],input->dx*input->cspBpp,input->dy);
curBuffer.start=pict.rtStart;
curBuffer.stop=pict.rtStop;
curBuffer.fieldType=pict.fieldtype;
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Buffering frame %i, %10.6f - %10.6f = %10.6f %s"),curInFrameNo,curBuffer.start/10000.0,curBuffer.stop/10000.0,(curBuffer.stop-curBuffer.start)/10000.0,_l("--"));
}
else
{
// Buffer frames with pulldown applied according to fieldtype interlace flags to get
// constant frame rate TFF video
//
// Example:
// +------------------- Number of previous frame (stored in pulldownBuffer)
// | +----------------- Number of current frame
// | | +--------------- TFF/BFF flag on previous frame
// | | | +------------- TFF/BFF flag on current frame
// | | | | +----- Frame(s) produced by combining these top & bottom fields
// | | | | |
// - - - - ------------
// - 1 T T 1T 1B|
// 1 2 T B 2T 2B|
// 2 3 B B 2T 3B|
// 3 4 B T 3T 4B|4T 4B|
// 4 5 T T 5T 5B|
// 5 6 T B 6T 6B|
// 6 7 B B 6T 7B|
// 7 8 B T 7T 8B|8T 8B|
// 8 9 T T 9T 9B|
// ...
// Buffer to store the previous frame
TframeBuffer& pulldownBuffer=buffers[numBuffers];
// pulldownBuffer has a frameNo of -1 if it was just initialized
bool hasPulldownBuffer=(pulldownBuffer.frameNo >= 0);
bool lastTFF=(pulldownBuffer.fieldType & FIELD_TYPE::INT_TFF) != 0;
bool curTFF=(pict.fieldtype & FIELD_TYPE::INT_TFF) != 0;
REFERENCE_TIME curDuration=pict.rtStop-pict.rtStart;
REFERENCE_TIME lastDuration=(hasPulldownBuffer ? pulldownBuffer.stop-pulldownBuffer.start : curDuration);
// 3:2 pulldown has alternating long and short frame durations, figure out which is which
REFERENCE_TIME shortDuration;
REFERENCE_TIME longDuration;
if (curDuration < lastDuration)
{
shortDuration=curDuration;
longDuration=lastDuration;
}
else
{
shortDuration=lastDuration;
longDuration=curDuration;
}
if (!hasPulldownBuffer)
{
// Just copy the first frame, whatever it is
if (isYV12)
{
TffPict::copy(curBuffer.data[0],curBuffer.pitch[0],input->src[0],input->stride1[0],input->dx ,input->dy);
TffPict::copy(curBuffer.data[1],curBuffer.pitch[1],input->src[1],input->stride1[1],input->dx/2,input->dy/2);
TffPict::copy(curBuffer.data[2],curBuffer.pitch[2],input->src[2],input->stride1[2],input->dx/2,input->dy/2);
}
else
TffPict::copy(curBuffer.data[0],curBuffer.pitch[0],input->src[0],input->stride1[0],input->dx*input->cspBpp,input->dy);
curBuffer.start=pict.rtStart;
curBuffer.stop=pict.rtStop;
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Buffering frame %i, %10.6f - %10.6f = %10.6f %s"),curInFrameNo,curBuffer.start/10000.0,curBuffer.stop/10000.0,(curBuffer.stop-curBuffer.start)/10000.0,_l("TT"));
}
else
{
// Combine fields into new frames and adjust the timestamps accordingly
if (lastTFF)
{
// T -> x
if (isYV12)
{
TffPict::copy(curBuffer.data[0],curBuffer.pitch[0],input->src[0],input->stride1[0],input->dx ,input->dy);
TffPict::copy(curBuffer.data[1],curBuffer.pitch[1],input->src[1],input->stride1[1],input->dx/2,input->dy/2);
TffPict::copy(curBuffer.data[2],curBuffer.pitch[2],input->src[2],input->stride1[2],input->dx/2,input->dy/2);
}
else
TffPict::copy(curBuffer.data[0],curBuffer.pitch[0],input->src[0],input->stride1[0],input->dx*input->cspBpp,input->dy);
char_t* fields;
if (curTFF)
{
// T -> T
curBuffer.start=pulldownBuffer.start+shortDuration;
curBuffer.stop=pulldownBuffer.stop+shortDuration;
fields=_l("TT");
}
else
{
hasPulldown=true;
// T -> B
curBuffer.start=pulldownBuffer.start+shortDuration;
curBuffer.stop=pulldownBuffer.stop+shortDuration/2;
fields=_l("TB");
}
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Buffering frame %i, %10.6f - %10.6f = %10.6f %s"),curInFrameNo,curBuffer.start/10000.0,curBuffer.stop/10000.0,(curBuffer.stop-curBuffer.start)/10000.0,fields);
}
else
{
hasPulldown=true;
// B -> x
if (isYV12)
{
TffPict::copy(curBuffer.data[0],curBuffer.pitch[0]*2,pulldownBuffer.data[0],pulldownBuffer.pitch[0]*2,input->dx ,input->dy/2);
TffPict::copy(curBuffer.data[1],curBuffer.pitch[1]*2,pulldownBuffer.data[1],pulldownBuffer.pitch[1]*2,input->dx/2,input->dy/4);
TffPict::copy(curBuffer.data[2],curBuffer.pitch[2]*2,pulldownBuffer.data[2],pulldownBuffer.pitch[2]*2,input->dx/2,input->dy/4);
TffPict::copy(curBuffer.data[0]+curBuffer.pitch[0],curBuffer.pitch[0]*2,input->src[0]+input->stride1[0],input->stride1[0]*2,input->dx ,input->dy/2);
TffPict::copy(curBuffer.data[1]+curBuffer.pitch[1],curBuffer.pitch[1]*2,input->src[1]+input->stride1[1],input->stride1[1]*2,input->dx/2,input->dy/4);
TffPict::copy(curBuffer.data[2]+curBuffer.pitch[2],curBuffer.pitch[2]*2,input->src[2]+input->stride1[2],input->stride1[2]*2,input->dx/2,input->dy/4);
}
else
{
TffPict::copy(curBuffer.data[0],curBuffer.pitch[0]*2,pulldownBuffer.data[0],pulldownBuffer.pitch[0]*2,input->dx*input->cspBpp,input->dy/2);
TffPict::copy(curBuffer.data[0]+curBuffer.pitch[0],curBuffer.pitch[0]*2,input->src[0]+input->stride1[0],input->stride1[0]*2,input->dx*input->cspBpp,input->dy/2);
}
if (!curTFF)
{
// B -> B
curBuffer.start=pulldownBuffer.start+shortDuration/2;
curBuffer.stop=pulldownBuffer.stop+shortDuration/2;
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Buffering frame %i, %10.6f - %10.6f = %10.6f %s"),curInFrameNo,curBuffer.start/10000.0,curBuffer.stop/10000.0,(curBuffer.stop-curBuffer.start)/10000.0,_l("BB"));
}
else
{
// B -> T
curBuffer.start=pulldownBuffer.start+shortDuration/2;
curBuffer.stop=pulldownBuffer.stop;
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Buffering frame %i, %10.6f - %10.6f = %10.6f %s"),curInFrameNo,curBuffer.start/10000.0,curBuffer.stop/10000.0,(curBuffer.stop-curBuffer.start)/10000.0,_l("BT"));
curBufferNo=(curBufferNo+1)%numBuffers;
buffersFilled++;
curInFrameNo++;
TframeBuffer& curBuffer2=buffers[curBufferNo];
curBuffer2.frameNo=curInFrameNo;
if (isYV12)
{
TffPict::copy(curBuffer2.data[0],curBuffer2.pitch[0],input->src[0],input->stride1[0],input->dx ,input->dy);
TffPict::copy(curBuffer2.data[1],curBuffer2.pitch[1],input->src[1],input->stride1[1],input->dx/2,input->dy/2);
TffPict::copy(curBuffer2.data[2],curBuffer2.pitch[2],input->src[2],input->stride1[2],input->dx/2,input->dy/2);
}
else
TffPict::copy(curBuffer2.data[0],curBuffer2.pitch[0],input->src[0],input->stride1[0],input->dx*input->cspBpp,input->dy);
curBuffer2.start=pulldownBuffer.start+shortDuration/2+shortDuration;
curBuffer2.stop=pulldownBuffer.stop+shortDuration;
curBuffer2.fieldType=FIELD_TYPE::INT_TFF;
if (debugPrint)
DPRINTF(_l("TimgFilterAvisynth: Buffering frame %i, %10.6f - %10.6f = %10.6f %s"),curInFrameNo,curBuffer2.start/10000.0,curBuffer2.stop/10000.0,(curBuffer2.stop-curBuffer2.start)/10000.0,_l("BT"));
}
}
}
// Frames that had pulldown applied are always TFF
curBuffer.fieldType=FIELD_TYPE::INT_TFF;
if (isYV12)
{
TffPict::copy(pulldownBuffer.data[0],pulldownBuffer.pitch[0],input->src[0],input->stride1[0],input->dx ,input->dy);
TffPict::copy(pulldownBuffer.data[1],pulldownBuffer.pitch[1],input->src[1],input->stride1[1],input->dx/2,input->dy/2);
TffPict::copy(pulldownBuffer.data[2],pulldownBuffer.pitch[2],input->src[2],input->stride1[2],input->dx/2,input->dy/2);
}
else
TffPict::copy(pulldownBuffer.data[0],pulldownBuffer.pitch[0],input->src[0],input->stride1[0],input->dx*input->cspBpp,input->dy);
pulldownBuffer.start=pict.rtStart;
pulldownBuffer.stop=pict.rtStop;
pulldownBuffer.fieldType=pict.fieldtype;
pulldownBuffer.frameNo=0;
}
if (applyPulldown == 2)
{
// Twiddle timestamps on current frame
// Buffer to store the previous frame properties
TframeBuffer& lastBuffer=buffers[numBuffers];
// lastBuffer has a frameNo of -1 if it was just initialized
bool hasLastBuffer=(lastBuffer.frameNo >= 0);
if (hasLastBuffer)
{
REFERENCE_TIME lastDuration=lastBuffer.stop-lastBuffer.start;
REFERENCE_TIME curDuration=curBuffer.stop-curBuffer.start;
REFERENCE_TIME avgDuration=(curDuration+lastDuration)/2;
lastBuffer.start=curBuffer.start;
lastBuffer.stop=curBuffer.stop;
if (curDuration > lastDuration)
curBuffer.start+=(curDuration-avgDuration);
else
curBuffer.stop+=(avgDuration-curDuration);
}
else
{
lastBuffer.start=curBuffer.start;
lastBuffer.stop=curBuffer.stop;
}
lastBuffer.frameNo=0;
}
curBufferNo=(curBufferNo+1)%numBuffers;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -