`
mmdev
  • 浏览: 12846102 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

x264函数调用关系图

 
阅读更多

1 encoder

2 slice write

3analyse



FFMPEG中MPEG-2编解码函数调用关系图

1 Encoder

(函数调用从左到右,下同;图片显示不全时,请下载显示)

2 P帧运动估计流程图

3 B帧运动估计流程图

4 decoder

ffmpeg的mpeg2编码I帧代码解读

首先说一下编码的函数层次:
MPV_encode_picture
—encode_thread
———encode_mb_hq
————encode_mb(编码一个宏块)
——————encode_mb_internal(编码I帧宏块,在这个函数里面选择不同的宏块编码器)
————————mpeg1_encode_mb(由于YUV的比例不一样,4:4:4或者4:2:0,进行宏块编码)
——————————mpeg1_encode_mb_internal(对宏块进行编码)
————————————mpeg1_encode_block(对一个block进行编码,注意这里面的宏块都是经过DCT和量化之后的数据):这个函数就是最需要看的咯:包括DC编码和AC编码,会选择不同的码表进行编码(详细过程看代码)

其次,所有的编码后的数据都是通过函数put_bits写到比特流中

第三,以上的代码解读都不包括诸如图片头之类的编码,相应的格式编码可以在相应层次中的函数里面找到。

第 四,libavcodec/mpegvideo_enc.c里面MPV_encode_init对编码进行初始化,主要是初始化,根据 avctx->codec_id选择不同的编码标准,进行不同的初始化,在656行,根据s->dct_quantize选择了DCT系数和 量化器(因为不同的编码标准,量化器是不一样的),然而在程序里面,统一由函数指针指向的函数dct_quantize完成

第五,在encode_mb_internal里面首先,进行了DCT和量化,然后进行霍夫曼编码——根据(s->codec_id)选择不同的编码器。DCT & quantize在1629行。

第五,在mpeg1_encode_block函数里面的block并没有进行zig-zag扫描,而 zig-zag扫描的过程,是在不断的产生新的索引index,这个步骤是在885行的j = s->intra_scantable.permutated[i];完成的,j就是zig-zag扫描之后的索引,根据j索引出block中的数据。

简单的说一下编码的过程:
1.初始化,包括选择DCT和量化器等等
2.编码一个图像(picture),将picture分成若干的mb(MacroBlock),这个时候要写入相应的图片头信息
3. 编码I帧MacroBlock,将MacroBlock分成若个小的block,由于YUV的比例不一样,因此每次需要编码的block的数量也是不一样 的,在函数mpeg1_encode_mb里面,就区分了CHROMA_420和其他格式拥有不同的block数量。
4.编码block,一个block包含三个编码对象:DC系数,AC系数(level)和游程长度。DC系数单独用差分编码,AC和run
联合在一起编码。这个过程都是在函数mpeg1_encode_block里面完成的。
1.MpegEncContext这个struct类型,一定要吃透,虽然代码是用C写得,但是写得很C++,这个MpegEncContext其实可以看做一个C++的类,里面定义了很多指针,这些指针指又指向了一些strcut,而这个struct其实相当于C++的成员函数,成员函数的初始化,一般是在XX_init函数里面初始化的。这一点,可以在后面的叙述中体现出来。

2.再说一下编码的过程,encode_mb_internal函数,做了MarcoBlock的编码,在1629行,开始做DCT&quant,1686行,开始做霍夫曼编码,而霍夫曼编码,对不同的标准来说,码表是不一样的,因此在1687行做了一个switch的选择,mpeg1和mpeg2,都是用的相同的mpeg1_encode_mb函数进行block的编码,而block内的编码,在以前的笔记中已经提到,过程这里不重复。

3.现在说DCT&quant,其中,1635行s->block_last_index[i] = s->dct_quantize(s, s->block[i], i, s->qscale, &overflow);,就是做DCT&quant。正如第1点中说的,dct_quantize本来只是MpegEncContext中的一个元素,类型为指针,指向一个struct,而这个struct就相当于C++里面的成员函数。现在,我们知道了在这个地方,相当于调用了一个成员函数,做了DCT&quant这件事情,接下来,讨论这个成员函数在哪里初始化的。

4.在Mpegvideo.c的MPV_encode_init函数里面,对编码所需要的一些“成员函数”进行了初始化。前面一堆东西,是做编码器的选择。在第656行,dct_quant这成员函数被初始化为dct_quant_c这个函数。于是,接下去找dct_quant_c这个函数的定义。发现,3649行,又调用了dsp.fdct这个成员函数,做离散余弦变换。接下来找dsp.fdct这个成员函数的初始化地方。
这个非常费劲,我找了半天才找到——在函数dsputil_init里面做了fdct的初始化,一步一步的跟踪调用关系,可以发现过程是这样的:
MPV_encode_init调用MPV_common_init,再调用dsputil_init,在dsputil_init里面初始化了fdct,而MPV_encode_init紧接着,执行前面提到的dct_quantize的初始化。
至此,整个初始化完成。
1.完整的初始化过程,函数调用关系如下:
encode_init
MPV_encode_init:里面要根据不同的Codec_ID来配置一些数据
MPV_common_init:基本的结构体的初始化,在此之前,高度宽度等变量已经设置好了
dsputil_init初始化了fdct而MPV_encode_init紧接着,执行前面提到的dct_quantize的初始化。
然而,这个时候量化表并没有初始化,量化表的初始化是用函数ff_set_qscale进行的。而这个函数的调用关系,在第二点中讲到
2.编码器运行的函数调用关系如下:
MPV_encode_picture:顶层函数
encode_picture:编码一副图像,这个时候首先要编码图像头,调用mpeg1_encode_picture_header函数,然后在2912行,通过s指针调用了encode_thread函数,开始编码
encode_thread里面,调用了ff_set_qscale,进行qscale的初始化,然后调用encode_mb_hq进行编码
encode_mb_hq调用encode_mb进行宏块编码
encode_mb调用encode_mb_internal进行帧内编码
encode_mb_internal调用mpeg1_encode_mb进行编码
mpeg1_encode_mb调用mpeg1_encode_mb_internal进行编码
mpeg1_encode_mb_internal调用mpeg1_encode_block进行16x16的块编码
3.关于header
mpeg1_encode_picture_header调用了mpeg1_encode_sequence_header写入了序列的头
mpeg1_encode_sequence_header调用了ff_write_quant_matrix这里面,包括了要填的量化表的写入,这个量化表是用户自定义的。在后面又调用了ff_mpeg1_encode_slice_header。
ff_mpeg1_encode_slice_header又调用了写header,写qscale的函数,写文件头。
下面解释一个block的编码以及编码码表
1.首先编码的是DC系数,在函数encode_dc里面进行。由于DC系数的码表有两个,分别针对Y帧和(Cr,Cb)帧。编码的时候,编码的是非负的系数,但是原始的DC系数有正有负,因此需要做一个映射。这一个映射,在encode_dc里面,首先就用
if(((unsigned) (diff+255)) >= 511)
分成了两部分,表示正负数的映射。而码表的选择,是根据component变量来选择的。整个编码过程和标准完全一样。但是代码中diff为正和为负的情况,表面上采用了不同的编码方法,但是实质上是完全一样的。
mpeg1_lum_dc_uni的初始化在ff_mpeg1_encode_init里面完成,查看这个初始化过程,其实就是一个编码过程。
2.对于其他系数的编码,根据标准,存在两种不同的情况:
a.(level,run)较小的情况,直接进行查表
b.(level,run)较大的情况,进行所谓的换码编码,首先是写入一个Escape code,然后在加上level和run
因此,首先需要判断(level,run)是否足够大,代码中用
if (alevel <= mpeg1_max_level[0][run])
来解决这个问题。mpeg1_max_level这个矩阵的构成在ff_mpeg1_encode_init函数中,通过调用init_rl函数来实现,至于这个具体怎么初始化的,很容易看懂的(如果这个都看不懂,那ffmpeg代码也就不要想看懂了)
3.在一个block的最后,需要编码end of block,也是通过查表
4.现在解释码表,所有要用到的vlc的码表存放在文件mpeg12data.c里面,
mpeg1_vlc就是标准中的码表B-14
mpeg2_vlc就是标准中的码表B-15
两个码表,第一列表示码字,第二列表示码字长度,对照标准上面的码表,很容易发现这两个数组的构成方法(具体是什么,看一下就知道了,很容易的)
看懂了这里,也就很容易看懂在mpeg12enc.c里面对于其他系数的编码了
最后要说的是,ffmpeg的代码写的非常的晦涩,写得非常的不对称,比如encode_dc就是这样的,码表的初始化也比较混乱,因而看起来很费劲


MPEG-4 AVC/H.264 信息

作者:haibara来源:pcicp.comDVDrip制作2006-6-15 14:13:02

本FAQ系列由(haibara)翻译,期间受到kaito_mkid(pcicp)帮助,在此感谢,由于Newbie的关系,如有翻译错误,还请各位指出,由Doom9的bond编撰的原文

译者注:基本专业名称我都以小括号形式加以解释,详细信息请自行查阅资料。

什么是MPEG-4?

MPEG-4(ISO 14496)是由制定了我们熟知的MPEG-1(MP3, VCD)和MPEG-2(DVD, SVCD)标准,并力于使各种音频/视频压缩格式和更多内容标准化的国际标准化组织(International Organization for Standardization/ISO)的工作组,即运动图像专家组(Moving Picture Experts Group/MPEG)发展的广泛的开放标准。
本质上MPEG-4标准不仅把目标定为标准化某些有发展前途的产品(例如达到DVD性能),而且含盖了一个能让产品供应商根据需要选择适当标准去执行的广泛的次级标准。

MPEG-4标准,如上所说,被分成许多不同的次级标准,在Doom9里我们使用者可能最感兴趣的部分如下:
- ISO 14496-1(Systems/系统),动画/交互性(类DVD菜单)
- ISO 14496-2(Video/视频),如Advanced Simple Profile(ASP/高级简单类),由XviD, DivX5, 3ivx...执行
- ISO 14496-3(Audio/音频),Advanced Audio Coding(AAC/先进音频编码)
- ISO 14496-10(Video/视频),Advanced Video Coding(AVC/进阶视频编码),著名有H.264
- ISO 14496-14(Container/容器),MP4容器格式(使用.mp4作扩展名)
- ISO 14496-17(Subtitles/字幕),MPEG-4时标文本字幕格式

这些信息页面正力于提供这些标准的大部分有用的信息,尤其是作为焦点的MPEG-4 ASP和AVC/H.264。


与封闭格式如Micro$oft的Windows Media相比,象MPEG-4一样的开放标准有什么可能的优势?

开放标准的一个好处是当创建产品时允许向所有人开放并遵循它。因此我们已经有许多不同的符合MPEG-4标准并可互相兼容的产品。
其次是互通性大范围的产品选择性,一个开放标准导致竞争,对顾客而言这意味着产品在竞争市场中能更好地提高品质,更少的价格和更关注顾客需求

但不要忘记这也许对我们来说最重要的一点:
一个开放标准允许开源发展,例如我们熟知的XviD。

ISO 14496-10 (Video) - 进阶视频编码(Advanced Video Coding/AVC)

有着AVC/H.264的MPEG-4标准定义了一个拥有最新,最高技术的实用的,充满尖端科技的视频编码格式。

2003年,ISO的MPEG(Moving Pictures Experts Group/运动图像专家组)与联合国(United Nations/UNO)下设的ITU(International Telecommunication Union/国际电信联盟)的VCEG(Video Coding Experts Group/视频编码专家组)这2大组织最终完成并共同规定了AVC/H.264视频编码标准,其中后者曾标准化H.263格式(现主用于视频会议)。
AVC/H.264标准它自身是由MPEG和VCEG的专家构成的Joint Video Team(JVT/联合视频组)发展的。

由MPEG来看,该标准被叫做MPEG-4 Part 10(ISO 14496-10);由ITU来看,它叫做H.264(ITU的公文号) 其中作为后者已广泛流传开来。
新标准选择Advanced Video Coding(AVC/进阶视频编码)作为“官方”名 - 因为对应视频的音频格式是Advanced Audio Coding(AAC/先进音频编码)。


AVC/H.264 Profile

AVC/H.264定义了4种不同的Profile(类):Baseline(基线类), Main(主要类), Extended(扩展类)和High Profile(高端类)(它们各自下分成许多个):

- Baseline Profile 提供I/P帧,仅支持progressive(逐行扫描)和CAVLC
- Extended Profile 提供I/P/B/SP/SI帧,仅支持progressive(逐行扫描)和CAVLC
- Main Profile 提供I/P/B帧,支持progressive(逐行扫描)和interlaced(隔行扫描),提供CAVLC或CABAC
- High Profile (也就是FRExt)在Main Profile基础上新增:8x8 intra prediction(8x8 帧内预测), custom quant(自定义量化), lossless video coding(无损视频编码), 更多的yuv格式(4:4:4...)

只有未来会告诉我们哪一种框架和工具最可能被用于DVD备份,但是我猜想会是有着以下的工具大力帮助的Main和/或High Profile(同样请核实MPEG-4 ASP的工具描述,除了GMC,所有的工具在AVC下都是可用的):

CAVLC/CABAC:
AVC/H.264定义了2种先进的重构数据流(包括macroblock-type(宏块), motionvectors(运动矢量) + reference-index(参考索引)...)的熵编码工具,一举超越MPEG-4 ASP:
Context-Adaptive Variable Length Coding(CAVLC/上下文自适应变长编码)和 Context-Adaptive Binary Arithmetic Coding(CABAC/上下文自适应二进制算术编码)
CABAC,与AVC/H.264中只是默认算法的CAVLC(也叫UVLC)相比,是个压缩率更强大的算法,据说能额外降低10-15%的比特率(特别在高码率)。CABAC(同CAVLC一样)是一种无损算法,因此不会降低质量,但会减缓编码和解码速度。

Loop/Deblocking Filter(循环/去块滤波器):
与预处理滤波器(例如通过avisynth作用于输入端),或后处理滤波器(通过解码器作用于最终输出端)相反,循环滤波器在编码过程中对每桢进行滤波,编码完成后被用于下一桢的参考。它能消除块效应,尤其在低码率时,但同样会减缓编码和解码速度。

Variable Block Sizes/Macroblock Partitions(块大小可变/宏块划分):
与MPEG-4 ASP(仅Inter4V/4MV能作16x16和8x8块变换)相比,AVC/H.264把动态搜寻精度(Motion Search Precision)提高到4x4(包含的步骤有8x4...)。子块大小是自适应/可变的,一个优秀的编码器应能对每个宏块明智地作出最恰当的划分大小决定。

Multiple Reference Frames(多重参考桢):
与MPEG-4 ASP(仅允许当前桢的前一桢作为参考桢)相比,AVC/H.264使用帧间搜索方式并提供成倍的参考桢选择,它意味着AVC/H.264编码能决定是否只是简单地参考前一桢或甚至参考比前桢更过去的桢。因此(例如某个P桢能参考最近I桢前的某桢)不得不提出一种新型桢型:IDR桢,是种其后的桢不允许参考其前的桢的I桢。使用多重参考桢会减慢编码和解码速度并且可能导致只能在IDR桢剪切。

Weighted Prediction(加权预测):
有了加权预测就能对参考桢进行加权(例如你能测量前一幅图象的亮度程度)。它特别有助于在那些随时可能淡入或淡出的场景中前后图象极为相似,只是画面变暗的图象的处理。WP对于同时出现淡入及淡出的图象没有效果(例如当图象从一个场景转到另一个场景就会同时出现淡入及淡出)。

Rate Distortion Optimisation(RDO/码率-失真/损耗最佳化):
只要编码器不得不在众多选择中作出绝择时,RDO允许选择最有效的编码方式(例如面临采用桢间/桢内的动态搜寻的决定...)
RDO不是AVC/H.264本身定义的工具,它是第一个由H.264参考软件引入的工具,可谓一种新的途径。其他的编码也能利用RDO,如XviD'的VHQ模式能使用RDO


AVC/H.264与其他流行的视频编码格式的比较测评:


现有的AVC/H.264编码

可用于终端用户的AVC/H.264执行者有x264,Nero,Apple, Sorenson, Elecard, Moonlight, VSS, mpegable, Envivio, Hdot264 (binary),DSPR,JM (参考软件) (binary),ffmpeg,Philips, FastVDO,Skal,Sony更多

编码器

- x264:第一个公开的可使用High Profile的编码器,开源(GPL)(源码),使用VFW的有:x264vfw,ffdshow(输出.avi),命令行的:x264cli(输出raw的.mp4),mencoder(输出raw的.avi)(Doom9的MeGUI)或ffmpeg
x264支持2pass, CABAC, 循环滤波, 多重B帧, 双向参考(B-Reference), 多重参考桢, 4x4 P帧块变换, 8x8 B帧块划分, 失真信号化(anamorphic signalling)和High Profile:8x8 dtc(离散余弦变换)与帧内预测, 无损视频编码和自定义无损量化矩阵(custom quant matrix)
- NeroDigital AVCNero Recode2内含,输出为.mp4
ND AVC支持2pass, CABAC, 自适应循环滤波, 多重B帧, 多重参考桢, 加权预测, 8x8 B帧块划分, 16x16 B帧块划分, 自适应量化(高度Psy)
- SorensonSorenson Squeeze 4内含,输出.mp4,
Sorenson支持2pass, 最大2连续B帧, 双向参考, 循环滤波和多重Slice
- AppleQuicktime 7内含,输出.mp4, .3gp和.mov,编码速度很慢
支持2pass, 最大1连续B帧, 循环滤波(0,0), 8x8 P帧块变换, 8x8 B帧块变换, 4x4 I帧块变换, 自适应量化, 5级Slice, 没有CABAC, 没有加权预测, 没有多重参考桢
- JM:此AVC参考软件v9.3版提供Main和High Profile:B/SP帧, CABAC, 循环滤波器, 4x4 块划分, 多重参考桢, 自适应量化, 差错修复(Error Resilience), RDO, 无损视频编码, 自定义量化), 比率控制(Rate Control)等...
- Hdot264:由doom9会员charact3r发展的开源(GPL)的VFW版参考软件,仍然以很老的参考软件(JM 4.0c)为基础
- VSS:免费的VFW编码器(可预览5天),以参考编码器为基础
- Elecard Elecard Mobile Converter内含,输出.mp4, MainConcept's v2 encoder也内含,输出.264和.mpg PS/TS
不再公开的:
- Moonlight:Moonlight的OneClick Compressor v1.1和CyberLink的PowerEncoder内含,输出.mpg
Moonlight支持1pass(VBR/CBR/预设 量化), CABAC, 循环滤波, 最大2连续B帧, 8x8 B帧块划分, 自适应量化, 自动调整PAR(Pixel Aspect Ratio/象素纵横比), 隔行扫描
- MainConcept:免费的编码器(有水印),输出.264和.mpg PS/TS
1pass(CBR/VBR/预设 量化), P帧重排(P-Frame Reorder), CABAC, 循环滤波, 多重B-Vops(Bidirectional Video Object Planes/双向视频对象平面), 多重参考桢, 4x4 P帧块划分), PAR, RDO
- mpegable:提供试用有限的免费VFW编码器(不以参考软件为基础),不支持YV12
mpegable支持仅限P帧的1pass(预设量化), 8x8 P帧块划分, 只支持CAVLC, 循环滤波
- Envivio4Coder内含,输出.mp4

解码器 (比较测评)

- ffmpeg:开源(LGPL),包含在ffdshow(VFW和DShow编码器),mplayerVideoLAN
支持B帧, 双向参考, CABAC, 循环滤波, 加权预测和High Profile (8x8 dct与帧内预测, 无损视频编码)
- Apple:Quicktime 7支持AVC解码,支持.mp4/.mov,解码速度很慢
仅支持最大1连续B帧, CABAC, 不作后帧参考的循环滤波, 多重B帧和隔行扫描
- NeroDigital AVC:Recode2附带DShow解码器和.mp4 Parser
支持Main和High Profile
- VSS:VFW解码器 (预览5天) 和DShow解码器 (限制30天)
VSS DShow支持.avi (支持VSSH和H264 fourcc), CABAC, 循环滤波, B帧
- ElecardElecard's MPEG Player v4.0MainConcept's v2 encoder内含
- Envivio:有个名叫EnvivioTV的非免费AVC DShow解码器,(从2.0版开始,当前版本为2-1-181)支持混合AVC的.mp4
- PhilipsAVC Alliance播放器内含免费的DShow AVC解码器(只支持raw AVC)
- FastVDO:有时间限制(每个视频文件5分钟)的High Profile DShow解码器
- Pegasus这里有发展不成熟的DShow AVC解码器
- Basic AVC Decoder用C编写,是一所大学的工程,见这里
不再公开的:
- Moonlight:DShow解码器/Parser支持混合AVC的.mpg, .mp4和.264 Moonlight's MPEG Player v3.0内含
支持Main和High Profile
- MainConcept:v1预览版提供免费DShow AVC解码器(有水印) 并且Parser支持AVC和.mpg PS/TS
- mpegable:提供试用有限的VFW解码器 (可用于DShow),支持.avi (支持 DAVC fourcc)


预览样本

NeroDigital:mp4,mp4
Sorenson:mp4
AVC Alliance:raw
Moonlight:raw/中码率,raw/低码率,raw,mpg
FastVDO:raw/high profile
Apple:mov
Videosoft: avi, avi/新, avi/老
Lead:ogm


当前AVC/H.264的争论

- 互通性:大多数执行者支持多种容器格式:
.mp4:由MPEG-4标准(ISO 14496-15)定义的AVC容器,Apple, Nero, Sorenson, Envivio, Elecard/Moonlight和x264都支持
.mpg PS/TS:由MPEG-2标准(ISO 13818-1, AMD3)定义的AVC容器,Mainconcept和Elecard/Moonlight支持
.avi:采取AVC-in-AVI的方式非标准,因此会造成不兼容问题。AVI和VFW的局限(如关于B帧或任意帧的编码顺序),混合这两种格式混合会完全阻碍AVC提供的所有可能特性的执行,因此可能降低质量,或至少降低处理速度和互通性,其竞争性也因此下降。当前VSS和x264(mencoder 和vfw)支持使用AVI
.264/.h264:未混合入容器的原始数据流。JM参考软件, x264cli, mencoder和mainconcept都可输出

- 速度:当前一些执行者编码器速度不敢恭维,依然只有x264和NeroDigital's AVC的编码器看上去能提供不俗的速度与品质。但这不会改变AVC是种先进的视频编码方式的事实。所以老的CPU编解码AVC会非常耗时


MPEG-4 AVC/H.264的硬件应用化 - HD-DVD/蓝光(Blu-ray)

DVD论坛(DVD Forum)和蓝光光盘协会(Blu-ray Disc Association)正在讨论能支持高清晰(High Definition)内容(存储容量完全超过当前的DVD)下一代DVD格式的继承人选:HD-DVD和BD-ROM

这里报道HD-DVD会强制采用MPEG-4 AVC/H.264,而蓝光支持老早被MPEG-4 AVC/H.264 High Profile纳入-这里

因此AVC/H.264极有可能成为下一代视频格式,会被广泛地使用和支持,就象今天MPEG-2(用于DVD)的情形一样

FFMPEG 学习笔记


一 Encoder函数调用图


1 avcodec_encode_video
|___ avcodec_check_dimensions
|___ avctx->codec->encode(for mpeg-2 call MPV_encode_picture)
|___ init_put_bits(for multiple thread)
|___ load_input_picture(copy data from input pic_arg)
|___ select_input_picture(I,B,P)
|___ MPV_frame_start
|___ encode_picture
| |___ s->avctx->execute
| |___ encode_thread
| |___ encode_mb
| |___ MPV_decode_mb
|
|
|___ MPV_frame_end


x264中的Decoder

在早期的x264版本中,包括decoder和encoder两部分,后来不知道出于什么原因,decoder部分的代码没有再继续维护,这部分代码一直保留到了20061009的版本(X264_BUILD 53);但因为期间encoder部分的代码有较大的改动,包括数据结构的变化,导致两部分代码只有在较低版本时才可以同时正常编译。

我使用#define X264_BUILD 0x0002版本的代码进行了测试。发现Decoder代码存在以下问题:

1 仅支持BaseLine的解码,因为其中没有B帧和CABAC的解码部分。

2 代码中有两个BUG需要自己解决一下。

a. x264_realloc函数中,把

*( (int*) ( (uint8_t*) p ) - sizeof( void ** ) -
sizeof( int ) );

改为

*( (int*) (( (uint8_t*) p ) - sizeof( void ** ) -
sizeof( int ) ));

b. x264_slice_header_ref_pic_reordering函数中,把

if( h->i_ref0 > h->pps->i_num_ref_idx_l0_active )
{
h->i_ref0 = h->pps->i_num_ref_idx_l0_active;
}
if( h->i_ref1 > h->pps->i_num_ref_idx_l1_active )
{
h->i_ref1 = h->pps->i_num_ref_idx_l1_active;
}
改为:

if( h->i_ref0 > h->sh.i_num_ref_idx_l0_active )
{
h->i_ref0 = h->sh.i_num_ref_idx_l0_active;
}
if( h->i_ref1 > h->sh.i_num_ref_idx_l1_active )
{
h->i_ref1 = h->sh.i_num_ref_idx_l1_active;
}

3 其它一些头文件的改动,因为两部分代码中有一些同名的文件,需要在include时加上相应的目录名。

x264 代码下载信息

2011-08-11

1 不同版本的x264下载地址:http://download.videolan.org/pub/videolan/x264/snapshots/

2 x264从20061010起(即这个版本x264-snapshot-20061010-2245.tar.bz2)不再支持decoder代码。

H.264/AVC中CAVLC编码方法简介

H.264/AVC中CAVLC编码方法简介

一 名词

TotalCoeffs:全部非零系数个数。(0~16)

TotalZeros:最后一个非零系数前的零的个数。

TrailingOnes:拖尾系数(即1)的个数。(0~3)

NC:当前块值。除色度的直流系数外(常数-1),其它系数类型NC值是根据当前左边4x4块的非零系数数目(NA)和当前块上面4x4的非零系数的数目(NB求得的。

计算NC的值

上面的块(NB)

左达的块(NA)

NC

X

X

(NA+NB)/2

X

NA

X

NB

0

选择非零系数个数和拖尾系数个数的编码表格(表格见毕书附录):

NC

表格

0<=NC<2

变长表格1

2<=NC<4

变长表格2

5<=NC<8

变长表格3

NC=-1

变长表格4

NC>=8

定长表格

二 编码过程

1. 对TotalCoeffs和TrailingOnes进行组合编码,称为Coeff_token。

2. 对拖尾系数的符号进行编码,+为1,-为0,从右向左。

3. 对非零系数(不包括拖尾系数,拖尾系数已经编码)进行编码,从右向左。

4. 对TotalZeros进行编码。

5. 对非零系数前的零的个数进行编码,从右向左,最后一个(从左边数第一个)非零系数前的零的个数不需要编码(剩下的零都是这个位置的)。

以下4x4块为例(毕书P123,原例有误):

0 0 -1 0

5 2 0 0

3 0 0 0

1 0 0 0

Z扫描完成后: 0,0,5,3,2,-1,0,0,0,1…

No

元素

数值

编码

说明

1

Coeff_token

TotalCoeffs=5,TrailingOnes=2

0000101

TotalCoeffs ,和TrailingOnes的组合进行编码

2-1

TrailingOnes_sign_flag

+

1

拖尾系数的符号,从右向左

2-2

TrailingOnes_sign_flag

0

3-1

Level(2)

1(suffixLength=0)

1

3-2

Level(1)

3(suffixLength=1)

0010

3-3

Level(0)

5(suffixLength=1)

000010

4

Total_zeros

5

101

5-1

Run_before(4)

ZeroLeft=5, run_before=3

010

5-2

Run_before(3)

ZeroLeft=2, run_before=0

1

5-3

Run_before(2)

ZeroLeft=2, run_before=0

1

5-4

Run_before(1)

ZeroLeft=2, run_before=0

1

5-5

Run_before(0)

ZeroLeft=2, run_before=2

最后一个不需要编码

编码输出:00001011010010000010101010111


1 encoder

2 slice write

3analyse

一 Encoder函数调用图


1 avcodec_encode_video
|___ avcodec_check_dimensions
|___ avctx->codec->encode(for mpeg-2 call MPV_encode_picture)
|___ init_put_bits(for multiple thread)
|___ load_input_picture(copy data from input pic_arg)
|___ select_input_picture(I,B,P)
|___ MPV_frame_start
|___ encode_picture
| |___ s->avctx->execute
| |___ encode_thread
| |___ encode_mb
| |___ MPV_decode_mb
|
|
|___ MPV_frame_end

在早期的x264版本中,包括decoder和encoder两部分,后来不知道出于什么原因,decoder部分的代码没有再继续维护,这部分代码一直保留到了20061009的版本(X264_BUILD 53);但因为期间encoder部分的代码有较大的改动,包括数据结构的变化,导致两部分代码只有在较低版本时才可以同时正常编译。

我使用#define X264_BUILD 0x0002版本的代码进行了测试。发现Decoder代码存在以下问题:

1 仅支持BaseLine的解码,因为其中没有B帧和CABAC的解码部分。

2 代码中有两个BUG需要自己解决一下。

a. x264_realloc函数中,把

*( (int*) ( (uint8_t*) p ) - sizeof( void ** ) -
sizeof( int ) );

改为

*( (int*) (( (uint8_t*) p ) - sizeof( void ** ) -
sizeof( int ) ));

b. x264_slice_header_ref_pic_reordering函数中,把

if( h->i_ref0 > h->pps->i_num_ref_idx_l0_active )
{
h->i_ref0 = h->pps->i_num_ref_idx_l0_active;
}
if( h->i_ref1 > h->pps->i_num_ref_idx_l1_active )
{
h->i_ref1 = h->pps->i_num_ref_idx_l1_active;
}
改为:

if( h->i_ref0 > h->sh.i_num_ref_idx_l0_active )
{
h->i_ref0 = h->sh.i_num_ref_idx_l0_active;
}
if( h->i_ref1 > h->sh.i_num_ref_idx_l1_active )
{
h->i_ref1 = h->sh.i_num_ref_idx_l1_active;
}

3 其它一些头文件的改动,因为两部分代码中有一些同名的文件,需要在include时加上相应的目录名。

2011-08-11

1 不同版本的x264下载地址:http://download.videolan.org/pub/videolan/x264/snapshots/

2 x264从20061010起(即这个版本x264-snapshot-20061010-2245.tar.bz2)不再支持decoder代码。

分享到:
评论

相关推荐

    x264详尽编码过程解析

    文章对x264中函数关系的调用、重要代码都做了极为详尽的分析与注释

    clang-callgraph:基于clang的工具,可从给定的C ++代码库生成调用图

    lang笔 一个基于clang的工具,可以从给定的C ++代码库生成调用图。 用法 ./clang-callgraph.py file.cpp|compile_commands.... 运行python脚本时,在解析所有代码库后,系统会提示您键入要获取其调用图的函数名称 例

    c语言二分法递归求解函数根

    二分法 解函数 c++语言 c语言 递归 数根

    C语言 递归调用程序和文件系统

    特别注意:请一定看清要求,做好准备,通过整理函数调用关系表理清程序框架,通过分析编写流程图理清每个函数的实现思路。 3. (自选题)编写程序,统计英文文件中的每个单词的出现次数(词频)。

    详解C++编程中对于函数的基本使用

    主调函数和被调用函数之间有数据传递关系。前面已提到:在定义函数时函数名后面括号中的变量名称为形式参数(formal parameter,简称形参),在主调函数中调用一个函数时,函数名后面括号中的参数(可以是一个表达式)...

    用函数求ASCII值

    请编制函数,按给定的替代关系对数组x中的所有字符进行替代,仍存入数组x的对应的位置上,最后调用函数把结果x输出。替代关系:f(p)=p*11%256 (p是数组中某一个字符的ASCII值,f(p)是计算后新字符的ASCII值),如果...

    api函数 for c#

    欢迎使用精灵 FOR c#&gt;希望大家能够喜欢!(需要.NET环境支持) ...函数与C#中函数的对应关系。 5。API常量查询(给出能够直接在C#中调用的代码) 6。显示对函数对操作系统的支持(WIN9X OR WIN2K)

    C语言程序设计标准教程

    2.实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。 3.实参和形参在数量...

    C# API精灵 助手 函数查询

    主要功能: ...函数与C#中函数的对应关系。 5。API常量查询(给出能够直接在C#中调用的代码) 6。显示对函数对操作系统的支持(WIN9X OR WIN2K) --------------------------

    计算机二级C语言上机真题

    给定程序中,函数fun的功能是:将形参n所指变量中,各位上为偶数的数去 除,剩余的数按原来从高位到低位的顺序组成...注意:由于NONO( )这个函数是改卷人用的,与考生没有什么关系,故下面从第2套试题开始均省略NONO( )

    .net数学表达式求解

    arg3变量(字符串),...., 之后都是变量,可以重复且变量个数不限,但是位置要和在arg1中公式里的位置先后关系一致 ///Parsing类基本上可以解释所有符合标准的公式,涉及函数包括 ///1 abs(x) 取绝对值|x| ...

    通用函数表达式求值-动态库

    使用exp.dll,您可以在自已的程序中方便地加入各种计算功能,系统编译执行速度极快,支持+,-,*,/,^,()及关系运算,和50余种标准函数, 用户也可以调用自定义的函数,其中提供的一些如if(cond, x, y)这样的条件函数,...

    数字信号处理实验一.docx

    调用conv()函数求上述两序列的卷积和 题三:编写计算两离散序列卷积和f(k)=f1(k)*f2(k)的实用函数dconv().要求该程序在计算出卷积和f(k)的同时,还绘出序列f1(k),f2(k)和f(k)的时域波形图,并返回f(k)的非零样值点...

    C程序结构化设计.pptx

    C语言程序设计;;结构化程序设计方法 定义:结构化程序设计方法是程序设计的先进方法和工具,其主要原则可以...定义:函数调用语句是在函数调用的基础上加分号“;”组成的 。 调用格式: 函数名称(实参表列); 举例: m

    Python函数的参数常见分类与用法实例详解

    注意:实参值(变量的值)与形参(变量名)的绑定关系只在函数调用时才会生效/绑定在函数调用结束后就立刻解除绑定。 2.函数的参数 位置即顺序,位置参数参数指的就是按照从左到右的顺序依次定义的参数。 3.有两种...

    曲线图Graph类

    3、调用SetLegendText设置图例,nIndex范围1-10,本函数在使用索引值 时与SetAxisData对应关系为:1对02对1依次排列,0索引设置图例标题文本 4、调用SetXLableData设置X轴标签 5、调用SetAxisData设置曲线数据,...

    MFC常用的类及其成员函数简介

    公共变量m_hWnd用于存放供API函数调用的窗口句柄。 CframeWnd类 从CWnd类派生而来,主要用来掌管一个窗口。其对象是一个框架窗口,包括边界、标题栏、菜单、最大化按钮、最小化按钮和一个激活的视图。常用成员函数:...

    TCPIP详解卷[1].part06

    18.6 TCP的状态变迁图 182 18.6.1 2MSL等待状态 183 18.6.2 平静时间的概念 186 18.6.3 FIN_WAIT_2状态 186 18.7 复位报文段 186 18.7.1 到不存在的端口的连接请求 187 18.7.2 异常终止一个连接 187 18.7.3 检测半...

    Graph+曲线图类

    3、调用SetLegendText设置图例,nIndex范围1-10,本函数在使用索引值 时与SetAxisData对应关系为:1对02对1依次排列,0索引设置图例标题文本 4、调用SetXLableData设置X轴标签 5、调用SetAxisData设置曲线数据,...

    详解Vue2.X的路由管理记录之 钩子函数(切割流水线)

    钩子函数:在路由切换的不同阶段调用不同的节点函数(钩子函数在我看来也就是:某个节点和时机触发的函数)  两者关系: 钩子函数 —&gt; 导航 :钩子函数 主要用来拦截导航,让它完成跳转或取消,在导航的不同阶段来...

Global site tag (gtag.js) - Google Analytics