h264检测是I帧还是P帧,解决录像第一帧有马赛克问题
- 格式:docx
- 大小:67.04 KB
- 文档页数:4
H264帧边界识别简介在Symbian平台上实现H264的RTSP流的播放原文:/asddg67/archive/2009/03/23/4017251. aspx 在Symbian平台上实现H264的RTSP流的播放/linzhiji/archive/2010/02/24/5323622.as px H264的数据读取最关键的地方就是如何识别一帧,因为ffmpeg的H264解码是按照一帧一帧解码的,如果送去解码的数据不是完整的一帧可能导致解码失败或者产生马赛克的情况。
以下是我在一个文档中摘取关于帧边界识别的一段,可以方便的解决相关的问题:帧边界识别简介H.264 将构成一帧图像所有nalu 的集合称为一个AU,帧边界识别实际上就是识别AU。
因为H.264 取消帧级语法,所以无法简单地从码流中获取AU。
解码器只有在解码的过程中,通过某些语法元素的组合才能判断一帧图像是否结束。
一般来说,解码器必须在完成一帧新图像的第一个slice_header 语法解码之后,才能知道前一帧图像已经结束。
因此,最严谨的AU 识别步骤如下:步骤1 对码流实施“去03 处理”。
步骤2 解析nalu 语法。
步骤3 解析slice_header 语法。
步骤4 综合判断前后两个nalu 以及对应的slice_header 中的若干个语法元素,看是否发生变化。
如果发生变化,则说明这两个nalu 属于不同的帧,否则说明这两个nalu 属于同一帧。
----结束显然,在解码前完成上述的AU 识别消耗许多CPU 资源,因此不推荐使用AU 方式解码为了提供一种简单的AU 识别方案,H.264 规定一种类型为09 的nalu,即编码器在每次完成一个AU 编码后,在码流中插入一个类型为09 的nalu,在这个前提下,解码器只需要从码流中搜索类型为09 的nalu 即可获得一个AU。
H.264 并不强制要求编码器插入类型为09 的nalu,因此并非所有的码流都具备这种特征。
序列、图像(存储单元)、宏块、像素一个序列的第一个图像叫做IDR 图像(立即刷新图像),IDR 图像都是I 帧图像。
H.264 引入IDR 图像是为了解码的重同步,当解码器解码到IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。
●I帧(帧内编码帧)是一种自带全部信息的独立帧,无需参考其它图像便可独立进行解码。
视频序列中的第一个帧始终都是I帧。
I帧可以用来实现快进、快退以及其它随机访问功能。
如果新的客户端将参与查看视频流,编码器将以相同的时间间隔或者根据要求自动插入I帧。
I帧的缺点在于它们会占用更多的数据位,但I帧不会产生可觉察的模糊现象。
●P帧(帧间预测编码帧)需要参考前面的I帧和/或P帧的不同部分才能进行编码。
与I帧相比,P帧通常占用更少的数据位,但其缺点是,由于P帧对前面的P和I参考帧有着复杂的依赖性,因此对传输错误非常敏感。
●B帧(双向预测编码帧)需要同时以前面的帧和后面的帧作为参考帧。
不是参考帧,不会造成解码错误的扩散。
运算比较复杂,CPU占用较高。
I、B、P各帧是根据压缩算法的需要人为定义的,它们都是实实在在的物理帧。
一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。
网络打包、网络抽象层单元(NALU)、片NALU的网络打包:(1) 额外开销要少,使MTU尺寸在100~64k字节范围都可以;(2) 不用对包内的数据解码就可以判别该包的重要性;(3) 载荷规范应当保证不用解码就可识别由于其他的比特丢失而造成的包不可解码;(4) 支持将NALU分割成多个RTP包;(5) 支持将多个NALU汇集在一个RTP包中。
●灵活宏块次序(FMO) 可以通过设置宏块次序映射表(MBAmap)来任意地指配宏块到不同的片组,FMO模式打乱了原宏块顺序,降低了编码效率,增加了时延,但增强了抗误码性能。
划分图像的模式各种各样,主要的有棋盘模式、矩形模式等。
论坛最近经常有人问H.264的效果等问题,我实在是没时间一一做答,再者各人观点不同,干脆给出个测试报告,大家自己评价吧。
测试条件:1、赛扬1G,256MB SDRAM,Win98SE2、H.264只支持16x16、8x8、4x4模式,部分MMX优化(量化等耗时部分没有优化)3、只测试 300 kbps、500 kbps、1000 kbps、1500 kbps几种环境4、MPEG4为半点MV,H.264为1/4点MV5、I帧间隔一律为646、帧率均设置为25 Hz7、MPEG4为了提高PSNR,没有使用MMX/SSE等简化算法测试序列:A、电影中截取的250帧,含有渐亮、渐暗、场景渐渐切换、全屏横向运动等复杂环境备注:1、MPEG4编码器输出的总PSNR均值和YUV分量和的均值不同,所以我重新计算了一下,新的值比编码器给出的大约大1左右;2、H.264编码器没有码率控制,只好使用修改Qp来控制了,在实际使用中由于有码率控制,所以效果应该比我的测试结果好。
3、H.264由于是简化版本,所以其编码速度约为1 fps4、H.264的码率只能精确到整数部分,小数部分均设为0了5、为了便于比较,H.264部分增测了一些码率测试结果(均为平均值):1、MPEG4部分视频序列A、H263量化方式:379.00 kbps: PSNR=39.767(Y=37.040, U=40.998, V=41.262) 559.22 kbps: PSNR=42.480(Y=40.432, U=43.298, V=43.709) 1073.48 kbps: PSNR=44.714(Y=42.861, U=45.415, V=45.865) 1583.01 kbps: PSNR=45.634(Y=43.598, U=46.378, V=46.926)视频序列A、MPEG4量化方式:375.12 kbps: PSNR=39.954(Y=37.059, U=41.297, V=41.505) 562.53 kbps: PSNR=42.647(Y=40.355, U=43.554, V=44.033) 1054.25 kbps: PSNR=45.140(Y=43.157, U=45.852, V=46.411) 1539.31 kbps: PSNR=46.311(Y=44.318, U=46.961, V=47.653) 2541.80 kbps: PSNR=47.082(Y=45.049, U=47.727, V=48.470)2、H.264部分视频序列A、2参考帧、CAVLC:295.00 kbps: PSNR=41.375(Y=38.805, U=42.424, V=42.894)489.00 kbps: PSNR=43.923(Y=42.187, U=44.500, V=45.081)533.00 kbps: PSNR=44.512(Y=42.664, U=45.151, V=45.720)1027.00 kbps: PSNR=46.866(Y=45.672, U=47.114, V=47.811)视频序列A、5参考帧、CAVLC:322.00 kbps: PSNR=41.855(Y=39.297, U=42.854, V=43.413)488.00 kbps: PSNR=43.896(Y=42.122, U=44.504, V=45.060)1024.00 kbps: PSNR=46.860(Y=45.650, U=47.118, V=47.813)视频序列A、2参考帧、CABAC:265.00 kbps: PSNR=41.925(Y=39.461, U=42.875, V=43.439)359.00 kbps: PSNR=43.362(Y=41.347, U=44.088, V=44.651)510.00 kbps: PSNR=44.712(Y=43.246, U=45.155, V=45.736)1015.00 kbps: PSNR=47.198(Y=46.067, U=47.406, V=48.122)视频序列A、5参考帧、CABAC:164.00 kbps: PSNR=39.635(Y=36.014, U=41.295, V=41.597)262.00 kbps: PSNR=41.855(Y=39.297, U=42.854, V=43.413)505.00 kbps: PSNR=44.722(Y=43.253, U=45.172, V=45.740)1008.00 kbps: PSNR=47.193(Y=46.050, U=47.419, V=48.110)视频序列A、1参考帧、CAVLC、2个B帧:536.00 kbps: PSNR=41.794(Y=39.420, U=42.723, V=43.239)。
视频编码之I帧、P帧、B帧
视频传输原理
视频是利⽤⼈眼视觉暂留的原理,通过播放⼀系列的图⽚,使⼈眼产⽣运动的感觉。
单纯传输视频画⾯,视频量⾮常⼤,对现有的⽹络和存储来说是不可接受的。
为了能够使视频便于传输和存储,⼈们发现视频有⼤量重复的信息,如果将重复信息在发送端去掉,在接收端恢复出来,这样就⼤⼤减少了视频数据的⽂件,因此有了H.264视频压缩标准。
在H.264压缩标准中I帧、P帧、B帧⽤于表⽰传输的视频画⾯。
I帧⼜称帧内编码帧,是⼀种⾃带全部信息的独⽴帧,⽆需参考其他图像便可独⽴进⾏解码,可以简单理解为⼀张静态画⾯。
视频序列中的第⼀个帧始终都是I帧,因为它是关键帧。
2、P帧
P帧⼜称帧间预测编码帧,需要参考前⾯的I帧才能进⾏编码。
表⽰的是当前帧画⾯与前⼀帧(前⼀帧可能是I帧也可能是P帧)的差别。
解码时需要⽤之前缓存的画⾯叠加上本帧定义的差别,⽣成最终画⾯。
与I帧相⽐,P帧通常占⽤更少的数据位,但不⾜是,由于P帧对前⾯的P 和I参考帧有着复杂的依耐性,因此对传输错误⾮常敏感。
B帧⼜称双向预测编码帧,也就是B帧记录的是本帧与前后帧的差别。
也就是说要解码B帧,不仅要取得之前的缓存画⾯,还要解码之后的画⾯,通过前后画⾯的与本帧数据的叠加取得最终的画⾯。
B帧压缩率⾼,但是对解码性能要求较⾼。
总结:
I帧只需考虑本帧;P帧记录的是与前⼀帧的差别;B帧记录的是前⼀帧及后⼀帧的差别,能节约更多的空间,视频⽂件⼩了,但相对来说解码的时候就⽐较⿇烦。
因为在解码时,不仅要⽤之前缓存的画⾯,⽽且要知道下⼀个I或者P的画⾯,对于不⽀持B帧解码的播放器容易卡顿。
数字视频压缩技术H264详解一个基于分组方式的接口,打包和相应的信令属于NAL的一部分。
这样,高编码效率和网络友好性的任务分别由VCL和NAL来完成。
VCL层包括基于块的运动补偿混合编码和一些新特性。
与前面的视频编码标准一样,H.264没有把前处理和后处理等功能包括在草案中,这样可以增加标准的灵活性。
NAL负责使用下层网络的分段格式来封装数据,包括组帧、逻辑信道的信令、定时信息的利用或序列结束信号等。
例如,NAL支持视频在电路交换信道上的传输格式,支持视频在Internet上利用RTP/UDP/IP传输的格式。
NAL包括自己的头部信息、段结构信息和实际载荷信息,即上层的VCL数据。
(如果采用数据分割技术,数据可能由几个部分组成)。
(2)高精度、多模式运动估计H.264支持1/4或1/8像素精度的运动矢量。
在1/4像素精度时可使用6抽头滤波器来减少高频噪声,对于1/8像素精度的运动矢量,可使用更为复杂的8抽头的滤波器。
在进行运动估计时,编码器还可选择“增强”内插滤波器来提高预测的效果。
在H.264的运动预测中,一个宏块(MB)可以按图2被分为不同的子块,形成7种不同模式的块尺寸。
这种多模式的灵活和细致的划分,更切合图像中实际运动物体的形状,大大提高了运动估计的精确程度。
在这种方式下,在每个宏块中可以包含有1、2、4、8或16个运动矢量。
在H.264中,允许编码器使用多于一帧的先前帧用于运动估计,这就是所谓的多帧参考技术。
例如2帧或3帧刚刚编码好的参考帧,编码器将选择对每个目标宏块能给出更好的预测帧,并为每一宏块指示是哪一帧被用于预测。
(3)4某4块的整数变换H.264与先前的标准相似,对残差采用基于块的变换编码,但变换是整数操作而不是实数运算,其过程和DCT基本相似。
这种方法的优点在于:在编码器中和解码器中允许精度相同的变换和反变换,便于使用简单的定点运算方式。
也就是说,这里没有“反变换误差”。
变换的单位是4某4块,而不是以往常用的8某8块。
H264 中的参考帧列表H264中允许从多至15个帧里面选择1帧或者2帧出来作为参考进行预测,所以必须引入一个列表来管理这些参考图像,对与P slice而言,对应 list0,对于B slice 而言,还需要多一个 list1,因为 B slice 是进行的两次预测!(一个前向一个后向\两个前向\两个后向)参考帧分为 long term / short term 两种,即所谓的长期参考帧和短期参考帧。
其中长期参考帧用 LongTermPicNum来进行索引,而短期参考帧则利用 frame_num 或者 POC 来进行索引(默认索引顺序即初始化顺序),再具体一点:P slice 的短期参考利用 frame_num 来进行索引,且按照降序排列(即离当前图像最近的前向图像排在第0位)B slice 的短期参考利用 POC 来进行索引,对其List0而言,先按照POC降序排列处于其前向的参考帧然后再按照POC升序排列处于其后向的参考帧;对其List1而言,先按照POC升序排列处于其后向的参考帧然后再按照POC降序排列处于其前向的参考帧。
对于每个MB而言,在mb_pred()中会传输其参考索引,以表明该MB从list0\list1中选择哪一个作为参考,而对于一个Slice 而言,可能存在该 Slice 内部大多数MB都选择了某一个索引号较大的参考帧,如设定list0中的索引从0~5,而大多数MB都选择了5,在用哥伦布码进行编码时,将会消耗较多的bit!所以在初始化排序好后,会根据当前 slice 的具体情况,对列表进行重排序,如将此时排在索引5位置的POC与排在0位置的POC进行交换,那么mb_pred()中传输参考索引所需的bit数就大大减少了!其中参考索引重排的语法在ref_pic_list_reordering()中有详细介绍!那么当一帧解完后,如何处理该帧呢?需不需要将其放入参考列表中?所以在h264的bit stream中还传输了dec_ref_pic_marking(),通过mmco这个玩意告诉我们当前的一帧接完后如何处理参考列表!TBD:剩下的一个问题就是,为什么要分长期参考和短期参考呢?以下是来自网上的答案,因为short term参考帧以frame_num做为索引,而frame_num是有最大值的,达到最大值后会进行取模,所以短期参考帧不能长期存在于参考列表中,因为一旦frame_num达到最大值后取模为0,该索引就失去意义了,而长期参考帧则不同!/********************************************************I guess there are two primary differences.1) Short-term reference pictures are indexed by referring to variablesthat are a function of their frame_num value. But frame_num is a modulocounter that wraps over periodically. Therefore there is a limit on howlong a short-term reference picture can remain in the buffer -- itcannot remain there after the frame_num value has wrapped all the wayaround and crossed over the same value again. In contrast, long-termreference pictures are referenced by an index that is explicitlyassigned to them by syntax -- their long-term frame index. So along-term reference picture can stay in the decoded picture buffer aslong as the encoder wants it to.2) There is no use of temporal (picture order count) relationships whenreferencing long-term reference pictures in the decoding process.**********************************************************/。
MediaCoderH.264格式编码参数设置及详解MediaCoder H.264格式编码参数设置及详解由于现在⼤部分视频转码都选择H.264格式进⾏编码,同时CUDA编码的画质还达不到x264软编码的质量(如果你对画质⽆要求,可以直接忽略该教程。
)所以该教程对Mediacoder H.264格式编码参数设置进⾏⼀次详解,希望对画质有⼀定要求编码爱好者有所帮助。
视频选项栏界⾯:视频质量/码率⽐例可选百分⽐,选择是否对原始视频码率进⾏压缩。
如果对画质要求较⾼,建议选择100%,即不对原始视频码率进⾏压缩。
码率模式:设置转换视频时所采⽤的编码⽅式。
可选项:1. 平均码率模式;2. 固定质量模式;3. 恒定码率模式;4. 恒定量化参数;5. 2次编码模式;6. 3次编码模式;建议:选择固定质量模式即对原始视频画质质量进⾏固定,编码后视频⼤⼩不可控。
格式:设置转换后临时的视频⽂件(未与⾳频⽂件封装之前)的格式。
可选项:XviD、H.264、MPEG1、MPEG2、MPEG4、Theora、Flash Video、Dirac Video、Windows Media Video、RealMedia、H.263、H.263+、H.261、MS-MPEG4-V2、DV Video、Motion JPEG、Lossless JPEG、Huffyuv、Snow、AMV、Raw Video建议:选择H.264(注意:格式的选择会影响下⾯容器的选择,不是所有的格式都能封装到⼀个容器中的!)容器:最后进⾏封装时使⽤的容器,如XXXX.AVI就是使⽤的AVI作为容器。
可选项:Default、AVI、MP4、Matroska、MPEG1、MPEG2、MPEG2-TS、Flash Video、ASF、3GP、3GP2、MOV、MJPEG、RealMedia、DV Forma、OGG、NUT、PMP、Raw Stream建议:选择MP4(MP4具有良好的播放兼容性,iphone、ipad等均可以直接点播)如果对兼容性没要求,建议选择MKV(注意:很多转换任务⼀开始就报有关容器的错误,是因为混流软件对转换后的⾳频⽂件或视频⽂件⽆法混流所致.具体MediaCoder 的混流器能封装什么格式的视频⽂件和⾳频⽂件,请参考其他有关资料!)复制视屏流:当勾选参数时,MediaCoder不会对原始视频进⾏转换,⽽是直接⽆损提取。
H264(NAL简介与I帧判断)1、NAL全称Network Abstract Layer, 即⽹络抽象层。
在H.264/AVC视频编码标准中,整个系统框架被分为了两个层⾯:视频编码层⾯(VCL)和⽹络抽象层⾯(NAL)。
其中,前者负责有效表⽰视频数据的内容,⽽后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。
因此我们平时的每帧数据就是⼀个NAL单元(SPS与PPS除外)。
在实际的H264数据帧中,往往帧前⾯带有00 00 00 01 或 00 00 01分隔符,⼀般来说编码器编出的⾸帧数据为PPS与SPS,接着为I帧……如下图:2、如何判断帧类型(是图像参考帧还是I、P帧等)?NALU类型是我们判断帧类型的利器,从官⽅⽂档中得出如下图:我们还是接着看最上⾯图的码流对应的数据来层层分析,以00 00 00 01分割之后的下⼀个字节就是NALU类型,将其转为⼆进制数据后,解读顺序为从左往右算,如下:(1)第1位禁⽌位,值为1表⽰语法出错(2)第2~3位为参考级别(3)第4~8为是nal单元类型例如上⾯00000001后有67,68以及65其中0x67的⼆进制码为:0110 01114-8为00111,转为⼗进制7,参考第⼆幅图:7对应序列参数集SPS其中0x68的⼆进制码为:0110 10004-8为01000,转为⼗进制8,参考第⼆幅图:8对应图像参数集PPS其中0x65的⼆进制码为:0110 01014-8为00101,转为⼗进制5,参考第⼆幅图:5对应IDR图像中的⽚(I帧)所以判断是否为I帧的算法为:(NALU类型 & 0001 1111) = 5 即 NALU类型 & 31 = 5⽐如0x65 & 31 = 5帧格式H264帧由NALU头和NALU主体组成。
NALU头由⼀个字节组成,它的语法如下:+---------------+|0|1|2|3|4|5|6|7|+-+-+-+-+-+-+-+-+|F|NRI| Type |+---------------+F: 1个⽐特.forbidden_zero_bit. 在 H.264 规范中规定了这⼀位必须为 0.NRI: 2个⽐特.nal_ref_idc. 取00~11,似乎指⽰这个NALU的重要性,如00的NALU解码器可以丢弃它⽽不影响图像的回放,0~3,取值越⼤,表⽰当前NAL越重要,需要优先受到保护。
第2章H.264基本原理和差错掩盖关键技术概述2.1 H.264的档次与级别H.264标准定义了三个档次的视频编码[16],每个档次可以支持特定的编码功能,并且每个档次都对编码器与解码器有一定的规定。
基本档次支持帧内和帧间编码(I、P条带)及自适应变长编码(CA VLC)的熵编码;主要档次支持交替视频,使用B条带的帧间编码,使用加权预测的帧间编码,以及基于算数编码(CABAC)的熵编码;扩展档次增加了SI、SP帧,并改进了错误恢复机制,但不支持交替视频或CABAC熵编码。
H.264标准中三个档次与其支持的视频编码工具间的关系如图2-1所示。
图2-1 H.264基本、主要和扩展档次编码器性能的改变可以通过参数设置来体现,例如,编码速率、图片大小采样处理率、缓冲大小等。
2.2 H.264编解码器H.264没有明确定义编码器,而是着重定义了编码视频位流的语法及对这种位流解码的方法。
图2-2是H.264编码器框图图2-2 H.264编码器H.264的编码器仍采用变换和预测的混合编码法[17],输入的帧或场n F 以宏块为单位处理,以帧间方式或帧内编码的方式来编码每个宏块,对于每个宏块,根据重构的图像样点来生成预测帧。
预测帧的生成是由当前块减去预测值PRED 块生成差值块n D ,并对差值块n D 进行块变换,再经过量化得到一组量化变换系数X ,最后熵编码重排序,熵编码系数与解码所需的头信息(运动矢量、预测模式量化函数等)一起组成一个压缩后的码流,进入到网络自适应层用于传输和存储。
编码器解码宏块为下一步预测提供一参考图像。
首先调整(1Q -)系数X ,反变换(1T -)生成差分块'n D ,预测块加上差分块'n D 得到重构的块'n F μ,由重构的块'n F 来重构参考图像(加入滤波器可以减少块失真的影响)。
图2-3 H.264解码器框图如图2-3可知,解码器从传输码流中获取到NAL 数据包。
H264基础简介前⾔H264是属于视频的编码层的标准格式,视频编码显然是为了压缩⼤⼩。
我们看下⼀个完全没压缩的视频数据⼤⼩。
假设视频是⾼清(1280 * 720),每秒30帧,也就是每秒的数据1280 * 720 *30 / 8(字节) /1024(KB)/1024(MB) = 3.11MB那么90分钟的电影就要16.7GB,这个数据量显然在当前⽹络下是不现实的。
视频压缩的原理就是去除视频冗余部分,下⾯列举下1,时间冗余时间冗余是序列图像(电视图像、动画)和语⾳数据中所经常包含的冗余。
图像序列中的两幅相邻的图像,后⼀幅图像与前⼀幅图像之间有较⼤的相关性,这反映为时间冗余。
同理,在语⾔中,由于⼈在说话时发⾳的⾳频是⼀连续的渐变过程,⽽不是⼀个完全的在时间上独⽴的过程,因⽽存在时间冗余。
2,空间冗余空间冗余是图像数据中经常存在的⼀种冗余。
在同⼀幅图像中,规则物体和规则背景(所谓规则是指表⾯颜⾊分布是有序的⽽不是杂乱⽆章的)的表⾯物理特性具有相关性,这些相关性的光成像结构在数字化图像中就表现为数据冗余。
,3,知识冗余有许多图像的理解与某些基础知识有相当⼤的相关性,例如:⼈脸的图像有固定的结构。
⽐如,嘴的上⽅有⿐⼦。
⿐⼦的上⽅有眼睛,⿐⼦位于正脸图像的中线上等等。
这类规律性的结构可由先验知识相背景知识得到,我们称此类冗余为知识冗余。
4,结构冗余有些图像从⼤域上看存在着⾮常强的纹理结构,例如布纹图像和草席图像,我们说它们在结构上存在冗余。
5,视觉冗余⼈类视觉系统对于图像场的任何变化,并不是都能感知的。
例如,对于图像的编码和解码处理时,由于压缩或量⽐截断引⼊了噪声⽽使图像发⽣了⼀些变化,如果这些变化不能为视觉所感知,则仍认为图像⾜够好。
事实上⼈类视觉系统⼀般的分辨能⼒约为26灰度等级,⽽⼀般图像量化采⽤28灰度等级,这类冗余我们称为视觉冗余。
通常情况下,⼈类视觉系统对亮度变化敏感,⽽对⾊度的变化相对不敏感;在⾼亮度区,⼈眼对亮度变化敏感度下降。
关于VideoCall马赛克问题处理总结一、问题描述测试发现,即使在4G信号覆盖很好的位置,VoLTE视频电话通话过程中也有图像马赛克的现象,此时语音质量清晰。
二、分析处理过程可以看出当时无线环境很好,RSRP保持在-80dBm以上,SINR保持在25dB以上。
下行PDCP层速率在500-600kbs左右,上行PDCP层速率在500-1000kbps左右。
查看UPDATE 200中主叫与被叫进行媒体格式协商后的视频格式配置为Profile-level-id=42C01E,FPS为30。
从H.264协议解释看,Profile-level-id决定了视频的类型和等级。
其中第一个字节表示视频的类型,第三个字节表示Level等级。
H.264对视频业务Profile分类为:Baseline、Extended、Main、High、High10、High422、High444等,其中Baseline主要用于可视电话、无线通讯等实时通信。
每种Profile对应的ID号如下:H.264对不同的Profile又定义了不同的level等级,如下:实时直播业务推荐的Profile及level等级如下表所示:根据本次VoLTE视频电话主被叫所协商的Profile-level-id,其中Profile id = 0x42,即十进制的66,表示Profile是BaseLine类型;Level=0x1E,即十进制的30,表示Level Number为3,等同于上表中实时直播业务的标清Baseline要求。
从Profile定义的level等级要求来看,此时要求的Max Video Bit Rate需10Mbps,根据如下常见视频格式的主要参数和带宽表,实际带宽要求至少为1216kbps:参考中国移动集团规范VOLTE高清视频业务申请带宽推荐值也为1216kbps。
Profile level 分辨率帧率申请带宽(kbps)3.1720P30 2176 (1280*720)3VGA30 1216 (640*480)2.2VGA15 896 (640*480)1.3QVGA30 640 (320*240)1.2QVGA15 424 (320*240)检查本次VoLTE视频通话业务过程中核心网最终下发的激活EPS 承载信令中,QCI=2对应的上行Guaranteed bit rate和Maximum bit rate只有536kbps,下行的Guaranteed bit rate和Maximum bit rate 只有960kbps,如下图:按照此速率配置,VoLTE视频业务过程中QCI2的保证速率和最大速率过低,致使上下行PDCP层速率无法满足level为3的视频格式要求,导致VoLTE视频业务质量下降,出现图像不清晰甚至马赛克的问题。
如何提取关键帧(I帧,P帧,B帧)开发流媒体播放器的时候,特别是在windows mobile,symbian(S60)平台开发时,很可能遇到需要自己开发播放器的情况。
S60平台提供了CVideoPlayUtility接口可以实现流媒体播放器,但由于非开源,所以相对于自己开发播放器,很多操作受到限制。
live555主要用于网络流接收,ffmpeg则是对接收到的数据进行编码/解码。
I帧,P帧,B 帧是视频流中三种分类,其中I帧也就是关键帧是基础帧,P帧一般根据I帧确定,而B帧需要前面两着的信息。
举例说:the Input sequence for video encoder1 2 3 4 5 6 7I B B P B B ILet's take 1,2,3.. as PTS for simplificationthe out sequence for video encoder ( this equals the decoder sequence)1 423 7 5 6I P B B I B B播放器LIVE555收到的序列顺序就应该是:1 423 7 5 6经过解码器解码,顺序又回到1 2 3 4 5 6 7这种正常顺序。
所以我们可以根据avcodec_decode_video来判断帧别。
avcodec_decode_video之后的顺序是一定的。
严格按照1 2 3 4。
这样的顺序来。
判断I帧,P,B帧方法:(1):假如解码成功,则不是I帧就是P帧(根据AVFrame->keyframe判断是否是I帧)。
假如不是I帧,也不是P帧,则只能是B帧(通过pts判断)。
(2):采用AVFrame->pict_type综合pts的办法:if(FF_I_TYPE==picture->pict_type){Printlog("<II>");}else if(FF_P_TYPE==picture->pict_type){Printlog("<PP>");}else if(FF_B_TYPE==picture->pict_type){Printlog("<BB>");}else if(FF_S_TYPE==picture->pict_type){Printlog("<SS>");}else{Printlog("<OtherType>");}正常情况下是不会打印出B帧的,因为解码成功的肯定是I帧或者是P帧.判断ffmpeg读到的packet是否为关键帧av_read_frame(avFormatCtx, readPacket)if(readpacket->flags &AV_PKT_FLAG_KEY ){key frame}//////如果是h264编码,从帧数据判断frame = |length|data|length后面紧跟着的第一个byte后5位如果是01001则为关键帧if((frame[4] & 0x1f) == 5){NSLog(@"关键帧");}else{NSLog(@"非关键帧");}。
八:H.264:i帧,p帧,b帧介绍i帧:帧内编码帧,i帧表示关键帧,它保留了一副画面完整的数据信息,解码的时候只需要这归真数据就可以完成(因为i帧里面包含了花面狸免得所有信息)。
i帧的特点:1:它是一个全帧压缩编码帧,它将全帧图像信息进行JPEG压缩编码以及传输。
2:解码的时候只需要通过i帧的数据就可以重构完整的图像。
3:i帧描述了图像背景和运动主题的详情4:i帧不需要参考其他画面二生成。
5:i帧是p帧和b帧的参考帧,i真的画面质量直接影响到了后面参考i帧的p帧和b真的图像质量。
6:i帧是基础帧,每一组里面只会有一个i帧。
7:i帧不需要参考运动矢量。
8:i帧所占数据的信息比较大。
p帧:前向预测编码帧,p帧表示的是这一帧跟之前一个关键帧(或p帧)之间的差别。
p帧解码的时候需要用到前面缓存的画面再爹加上这一阵的差别信息,生成完整的图像信息。
p帧的预测与重构。
p帧是以i帧为参考帧,在i帧中找出'某点'的预测值和运动矢量。
预测差别值和运动矢量一起传输,在接收端根据运动矢量从i帧中找出来p帧'某点'的预测值并且与差值相叠加得到p 帧'某点'的结果。
从而得到一个完整的p帧。
p帧的特点:1:p帧是i帧后面相隔1~2帧的编码帧。
2:p帧采用运动补偿的方法传送它与前面的i帧或者p帧的差值以及运动矢量(预测误差)。
3:解码的时候必须将i帧中的预测值与预测误差求和之后才能重构完整的p真图像。
4:p帧属于向前预测的帧间编码,它只参考钱爱你最靠近它的i帧或者p帧。
5:p可以是后面的p真的参考帧,也可以是后面的b真的参考帧。
6:犹豫p帧是参考帧,它可能造成解码错误的扩散。
7:p真的压缩比例比较高。
B帧:双向预测内插编码帧。
B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。
h264检测是I帧还是P帧,解决录像第一帧有马赛克问题最近使用h264码流数据进行录像,但是录出来的第一帧有马赛克,究其原因是录像的第一帧不是关键帧,所以需要录像是需要判断第一帧是否是关键帧,方法有两种,第一种是原码流的基础上查找,第二种是将原码流传递给ffmpeg让ffmpeg判断key_frame,第二种相对简单,但是由于这样一来录像和解码视频切合的太紧密,之后修改比较麻烦,所以选择第一种方案,查看注释1可以明白如何检测h264码流的关键帧,下面是我截取原码流的关键帧和p帧0000000 :是sps0000000 : 是pps0000000 : 是帧类型关键帧类型:1.<span style="color:#FF0000;"><span style="font-size:24px;">0000000: <span style="color:#CCCCCC;">0000 0001 6742 401f 9654 0501 ed00 f39e ....gB@..T......2.0000010: a</span><span style="color:#3366FF;">000 0000 0168 ce3880</span>00 0000 01<span style="color:#000000;">65</span> 8880 .....h.8.....e..3.0000020: 4001 8231 2000 4f11 d84d 5fff fb3b c28a @..1 .O..M_..;..4.0000030: 00bc fc83 03db b3e3 8603 9c59 fa0f a82c ...........Y...,5.0000040: df55 fdf6 8414 032a e766 bd4b fbea 05af .U.....*.f.K....</span>6.</span>P帧类型:1.0000000: <span style="color:#C0C0C0;">0000 0001 6742 401f 9654 0501 ed00 f39e ....gB@..T......2.0000010: a</span><span style="color:#3366FF;">000 0000 0168 ce3880</span>00 0000 01<span style="color:#000000;">41</span> 9a02 .....h.8.....A..3.0000020: 0586 7cb9 9125 5788 8f90 7f1f 1930 7eef ..|..%W......0~.4.0000030: 6383 bebd 2cc5 3627 92c3 390b 46dc d4a5 c...,.6'..9.F...5.0000040: 774b 3484 57f8 9840 fba3 1dd6 800f 2242 wK4.W..@......"B6.0000050: 8816 080f 8f8d 84c6 09aa cda6 363d 00da ............6=..7.0000060: b563 4392 bc65 93e2 63bb 6d30 472e 3ef1 .cC..e..c.m0G.>.8.0000070: 545d 6a3f 36c3 2f7d 6b1e 3c91 d15d d687 T]j?6./}k.<..]..所以在代码中需要检索第29个字节,来判断是65还是41,1.public static String byteToHexString(byte src){2. StringBuilder stringBuilder = new StringBuilder("");3. int v = src & 0xFF;4. String hv = Integer.toHexString(v);5.if (hv.length() < 2) {6. stringBuilder.append(0);7. }8. stringBuilder.append(hv);9.return stringBuilder.toString();10. }11.p rivate boolean isFirstIFrame = true;12.p rivate String IFrame = "65";//关键帧是0x6513.//<span style="font-size:16px"></span>bArrayImage是存放h264原码流字节数组14.i f (是在录像) {15.if (isFirstIFrame) {16. String type = byteToHexString(bArrayImage[29]);17.if (type.equals(IFrame)) { //第29个字符是判断帧的类型18. isFirstIFrame = false;19. ShootingVideoData(bArrayImage, Video_Data_iVideoLen);//录制第一帧:关键帧20. }21. }else {22. ShootingVideoData(bArrayImage, Video_Data_iVideoLen);23. }24. }这样在录制出的第一帧录像就没有马赛克了。
H264--1--编码原理以及I帧B帧P帧H264--1--编码原理以及I帧B帧P帧前言-----------------------H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内。
所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像帧A,随后的B帧就不编码全部图像,只写入与A帧的差别,这样B帧的大小就只有完整帧的1/10或更小!B帧之后的C帧如果变化不大,我们可以继续以参考B的方式编码C帧,这样循环下去。
这段图像我们称为一个序列(序列就是有相同特点的一段数据),当某个图像与之前的图像变化很大,无法参考前面的帧来生成,那我们就结束上一个序列,开始下一段序列,也就是对这个图像生成一个完整帧A1,随后的图像就参考A1生成,只写入与A1的差别内容。
在H264协议里定义了三种帧,完整编码的帧叫I帧,参考之前的I帧生成的只包含差异部分编码的帧叫P帧,还有一种参考前后的帧编码的帧叫B帧。
H264采用的核心算法是帧内压缩和帧间压缩,帧内压缩是生成I 帧的算法,帧间压缩是生成B帧和P帧的算法。
----------------------序列的说明----------------------在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,以I帧开始,到下一个I帧结束。
一个序列的第一个图像叫做IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。
H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。
这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。
MPEG帧的概念和H.264的补充MPEG定义根据MPEG的定义,帧分为I帧,B帧,P帧。
这些帧定义如下:I帧:就是关键帧,I帧压缩采用基准帧模式,只提供帧内压缩,即把帧图像压缩到I帧时,仅仅考虑了帧内的图像。
I帧压缩不能除去帧间冗余度。
帧内压缩基于离散余弦变换(DCT),类似于JPEG和H.261图像中使用DCT的压缩标准。
I帧压缩可以得到6;1的压缩比而不产生任何可觉察的模糊现象。
B帧:为双向帧间编码。
它从前面和后面的I帧或P帧中提取数据。
B帧基于当前帧与前一帧和后一帧图像之间的差别进行压缩。
B帧压缩可以达到200:1的压缩比,其文件尺寸一般为I帧压缩尺寸的15%,不到P帧压缩尺寸的一半。
P帧:采用了前向预测,意思是P帧是根据前面的P帧或I帧预测得来的。
P帧采用预测编码,利用相邻帧的一般统计信息进行预测。
也就是说,它考虑运动特性,提供帧间编码。
P帧预测当前帧与前面最近的I帧或P帧的差别。
H.264补充H.264中也有I B P帧,不同的是,H.264是以多幅图像为参考,因此可以获取更高的压缩比,以及更连贯的动作。
但是这也造成H.264耗资源大,延时也略大于MPEG-4。
除了I B P帧外,H.264提出了SP和SI帧,这两种帧介于I和P之间。
SP的编码原理和P类似,仍是基于帧间预测的运动补偿预测编码,两者之间的差异在于SP帧能够参照不同参考帧重构出相同的图像帧。
充分利用这一特性,SP帧可以取代I帧,广泛应用于Bitstream Switching, Splicing, Random Access, Fast Forward Fast Backward以及Error Recovery等应用中。
同时大大降低了码率的开销。
SI则是基于帧内预测的编码技术,其重构图像的方法和SP完全相同。
SP帧的编码效率尽管略低于P,却远远高于I,大大改善了H.264的网络亲和性,支持灵活的流媒体服务应用,具有很强的抗误码性能,适于在噪声干扰大、丢包率高的无线信道中传输。
【H264】码流结构详解⽆论是解析视频⽂件或者通过⽹络传输,其实都是⼀串字节序列。
H264 码流就是按照⼀定的规则组织排列的字节串。
⼀、码流的组织形式在 H264 中完全没有 I 帧、P 帧、B 帧、IDR 帧的概念,之所以沿⽤这些说法是为了表明数据的编码模式。
H264 码流的组织形式从⼤到⼩排序是:视频序列(video sequence)、图像(frame/field-picture)、⽚组(slice group)、⽚(slice)、宏块(macroblock)、⼦块(sub-block)、像素(pixel)。
⼆、码流功能的⾓度从码流功能的⾓度可以分为两层:视频编码层(VCL)和⽹络提取层(NAL)VCL:进⾏视频编解码,包括预测(帧内预测和帧间预测),DCT 变化和量化,熵编码和切分数据等功能,是为了实现更⾼的视频压缩⽐。
NAL:负责以⽹络所要求的恰当的⽅式对 VCL 数据进⾏打包和传送。
VCL 是管理 H264 的视频数据层,是为了实现更⾼的视频压缩⽐,那 VCL 究竟是怎么管理 H264 视频数据的呢?抛开 H264 压缩算法细节来看就 3 步:压缩:预测(帧内预测和帧间预测)-> DCT 变化和量化 -> ⽐特流编码;切分数据,主要为了第三步。
这⾥⼀点,⽹上看到的“切⽚(slice)”、“宏块(macroblock)”是在VCL 中的概念,⼀⽅⾯提⾼编码效率和降低误码率、另⼀⽅⾯提⾼⽹络传输的灵活性。
压缩切分后的 VCL 数据会包装成为 NAL 中的⼀部分。
下⾯要重点讲解下 NAL。
三、⽹络提取层(NAL)NAL,英⽂全称为 Network Abstraction Layer,这块和 H264 压缩算法⽆关,涉设计出 NAL 的⽬的就是为了获得 “network-friendly”,即为了实现良好的⽹络亲和性,即可适⽤于各种传输⽹络。
终于要讲 NAL 了,但是,我们需要先看 NAL的组成单元 - NALU。
h264检测是I帧还是P帧,解决录像第一帧有马赛克问题
最近使用h264码流数据进行录像,但是录出来的第一帧有马赛克,究其原因是录像的第一帧不是关键帧,所以需要录像是需要判断第一帧是否是关键帧,方法有两种,第一种是原码流的基础上查找,第二种是将原码流传递给ffmpeg让ffmpeg判断key_frame,第二种相对简单,但是由于这样一来录像和解码视频切合的太紧密,之后修改比较麻烦,所以选择第一种方案,查看注释1可以明白如何检测h264码流的关键帧,下面是我截取原码流的关键帧和p帧
0000000 :是sps
0000000 : 是pps
0000000 : 是帧类型
关键帧类型:
1.<span style="color:#FF0000;"><span style="font-size:24px;">000000
0: <span style="color:#CCCCCC;">0000 0001 6742 401f 9654 0501 ed0
0 f39e ....gB@..T......
2.0000010: a</span><span style="color:#3366FF;">000 0000 0168 ce38
80</span>00 0000 01<span style="color:#000000;">65</span> 8880 .
....h.8.....e..
3.0000020: 4001 8231 2000 4f11 d84d 5fff fb3b c28a @..1 .O..M_..;.
.
4.0000030: 00bc fc83 03db b3e3 8603 9c59 fa0f a82c ...........Y...
,
5.0000040: df55 fdf6 8414 032a e766 bd4b fbea 05af .U.....*.f.K...
.</span>
6.</span>
P帧类型:
1.0000000: <span style="color:#C0C0C0;">0000 0001 6742 401f 9654 05
01 ed00 f39e ....gB@..T......
2.0000010: a</span><span style="color:#3366FF;">000 0000 0168 ce38
80</span>00 0000 01<span style="color:#000000;">41</span> 9a02 .
....h.8.....A..
3.0000020: 0586 7cb9 9125 5788 8f90 7f1f 1930 7eef ..|..%W......0~
.
4.0000030: 6383 bebd 2cc5 3627 92c3 390b 46dc d4a5 c...,.6'..9.F..
.
5.0000040: 774b 3484 57f8 9840 fba3 1dd6 800f 2242 wK4.W..@......"
B
6.0000050: 8816 080f 8f8d 84c6 09aa cda6 363d 00da ............6=.
.
7.0000060: b563 4392 bc65 93e2 63bb 6d30 472e 3ef1 .cC..e..c.m0G.>
.
8.0000070: 545d 6a3f 36c3 2f7d 6b1e 3c91 d15d d687 T]j?6./}k.<..].
.
所以在代码中需要检索第29个字节,来判断是65还是41,
1.public static String byteToHexString(byte src){
2. StringBuilder stringBuilder = new StringBuilder("");
3. int v = src & 0xFF;
4. String hv = Integer.toHexString(v);
5.if (hv.length() < 2) {
6. stringBuilder.append(0);
7. }
8. stringBuilder.append(hv);
9.return stringBuilder.toString();
10. }
11.p rivate boolean isFirstIFrame = true;
12.p rivate String IFrame = "65";//关键帧是0x65
13.//<span style="font-size:16px"></span>bArrayImage是存放h264原码流
字节数组
14.i f (是在录像) {
15.if (isFirstIFrame) {
16. String type = byteToHexString(bArrayImage[29]
);
17.if (type.equals(IFrame)) { //第29个字符是
判断帧的类型
18. isFirstIFrame = false;
19. ShootingVideoData(bArrayImage, Video_Data
_iVideoLen);//录制第一帧:关键帧
20. }
21. }else {
22. ShootingVideoData(bArrayImage, Video_Data_iVi
deoLen);
23. }
24. }
这样在录制出的第一帧录像就没有马赛克了。
注释1:检测h264中I帧,P帧
今天在网上找了一些资料,知道了如何检测h264中的帧类型,在这里记录下来。
首先,贴出nal单元类型定义(图从《新一代视频压缩编码标准H.264》摘录):
假设一段h264的码流为:00 00 00 01 41 E6 60……
其中的00 00 00 01为起始码,而起始码之后的下一个字节就可以检测出这一帧的类型。
在上面的码流中起始码之后的字节位0x41,换算成二进制为0100 0001。
注:我解读顺序为从左往右算。
(1)第1位禁止位,值为1表示语法出错
(2)第2~3位为参考级别
(3)第4~8为是nal单元类型,在此处为0 0001换算成十进制为1。
根据上图可知道这段码流是【不分区、非IDR图像的片】,新濠天地娱乐场 在baseline的档次中就是P帧,因为baseline没有B帧。
如果是另一段码流:00 00 00 01 65 E8……
那么根据0x65字节(0110 0101)根据后5位换算十进制为5,也就是【IDR图像中的片】,即I帧。
用代码的方式可以这样写,int type = 0x65 & 0x1f,然后根据type在表中查找即可获得需要的结果。