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

📄 timgfiltergrab.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 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 "TimgFilterGrab.h"
#include "TgrabSettings.h"
#include "Tdll.h"
#include "IffdshowBase.h"
#include "IffdshowDecVideo.h"
#include "TimgFilters.h"

//========================== TimgExportLibavcodec ===========================
TimgFilterGrab::TimgExportLibavcodec::TimgExportLibavcodec(const Tconfig *config,IffdshowBase *deci,CodecID IcodecId):codecId(IcodecId)
{
 deci->getLibavcodec(&dll);
 ok=(dll && dll->ok);
 avctx=NULL;picture=NULL;
}
TimgFilterGrab::TimgExportLibavcodec::~TimgExportLibavcodec()
{
 done();
 if (dll) dll->Release();
}
void TimgFilterGrab::TimgExportLibavcodec::init(unsigned int dx,unsigned int dy)
{
 avctxinited=false;
 if (dll->ok && !dll->dec_only)
  {
   AVCodec *avcodec=dll->avcodec_find_encoder(codecId);
   avctx=dll->avcodec_alloc_context();
   avctx->width=dx;
   avctx->height=dy;
   avctx->flags=CODEC_FLAG_QSCALE;
   avctx->pix_fmt=csp_ffdshow2lavc(requiredCSP());
   avctx->time_base.num=avctx->time_base.den=1;
   if (dll->avcodec_open(avctx,avcodec)<0)
    {
     ok=false;
     return;
    }
   avctxinited=true;
   picture=dll->avcodec_alloc_frame();
   inited=true;
  }
}
int TimgFilterGrab::TimgExportLibavcodec::compress(const unsigned char *src[4],stride_t stride[4],unsigned char *dst,unsigned int dstlen,int qual)
{
 if (!avctx) return 0;
 for (int i=0;i<4;i++)
  {
   picture->data[i]=(uint8_t*)src[i];
   picture->linesize[i]=(int)stride[i];
  }
 picture->quality=setQual(qual);
 int len=dll->avcodec_encode_video(avctx,dst,dstlen,picture);
 return len>0?len:0;
}
void TimgFilterGrab::TimgExportLibavcodec::done(void)
{
 if (avctx)
  {
   if (avctxinited) dll->avcodec_close(avctx);avctxinited=false;
   dll->av_free(avctx);avctx=NULL;
   dll->av_free(picture);picture=NULL;
  }
 inited=false;
}

//============================== TimgExportBMP =============================
TimgFilterGrab::TimgExportBMP::TimgExportBMP(void)
{
 memset(&bfh,0,sizeof(bfh));
 memcpy(&bfh.bfType,"BM",2);
 bfh.bfOffBits=sizeof(bch)+sizeof(bfh);
 memset(&bch,0,sizeof(bch));
 bch.bcSize=sizeof(bch);
 bch.bcPlanes=1;
 bch.bcBitCount=24;
 ok=true;
}
void TimgFilterGrab::TimgExportBMP::init(unsigned int dx,unsigned int dy)
{
 bch.bcWidth=(WORD)dx;bch.bcHeight=(WORD)dy;
 inited=true;
}
int TimgFilterGrab::TimgExportBMP::compress(const unsigned char *src[4],stride_t stride[4],unsigned char *dst,unsigned int dstlen,int qual)
{
 memcpy(dst,&bfh,sizeof(bfh));
 memcpy(dst+sizeof(bfh),&bch,sizeof(bch));
 TffPict::copy(dst+sizeof(bfh)+sizeof(bch),bch.bcWidth*3,src[0],stride[0],bch.bcWidth*3,bch.bcHeight);
 bfh.bfSize=sizeof(bfh)+sizeof(bch)+bch.bcWidth*bch.bcHeight*3;
 return bfh.bfSize;
}

//============================== TimgFilterGrab =============================
TimgFilterGrab::TimgFilterGrab(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
 exp[0]=exp[1]=exp[2]=NULL;
 dstbuf=NULL;dstbuflen=0;
 now=0;
}
TimgFilterGrab::~TimgFilterGrab()
{
 if (exp[0]) delete exp[0];exp[0]=NULL;
 if (exp[1]) delete exp[1];exp[1]=NULL;
 if (exp[2]) delete exp[2];exp[2]=NULL;
}
void TimgFilterGrab::done(void)
{
 if (dstbuf) ::free(dstbuf);dstbuf=NULL;
}
void TimgFilterGrab::onSizeChange(void)
{
 done();
 if (exp[0]) exp[0]->done();
 if (exp[1]) exp[1]->done();
 if (exp[2]) exp[2]->done();
}

bool TimgFilterGrab::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg)
{
 return true;
}

int TimgFilterGrab::getSupportedInputColorspaces(const TfilterSettingsVideo *cfg0) const
{
 const TgrabSettings *cfg=(const TgrabSettings*)cfg0;
 return exp[cfg->format] && exp[cfg->format]->ok?exp[cfg->format]->requiredCSP():FF_CSPS_MASK;
}

HRESULT TimgFilterGrab::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
 const TgrabSettings *cfg=(const TgrabSettings*)cfg0;
 LONG wasNow=now;
 if (cfg->is || wasNow)
  {
   int framenum=deci->getParam2(IDFF_currentFrame);
   if (wasNow ||
       (cfg->mode==0 && (framenum%cfg->step==0)) ||
       (cfg->mode==1 && (framenum==cfg->frameNum)) ||
       (cfg->mode==2 && isIn(framenum,cfg->frameNum1,cfg->frameNum2) && (framenum-cfg->frameNum1)%cfg->step==0))
    {
     if (!exp[cfg->format])
      switch (cfg->format)
       {
        case 0:exp[0]=new TimgExportJPEG(parent->config,deci);break;
        case 1:exp[1]=new TimgExportBMP;break;
        case 2:exp[2]=new TimgExportPNG(parent->config,deci);break;
       }

     if (exp[cfg->format]->ok)
      {
       init(pict,cfg->full,0);

       if (!exp[cfg->format]->inited)
        exp[cfg->format]->init(pictRect.dx,pictRect.dy);

       if (exp[cfg->format]->ok)
        {
         const unsigned char *src[4];
         getCur(exp[cfg->format]->requiredCSP(),pict,cfg->full,src);

         if (!dstbuf) dstbuf=(unsigned char*)malloc(dstbuflen=pictRect.dx*pictRect.dy*4+1024);

         int len=exp[cfg->format]->compress(src,stride1,dstbuf,dstbuflen,cfg->qual);
         if (len)
          {
           char_t name[MAX_PATH];
           tsprintf(name,_l("%s%0*i.%s"),cfg->prefix,cfg->digits,framenum,TgrabSettings::formats[cfg->format].ext);
           char_t flnm[MAX_PATH];
           _makepath(flnm,NULL,cfg->path,name,NULL);
           FILE *f=fopen(flnm,_l("wb"));
           if (f)
            {
             fwrite(dstbuf,1,len,f);
             fclose(f);
            }
          }
        }
      }
    }
  }
 if (wasNow) InterlockedDecrement((LONG*)&now);
 return parent->deliverSample(++it,pict);
}

HRESULT TimgFilterGrab::queryInterface(const IID &iid,void **ptr) const
{
 if (iid==IID_IimgFilterGrab) {*ptr=(IimgFilterGrab*)this;return S_OK;}
 else return E_NOTIMPL;
}
STDMETHODIMP TimgFilterGrab::grabNow(void)
{
 InterlockedIncrement((LONG*)&now);
 return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -