X264的编译改错
- 格式:docx
- 大小:41.24 KB
- 文档页数:20
菜鸟初学在vc下编译x264详解(zazaniao) 小弟初次接触x264,超级大菜鸟一只,把初学vc6下编译x264的经历说下,希望对以后学习x264的人有那么一点点帮助吧:)。
是用的x264是peter lee编译过的x264060805版本(压缩包里有《如何在vc6下编译x264》、《x264编译问题合集》2个文件帮助很大)(很多地方有下的,h.264乐园的ftp上也有)。
也可以在/x264/index.htm下载首先按照peter lee的如何在vc6下编译x264(这篇文章很多地方有的)操作。
只说下我操作时越到的问题(相关软件链接见《如何在vc6下编译x264》):1、Service Pack 5 for Visual Studio 6有中文版和英文版2种,我的vc是中文企业版,下载中文版的server pack 5安装不了,换成英文版的,ok啦。
这个需要解压缩,然后安装,不要直接解压缩在Program Files\Microsoft Visual Studio目录下,我就范了这个弱智的错误。
2、Visual C++ 6.0 Processor Pack 下载直接安装就好了。
3、NASM 略4、DirectX 9.0 SDK 解压缩,然后安装软件全部安装好,接下来就开始编译拉。
打开文件夹:x264060805\build\win32,(注x264060805这个文件是解压缩时根据个人习惯命名的,build\win32是固有的)在win32文件夹下面双击x264.dsw就进入vc界面拉。
如图:有2个1级目录。
1、对着libx264 files点击右键,选择set as active project,然后build(快捷键:F7)。
2、对着x264 files点击右键,选择set as active project,然后build(快捷键:F7)。
如果编译处了什么问题,请查看peter lee的/x264/index.htm如果编译通过,接下来还要设置一些东东:project->projectsettings->debugExecutable for debug session 自动生成的。
X264编码参数设置By:林立翔standfly@北京邮电大学多媒体通信中心2011-11一,X264版本本项目使用X264编码版本为20091008-2245,附带FFMPEG解码器用以验证编码效果。
二,编译条件本测试在windows xp平台下的visual studio 2008 编译环境下进行三,软件配置1. 打开X264CODEC文件夹,双击X264CODEC解决方案,用Visual Studio 2008打开工程文档2. 单击左上角解决方案资源管理器中X264ENCODE解决方案—>击右键 左击属性,进入X264ENCODE属性页—>选择配置属性—>调试—>在右栏的命令参数中输入所需的编码参数。
四,编码参数设置1.x264基本参数设置格式[--参数名参数值 ...] --output 输出文件输入文件其中方括号里是可输入可不输入的,“...”是可以输很多个的意思。
观察这个形式,每个参数名之前要加“--”,空格后跟此参数名的参数值;一定要有“--output”并指定输出文件;一定要指定输入文件,但前面没有“--”之类的提示符号。
此外,还有短参数模式。
这是为了简化某些常用参数名设计的。
一个“-”加一个字母构成一个短参数名,和与之对应的普通参数名效果一样。
注意此时这个字母区分大小写。
在--fullhelp 列表里,有短参数的参数的短参数都列在此参数的前面。
2.本测试预设的编码参数--crf 23 --tune psnr --preset medium --output X:\xxx\xxx.264 --fps 25 X:\广科院测试序列\左测试序列1.yuv 1920x1080其中,1).crfcrf为一种根据片子质量自动分配码率的 vbr 码率控制方式。
可用的值从 1到 51,越小编码质量越好,码率越高。
一般使用 16 到 24可以为浮点。
本测试预采用此参数或许不同码率下的编码数据。
习笔记(一)(x264编码流程)经过一段时间的学习我对h264也有了一个初步的大体的了解,今天在这里说一下h264中x264的开源code的编码的解析并附一张我自己画的流程图便于大家理解,又不对的地方清大家指教一二,偶必定三顾茅庐寻得真理。
:)首先我们进入x264.c中的main函数.刚开始是读取默认参数,如果你设置了参数的话会修改param的.i_ret = Encode( ¶m, fin, fout );这条语句使过程进入x264.c中的Encode函数. (这个函数就是x264的编码程序)X.264_encode函数.A i_frame_total = 0;if( !fseek( fyuv, 0, SEEK_END ) ){int64_t i_size = ftell( fyuv );fseek( fyuv, 0, SEEK_SET );i_frame_total = i_size / ( param->i_width * param->i_height * 3 / 2 )}这段调用了fseek()函数,对输入的视频文件计算其总帧数。
B. 函数 h = x264_encoder_open( param )对不正确的参数进行修改,并对各结构体参数和cabac编码,预测等需要的参数进行初始化.然后才能进行下一步的编码。
C. 函数 pic = x264_picture_new( h );定义在\CORE\common.c 中.此函数的作用是分给能容纳sizeof(x264_picture_t)字节数的空间,然后进行初始化.这里说明一下x264_picture_t和x264_frame_t的区别.前者是说明一个视频序列中每帧的特点.后者存放每帧实际的象素值.D. 调用fread()函数一次读入一帧,分亮度和色度分别读取.这里要看到c语言中的File文件有一个文件位置指示器,调用fread()函数会使文件指示器自动移位,这就是一帧一帧读取的实现过程.for( i_frame = 0, i_file = 0; i_ctrl_c == 0 ; i_frame++ ){int i_nal;x264_nal_t *nal;int i;/* read a frame */if( fread( pic->plane[0], 1, param->i_width * param->i_height, fyuv ) <= 0 ||fread( pic->plane[1], 1, param->i_width * param->i_height / 4, fyuv ) <= 0 ||fread( pic->plane[2], 1, param->i_width * param->i_height / 4, fyuv ) <= 0 ){break;}这里文件已经指示器发生了位移if( x264_encoder_encode( h, &nal, &i_nal, pic ) < 0 ){fprintf( std err, “x264_encoder_encode failed\n” );}……}E. 进入x264_encoder_encode( h, &nal, &i_nal, pic )函数,该函数定义在/Enc/encoder.c中.函数中先定义了如下三个参数:int i_nal_type; nal存放的数据类型, 可以是sps,pps等多种.int i_nal_ref_idc; nal的优先级,nal重要性的标志位.int i_slice_type; slice的类型的这里先说明一下:我们假设一个视频序列如下:I B B P B B P我们编码是按I P B B P B B的顺序,这就是frame的编号但是编码器如何来区分他们并把他们重新排序呢?我们来看看编码器是如何区分读入的一帧是I帧,P帧,或者B帧?以I B B P B B P为例.if( h->i_frame % (h->param.i_iframe * h->param.i_idrframe) == 0 ){确定这是立即刷新片.}if( h->param.i_bframe > 0 )//判断h是否为B帧然后对其进行下一步操作.我们编完I帧后碰到了一个B帧,这时我们先不对它进编码.而是采用frame= x264_encoder_frame_put_from_picture( h, h->frame_next, pic )函数将这个B帧放进h->frame_next中.在h中同时定义了下面几个帧数组用以实现帧的管理.x264_frame_t *bframe_current[X264_BFRAME_MAX]; /* store the sequence of b frame being encoded */x264_frame_t *frame_next[X264_BFRAME_MAX+1]; /* store the next sequence of frames to be encoded *///这个是定义下一个帧,但不一定是B帧. x264_frame_t *frame_unused[X264_BFRAME_MAX+1]; /* store unused frames */同时还有下面4个函数(定义在\ENCODER\encoder.c中).x264_encoder_frame_put_from_picture();x264_encoder_frame_put() ();x264_encoder_frame_get();x264_frame_copy_picture();这3个数组和4个函数可以说完成了整个帧的类型的判定问题.在不对P帧进行编码之前,我们不对B帧进行编码,只是把B帧放进缓冲区(就是前面提到的数组).例如视频序列:I B B P B B P先确立第一个帧的类型,然后进行编码.然后是2个B帧,我们把它放进缓冲区数组.然后是P帧,我们可以判定它的类型并进行编码.同时,我们将缓冲区的B帧放进h->bframe_current[i],不过这时P帧前的两个B帧并没有编码.当读到P帧后面的第一个B帧时,我们实际上才将h->bframe_current数组中的第一个B帧编码,也就是将在I帧后面的第一个B帧编码.依此类推.(帧的有关理解学习笔记(二))F. 建立参考帧列表的操作,这里调用了函数x264_reference_build_list( h, h->fdec->i_poc ); (定义在\ENCODER\encoder.c中).光调用这个函数是不行的,它是和后面的这个函数(如下)一起配合工作的.if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE )//判断为B 帧.{x264_reference_update( h );}If条件是判断当前帧是否是B帧,如果是的话就不更新参考列表,因为B帧本来就不能作为参考帧嘛!如果是I帧或P帧的话,就更新参考帧列表.G. 下面是写slice的操作./* Init bitstream context */h->out.i_nal = 0;//out的声明在bs.h中.bs_init( &h->out.bs, h->out.p_bitstream, h->out.i_bitstream );//空出8位./* Write SPS and PPS */if( i_nal_type == NAL_SLICE_IDR ){/* generate sequence parameters */x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST ); x264_sps_write( &h->out.bs, h->sps );x264_nal_end( h );/* generate picture parameters */x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST ); x264_pps_write( &h->out.bs, h->pps );x264_nal_end( h );x264_slice_write() (定义在\ENCODER\encoder.c中),这里面是编码的最主要部分..下面这个循环,它是采用for循环对一帧图像的所有块依次进行编码.for( mb_xy = 0, i_skip = 0; mb_xy < h->sps->i_mb_width * h->sps->i_mb_height; mb_xy++ )//h->sps->i_mb_width指的是从宽度上说有多少个宏快. { const int i_mb_y = mb_xy / h->sps->i_mb_width;const int i_mb_x = mb_xy % h->sps->i_mb_width;//这两个变量是定义宏块的位置../* load cache */x264_macroblock_cache_load( h, i_mb_x, i_mb_y );//是把当前宏块的up宏块和left宏块的intra4×4_pred_mode,non_zero_count加载进来,放到一个数组里面,这个数组用来直接得到当前宏块的左侧和上面宏块的相关值.要想得到当前块的预测值,要先知道上面,左面的预测值,它的目的是替代getneighbour函数./* analyse parameters* Slice I: choose I_4×4 or I_16×16 mode* Slice P: choose between using P mode or intra (4×4 or 16×16)* */TIMER_START( i_mtime_analyse );x264_macroblock_analyse( h );//定义在analyse.h中.TIMER_STOP( i_mtime_analyse );/* encode this macrobock -> be carefull it can change the mb type to P_SKIP if needed */TIMER_START( i_mtime_encode );x264_macroblock_encode( h );//定义在Enc/encoder.c中.TIMER_STOP( i_mtime_encode );到这就已经完成编码的主要过程了,后面就是熵编码的过程了.。
X264编码参数设置By:林立翔standfly@北京邮电大学多媒体通信中心2011-11一,X264版本本项目使用X264编码版本为20091008-2245,附带FFMPEG解码器用以验证编码效果。
二,编译条件本测试在windows xp平台下的visual studio 2008 编译环境下进行三,软件配置1. 打开X264CODEC文件夹,双击X264CODEC解决方案,用Visual Studio 2008打开工程文档2. 单击左上角解决方案资源管理器中X264ENCODE解决方案—>击右键 左击属性,进入X264ENCODE属性页—>选择配置属性—>调试—>在右栏的命令参数中输入所需的编码参数。
四,编码参数设置1.x264基本参数设置格式[--参数名参数值 ...] --output 输出文件输入文件其中方括号里是可输入可不输入的,“...”是可以输很多个的意思。
观察这个形式,每个参数名之前要加“--”,空格后跟此参数名的参数值;一定要有“--output”并指定输出文件;一定要指定输入文件,但前面没有“--”之类的提示符号。
此外,还有短参数模式。
这是为了简化某些常用参数名设计的。
一个“-”加一个字母构成一个短参数名,和与之对应的普通参数名效果一样。
注意此时这个字母区分大小写。
在--fullhelp 列表里,有短参数的参数的短参数都列在此参数的前面。
2.本测试预设的编码参数--crf 23 --tune psnr --preset medium --output X:\xxx\xxx.264 --fps 25 X:\广科院测试序列\左测试序列1.yuv 1920x1080其中,1).crfcrf为一种根据片子质量自动分配码率的 vbr 码率控制方式。
可用的值从 1到 51,越小编码质量越好,码率越高。
一般使用 16 到 24可以为浮点。
本测试预采用此参数或许不同码率下的编码数据。
[VCB-Studio][教程09]x264参数设置VCB-Studio教程09 x264参数设置0. 前言本教程旨在讲述x264参数设置的技巧,并侧重于vcb-s定位的使用:10bit,动漫,高码率,高参数。
对于非这类定位的压制,虽有叙述但不详细。
本教程请搭配MeGUI的参数设置面板一起阅读:本教程会按照标签卡(Main->Frame Type->…->Misc)分别讲解,每个标签卡内,按照从左上到左下,到右上到右下的顺序,讲述每个参数的使用,并给出它们在批处理命令行中的写法。
或者,你完全可以在MeGUI中调好,然后复制下方的命令行(去掉开头的program和结尾的--output "output" "input")到批处理。
后续会有教程讲述低码率下8bit压制的技巧。
不要将本篇中讲述的任何参数和逻辑套用在x265上。
1. Main标签卡,x264基础设置Main标签卡里面都是最主要的参数,新手上路,掌握Main标签卡的内容,就足以去一些普通字幕组担任压制了。
Encoding Mode(rc,ratecontrol,码率控制方法):ABR: Average Bit Rate,指定一个平均码率。
x264会试图让整部视频的平均码率达到你的给定值。
如果视频前后编码复杂度相差很大,那么码率的时间分配效果就很差,尤其是到了结尾,为了达到预定的码率值,x264经常不得不采用过高/过低的码率。
所以一般不推荐这个模式。
命令行: --bitrate 1000,1000是码率,单位Kbps。
Const quantizer:cq模式,固定量化模式。
所有P帧(下文有讲)采用一个固定的Quantizer。
Quantizer, 量化,是一种衡量图像压缩程度的方法,用0-69的浮点数表示,0为无损。
图像被压缩的越多,量化值越大,码率越低,注意量化值不一定代表目视质量,比如说一个纯色的图像可以以很高的量化值被量化,占用的体积很小,而一个很复杂的图像就算量化值不高,但是压缩后观感也可能很差。
x264 编码器API调用时的参数设置x264DLL在调用时主要需要调整的参数包括:第一,profile,也就是使用baseline还是main,还是high编码。
可以通过该接口设置x264_param_apply_profile();第二, 编码复杂度param.i_level_idc=30;第三,图像质量控制param.rc.f_rf_constant = 25;param.rc.f_rf_constant_max = 45;rc.f_rf_constant是实际质量,越大图像越花,越小越清晰。
param.rc.f_rf_constant_max ,图像质量的最大值。
第四, 码率控制一开始我使用恒定码流设置,无论我怎么设置,都无法控制实际码流,后来换成平均码流后,就行了。
param.rc.i_rc_method = X264_RC_ABR;//参数i_rc_method表示码率控制,CQP(恒定质量),CRF(恒定码率),ABR(平均码率)param.rc.i_vbv_max_bitrate=(int)((m_bitRate*1.2)/1000) ; // 平均码率模式下,最大瞬时码率,默认0(与-B设置相同)param.rc.i_bitrate = (int)m_bitRate/1000;x264使用的bitrate需要/1000。
第五,使用实时视频传输时,需要实时发送sps,pps数据param.b_repeat_headers = 1; // 重复SPS/PPS 放到关键帧前面该参数设置是让每个I帧都附带sps/pps。
第六. I帧间隔我是将I帧间隔与帧率挂钩的,以控制I帧始终在指定时间内刷新。
以下是2秒刷新一个I帧param.i_fps_num = (int)m_frameRate;param.i_fps_den = 1;param.i_keyint_max = m_frameRate * 2;第七,编码延迟在使用中,开始总是会有编码延迟,导致我本地编码立即解码回放后也存在巨大的视频延迟,后来发现设置x264_param_default_preset(¶m, "fast" , "zerolatency" );后就能即时编码了。
修改编译选项-mv6400为-mv64x+,编译结果出错:__strasgi_64plus未定义,更新rts6400.lib 为rts64plus.lib后编译通过,速度没有显著变化。
修改编译选项,添加-pm 及-o3,进行程序级优化。
代码未做任何改动,重新编译通过。
优化编译耗时近15分钟(AMD athlon 64bit 3200+ 2.01G, CPU, 1G内存),一帧压缩时间降到2秒。
我注释掉了取时间函数,所以得不到精确的fps。
优化前对foreman的测试序列还能跑个40多帧,优化编译后跑了两帧就飞掉了,我想是因为我随意分配段到内存空间的关系,不过我觉得目前深究这个问题没意义。
-mv6400/-mv64x+这类编译选项告诉编译器目标平台的DSP核类型。
-pm 告诉编译器需对整个项目的所有模块进行联合观测,以取得最优的优化效果,所以没加这个选项以前每个c文件对应一个obj文件,加了这个选项之后所有c文件被合并为一个obj中了。
-o3 告诉编译器对工程进行最高级的优化。
-pm -o3一般都是联合使用的。
配合线性汇编和instrinsics,再加上DSP的DMA搬运大块数据,优化目标就可实现。
做到这里我突然感觉优化应该没那么困难,虽然目前我一帧压缩需要2秒。
当初我觉得难搞到不行,实在是因为我什么都不懂的关系。
优化是以后的事情,现在还是转到x264的代码上面,我对整个x264算法现在有一个大体的理解:算法大体可以分为三层:1.最上面的main()层,x264_param_default()完成压缩默认参数的设置,结构opt中放置的是输入输出文件的句柄,parse()这个函数是解析命令行的,default参数有几个在这里会被命令行改掉,opt的参数同时也在parse中被赋值。
对于DSP的移植来看,这两个函数可以并成一个,直接为param 和opt这两个结构赋上定死的值就可以,parse中解析命令行的循环可以去掉,这一点在上篇有详细的代码。
x264实时编码的码率控制--一个简单的QP调节方法x264实时编码的码率控制一个简单的QP调节方法在用x264做实时视频,由于用在智能手机上,计算能力有限,网络带宽有限,故设计了一个简单的新的码率控制算法,效果还不错,与大家分享。
一般做实时视频,x264作者推荐用vbv-CBR模式,这样来稳定码流,适应带宽。
但对于嵌入式系统,CBR模式计算量较大。
CBR模式需要进行前期的半精度SATD值计算,以得到图像复杂度,进而得到预计的bits(这一SATD还用在slice type的选择,实际这个计算过程的函数就叫slice_type_decision,在lookaheand_get_frame中);通过预计bits与期望bits的比较得到qscale,进而得到本编码帧的QP。
当然若用上mb_tree,aq_mode 还更复杂。
这一前期的计算过程大致占整个计算量的12%-20%(根据参数的不同),但若略去这步,使用固定QP,码率波动较大。
现设计了一个新的模式,利用帧间的相似性,根据上一帧编码的实际bits与期望bits的差,来调节QP(帧级调整)。
实现上的思路也很简单,利用CQP模式的壳,在每帧编码前再次调节QP。
需要采用参数如下:--bframes 0 不要B帧对于嵌入式,手机等系统,建议采用:--scenecut 0---(不需额外增加i 帧,由于实时不需b帧,故一个GOP组中,只有一个IDR 帧及其余的P帧);--subme 1 1/4精度的SAD值--no-8x8dct (这个是high profile, 不需要,同样可加快编码,节省码流)--partition none 不要划分(可提高编码速度,节省码流,psnr基本不变)其余参数可参见,x264 --preset-veryfast的参数配置;好了接下来是帧级的码流控制,即调节QP;1. 在x264参数中添加新码率控制的参数(get_opt函数),如:--newqp2. 这个newqp与CQP,可以起使用。
X264的编译改错:12月1.将所有的X264_LOG用LOG_printf代替,去掉common.c中的x264_log,log_default2.所有的fprintf()即对文件的操作应该去掉3.去掉信噪比的计算,因为在解码端也可得到在common.c中param->analyse.b_psnr = 0;//是否使用信噪比4.设置set_en.c中的sps->b_vui = 0;表示vui信息不出现在码流中;sps->b_frame_mbs_only = 1;表示采用所有图像均帧编码5.屏蔽掉:CAVLC_EN.C中的else if( i_mb_type == B_8x8 ),else if( i_mb_type !=B_DIRECT ),else if( i_mb_type == B_DIRECT ), else if( i_mb_type == B_8x8 )6.去掉common.h中的CHECKED_MALLOC中的if(!var)...(即检查分配内存成功与否)7.屏蔽掉ratecontrol_en.c中的x264_ratecontrol_new中的if( h- >param.rc.i_rc_method== X264_RC_CRF)..和/* Load stat file and init 2pass algo */ if( h->param.rc.b_stat_read )...8.去掉slicetype_decision_en.c中的if( h->param.rc.b_stat_read ) {...}和voidx264_slicetype_analyse( x264_t *h )函数,ratecontrol_en.c中的x264_ratecontrol_slice_type函数9.去掉ratecontrol_en.c中的update_vbv函数中的if( rcc->buffer_fill < 0&& !rcc->b_2pass )..., rate_estimate_qscale中的if( rcc->b_2pass )..init_pass2(){...}函数10.去掉encoder_en.c中的x264_validate_levels( h )语句和set_en.c中对应的函数以上有一些修改涉及到检查参数的正确性,是因为在保证参数正确性的情况下这些语句是可以去除的12月1.去掉if( h->param.rc.b_stat_read )开头的语句2.去掉assert()语句3.将CCS中的程序中的fprintf(...)全部去掉,(因为涉及到文件的操作,使用USB口传输很耗时)4.去掉exit(-1)之类报告程序错误的函数5.去掉encoder_en中的#ifdef DEBUG_MB_TYPE...#endif之间的语句6.去掉common.c中的x264_param_parse()函数7.去掉analyse_en.c中的static const int i_mb_b_cost_table[19]类似的数组(B帧用到的),以及以if( h->sh.i_type == SLICE_TYPE_B )...开头的语句12月1.去掉analyse_en.c中的x264_mb_analyse_inter_direct(),x264_mb_analyse_inter_b16x16(),x264_mb_analyse_inter_b8x8,x264_mb_analyse_inter_b16x8,x264_mb_analyse_inter_b8x16()等五个函数,这五个函数是用来进行B帧帧间预测的,不需要用到2.去掉macroblock.c中的if( h->sh.i_type == SLICE_TYPE_B && h->param.b_cabac )...3.去掉所有以if( h->sh.i_type == SLICE_TYPE_B )..开头的语句4.去掉以if( h->param.analyse.b_psnr )...开头计算PSNR的语句5.将以for( i_list = 0; i_list < (h->sh.i_type == SLICE_TYPE_B ? 2 : 1 );i_list++ )的循环去掉,因为不使用P帧只执行一次,不需循环但需加入i_list = 0;置初值6将#ifdef _BS_H#warning FIXME Multiple inclusion of bs.h#else#define _BS_H改为:#ifndef _BS_H#define _BS_H7.analyse_en.c中的x264_mb_analyse_b_rd(),refine_bidir()函数去掉8.去掉cavlc_en.c中的uint8_t mb_type_b_to_golomb[3][9]和sub_mb_type_b_to_golomb[13]数组9.去掉common.c中的parse_enum(),parse_cqm(),atobool()函数希望:将encoder_en.c中的if( h->param.rc.psz_stat_out )h->param.rc.psz_stat_out = strdup( h->param.rc.psz_stat_out );这样就不需要自己定义的strdup函数了12月1.去掉encoder_en.c的x264_encoder_encode()函数中的两个没有用到的变量:i_mb_i和i_mb_p(在CCS编译时的警告提示这两个变量定义但未被使用,其它有类似的警告也可以考虑去掉)2.去掉frame.c中的x264_frame_new()函数中的以fail:标号开头的三句话(在程序中不会调用) 去掉macroblock.c中的x264_macroblock_cache_init()函数中的以fail:标号开头的两句话3.pridect.c中的UNUNSED变量该如何处理?(CCS中警告说没有使用,但直接删除在VC下会报错!)4.去掉所有以#ifdef HAVE_MMXEXT ...#endif的语句5.去掉ratecontrol_en.c中的parse_zones相关的三处代码6.去掉encoder_en.c中的x264_encoder_close()函数中的x264_ratecontrol_summary( h )函数及在ratecontrol.c中的相应代码(因为在这个函数中调用了if(rc->b_abr)...;7.去掉ratecontrol_en.c中的与rate_estimate_qscale()和get_diff_limited_q()有关的函数8.去掉x264.c中的strtable_lookup()函数,与/* update status line (up to 1000 times per input file) */有关的语句*******************1.考虑将ratecontrol_en.h中的声明的函数在程序中被使用的地方全部替换!!!即删掉ratecontrol_en.c文件,不使用码率控制2.去掉以rc->b_abr,b->2pass判断的语句12月1.去掉ratecontrol_en.c中的get_qscale()和clip_qscale()函数2.去掉encoder_en.c中的关于x264_psnr()的宏及调用它的函数(不计算信噪比)ratecontrol_en.c中的调用:1.Searching for 'x264_ratecontrol_start'...F:\H.264\youhua\x264Vc\encoder_en.c(1350): x264_ratecontrol_start( h,i_slice_type,h->fenc->i_qpplus1 );2.Searching for 'x264_ratecontrol_new'...F:\H.264\youhua\x264Vc\encoder_en.c(617): if( x264_ratecontrol_new( h) < 0 )3.Searching for 'x264_ratecontrol_delete'...F:\H.264\youhua\x264Vc\encoder_en.c(1842): x264_ratecontrol_delete( h);4.Searching for 'x264_ratecontrol_threads_start'...F:\H.264\youhua\x264Vc\encoder_en.c(1124):x264_ratecontrol_threads_start( h );F:\H.264\youhua\x264Vc\encoder_en.c(1148):x264_ratecontrol_threads_start( h );5.Searching for 'x264_ratecontrol_slice_type'...F:\H.264\youhua\x264Vc\slicetype_decision_en.c(381):x264_ratecontrol_slice_type( h, h->frames.next[i]->i_frame );(已经被去掉)6.Searching for 'x264_ratecontrol_mb'...F:\H.264\youhua\x264Vc\encoder_en.c(1074):x264_ratecontrol_mb(h, bs_pos(&h->out.bs) - mb_spos);7.earching for 'x264_ratecontrol_qp'...F:\H.264\youhua\x264Vc\analyse_en.c(1950): x264_mb_analyse_init( h,&analysis,x264_ratecontrol_qp( h ) );F:\H.264\youhua\x264Vc\encoder_en.c(1351): i_global_qp =x264_ratecontrol_qp( h );8.Searching for 'x264_ratecontrol_end'...F:\H.264\youhua\x264Vc\encoder_en.c(1541): x264_ratecontrol_end( h,i_frame_size * 8 ); 1.修改x264.c中的Encode_frame()和Encode()函数,修改原来程序中的编码一帧,写一帧到输出文件为编码所有的帧完成后再一次写入到输出文件中(此处给存放输出文件的缓冲只分配了1M大小)12月1.在编译选项中添加-k,-mw,可以生成反馈文件信息(.asm)12月修改X264.C中的main函数,为输入的文件分配一个缓冲,p_readYUV,5M大小.先将YUV文件读入到这个缓冲中,然后在编码时每次读取YU的V分量只需要使用MEMCPY从内存中复制对应的数据即可.两天时间,终于快解决这个输入缓冲的问题!这样做仍然在CCS中仍然是将PC上的YUV文件通过USB口读取到EVM的SDRAM中,速度仍然很慢,今后要是能使用网络传输应该会快很多,但现在主要是作优化,只要与PC通信的这块能够不占入编码时间就很好了.主要代码如下:/* raw 420 yuv file operation */int open_file_yuv( char *psz_filename, hnd_t *p_handle, x264_param_t*p_param ){....//获得文件的长度fseek(h->fh,0,SEEK_END);i_file_length =ftell(h->fh);fseek(h->fh,0,SEEK_SET);//读取YUV文件fread(p_readYUV,1,i_file_length,h->fh);...}int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame ){yuv_input_t *h = handle;/* if( i_frame != h->next_frame )if( fseek( h->fh, (uint64_t)i_frame * h->width * h->height * 3 /2, SEEK_SET ) )return -1;*//* if( fread( p_pic->img.plane[0], 1, h->width * h->height,h->fh ) <= 0|| fread( p_pic->img.plane[1], 1, h->width * h->height / 4,h->fh ) <= 0|| fread( p_pic->img.plane[2], 1, h->width * h->height / 4,h->fh ) <= 0 )return -1;*///从内存中复制数据memcpy(p_pic->img.plane[0], p_readYUVBuffer , h->width *h->height);memcpy(p_pic->img.plane[1], p_readYUVBuffer+h->width * h->height , h->width * h->height/ 4); memcpy(p_pic->img.plane[2], p_readYUVBuffer +h->width *h->height+ h->width * h->height/ 4, h->width * h->height/ 4);p_readYUVBuffer=p_readYUVBuffer +h->width * h->height+ h->width * h->height/ 4+ h->width * h->height/ 4;h->next_frame = i_frame+1;return 0;}在CCS中的char 换成uint8_t12月修改DSP/BIOS,将BIOS的对象分配到IRAM中,将BIOS需要的STACK分配在DDR2FORHEAP中,1.此时在p_readYUVBuffer=x264_malloc(0x500000);分配5M的输入缓冲时占了较长时间(估计有10分钟了)修改COMMON.C中的X264_malloc,将buf = (uint8_t *) malloc( i_size + 15 +sizeof( void ** ) +sizeof( int ) );改成:buf=(uint8_t *)MEM_calloc(DDR2forHeap, i_size + 15 +sizeof( void ** ) +sizeof( int ),0); (使用DSP/BIOS提供的MEM分配函数)12月1.下午将fread从CCS中读到的数据,用CCS的DATA->SAVE把对应的foreman01.yuv文件保存为DATA格式的foreman01.dat,以后要作测试时,直接使用DATA-->LOAD将其导入到SRAM中即可2.调试时出现问题:在编码第一帧后又返回到了主函数,这样一直在重复编码一帧!不知道是不是因为将main()和smain()函数放在同一个x264.c文件里面的缘故?是不是main()函数必须单独作一个文件?在log_printf.pjt工程里证明不是因为必须在一个文件里的问题3.以上出现程序跑飞的原因可能是因为TSK0的任务堆栈太小(默认是1024),在DSP/BIOS里改成了(10000)4.是在encoder_en.c中的x264_slice_write函数中又跑到主函数中去的可能是因为文件操作的原因?12月1.关于用CCS的DATA->SAVE把对应的foreman01.yuv文件保存为DATA格式的foreman01.dat,以后要作测试时,直接使用DATA-->LOAD将其导入到SRAM中,在CCS中使用VIEW-MEMORY查看内存中的数的读的方法:如DAT文件如下1651 1 85000010 0 11fb800xFFC9280A0xFEFEFEF70xFEFEFEFE0xFEFEFEFE0xFEFEFEFE0xFEFEFEFE0xFEFEFEFE0xFEFEFEFE0xFEFEFEFE0xFEFEFEFE0xFEFEFEFE0xE9FEFFFD....................在SRAM中0x8500 0010存放第一个数0xFFC9280A,第二个数的0xFEFEFEF7的地址为0x8500 0010 + 4*(2-1)=0x8500 0014,第12个数0xE9FEFFFD的地址为0x8500 0010+4*(C-1)=0x8500 003C;最后一个数(第1178496个数)的地址为 0x8500 0010 + 4*(11fb80-1)=0x8547 ee0c;(1178496转换为十六进制为0x11fb80);即第n个数的存放地址为0x8500 0010+4*(n(十六进制)-1);12月将所有的fseek换成lseek(/dv_rss.asp?s=xhtml&boardid=20&id=118797) 仍不能解决问题!!!12月1.尝试方法:恢复1.17号的X264.C文件,即还是采用fopen,fread,从PC上读一帧编码后再从PC上读另一帧,看是否正常使用DATA-LOAD的备份文件为:复件 (4) x264.c在使用DATA-LOAD的程序中似乎可以不需要open_file_yuv.. 使用类似的程序在VC下可以正常编码..问题得到解决:将ccs中的macroblock.c用F:\H.264\youhua\x264Vc目录下的macroblock.c文件替换,就可以正常编码了可见当时对这两个文件没有同步更新!!!导致一个跨越年度的错误!!但生成的文件有800多kb,12月将DSP/BIOS中的MEM重新分配,使p_writeBuffer与p_readBuffer不指向同一块内存,生成的文件大为缩小,只有132KB,但是编码30帧的速度仍然需时近5分钟12月使用BUILD OPTION:-g -k -o3 -fr"$(Proj_dir)\Debug" -d"_DEBUG" -d"__X264__" -mw -mv6400+ --mem_model:data=far速度30帧大约需要1分钟对于fps的计算仍未清楚,clock()两次运行同样的程序得到的时间竟然不同!12月仍然在研究使用何种方法来获得程序运行的时间,clock()只有用load6x()时才较准确,CLK_getltime()是推荐的用法,不过要引入中断新建一个工作(在F:\DSP\CCS\CLK)专门用来测试CLK_getltime()的用法,发现:1.只有用timer0时,定时器中断才能进入,2.使用Profile菜单中的clock->view看时钟时,根据DSP/BIOS中的CLK manager中的Specify input clock rate来,得到的clock不同,默认这项是选中的,27MHZ时得到的cycle数比不选中时(594MHZ)时少的多,这可能也是采用clock()不准确的原因12月跟昨天一样的程序,同样的DSP/BIOS配置,昨天可以用CLK_getltime()获取时间,今天为什么就返回的是0了???1.将dsp264_3.pjt的DSP/BIOS的CLK manager中选中为timer0在x264.c的encode函数中将计算fps,需获得开始时间改为:i_start=CLK_getltime();i_end=CLK_getltime();调试程序时测得i_start=15 ,i_end=55462 (单位ms),fps=31(帧)/i_end-i_start=0.56(帧/秒) 与实际观测相近12月1.删除mdate.c及相关的X264_mdate()宏,使用CLK_getltime()获取时间(删除common.h中的int64_t x264_mdate( void );encoder_en.c中的#define TIMER_START( d ) \...宏,和encoder_en.c中的调用了TIMER_START()和TIMER_STOP的宏的行(这在VC上可以成功))2.变量存储类型调整:在VC中long和int 都是定义成32位,(见MSDN)而在CCS中long定义成40位,因此将CCS中的long换成int在VC中同步更新4.去掉if __x264__..else语句5.在x264.c中的encode函数中加入double fps,然而程序运行时却发现fps一直都是未定义变量,对x264.c去掉-O3编译选项,即可认出fps,可能是O3选项优化时将这句代码删掉了...,若去掉O3选项,编码速度很慢!将double fps设为全局变量,可以正常计算,前两天在测试clock()和CLK_getltime(),今天晚上就在测试这个fps的计算了,期间犯过将ms转换为s 乘1000的低级错误...真是效率低!12月1.加入-pm和-pm op0和-pm op2 -pm -op3优化选项编译,结果程序又重复编译第一帧了...2.加入-pm -op1优化选项,出现错误:[Linking...]"C:\CCStudio_v3.3\C6000\cgtools\bin\cl6x"-@"Debug.lkf"<Linking>undefined first referencedsymbol in file--------- ----------------_smain F:\\H.264\\dsp264_3\\Debug\\dsp264_3cfg.obj>> error: symbol referencing errors - './Debug/dsp264_3.out' not built 在int smain()函数前加入:#pragma FUNC_EXT_CALLED (smain);BUILD无错误,但仍然程序重复编译第一帧12月1.使用-k -o3 -fr"$(Proj_dir)\Debug" -d"_DEBUG" -mt -mw -mv6400+ --mem_model:data=far选项,编码速度为0.60fps2.-k -pm -op0 -o3 -fr"$(Proj_dir)\Debug" -d"_DEBUG" -mt -mw -mv6400+ --mem_model:data=far ...0.46fps,foreman01.264文件>157KB昨天使用-pm -op0选项不成功可能是因为不能加上-g选项12月参考:F:\H.264\移植\g宋扬-基于TMS320DM642DSP的H_264编码器优化与设计.nh1.项目级优化:使用-o3 -k -mt –mw12月1.参考F:\H.264\移植\gH_264视频编码技术研究及其在TI_DSPDM642上的实现.nh的<<3.5.3节对X264帧间预测模式选择算法的改进>>修改帧间预测算法,在X264VC中的analyse_en.c中修改,主要是屏蔽了Void x264_macroblock_analyse( x264_t *h )函数中if( analysis.b_mbrd ){/* refine later */}else if( i_partition == D_16x16 ){// x264_me_refine_qpel( h, &analysis.l0.me16x16 ); 与此类似的1/4像素精度搜索i_cost = analysis.l0.me16x16.cost;}这段算法还是不能删除!因为这些就是在在选择了最优预测模式后的分像素精度搜索12月1.去掉VC版本中pixel.c中void x264_pixel_init()关于PSNR的计算:INIT( ssd,),INIT( sad_x3, );在dsp264_3.pjt中作相应修改12月1.去掉VC...pixel.c中pixel_sa8d_wxh()...及与sa8d相关的语句,在CCS 中亦作相应修改12月根据CCS中函数结构和调用约定,对于x264_pixel_sad_16x16之类的static int name( uint8_t *pix1, int i_stride_pix1, \uint8_t *pix2, int i_stride_pix2 )函数,在传递参数时前四个参数分别是A4,B4,A6,B6,将这些函数形参先后顺序改为 static int name( uint8_t *pix1,uint8_t *pix2, int i_stride_pix1,inti_stride_pix2 ) 似乎更利于CCS的并行运行.因为对于pix1,pix2分别是参考宏块,分别采用A4,B4,作为寄存器调用,可以减少一次T通道的使用(但可能会增加X的使用了)先在VC中更改形参的次序,以"h->pixf.sad"为关键字搜索,修改如下地方: F:\H.264\youhua\x264Vc\me_en.c(52): /*int cost =h->pixf.sad[i_pixel](m->p_fenc[0], FENC_STRIDE,\&p_fref[(my)*m->i_stride[0]+(mx)],m->i_stride[0] )\+ BITS_MVD(mx,my);\*/修改为:int cost = h->pixf.sad[i_pixel]( m->p_fenc[0],&p_fref[(my)*m->i_stride[0]+(mx)],\FENC_STRIDE, m->i_stride[0] )\+ BITS_MVD(mx,my);\ 即交换第二个和第三个形参的位置.以下修改类似F:\H.264\youhua\x264Vc\me_en.c(62): int cost =h->pixf.sad[i_pixel](m->p_fenc[0], FENC_STRIDE, src, stride ) \F:\H.264\youhua\x264Vc\me_en.c(70): h->pixf.sad_x3[i_pixel]( m->p_ fenc[0],\F:\H.264\youhua\x264Vc\me_en.c(83): h->pixf.sad_x4[i_pixel]( m->p_ fenc[0],\F:\H.264\youhua\x264Vc\me_en.c(101): h->pixf.sad_x4[i_pixel]( m->p _fenc[0],\F:\H.264\youhua\x264Vc\me_en.c(468): const int enc_dc =h->pixf.sad[i_pixel]( m->p_fenc[0], FENC_STRIDE, zero, 16 );F:\H.264\youhua\x264Vc\me_en.c(544): int cost =h->pixf.sad[i_pixel](m->p_fenc[0], FENC_STRIDE, src, stride ) \F:\H.264\youhua\x264Vc\me_en.c(622): h->pixf.sad_x4[i_pixel]( m->p_fe nc[0], src0, src1, src2, src3, stride, costs );修改了:me_en.c中的#define COST_MV( mx, my )\,#defineCOST_MV_PRED( mx,my ) \,const int enc_dc = h->pixf.sad[i_pixel]( m->p_fenc[0], zero,FENC_STRIDE,16 );#define COST_MV_SAD( mx, my ) \和pixel.c中的static int name( uint8_t *pix1, uint8_t *pix2, \int i_stride_pix1, int i_stride_pix2 )及SAD_x3和SAD_x4中的参数顺序和pixel.h中,添加typedef int (*x264_pixel_sad_t) ( uint8_t *, uint8_t *,int, int );及将x264_pixel_function_t结构体中的x264_pixel_cmp_t sad[7];改为:x264_pixel_sad_t sad[7];作以上修改后,release版速度只有8.94fps,不知是不是重启后速度会快些以此修改dsp264_3中对应的文件,将原有文件作备份(后缀名后加08311)12月1.经昨日修改之后,在X264_PIXEL_sad_16x16线性汇编中的软件流水信息显示的是ii= 3 Schedule found with 5 iterations in parallel .C中的...是ii = 4 Schedule found with 4 iterations in parallel比未经修改的速度应该有提升,然而程序运行总出错:编译一帧后即停止运行2.经昨日修改的VC今天重启电脑运行,速度可以达到15.74fps,因此昨日所作修改对程序不会造成影响12月1.将CCS中bs.h,common.h等中的int类型的数据改为short,(函数返回类型的int不变)改动前:far段:002dd248(Byte),.text 00040460,.const 00007631,.cinit 00001484,改动后:.const 000064a9 ,其它无变化2.彻底删除了csp.c文件。