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

📄 timgfilteravisynth.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 3 页
字号:
 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 + -