自己在学习h264的路上,欢迎讨论交流。

  前段时间研究JM出品的h264编码器,代码实在看不下去,因此换了个角度来研究诸多算法——逆向方式(解码),本系列文章记录一些遇到的东西和思考。

1. JM介绍

   JM编解码器,是一个纯软件编解码器,由位于德国的海因里希赫兹研究所(Heinrich Hertz Institute)推出,是h264官方推荐的用于研究avc算法的软件。

2. JM & x264

  JM但其未做太多优化,速度较慢,用于科研需求。x264则是JM的升级版,编码速度较快,广泛应用于企业,例如网上下载的视频,(目前的时间节点)毫不夸张地说,50%以上都是由x264压制而来。

  抄一段网上的对比:

1,X264简化了JM的代价(或者叫成本)计算方法,去掉了一些代码,进行了估算。
2,JM中是要把编码后的比特数进行加权运算后作为代价的一部分进行比较的,X264把这个部分的代码删除了,即没有把编码后的比特数作为代价的一部分。
3,X264进行了SSE2,MMX的优化。
4,X264对JM的数据结构部分进行了优化,以加快内存的数据读取速度。
5,由于JM不断地升级。JM代码里面有了很多的快速算法,包括快速搜索算法。X264则没有这些快速算法。(网上抄来的,这条明显说颠倒了)

