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

📄 tvideocodeclibmpeg2.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 "IffdshowDecVideo.h"
#include "TvideoCodecLibmpeg2.h"
#include "Tdll.h"
#include "Tconfig.h"
#include "libmpeg2/include/attributes.h"
#include "libmpeg2/libmpeg2/mpeg2_internal.h"
#include "libavcodec/avcodec.h"
#include "ffdebug.h"
#include "dsutil.h"
#include "cc_decoder.h"

const char_t* TvideoCodecLibmpeg2::dllname=_l("libmpeg2_ff.dll");

TvideoCodecLibmpeg2::TvideoCodecLibmpeg2(IffdshowBase *Ideci,IdecVideoSink *Isink):
 Tcodec(Ideci),TcodecDec(Ideci,Isink),
 TvideoCodec(Ideci),
 TvideoCodecDec(Ideci,Isink),
 ccDecoder(NULL)
{
 dll=new Tdll(dllname,config);
 dll->loadFunction(mpeg2_set_accel,"mpeg2_set_accel");
 dll->loadFunction(mpeg2_accel,"mpeg2_accel");
 dll->loadFunction(mpeg2_init,"mpeg2_init");
 dll->loadFunction(mpeg2_info,"mpeg2_info");
 dll->loadFunction(mpeg2_parse,"mpeg2_parse");
 dll->loadFunction(mpeg2_buffer,"mpeg2_buffer");
 dll->loadFunction(mpeg2_close,"mpeg2_close");
 dll->loadFunction(mpeg2_reset,"mpeg2_reset");
 dll->loadFunction(mpeg2_set_rtStart,"mpeg2_set_rtStart");
 ok=dll->ok;
 if (ok)
  {
   int accel=0;
   if (Tconfig::cpu_flags&FF_CPU_MMX   ) accel|=MPEG2_ACCEL_X86_MMX;
   if (Tconfig::cpu_flags&FF_CPU_3DNOW ) accel|=MPEG2_ACCEL_X86_3DNOW;
   if (Tconfig::cpu_flags&FF_CPU_MMXEXT) accel|=MPEG2_ACCEL_X86_MMXEXT;
   if (Tconfig::cpu_flags&FF_CPU_SSE2  ) accel|=MPEG2_ACCEL_X86_SSE2;
   mpeg2_set_accel(accel);
  }
 mpeg2dec=NULL;info=NULL;quants=NULL;quantBytes=1;extradata=NULL;buffer=NULL;
 buffer=new Tbuffer();
}
void TvideoCodecLibmpeg2::init(void)
{
 mpeg2dec=mpeg2_init();
 info=mpeg2_info(mpeg2dec);
 wait4Iframe=true;
 sequenceFlag=FIELD_TYPE::SEQ_START;
}
bool TvideoCodecLibmpeg2::beginDecompress(TffPictBase &pict,FOURCC infcc,const CMediaType &mt,int sourceFlags)
{
 if (extradata) delete extradata;
 extradata=new Textradata(mt,16);
 init();
 oldpict.rtStop=0;
 pict.csp=FF_CSP_420P;
 return true;
}
void TvideoCodecLibmpeg2::end(void)
{
 if (mpeg2dec) mpeg2_close(mpeg2dec);mpeg2dec=NULL;
 if (quants) free(quants);quants=NULL;
}
TvideoCodecLibmpeg2::~TvideoCodecLibmpeg2()
{
 end();
 if (dll) delete dll;
 if (extradata) delete extradata;
 if (ccDecoder) delete ccDecoder;
 if (buffer) delete buffer;
}

HRESULT TvideoCodecLibmpeg2::decompress(const unsigned char *src,size_t srcLen,IMediaSample *pIn)
{
 HRESULT hr=decompressI(src,srcLen,pIn);
 int len=mpeg2dec->buf_end - mpeg2dec->buf_start;
 if (len>0)
  {
   unsigned char *b=(unsigned char *)buffer->alloc(len);
   memcpy(b, mpeg2dec->buf_start, len);
   mpeg2_buffer(mpeg2dec, b, b+len);
  }
 return hr;
}

