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

📄 tvideocodeclibavcodec.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    {
     used_bytes=libavcodec->avcodec_decode_video(avctx,frame,&got_picture,extradata->data,(int)extradata->size);
     sendextradata=false;
     if (used_bytes>0) used_bytes=0;
    }
   else
    {
     unsigned int neededsize=size+FF_INPUT_BUFFER_PADDING_SIZE;
     if (ffbuflen<neededsize)
      ffbuf=(unsigned char*)realloc(ffbuf,ffbuflen=neededsize);
     if (src)
      {
       memcpy(ffbuf,src,size);memset(ffbuf+size,0,FF_INPUT_BUFFER_PADDING_SIZE);
       used_bytes=libavcodec->avcodec_decode_video(avctx,frame,&got_picture,ffbuf,size);
      }
     else
      used_bytes=libavcodec->avcodec_decode_video(avctx,frame,&got_picture,NULL,0);
    }
   if (used_bytes<0)
    return S_FALSE;
   if (got_picture && frame->data[0])
    {
     int frametype;
     if (avctx->codec_id==CODEC_ID_H261)
      frametype=FRAME_TYPE::I;
     else
      switch (frame->pict_type)
       {
        case FF_P_TYPE:frametype=FRAME_TYPE::P;break;
        case FF_B_TYPE:frametype=FRAME_TYPE::B;break;
        case FF_I_TYPE:frametype=FRAME_TYPE::I;break;
        case FF_S_TYPE:frametype=FRAME_TYPE::GMC;break;
        case FF_SI_TYPE:frametype=FRAME_TYPE::SI;break;
        case FF_SP_TYPE:frametype=FRAME_TYPE::SP;break;
        case 0:frametype=pIn && pIn->IsSyncPoint()==S_OK?FRAME_TYPE::I:FRAME_TYPE::P;break;
        default:frametype=FRAME_TYPE::UNKNOWN;break;
       }
     if (pIn && pIn->IsPreroll()==S_OK)
      return sinkD->deliverPreroll(frametype);
     int fieldtype=frame->interlaced_frame?(frame->top_field_first?FIELD_TYPE::INT_TFF:FIELD_TYPE::INT_BFF):FIELD_TYPE::PROGRESSIVE_FRAME;
     if (frame->play_flags&CODEC_FLAG_QPEL) frametype|=FRAME_TYPE::QPEL;
     int csp=csp_lavc2ffdshow(avctx->pix_fmt);
     if ((avctx->flags&CODEC_FLAG_GRAY) && csp_isYUVplanar(csp)) // workaround for green picture when decoding mpeg with CODEC_FLAG_GRAY, the problem is probably somewhere else
      {
       if (frame->data[1][0]!=128) memset(frame->data[1],128,frame->linesize[1]*avctx->height/2);
       if (frame->data[2][0]!=128) memset(frame->data[2],128,frame->linesize[2]*avctx->height/2);
      }
     Trect r(0,0,avctx->width,avctx->height);
     if (avctx->sample_aspect_ratio.num &&
         !(isMPC_matroska && avctx->sample_aspect_ratio.num==1 && avctx->sample_aspect_ratio.den==1)
        )  // With MPC's internal matroska splitter, AR is not reliable.
      r.sar=avctx->sample_aspect_ratio;
     else
      r.sar=containerSar;
     quants=frame->qscale_table;
     quantsStride=frame->qstride;
     quantType=frame->qscale_type;
     h264.deblocking_filter=avctx->h264_deblocking_filter;
     h264.slice_alpha_c0_offset=avctx->h264_slice_alpha_c0_offset;
     h264.slice_beta_offset=avctx->h264_slice_beta_offset;
     quantsDx=(r.dx+15)>>4;quantsDy=(r.dy+15)>>4;
     const stride_t linesize[4]={frame->linesize[0],frame->linesize[1],frame->linesize[2],frame->linesize[3]};
     TffPict pict(csp,frame->data,linesize,r,true,frametype,fieldtype,srcLen0,pIn,avctx->palctrl); //TODO: src frame size
     pict.gmcWarpingPoints=frame->num_sprite_warping_points;pict.gmcWarpingPointsReal=frame->real_sprite_warping_points;
     if (neroavc)
      {
       pict.rtStart=frame->rtStart;
       if (pict.rtStart==REFTIME_INVALID)
        pict.rtStart=oldpict.rtStop;
       if (avgTimePerFrame==-1)
        deciV->getAverageTimePerFrame(&avgTimePerFrame);
       if (avgTimePerFrame)
        pict.rtStop=pict.rtStart+avgTimePerFrame+frame->repeat_pict*avgTimePerFrame/2;
       else
        pict.rtStop=pict.rtStart+1;
       if (avctx->codec_tag==FOURCC_MPG1 || avctx->codec_tag==FOURCC_MPG2)
        pict.mediatimeStart=pict.mediatimeStop=REFTIME_INVALID;
       oldpict=pict;
      }
     else if (theorart)
      pict.rtStop=(pict.rtStart=frame->rtStart-segmentTimeStart)+1;
     else
      if (avctx->has_b_frames)
       {
        pict.rtStart=b[posB].rtStart;
        pict.rtStop=b[posB].rtStop;
        pict.srcSize=b[posB].srcSize;
       }
     //DPRINTF("%I64i",pict.rtStart);
     HRESULT hr=sinkD->deliverDecodedSample(pict);
     if (FAILED(hr) || (used_bytes && sinkD->acceptsManyFrames()!=S_OK) || avctx->codec_id==CODEC_ID_LOCO)
      return hr;
    }
   else
    if (!src)
     break;
   if(!used_bytes && codecId==CODEC_ID_SVQ3) return S_FALSE;
   src+=used_bytes;
   size-=used_bytes;
  }
 return S_OK;
}

