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

📄 tvideocodeclibavcodec.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  }
 else
  {
   avctx->i_quant_factor=1.0f;
   avctx->i_quant_offset=0.0f;
  }

 if (coCfg->trellisquant && sup_trellisQuant(coCfg->codecId))
  {
   avctx->flags|=CODEC_FLAG_TRELLIS_QUANT;
   if (coCfg->me_cbp_rd && sup_cbp_rd(coCfg->codecId)) avctx->flags|=CODEC_FLAG_CBP_RD;
  }
 if (coCfg->quant_type==QUANT::MPEG && sup_MPEGquant(coCfg->codecId))
  avctx->mpeg_quant=1;
 else if (coCfg->quant_type==QUANT::CUSTOM && sup_customQuantTables(coCfg->codecId))
  {
   avctx->mpeg_quant=1;
   avctx->intra_matrix=(uint16_t*)malloc(sizeof(uint16_t)*64);
   avctx->inter_matrix=(uint16_t*)malloc(sizeof(uint16_t)*64);
   ownmatrices=true;
   for (int i=0;i<64;i++)
    {
     avctx->intra_matrix[i]=((uint8_t*)&coCfg->qmatrix_intra_custom0)[i];
     avctx->inter_matrix[i]=((uint8_t*)&coCfg->qmatrix_inter_custom0)[i];
    }
  }

 if (sup_quantBias(coCfg->codecId))
  {
   if (coCfg->isIntraQuantBias) avctx->intra_quant_bias=coCfg->intraQuantBias;
   if (coCfg->isInterQuantBias) avctx->inter_quant_bias=coCfg->interQuantBias;
  }
 avctx->dct_algo=coCfg->dct_algo;
 if (sup_qns(coCfg->codecId)) avctx->quantizer_noise_shaping=coCfg->qns;
 if (mpeg2_codec(coCfg->codecId)) avctx->intra_dc_precision=coCfg->mpeg2_dc_prec;

 avctx->pix_fmt=PIX_FMT_YUV420P;
 switch (coCfg->codecId)
  {
   case CODEC_ID_HUFFYUV:
    {
     avctx->strict_std_compliance=FF_COMPLIANCE_EXPERIMENTAL;
     avctx->prediction_method=coCfg->huffyuv_pred;
     switch (coCfg->huffyuv_csp)
      {
       case 0:avctx->pix_fmt=PIX_FMT_YUV422P;break;
       case 1:avctx->pix_fmt=PIX_FMT_YUV420P;break;
      }
     avctx->context_model=coCfg->huffyuv_ctx;
     break;
    }
   case CODEC_ID_FFV1:
    {
     avctx->strict_std_compliance=FF_COMPLIANCE_EXPERIMENTAL;
     avctx->coder_type=coCfg->ffv1_coder;
     avctx->context_model=coCfg->ffv1_context;
     switch (coCfg->ffv1_csp)
      {
       case FOURCC_YV12:avctx->pix_fmt=PIX_FMT_YUV420P;break;
       case FOURCC_444P:avctx->pix_fmt=PIX_FMT_YUV444P;break;
       case FOURCC_422P:avctx->pix_fmt=PIX_FMT_YUV422P;break;
       case FOURCC_411P:avctx->pix_fmt=PIX_FMT_YUV411P;break;
       case FOURCC_410P:avctx->pix_fmt=PIX_FMT_YUV410P;break;
       case FOURCC_RGB3:avctx->pix_fmt=PIX_FMT_RGB32;break;
      }
     break;
    }
   case CODEC_ID_MJPEG:
    avctx->pix_fmt=PIX_FMT_YUVJ420P;
    break;
   case CODEC_ID_LJPEG:
    {
     switch (coCfg->ljpeg_csp)
      {
       case FOURCC_YV12:avctx->pix_fmt=PIX_FMT_YUVJ420P;break;
       case FOURCC_RGB3:avctx->pix_fmt=PIX_FMT_RGB32;break;
      }
     break;
    }
   case CODEC_ID_DVVIDEO:
    {
     PixelFormat lavc_csp=csp_ffdshow2lavc(csp);
     if (!coCfg->getDVprofile(avctx->width,avctx->height,lavc_csp))
      {
       deci->dbgError(_l("Can't find matching DV profile\r\nDV supports 720x480 and 720x576."));
       return ICERR_ERROR;
      }
     else
      avctx->pix_fmt=lavc_csp;
     break;
    }
   case CODEC_ID_H261:
    {
     if ((avctx->width==176 && avctx->height==144) || (avctx->width==352 && avctx->height==288))
      break;
     else
      {
       int errorbox;
       deci->getParam(IDFF_errorbox,&errorbox);
       if (errorbox)
        MessageBox(NULL,_l("h.261 supports 176x144 and 352x288"),_l("ffdshow libavcodec encoder error"),MB_ICONERROR|MB_OK);
       return ICERR_ERROR;
      }
    }
   case CODEC_ID_SVQ1:
    avctx->pix_fmt=PIX_FMT_YUV410P;break;
    break;
   case CODEC_ID_H263P:
    avctx->flags|=coCfg->H263Pflags;
    break;
   case CODEC_ID_H263:
    avctx->flags|=coCfg->H263Pflags&CODEC_FLAG_OBMC;
    break;
   case CODEC_ID_MPEG4:
    avctx->flags|=coCfg->H263Pflags&CODEC_FLAG_LOOP_FILTER;
    break;
   case CODEC_ID_MPEG2VIDEO:
    if (coCfg->svcd_scan_offset) avctx->flags|=CODEC_FLAG_SVCD_SCAN_OFFSET;
    break;
   case CODEC_ID_SNOW:
    avctx->strict_std_compliance=FF_COMPLIANCE_EXPERIMENTAL;
    avctx->prediction_method=1;//coCfg->huffyuv_pred;
    if (coCfg->me_iterative)
     avctx->me_method=ME_ITER;
    break;
  }
 if (avctx->flags&CODEC_FLAG_OBMC && coCfg->me_hq!=FF_MB_DECISION_SIMPLE) avctx->flags&=~CODEC_FLAG_OBMC;

 switch (cfgcomode)
  {
   case ENC_MODE::CBR:
    avctx->bit_rate=coCfg->bitrate1000*1000;
    avctx->bit_rate_tolerance=coCfg->ff1_vratetol*8*1000;
    avctx->qcompress=coCfg->ff1_vqcomp/100.0f;
    avctx->qblur=(coCfg->ff1_stats_mode&FFSTATS::WRITE?coCfg->ff1_vqblur2:coCfg->ff1_vqblur1)/100.0f;
    avctx->max_qdiff=coCfg->ff1_vqdiff;
    avctx->rc_qsquish=coCfg->ff1_rc_squish?1.0f:0.0f;
    avctx->rc_max_rate   =coCfg->ff1_rc_max_rate1000*1000;
    avctx->rc_min_rate   =coCfg->ff1_rc_min_rate1000*1000;
    avctx->rc_buffer_size=coCfg->ff1_rc_buffer_size;
    avctx->rc_initial_buffer_occupancy=avctx->rc_buffer_size*3/4;
    avctx->rc_buffer_aggressivity=1.0f;
    break;
   case ENC_MODE::VBR_QUAL:
   case ENC_MODE::VBR_QUANT:
    avctx->bit_rate=400000;
    break;
   case ENC_MODE::PASS2_1:
    avctx->flags|=CODEC_FLAG_QSCALE;
    break;
   case ENC_MODE::PASS2_2_EXT:
   case ENC_MODE::PASS2_2_INT:
    avctx->flags|=CODEC_FLAG_QSCALE;
    break;
   case ENC_MODE::UNKNOWN:
    break;
   default:return ICERR_ERROR;
  }

 if (sup_LAVC2PASS(coCfg->codecId))
  {
   if (coCfg->ff1_stats_mode&FFSTATS::READ && cfgcomode==ENC_MODE::CBR)
    {
     statsfile=fopen(coCfg->ff1_stats_flnm,_l("rb"));
     if (statsfile)
      {
       avctx->flags|=CODEC_FLAG_PASS2;
       int statslen=_filelength(fileno(statsfile));
       avctx->stats_in=(char*)malloc(statslen+1);
       avctx->stats_in[statslen]='\0';
       fread(avctx->stats_in,1,statslen,statsfile);
       fclose(statsfile);statsfile=NULL;
      }
    }
   if (coCfg->ff1_stats_mode&FFSTATS::WRITE)
    {
     statsfile=fopen(coCfg->ff1_stats_flnm,_l("wt"));
     if (statsfile)
      avctx->flags|=CODEC_FLAG_PASS1;
    }
  }

 if (sup_quantProps(coCfg->codecId) && coCfg->is_lavc_nr) avctx->noise_reduction=coCfg->lavc_nr;

 avctx->sample_aspect_ratio=coCfg->sar(avctx->width,avctx->height).reduce(255);

 if (sup_bframes(coCfg->codecId) && coCfg->isBframes)
  {
   avctx->max_b_frames=coCfg->max_b_frames;
   avctx->b_quant_factor=coCfg->b_quant_factor/100.0f;
   avctx->b_quant_offset=coCfg->b_quant_offset/100.0f;
   avctx->b_frame_strategy=coCfg->b_dynamic && !(avctx->flags&CODEC_FLAG_PASS2)?1:0;
   avctx->bidir_refine=coCfg->b_refine;
   if (coCfg->dx50bvop && sup_closedGop(coCfg->codecId))
    {
     avctx->flags|=CODEC_FLAG_CLOSED_GOP;
     avctx->scenechange_threshold=1000000000;
    }
  }

 if (sup_masking(coCfg->codecId))
  {
   if (coCfg->is_ff_lumi_masking) avctx->lumi_masking=coCfg->ff_lumi_masking1000/1000.0f;
   if (coCfg->is_ff_temporal_cplx_masking) avctx->temporal_cplx_masking=coCfg->ff_temporal_cplx_masking1000/1000.0f;
   if (coCfg->is_ff_spatial_cplx_masking) avctx->spatial_cplx_masking=coCfg->ff_spatial_cplx_masking1000/1000.0f;
   if (coCfg->is_ff_p_masking) avctx->p_masking=coCfg->ff_p_masking1000/1000.0f;
   if (coCfg->is_ff_dark_masking) avctx->dark_masking=coCfg->ff_dark_masking1000/1000.0f;
   if (coCfg->is_ff_border_masking) avctx->border_masking=coCfg->ff_border_masking1000/1000.0f;
   if (coCfg->ff_naq) avctx->flags|=CODEC_FLAG_NORMALIZE_AQP;
   if (coCfg->isElimLum) avctx->luma_elim_threshold=coCfg->elimLumThres;
   if (coCfg->isElimChrom && !coCfg->gray) avctx->chroma_elim_threshold=coCfg->elimChromThres;
  }
 isAdaptive=coCfg->isLAVCadaptiveQuant();
 if (isAdaptive)
  {
   avctx->lmin=coCfg->q_mb_min*FF_QP2LAMBDA;
   avctx->lmax=coCfg->q_mb_max*FF_QP2LAMBDA;
  }
 else
  {
   avctx->lmin=coCfg->getMinMaxQuant().first *FF_QP2LAMBDA;
   avctx->lmax=coCfg->getMinMaxQuant().second*FF_QP2LAMBDA;
  }

 RcOverride rces[2];int rcescount=0;
 if (coCfg->isCreditsStart && cfgcomode==ENC_MODE::CBR && coCfg->ff1_stats_mode&FFSTATS::READ)
  {
   RcOverride &rce=rces[rcescount];
   rce.start_frame=coCfg->creditsStartBegin;
   rce.end_frame=coCfg->creditsStartEnd;
   switch (coCfg->credits_mode)
    {
     case CREDITS_MODE::QUANT:rce.qscale=coCfg->limitq(coCfg->credits_quant_i);rce.quality_factor=1;break;
     case CREDITS_MODE::PERCENT:rce.qscale=0;rce.quality_factor=coCfg->credits_percent/100.0f;break;
    }
   rcescount++;
  }
 if (coCfg->isCreditsEnd && cfgcomode==ENC_MODE::CBR && coCfg->ff1_stats_mode&FFSTATS::READ)
  {
   RcOverride &rce=rces[rcescount];
   rce.start_frame=coCfg->creditsEndBegin;
   rce.end_frame=coCfg->creditsEndEnd;
   switch (coCfg->credits_mode)
    {
     case CREDITS_MODE::QUANT:rce.qscale=coCfg->limitq(coCfg->credits_quant_i);rce.quality_factor=1;break;
     case CREDITS_MODE::PERCENT:rce.qscale=0;rce.quality_factor=coCfg->credits_percent/100.0f;break;
    }
   rcescount++;
  }
 if ((avctx->rc_override_count=rcescount)!=0)
  avctx->rc_override=rces;

 // save av_log_callback and set custom av_log that shows message box.
 void (*avlogOldFunc)(AVCodecContext*, int, const char*, va_list);
 int errorbox;
 deci->getParam(IDFF_errorbox,&errorbox);
 if (errorbox)
  {
   avlogOldFunc=(void (*)(AVCodecContext*, int, const char*, va_list))(libavcodec->av_log_get_callback());
   libavcodec->av_log_set_callback(Tlibavcodec::avlogMsgBox);
  }

 int err=libavcodec->avcodec_open(avctx,avcodec);

 // restore av_log_callback
 if (errorbox)
  libavcodec->av_log_set_callback(avlogOldFunc);
 if (err<0)
  {
   avctx->codec=NULL;
   return ICERR_ERROR;
  }
 if (avctx->stats_in) {free(avctx->stats_in);avctx->stats_in=NULL;}
 codecinited=true;
 return ICERR_OK;
}