HRESULT TvideoCodecLibmpeg2::decompressI(const unsigned char *src,size_t srcLen,IMediaSample *pIn)
{
 //if (pIn->IsDiscontinuity()) onSeek();
 REFERENCE_TIME rtStart=REFTIME_INVALID,rtStop=_I64_MIN;
 HRESULT hr=pIn->GetTime(&rtStart,&rtStop);
 if (FAILED(hr))
  rtStart=rtStop=REFTIME_INVALID;

 int len=(int)srcLen;
 while (len>=0)
  {
   mpeg2_state_t state=mpeg2_parse(mpeg2dec);
   switch (state)
    {
     case STATE_BUFFER:
      if (len==0)
       len=-1;
      else
       {
        mpeg2_buffer(mpeg2dec,src,src+len);
        len=0;
       }
      break;
     case STATE_GOP:
      if(mpeg2dec->info.user_data_len > 4 && *(DWORD*)mpeg2dec->info.user_data == 0xf8014343)
       {
        if (!ccDecoder) ccDecoder=new TccDecoder(deciV);
        ccDecoder->decode(mpeg2dec->info.user_data+2,mpeg2dec->info.user_data_len-2);
       }
      break;
     case STATE_SEQUENCE:
      {
       sequenceFlag=FIELD_TYPE::SEQ_START;

       avgTimePerFrame=10LL*info->sequence->frame_period/27;
       deciV->setAverageTimePerFrame(&avgTimePerFrame,true);
       break;
      }
     case STATE_PICTURE:
      mpeg2dec->decoder.quant_stride=quantsStride=quantsDx=(info->sequence->picture_width+15)>>4;
      quantsDy=(info->sequence->picture_height+15)>>4;
      quants=mpeg2dec->decoder.quant_store=(char*)realloc(quants, quantsStride*quantsDy*2);
      quantType=1;
      mpeg2_set_rtStart(mpeg2dec,rtStart);
      rtStart=REFTIME_INVALID;
      break;
     case STATE_END:
      sequenceFlag=FIELD_TYPE::SEQ_END;

     case STATE_SLICE:
      //if (info->display_fbuf && (!wait4Iframe || (info->display_picture->flags&PIC_MASK_CODING_TYPE)==PIC_FLAG_CODING_TYPE_I))
      if (info->display_picture && info->discard_fbuf && !(info->display_picture->flags&PIC_FLAG_SKIP))
       {
        int frametype;
        if (info->sequence->flags&SEQ_FLAG_MPEG2) quantType=FF_QSCALE_TYPE_MPEG2;
        switch (info->display_picture->flags&PIC_MASK_CODING_TYPE)
         {
          case PIC_FLAG_CODING_TYPE_I:frametype=FRAME_TYPE::I;break;
          case PIC_FLAG_CODING_TYPE_B:frametype=FRAME_TYPE::B;break;
          default:
          case PIC_FLAG_CODING_TYPE_P:frametype=FRAME_TYPE::P;break;
         }
        if (pIn->IsPreroll()==S_OK)
         return sinkD->deliverPreroll(frametype);
        int fieldtype;
        if(info->sequence->flags&SEQ_FLAG_PROGRESSIVE_SEQUENCE)
         fieldtype = FIELD_TYPE::PROGRESSIVE_FRAME;
        else if(info->display_picture->flags&PIC_FLAG_TOP_FIELD_FIRST)
         fieldtype = FIELD_TYPE::INT_TFF;
        else
         fieldtype = FIELD_TYPE::INT_BFF;

        if (sequenceFlag != FIELD_TYPE::SEQ_START || frametype == FRAME_TYPE::I)
         {
          fieldtype|=sequenceFlag;

          sequenceFlag=0;
         }

        unsigned char *data[4]={info->display_fbuf->buf[0],info->display_fbuf->buf[1],info->display_fbuf->buf[2],NULL};
        stride_t stride[4]={info->sequence->width,info->sequence->chroma_width,info->sequence->chroma_width,0};
        int csp;
        switch ((info->sequence->chroma_width==info->sequence->width)+(info->sequence->chroma_height==info->sequence->height))
         {
          case 1:csp=FF_CSP_422P;break;
          case 2:csp=FF_CSP_444P;break;
          default:
          case 0:csp=FF_CSP_420P;break;
         }
        TffPict pict(csp,data,stride,Trect(0,0,info->sequence->picture_width,info->sequence->picture_height,info->sequence->pixel_width,info->sequence->pixel_height),true,frametype,fieldtype,srcLen,NULL); //TODO: src frame size
        pict.rtStart=info->display_picture->rtStart;
        if (pict.rtStart==REFTIME_INVALID) pict.rtStart=oldpict.rtStop;
        pict.rtStop=pict.rtStart+avgTimePerFrame*info->display_picture->nb_fields/(info->display_picture_2nd?1:2);
        oldpict=pict;
        if (frametype==FRAME_TYPE::I)
         wait4Iframe=false;
        if (!wait4Iframe)
         {
          hr=sinkD->deliverDecodedSample(pict);
          if (FAILED(hr))
           return hr;
         }
        else
         DPRINTF(_l("libmpeg2: waiting for keyframe"));
       }
      break;
    }
  }
 return S_OK;
}

bool TvideoCodecLibmpeg2::onSeek(REFERENCE_TIME segmentStart)
{
 end();
 init();
 if (extradata && extradata->data)
  mpeg2_buffer(mpeg2dec,extradata->data,extradata->data+extradata->size);
 oldpict.rtStop=0;
 return true;
}

⌨️ 快捷键说明

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