bool TvideoCodecLibavcodec::onSeek(REFERENCE_TIME segmentStart)
{
 wasKey=false;
 segmentTimeStart=segmentStart;
 posB=1;b[0].rtStart=b[1].rtStart=b[0].rtStop=b[0].rtStop=0;b[0].srcSize=b[1].srcSize=0;
 return avctx?(libavcodec->avcodec_flush_buffers(avctx),true):false;
}
bool TvideoCodecLibavcodec::onDiscontinuity(void)
{
 wasKey=false;
 return true;
}

const char_t* TvideoCodecLibavcodec::getName(void) const
{
 if (avcodec)
  {
   tsprintf(codecName,_l("libavcodec %s"),(const char_t*)text<char_t>(avcodec->name));
   return codecName;
  }
 else return _l("libavcodec");
}
void TvideoCodecLibavcodec::getEncoderInfo(char_t *buf,size_t buflen) const
{
 int xvid_build,divx_version,divx_build,lavc_build;
 if (avctx && (mpeg12_codec(codecId) || mpeg4_codec(codecId) || x264_codec(codecId) || codecId==CODEC_ID_FLV1))
  {
   libavcodec->avcodec_get_encoder_info(avctx,&xvid_build,&divx_version,&divx_build,&lavc_build);
   if (xvid_build)
    tsnprintf(buf,buflen,_l("XviD build %i"),xvid_build);
   else if (lavc_build)
    tsnprintf(buf,buflen,_l("libavcodec build %i"),lavc_build);
   else if (divx_version || divx_build)
    tsnprintf(buf,buflen,_l("DivX version %i.%02i, build %i"),divx_version/100,divx_version%100,divx_build);
   else
    strncpy(buf,_l("unknown"),buflen);
  }
 else
  strncpy(buf,_l("unknown"),buflen);
 buf[buflen-1]='\0';
}

void TvideoCodecLibavcodec::line(unsigned char *dst,unsigned int _x0,unsigned int _y0,unsigned int _x1,unsigned int _y1,stride_t strideY)
{
 drawline< TaddColor<100> >(_x0,_y0,_x1,_y1,100,dst,strideY);
}