HRESULT TvideoCodecLibavcodec::compress(const TffPict &pict,TencFrameParams &params)
{
 if (coCfg->mode==ENC_MODE::VBR_QUAL)
  {
   frame->quality=(100-coCfg->qual)*40;
   avctx->flags|=CODEC_FLAG_QSCALE;
  }
 else
  if (params.quant==-1)
   avctx->flags&=~CODEC_FLAG_QSCALE;
  else
   {
    avctx->flags|=CODEC_FLAG_QSCALE;
    frame->quality=coCfg->limitq(params.quant)*FF_QP2LAMBDA;
    avctx->qmin_i=avctx->qmax_i=0;
    avctx->qmin_b=avctx->qmax_b=0;
   }

 if (isAdaptive)
  if (!coCfg->isInCredits(params.framenum))
   {
    avctx->lmin=coCfg->q_mb_min*FF_QP2LAMBDA;
    avctx->lmax=coCfg->q_mb_max*FF_QP2LAMBDA;
   }
  else
   {
    avctx->lmin=coCfg->getMinMaxQuant().first *FF_QP2LAMBDA;
    avctx->lmax=coCfg->getMinMaxQuant().second*FF_QP2LAMBDA;
   }

 frame->top_field_first=(avctx->flags&CODEC_FLAG_INTERLACED_DCT && coCfg->interlacing_tff)?1:0;

 switch (params.frametype)
  {
   case FRAME_TYPE::I:frame->pict_type=FF_I_TYPE;break;
   case FRAME_TYPE::P:frame->pict_type=FF_P_TYPE;break;
   case FRAME_TYPE::B:frame->pict_type=FF_B_TYPE;break;
   default:frame->pict_type=0;break;
  }
 bool flushing=!pict.data[0];
 if (!flushing)
  for (int i=0;i<4;i++)
   {
    frame->data[i]=(uint8_t*)pict.data[i];
    frame->linesize[i]=(int)pict.stride[i];
   }
 HRESULT hr=S_OK;
 while (frame->data[0] || flushing)
  {
   frame->pts=AV_NOPTS_VALUE;
   TmediaSample sample;
   if (FAILED(hr=sinkE->getDstBuffer(&sample,pict)))
    return hr;
   params.length=libavcodec->avcodec_encode_video(avctx,sample,sample.size(),!flushing?frame:NULL);
   if ((int)params.length<0)
    return sinkE->deliverError();
   else if (params.length==0 && flushing)
    break;
   if (coCfg->ff1_stats_mode&FFSTATS::WRITE && statsfile)
    fprintf(statsfile,"%s",avctx->stats_out);

   if (/*!isAdaptive || */!avctx->coded_frame->qscale_table)
    params.quant=int(avctx->coded_frame->quality/FF_QP2LAMBDA+0.5);
   else
    {
     unsigned int sum=0;
     for (unsigned int y=0;y<mb_height;y++)
      for (unsigned int x=0;x<mb_width;x++)
       sum+=avctx->coded_frame->qscale_table[x+y*avctx->coded_frame->qstride];
     params.quant=roundDiv(sum,mb_count);
    }

   params.kblks=avctx->i_count;
   params.mblks=avctx->p_count;
   params.ublks=avctx->skip_count;

   switch (avctx->coded_frame->pict_type)
    {
     case FF_I_TYPE:params.frametype=FRAME_TYPE::I;break;
     case FF_P_TYPE:params.frametype=FRAME_TYPE::P;break;
     case FF_B_TYPE:params.frametype=FRAME_TYPE::B;break;
     case FF_S_TYPE:params.frametype=FRAME_TYPE::GMC;break;
     case FF_SI_TYPE:params.frametype=FRAME_TYPE::SI;break;
     case FF_SP_TYPE:params.frametype=FRAME_TYPE::SP;break;
     case 0:params.frametype=FRAME_TYPE::DELAY;break;
    }
   params.keyframe=!!avctx->coded_frame->key_frame;

   if (psnr)
    {
     params.psnrY=avctx->coded_frame->error[0];
     params.psnrU=avctx->coded_frame->error[1];
     params.psnrV=avctx->coded_frame->error[2];
    }
   if (FAILED(hr=sinkE->deliverEncodedSample(sample,params)))
    return hr;
   frame->data[0]=NULL;
  }
 return hr;
}

const char* TvideoCodecLibavcodec::get_current_idct(void)
{
 if (avctx && (mpeg12_codec(codecId) || mpeg4_codec(codecId) || x264_codec(codecId) || codecId==CODEC_ID_FLV1))
  return libavcodec->avcodec_get_current_idct(avctx);
 else
  return NULL;
}

⌨️ 快捷键说明

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