XVID基本参数解析
XVID,X264等是MPEG4、H264标准的开源编码器,其中X264只有编码部分,解码部分需要FFMPEG完成;XVID有编解码部分,其中解码亦可以利用FFMPEG中的MPEG4完成解码。视频压缩算法的计算复杂度,都是比较高的。其中具有最大计算复杂度有三部分:宏块搜素运动补偿部分、码率控制部分、滤波算法部分;这三部分占据了算法复杂度的绝大部分资源。
XVID参数解释:
参数的设置集中在FFMPEG中的libxvidff.C中的 ff_xvid_encode_init()函数里面,主要是对编码上下文进行初始化赋值操作,此函数中的宏定义在XVID.H之中:
ff_xvid_encode_init(AVCodecContext *avctx) {
int xerr, i;
int xvid_flags = avctx->flags;
xvid_context_t *x = avctx->priv_data;
uint16_t *intra, *inter;
int fd;
xvid_plugin_single_t single;
xvid_ff_pass1_t rc2pass1;
xvid_plugin_2pass2_t rc2pass2;
xvid_gbl_init_t xvid_gbl_init;
xvid_enc_create_t xvid_enc_create;
xvid_enc_plugin_t plugins[7];
/* Bring in VOP flags from ffmpeg command-line */
x->vop_flags = XVID_VOP_HALFPEL; /* Bare minimum quality */ 半像素运动插值
if( xvid_flags & CODEC_FLAG_4MV )
x->vop_flags |= XVID_VOP_INTER4V; /* Level 3 */每个宏块分配四个运动矢量
if( xvid_flags & CODEC_FLAG_TRELLIS_QUANT)
x->vop_flags |= XVID_VOP_TRELLISQUANT; /* Level 5 */
if( xvid_flags & CODEC_FLAG_AC_PRED )
x->vop_flags |= XVID_VOP_HQACPRED; /* Level 6 * /高质量的AC预测
if( xvid_flags & CODEC_FLAG_GRAY )
x->vop_flags |= XVID_VOP_GREYSCALE;
/* Decide which ME quality setting to use */
x->me_flags = 0;
switch( avctx->me_method ) { //宏块搜索区域,搜索算法
case ME_FULL: /* Quality 6 */
x->me_flags |= XVID_ME_EXTSEARCH16/* extend PMV by more searches */
| XVID_ME_EXTSEARCH8;/* use diamond/square for extended 8x8 search */
case ME_EPZS: /* Quality 4 */
x->me_flags |= XVID_ME_ADVANCEDDIAMOND8/* use advdiamond for XVID_ME_EXTSEARCH8 */
| XVID_ME_HALFPELREFINE8
| XVID_ME_CHROMA_PVOP/* also use chroma for P_VOP/S_VOP ME */
| XVID_ME_CHROMA_BVOP;/* also use chroma for B_VOP ME */
case ME_LOG: /* Quality 2 */
case ME_PHODS:
case ME_X1:
x->me_flags |= XVID_ME_ADVANCEDDIAMOND16/* use advdiamonds instead of diamonds as search pattern */
| XVID_ME_HALFPELREFINE16;
case ME_ZERO: /* Quality 0 */
default:
break;
}
/* Decide how we should decide blocks */
switch( avctx->mb_decision ) { //是否选择码率控制方式 avctx->mb_decision=1时,编码一帧时间迅速增加
case 2:
x->vop_flags |= XVID_VOP_MODEDECISION_RD;
x->me_flags |= XVID_ME_HALFPELREFINE8_RD
| XVID_ME_QUARTERPELREFINE8_RD
| XVID_ME_EXTSEARCH_RD
| XVID_ME_CHECKPREDICTION_RD;
case 1:
if( !(x->vop_flags & XVID_VOP_MODEDECISION_RD) )
x->vop_flags |= XVID_VOP_FAST_MODEDECISION_RD;
x->me_flags |= XVID_ME_HALFPELREFINE16_RD
| XVID_ME_QUARTERPELREFINE16_RD;
default:
break;
}
/* Bring in VOL flags from ffmpeg command-line */
x->vol_flags = 0;
if( xvid_flags & CODEC_FLAG_GMC ) {
x->vol_flags |= XVID_VOL_GMC;
x->me_flags |= XVID_ME_GME_REFINE;
}
if( xvid_flags & CODEC_FLAG_QPEL ) { //是否允许1/4像素
x->vol_flags |= XVID_VOL_QUARTERPEL;
x->me_flags |= XVID_ME_QUARTERPELREFINE16;
if( x->vop_flags & XVID_VOP_INTER4V )
x->me_flags |= XVID_ME_QUARTERPELREFINE8;
}
memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init));
xvid_gbl_init.version = XVID_VERSION;
xvid_gbl_init.debug = 0;
#ifdef ARCH_POWERPC
/* XviD's PPC support is borked, use libavcodec to detect */
#if HAVE_ALTIVEC==1
if( has_altivec() ) {
xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_ALTIVEC;
} else
#endif
xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
#else
/* XviD can detect on x86 */
xvid_gbl_init.cpu_flags = 0;
#endif
/* Initialize */
xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);
/* Create the encoder reference */
memset(&xvid_enc_create, 0, sizeof(xvid_enc_create));
xvid_enc_create.version = XVID_VERSION;
/* Store the desired frame size */
xvid_enc_create.width = x->xsize = avctx->width; //图像宽度
xvid_enc_create.height = x->ysize = avctx->height; //图像高度
/* XviD can determine the proper profile to use */
xvid_enc_create.profile = XVID_PROFILE_S_L3; // 编码设定档次和级别 //压缩级别,MPEG4-ASP最高压缩级别
/* We don't use zones or threads */
xvid_enc_create.zones = NULL;
xvid_enc_create.num_zones = 0;
xvid_enc_create.num_threads = 0;
xvid_enc_create.plugins = plugins;
xvid_enc_create.num_plugins = 0;
/* Initialize Buffers */
x->twopassbuffer = NULL;
x->old_twopassbuffer = NULL;
x->twopassfile = NULL;
if( xvid_flags & CODEC_FLAG_PASS1 ) {
}
x->twopassbuffer[0] = x->old_twopassbuffer[0] = 0;
plugins[xvid_enc_create.num_plugins].func = xvid_ff_2pass;
plugins[xvid_enc_create.num_plugins].param = &rc2pass1;
xvid_enc_create.num_plugins++;
} else if( xvid_flags & CODEC_FLAG_PASS2 ) {//第二次编码,需要第一次编码生成的文件才可以完成第二次编码,不适用实时编码
memset(&rc2pass2, 0, sizeof(xvid_plugin_2pass2_t));
rc2pass2.version = XVID_VERSION;
rc2pass2.bitrate = avctx->bit_rate;
close(fd);
rc2pass2.filename = x->twopassfile;
plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2;
plugins[xvid_enc_create.num_plugins].param = &rc2pass2;
xvid_enc_create.num_plugins++;
} else if( !(xvid_flags & CODEC_FLAG_QSCALE) ) {
/* Single Pass Bitrate Control! */
memset(&single, 0, sizeof(xvid_plugin_single_t));
single.version = XVID_VERSION;
single.bitrate = avctx->bit_rate;
plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single;
plugins[xvid_enc_create.num_plugins].param = &single;
xvid_enc_create.num_plugins++;
}
/* Luminance Masking */
if( 0.0 != avctx->lumi_masking ) {
plugins[xvid_enc_create.num_plugins].func = xvid_plugin_lumimasking;
plugins[xvid_enc_create.num_plugins].param = NULL;
xvid_enc_create.num_plugins++;
}
/* Frame Rate and Key Frames */
xvid_correct_framerate(avctx);
xvid_enc_create.fincr = avctx->time_base.num;
xvid_enc_create.fbase = avctx->time_base.den;
if( avctx->gop_size > 0 )
xvid_enc_create.max_key_interval = avctx->gop_size; //图像组的长度设定
else
xvid_enc_create.max_key_interval = 240; /* XviD's best default */
/* Quants */
if( xvid_flags & CODEC_FLAG_QSCALE ) x->qscale = 1; ///encodes[i]->codec.vcc->flags|=CODEC_FLAG_QSCALE; 选择常量化/ //质量控制=量化参数,1~31,数值越小质量越高
else x->qscale = 0;
xvid_enc_create.min_quant[0] = avctx->qmin;
xvid_enc_create.min_quant[1] = avctx->qmin;
xvid_enc_create.min_quant[2] = avctx->qmin;
xvid_enc_create.max_quant[0] = avctx->qmax;
xvid_enc_create.max_quant[1] = avctx->qmax;
xvid_enc_create.max_quant[2] = avctx->qmax;
/* Quant Matrices */
x->intra_matrix = x->inter_matrix = NULL;
if( avctx->mpeg_quant ) //允许MPEG量化 量化矩阵
x->vol_flags |= XVID_VOL_MPEGQUANT;
if( (avctx->intra_matrix || avctx->inter_matrix) ) { //可以自己设定量化矩阵avctx->intra_matrix,avctx->inter_matrix
x->vol_flags |= XVID_VOL_MPEGQUANT;
if( avctx->intra_matrix ) {
intra = avctx->intra_matrix;
x->intra_matrix = av_malloc(sizeof(unsigned char) * 64);
} else
intra = NULL;
if( avctx->inter_matrix ) {
inter = avctx->inter_matrix;
x->inter_matrix = av_malloc(sizeof(unsigned char) * 64);
} else
inter = NULL;
for( i = 0; i < 64; i++ ) {
if( intra )
x->intra_matrix[i] = (unsigned char)intra[i];
if( inter )
x->inter_matrix[i] = (unsigned char)inter[i];
}
}
/* Misc Settings */
xvid_enc_create.frame_drop_ratio = 0; //丢帧率;0~100
xvid_enc_create.global = 0;
if( xvid_flags & CODEC_FLAG_CLOSED_GOP )
xvid_enc_create.global |= XVID_GLOBAL_CLOSED_GOP;
/* Determines which codec mode we are operating in */
avctx->extradata = NULL;
avctx->extradata_size = 0;
if( xvid_flags & CODEC_FLAG_GLOBAL_HEADER ) {
/* In this case, we are claiming to be MPEG4 */
x->quicktime_format = 1;
avctx->codec_id = CODEC_ID_MPEG4;
} else {
/* We are claiming to be XviD */
x->quicktime_format = 0;
if(!avctx->codec_tag)
avctx->codec_tag = ff_get_fourcc("xvid");
}
/* Bframes */
xvid_enc_create.max_bframes = avctx->max_b_frames;
xvid_enc_create.bquant_offset = 100 * avctx->b_quant_offset;
xvid_enc_create.bquant_ratio = 100 * avctx->b_quant_factor;
if( avctx->max_b_frames > 0 && !x->quicktime_format ) xvid_enc_create.global |= XVID_GLOBAL_PACKED;
/* Create encoder context */
xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL); //建立编码上下文
if( xerr ) {
av_log(avctx, AV_LOG_ERROR, "XviD: Could not create encoder reference\n");
return -1;
}
x->encoder_handle = xvid_enc_create.handle;
avctx->coded_frame = &x->encoded_picture;
return 0;
}
int ff_xvid_encode_frame(AVCodecContext *avctx,
unsigned char *frame, int buf_size, void *data) { 开始编码一帧
xerr = xvid_encore(x->encoder_handle, XVID_ENC_ENCODE,
&xvid_enc_frame, &xvid_enc_stats); //开始编码一帧
}
XVID的量化可以有三种方式:常量化,用户自己设定量化矩阵,调用默认的量化矩阵
XVID基本参数解析相关推荐
- Go 学习笔记(45)— Go 标准库之 flag(命令行参数解析)
1. 参数解析说明 import "flag" flag 包实现了命令行参数的解析.每个参数认为一条记录,根据实际进行定义,到一个 set 集合.每条都有各自的状态参数. 使用 f ...
- google gflags的参数解析,便捷实用
命令行参数解析,一直是我们后段开发人员需要经常使用的一个功能,用来从终端解析接口的输入 ,并做出对应的处理.这里为使用C++/python的开发人员推荐一个便捷的命令行解析接口集 gflags. 我们 ...
- 【Qt】通过QtCreator源码学习Qt(六):命令行参数解析实现
参考下大神的命令行参数解析是如何是实现的 //使用const char []代替宏定义字符串,我以前都是用const QString,想想好傻 const char SETTINGS_OPTION[] ...
- url参数解析 url解析 ?解析成对象
微信小程序开发交流qq群 173683895 承接微信小程序开发.扫码加微信. 正文: 代码: // url参数解析 function getUrlkey(url) {var params ...
- JS 把url的参数解析成对象
微信小程序开发交流qq群 173683895 承接微信小程序开发.扫码加微信. 正文: 实现思路:请看log和打印结果 // url参数解析 function getUrlkey(url) ...
- python命令行参数解析OptionParser类用法实例
python命令行参数解析OptionParser类用法实例 本文实例讲述了python命令行参数解析OptionParser类的用法,分享给大家供大家参考. 具体代码如下: from opt ...
- 介绍Shell脚本的参数解析工具
Argbash是一个代码生成器,它为你的脚本生成一个量身定制的解析库.与其他bash模块的通用代码不同,它生成你的脚本所需的最少代码. Argbash是一个代码生成器,它为你的脚本生成一个量身定制的解 ...
- 3gpp文件头文件解析_居于LLVM 的命令行参数解析
在写命令行程序的时候经常需要解析各种命令行参数.打印help信息等,觉得非常的麻烦.今天介绍一种超级棒的命令参数解析的方法:居于LLVM 的命令行参数解析,有了它妈妈再也不用担心我不会解析命令行参数^ ...
- Python命令行参数解析模块------argparse
首先,argparse 是python自带的命令行参数解析包,可以用来方便地读取命令行参数,当你的代码需要频繁地修改参数的时候,使用这个工具可以将参数和代码分离开来,让你的代码更简洁,适用范围更广 ...
最新文章
- struts2下的Action配置的各项默认值
- XSS-Game level 6
- 函数名的使用-闭包-迭代器
- 【Oracle】rollup函数
- 非IE内核浏览器支持activex插件
- PHP环境配置遇到的问题与解决
- 计算机控制试题库 百度文库,计算机控制技术练习题附答案_百度文库.doc
- 滤芯怎么换 石头机器人_拆开看个究竟,石头扫拖一体机器人T6到底如何?
- PerformanceTest
- 3G 模块驱动应用开发总结
- [阿毛]Ubuntu 16安装CH340串口驱动
- 只会增删改查的程序员出路在哪里?
- 判断手机是否处于静音、震动、正常模式
- 变焦光学系统工作原理及初始结构设计方法
- 什么是token及怎样生成token
- Visual Studio 中使用万能头文件 #include <bits/stdc++.h>
- Mysql组合索引使用和用法
- 龙芯1D处理器用户手册
- 物联网项目——具体分工
- 足不出户也能放风筝?OpenGL 一招搞定!