void TvideoCodecLibavcodec::draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, stride_t stride,int mulx,int muly,int dstdx,int dstdy)
{
 sx=limit(mulx*sx>>12,0,dstdx-1);sy=limit(muly*sy>>12,0,dstdy-1);
 ex=limit(mulx*ex>>12,0,dstdx-1);ey=limit(muly*ey>>12,0,dstdy-1);
    int dx,dy;

    dx= ex - sx;
    dy= ey - sy;

    if(dx*dx + dy*dy > 3*3){
        int rx=  dx + dy;
        int ry= -dx + dy;
        int length= ff_sqrt((rx*rx + ry*ry)<<8);

        //FIXME subpixel accuracy
        rx= roundDiv(rx*3<<4, length);
        ry= roundDiv(ry*3<<4, length);

        line(buf, sx, sy, sx + rx, sy + ry, stride);
        line(buf, sx, sy, sx - ry, sy + rx, stride);
    }
    line(buf, sx, sy, ex, ey, stride);
}

bool TvideoCodecLibavcodec::drawMV(unsigned char *dst,unsigned int dstdx,stride_t stride,unsigned int dstdy) const
{
 if (!frame->motion_val || !frame->mb_type || !frame->motion_val[0]) return false;

 #define IS_8X8(a)  ((a)&MB_TYPE_8x8)
 #define IS_16X8(a) ((a)&MB_TYPE_16x8)
 #define IS_8X16(a) ((a)&MB_TYPE_8x16)
 #define IS_INTERLACED(a) ((a)&MB_TYPE_INTERLACED)
 #define USES_LIST(a, list) ((a) & ((MB_TYPE_P0L0|MB_TYPE_P1L0)<<(2*(list))))

 const int shift= 1 + ((frame->play_flags&CODEC_FLAG_QPEL)?1:0);
 const int mv_sample_log2= 4 - frame->motion_subsample_log2;
 const int mv_stride= (frame->mb_width << mv_sample_log2) + (avctx->codec_id == CODEC_ID_H264 ? 0 : 1);
 int direction=0;

 int mulx=(dstdx<<12)/avctx->width;
 int muly=(dstdy<<12)/avctx->height;

 for(int mb_y=0; mb_y<frame->mb_height; mb_y++)
  for(int mb_x=0; mb_x<frame->mb_width; mb_x++)
   {
    const int mb_index= mb_x + mb_y*frame->mb_stride;
    if (!USES_LIST(frame->mb_type[mb_index], direction))
     continue;
    if(IS_8X8(frame->mb_type[mb_index]))
     for(int i=0; i<4; i++)
      {
       int sx= mb_x*16 + 4 + 8*(i&1) ;
       int sy= mb_y*16 + 4 + 8*(i>>1);
       int xy= (mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*mv_stride)<<(mv_sample_log2-1);
       int mx= (frame->motion_val[direction][xy][0]>>shift) + sx;
       int my= (frame->motion_val[direction][xy][1]>>shift) + sy;
       draw_arrow(dst,sx,sy,mx,my,stride,mulx,muly,dstdx,dstdy);
      }
    else if(IS_16X8(frame->mb_type[mb_index]))
     for(int i=0; i<2; i++)
      {
       int sx=mb_x*16 + 8;
       int sy=mb_y*16 + 4 + 8*i;
       int xy=(mb_x*2 + (mb_y*2 + i)*mv_stride) << (mv_sample_log2-1);
       int mx=frame->motion_val[direction][xy][0]>>shift;
       int my=frame->motion_val[direction][xy][1]>>shift;
       if (IS_INTERLACED(frame->mb_type[mb_index]))
        my*=2;
       draw_arrow(dst,sx,sy,mx+sx,my+sy,stride,mulx,muly,dstdx,dstdy);
      }
    else if(IS_8X16(frame->mb_type[mb_index]))
     for(int i=0; i<2; i++)
      {
       int sx=mb_x*16 + 4 + 8*i;
       int sy=mb_y*16 + 8;
       int xy= (mb_x*2 + i + mb_y*2*mv_stride) << (mv_sample_log2-1);
       int mx=(frame->motion_val[direction][xy][0]>>shift);
       int my=(frame->motion_val[direction][xy][1]>>shift);
       if(IS_INTERLACED(frame->mb_type[mb_index]))
        my*=2;
       draw_arrow(dst,sx,sy,mx+sx,my+sy,stride,mulx,muly,dstdx,dstdy);
      }
    else
     {
      int sx= mb_x*16 + 8;
      int sy= mb_y*16 + 8;
      int xy= (mb_x + mb_y*mv_stride) << mv_sample_log2;
      int mx= (frame->motion_val[direction][xy][0]>>shift) + sx;
      int my= (frame->motion_val[direction][xy][1]>>shift) + sy;
      draw_arrow(dst,sx,sy,mx,my,stride,mulx,muly,dstdx,dstdy);
     }
   }
 #undef IS_8X8
 #undef IS_16X8
 #undef IS_8X16
 #undef IS_INTERLACED
 #undef USES_LIST
 return true;
}

