📄 tvideocodeclibavcodec.cpp
字号:
}
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 ¶ms)
{
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 + -