3. 使用哪个版本?

  jm8.6版本是最经典的版本,网上资料较齐全,建议下载该版本。

  读者可自行去官网下载代码,来编译和运行。该软件同时支持Win和Linux平台下构建,下载的代码中已经建了vc工程,也包括Makefile。

  JM目录结构如下:

  1 $ tree
  2 .
  3 |-- CHANGES.TXT
  4 |-- Changes_detail.txt
  5 |-- Readme.txt
  6 |-- bin
  7 |   |-- decoder.cfg
  8 |   |-- encoder_baseline.cfg
  9 |   |-- encoder_extended.cfg
 10 |   |-- encoder_main.cfg
 11 |   |-- foreman_part_qcif.yuv
 12 |   |-- leakybucketrate.cfg
 13 |   |-- sg0conf.cfg
 14 |   |-- sg2conf.cfg
 15 |   `-- sg6conf.cfg
 16 |-- copyright.txt
 17 |-- disclaimer.txt
 18 |-- doc
 19 |   |-- coding_style.doc
 20 |   |-- doxygen.txt
 21 |   |-- foot.html
 22 |   |-- h26l.css
 23 |   |-- ldecod.dox
 24 |   `-- lencod.dox
 25 |-- ldecod
 26 |   |-- Makefile
 27 |   |-- inc
 28 |   |   |-- annexb.h
 29 |   |   |-- biaridecod.h
 30 |   |   |-- block.h
 31 |   |   |-- cabac.h
 32 |   |   |-- context_ini.h
 33 |   |   |-- contributors.h
 34 |   |   |-- ctx_tables.h
 35 |   |   |-- defines.h
 36 |   |   |-- elements.h
 37 |   |   |-- erc_api.h
 38 |   |   |-- erc_do.h
 39 |   |   |-- erc_globals.h
 40 |   |   |-- errorconcealment.h
 41 |   |   |-- fmo.h
 42 |   |   |-- global.h
 43 |   |   |-- header.h
 44 |   |   |-- image.h
 45 |   |   |-- leaky_bucket.h
 46 |   |   |-- loopfilter.h
 47 |   |   |-- macroblock.h
 48 |   |   |-- mb_access.h
 49 |   |   |-- mbuffer.h
 50 |   |   |-- memalloc.h
 51 |   |   |-- nalu.h
 52 |   |   |-- nalucommon.h
 53 |   |   |-- output.h
 54 |   |   |-- parset.h
 55 |   |   |-- parsetcommon.h
 56 |   |   |-- rtp.h
 57 |   |   |-- sei.h
 58 |   |   `-- vlc.h
 59 |   `-- src
 60 |       |-- annexb.c
 61 |       |-- biaridecod.c
 62 |       |-- block.c
 63 |       |-- cabac.c
 64 |       |-- context_ini.c
 65 |       |-- erc_api.c
 66 |       |-- erc_do_i.c
 67 |       |-- erc_do_p.c
 68 |       |-- errorconcealment.c
 69 |       |-- filehandle.c
 70 |       |-- fmo.c
 71 |       |-- header.c
 72 |       |-- image.c
 73 |       |-- ldecod.c
 74 |       |-- leaky_bucket.c
 75 |       |-- loopFilter.c
 76 |       |-- macroblock.c
 77 |       |-- mb_access.c
 78 |       |-- mbuffer.c
 79 |       |-- memalloc.c
 80 |       |-- nal.c
 81 |       |-- nal_part.c
 82 |       |-- nalu.c
 83 |       |-- nalucommon.c
 84 |       |-- output.c
 85 |       |-- parset.c
 86 |       |-- parsetcommon.c
 87 |       |-- rtp.c
 88 |       |-- sei.c
 89 |       `-- vlc.c
 90 |-- ldecod.dsp
 91 |-- ldecod.dsw
 92 |-- ldecod.vcproj
 93 |-- lencod
 94 |   |-- Makefile
 95 |   |-- inc
 96 |   |   |-- annexb.h
 97 |   |   |-- biariencode.h
 98 |   |   |-- block.h
 99 |   |   |-- cabac.h
100 |   |   |-- configfile.h
101 |   |   |-- context_ini.h
102 |   |   |-- contributors.h
103 |   |   |-- ctx_tables.h
104 |   |   |-- defines.h
105 |   |   |-- elements.h
106 |   |   |-- fast_me.h
107 |   |   |-- fmo.h
108 |   |   |-- global.h
109 |   |   |-- header.h
110 |   |   |-- image.h
111 |   |   |-- intrarefresh.h
112 |   |   |-- leaky_bucket.h
113 |   |   |-- macroblock.h
114 |   |   |-- mb_access.h
115 |   |   |-- mbuffer.h
116 |   |   |-- memalloc.h
117 |   |   |-- minmax.h
118 |   |   |-- mv-search.h
119 |   |   |-- nalu.h
120 |   |   |-- nalucommon.h
121 |   |   |-- output.h
122 |   |   |-- parset.h
123 |   |   |-- parsetcommon.h
124 |   |   |-- ratectl.h
125 |   |   |-- rdopt_coding_state.h
126 |   |   |-- refbuf.h
127 |   |   |-- rtp.h
128 |   |   |-- sei.h
129 |   |   `-- vlc.h
130 |   `-- src
131 |       |-- annexb.c
132 |       |-- biariencode.c
133 |       |-- block.c
134 |       |-- cabac.c
135 |       |-- configfile.c
136 |       |-- context_ini.c
137 |       |-- decoder.c
138 |       |-- fast_me.c
139 |       |-- filehandle.c
140 |       |-- fmo.c
141 |       |-- header.c
142 |       |-- image.c
143 |       |-- intrarefresh.c
144 |       |-- leaky_bucket.c
145 |       |-- lencod.c
146 |       |-- loopFilter.c
147 |       |-- macroblock.c
148 |       |-- mb_access.c
149 |       |-- mbuffer.c
150 |       |-- memalloc.c
151 |       |-- mv-search.c
152 |       |-- nal.c
153 |       |-- nalu.c
154 |       |-- nalucommon.c
155 |       |-- output.c
156 |       |-- parset.c
157 |       |-- parsetcommon.c
158 |       |-- ratectl.c
159 |       |-- rdopt.c
160 |       |-- rdopt_coding_state.c
161 |       |-- refbuf.c
162 |       |-- rtp.c
163 |       |-- sei.c
164 |       |-- slice.c
165 |       |-- vlc.c
166 |       `-- weighted_prediction.c
167 |-- lencod.dsp
168 |-- lencod.dsw
169 |-- lencod.vcproj
170 |-- rtpdump
171 |   |-- ReadMe.txt
172 |   |-- StdAfx.cpp
173 |   |-- StdAfx.h
174 |   |-- rtpdump.cpp
175 |   `-- rtpdump.dsp
176 |-- tml.dsw
177 |-- tml.sln
178 `-- unixprep.sh
179 
180 9 directories, 167 files
View Code

4. 构建、运行流程

  本人在Win10+mingw环境做开发验证,此外还需将一些编译工具链(gcc/ld等gcc家族产品)准备好,才能使用Makefile。

  1. 进入ldecod目录,执行make,即可编译出解码器,最终会将可执行文件ldecod.exe拷贝到根目录下的bin文件夹中。(可能会遇到几个预处理错误问题,是关于不同平台下最大值的定义)

  2.与上面类似,进入lencod目录,构建出编码器。

  3.进入bin目录,执行命令:

  ./ldecod.exe decoder.cfg

  其中,decoder.cfg指定了裸码流路径(不能是mp4等带文件容器格式的文件,必须是NALU形式的裸数据——可由ffmpeg提取出来)、解码后yuv文件输出路径等参数。