//------------------------------ compression ------------------------------
void TvideoCodecLibavcodec::getCompressColorspaces(Tcsps &csps,unsigned int outDx,unsigned int outDy)
{
 switch (coCfg->codecId)
  {
   case CODEC_ID_HUFFYUV:
    if (coCfg->huffyuv_csp==0)
     csps.add(FF_CSP_422P);
    else
     csps.add(FF_CSP_420P);
    break;
   case CODEC_ID_FFV1:
    switch (coCfg->ffv1_csp)
     {
      case FOURCC_YV12:csps.add(FF_CSP_420P);break;
      case FOURCC_444P:csps.add(FF_CSP_444P);break;
      case FOURCC_422P:csps.add(FF_CSP_422P);break;
      case FOURCC_411P:csps.add(FF_CSP_411P);break;
      case FOURCC_410P:csps.add(FF_CSP_410P);break;
      case FOURCC_RGB3:csps.add(FF_CSP_RGB32);break;
     }
    break;
   case CODEC_ID_MJPEG:
    csps.add(FF_CSP_420P|FF_CSP_FLAGS_YUV_JPEG);
    break;
   case CODEC_ID_LJPEG:
    if (coCfg->ljpeg_csp==FOURCC_RGB3)
     csps.add(FF_CSP_RGB32);
    else
     csps.add(FF_CSP_420P);
    break;
   case CODEC_ID_DVVIDEO:
    {
     std::vector<const DVprofile*> profiles=coCfg->getDVprofile(outDx,outDy);
     if (!profiles.empty())
      {
       for (std::vector<const DVprofile*>::const_iterator p=profiles.begin();p!=profiles.end();p++)
        csps.add(csp_lavc2ffdshow((*p)->pix_fmt));
      }
     else
      csps.add(FF_CSP_420P); //won't be used anyway
     break;
    }
   case CODEC_ID_SVQ1:
    csps.add(FF_CSP_410P);
    break;
   default:
    csps.add(FF_CSP_420P);
    break;
  }
}

bool TvideoCodecLibavcodec::supExtradata(void)
{
 return coCfg->codecId==CODEC_ID_HUFFYUV || (sup_globalheader(coCfg->codecId) && coCfg->globalHeader);
}
bool TvideoCodecLibavcodec::getExtradata(const void* *ptr,size_t *len)
{
 if (!avctx || !len) return false;
 *len=avctx->extradata_size;
 if (ptr) *ptr=avctx->extradata;
 return true;
}

LRESULT TvideoCodecLibavcodec::beginCompress(int cfgcomode,int csp,const Trect &r)
{
 _mm_empty();
 avctx=libavcodec->avcodec_alloc_context();
 frame=libavcodec->avcodec_alloc_frame();

 avcodec=libavcodec->avcodec_find_encoder((CodecID)coCfg->codecId);
 if (!avcodec) return ICERR_ERROR;

 this->cfgcomode=cfgcomode;

 if (coCfg->numthreads>1 && sup_threads(coCfg->codecId))
  libavcodec->avcodec_thread_init(avctx,threadcount=coCfg->numthreads);
 else
  threadcount=0;

 avctx->width=r.dx;avctx->height=r.dy;
 mb_width =(avctx->width+15)/16;
 mb_height=(avctx->height+15)/16;
 mb_count=mb_width*mb_height;
 avctx->time_base.den=deci->getParam2(IDFF_enc_fpsRate);
 avctx->time_base.num=deci->getParam2(IDFF_enc_fpsScale);
 if (avctx->time_base.den>(1<<16)-1)
  {
   avctx->time_base.num=(int)(0.5+(double)avctx->time_base.num/avctx->time_base.den*((1<<16)-1));
   avctx->time_base.den=(1<<16)-1;
  }
 if (coCfg->codecId==CODEC_ID_FFV1)
  avctx->gop_size=coCfg->ffv1_key_interval;
 else
  avctx->gop_size=coCfg->max_key_interval;

 avctx->codec_tag=coCfg->fourcc;
 if (sup_interlace(coCfg->codecId) && coCfg->interlacing) avctx->flags|=CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME;
 if (sup_globalheader(coCfg->codecId) && coCfg->globalHeader) avctx->flags|=CODEC_FLAG_GLOBAL_HEADER;
 if (sup_part(coCfg->codecId) &&coCfg->part) avctx->flags|=CODEC_FLAG_PART;
 if (coCfg->codecId!=CODEC_ID_SNOW && coCfg->codecId!=CODEC_ID_H261) avctx->mb_decision=coCfg->me_hq;
 if (coCfg->me_4mv && sup_4mv(coCfg->codecId)) avctx->flags|=CODEC_FLAG_4MV;
 if (sup_qpel(coCfg->codecId) && coCfg->me_qpel)
  {
   avctx->flags|=CODEC_FLAG_QPEL;
   avctx->me_subpel_quality=coCfg->me_subq;
  }
 psnr=deci->getParam2(IDFF_enc_psnr);if (psnr) avctx->flags|=CODEC_FLAG_PSNR;
 if (coCfg->me_mv0 && sup_me_mv0(coCfg->codecId) && coCfg->me_hq>0) avctx->flags|=CODEC_FLAG_MV0;
 avctx->me_cmp=coCfg->me_cmp;if (coCfg->me_cmp_chroma && !coCfg->gray) avctx->me_cmp|=FF_CMP_CHROMA;
 avctx->me_sub_cmp=coCfg->me_subcmp;if (coCfg->me_subcmp_chroma && !coCfg->gray) avctx->me_sub_cmp|=FF_CMP_CHROMA;
 avctx->mb_cmp=coCfg->mb_cmp;if (coCfg->mb_cmp_chroma && !coCfg->gray) avctx->mb_cmp|=FF_CMP_CHROMA;
 avctx->dia_size=Tlibavcodec::dia_sizes[coCfg->dia_size].size;
 avctx->last_predictor_count=coCfg->me_last_predictor_count;
 avctx->pre_me=coCfg->me_prepass;
 avctx->me_pre_cmp=coCfg->me_precmp;if (coCfg->me_precmp_chroma && !coCfg->gray) avctx->me_pre_cmp|=FF_CMP_CHROMA;
 avctx->pre_dia_size=Tlibavcodec::dia_sizes[coCfg->dia_size_pre].size;
 avctx->nsse_weight=coCfg->me_nsse_weight;
 if (sup_gray(coCfg->codecId) && coCfg->gray) avctx->flags|=CODEC_FLAG_GRAY;

 if (coCfg->isQuantControlActive())
  {
   avctx->qmin_i=coCfg->limitq(coCfg->q_i_min);avctx->qmax_i=coCfg->limitq(coCfg->q_i_max);
   avctx->qmin  =coCfg->limitq(coCfg->q_p_min);avctx->qmax  =coCfg->limitq(coCfg->q_p_max);
   avctx->qmin_b=coCfg->limitq(coCfg->q_b_min);avctx->qmax_b=coCfg->limitq(coCfg->q_b_max);
  }
 else
  {
   avctx->qmin_i=avctx->qmin=avctx->qmin_b=coCfg->getMinMaxQuant().first;
   avctx->qmax_i=avctx->qmax=avctx->qmax_b=coCfg->getMinMaxQuant().second;
  }

 if (coCfg->codecId!=CODEC_ID_MJPEG)
  {
   avctx->i_quant_factor=coCfg->i_quant_factor/100.0f;
   avctx->i_quant_offset=coCfg->i_quant_offset/100.0f;

⌨️ 快捷键说明

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