精华内容
下载资源
问答
  • h264 编码器

    2019-04-16 18:58:10
    业界第一款支持多业务扩展的h264实时编码器,采用了先进的数字视频压缩优化算法。
  • 音视频高手课08-H264 I帧 P帧 B帧及手写H264编码器 1 三种帧的说明 1、I 帧:帧内编码帧,帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面) I 帧的特点: a....

    音视频高手课08-H264 I帧 P帧 B帧及手写H264编码器

    1 三种帧的说明

    1、I 帧:帧内编码帧,帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)

    I 帧的特点:

    • a. 它是一个全帧压缩编码帧,它将全帧图像信息进行JPEG压缩编码及传输

    • b. 解码时仅用I 帧的数据就可重构完整图像

    • c. I 帧描述了图像背景和运动主体的详情

    • d. I 帧不需要参考其他画面而生成

    • e. I 帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量)

    • f. I 帧不需要考虑运动矢量

    • g. I 帧所占数据的信息量比较大

      P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)

    P帧的预测与重构:P帧是以 I 帧为参考帧,在 I 帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运行矢量从 I 帧找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。

    P帧的特点:

    • a. P帧是 I 帧后面相隔1~2帧的编码帧

    • b. P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差)

    • c. 解码时必须将帧中的预测值与预测误差求和后才能重构完整的P帧图像

    • d. P帧属于前向预测的帧间编码。它只参考前面最靠近它的 I 帧或P帧

    • e. 由于P帧是参考帧,它可能造成解码错误的扩散

    • f. 由于是差值传送,P帧的压缩比较高

    3、B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),换言之,要解码B帧。不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。

    B帧的预测与重构

    ​ B帧以前面的 I 或P帧和后面的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中“找出(算出)”预测值并与差值求和,得到B帧“某点”样值,从而可得到完整的B帧。

    B帧的特点:

    • a. B帧是由前面的 I 或P帧和后面的P帧进行预测的

    • b. B帧传送的是它与前面的 I 或P帧和后面的P帧之间的预测误差及运动矢量

    • c. B帧是双向预测编码帧

    • d. B帧压缩比最高,因为它只反映并参考帧间运动主体的变化情况,预测比较准确

    • e. B帧不是参考帧,不会造成解码错误的扩散

    注:I、B、P帧是根据压缩算法的需要,是人为定义的,他们都是实实在在的物理帧。
    一般来说,帧的压缩率是7(跟JPG差不多),
    P帧是20,B帧可以达到50.可见使用B帧能节省大量空间,
    节省出来的空间可以用来保存多一些帧,这样在相同码率下,可以提供更好的画质。
    

    1.2 压缩算法的说明

    h264的压缩方法

    • 1、分组:把几帧图像分为一组(GOP,也就是一个序列),为防止运动变化,帧数不宜取多
    • 2、定义帧:将每组内各帧图像定义为三种类型,即 I 帧、B帧和P帧
    • 3、预测帧:以帧作为基础帧,以帧预测P帧,再由 I 帧和P帧预测B帧
    • 4、数据传输:最后将 I 帧数据与预测的差值信息进行存储和传输

    帧内(Intraframe)压缩也称为空间压缩(Spatial compression)。当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,因此可以独立的解码、显示。帧内压缩一般达不到很高的压缩,跟编码jpeg差不多。

    帧间(Interframe)压缩的原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点,也即连续的视频及其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减少压缩比。帧间压缩也称为时间压缩,它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩一般是无损的。帧差值(Frame differencing)算法是一种典型的时间压缩发,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。

    顺便说下有损(Lossy)压缩和无损(Lossy less)压缩。无损压缩也即压缩前和解压缩后的数据完全一致。多数的无损压缩都采用RLE行程编码算法。有损压缩意味着解压缩后的数据与压缩前的数据不一致。在压缩的过程中要丢失一些人眼和耳朵所不敏感的图像或音频信息,而且丢失的信息不可恢复。几乎所有高压缩的算法都采用有损压缩,这样才能达到低数据率的目标。丢失的数据率与压缩比有关,压缩比越小,丢失的数据越多,解压缩后的效果一般越差。此外,某些有损压缩算法采用多次重复压缩的方式,这样还会引起额外的数据丢失。


    2 手写H264编码器

    要彻底理解视频编码原理,看书都是虚的,需要实际动手,实现一个简单的视频编码器:

    知识准备:基本图像处理知识,信号的时域和频域问题,熟练掌握傅立叶正反变换,一维、二维傅立叶变换,以及其变种,dct变换,快速dct变换。

    2.1.1 第一步:实现有损图像压缩和解压
    参考 JPEG原理,将RGB->YUV,然后Y/U/V看成三张不同的图片,将其中一张图片分为 8x8的block进行 dct变换(可以直接进行二维dct变换,或者按一定顺序将8x8的二维数组整理成一个64字节的一维数组),还是得到一个8x8的整数频率数据。于是表示图像大轮廓的低频信号(人眼敏感的信号)集中在 8x8的左上角;表示图像细节的高频信号集中在右下角。

    ​ 接着将其量化,所谓量化,就是信号采样的步长,8x8的整数频率数据块,每个数据都要除以对应位置的步长,左上角相对重要的低频信号步长是1,也就是说0-255,是多少就是多少。而右下角是不太重要的高频信号,比如步长取10,那么这些位置的数据都要/10,实际解码的时候再将他们10恢复出来,这样经过编码的时候/10和解码的时候10,那么步长为10的信号1, 13, 25, 37就会变成规矩的:0, 10, 20, 30, 对小于步长10的部分我们直接丢弃了,因为高频不太重要。

    经过量化以后,8x8的数据块左上角的数据由于步长小,都是比较离散的,而靠近右下角的高频数据,都比较统一,或者是一串0,因此图像大量的细节被我们丢弃了,这时候,我们用无损压缩方式,比如lzma2算法(jpeg是rle + huffman)将这64个byte压缩起来,由于后面高频数据步长大,做了除法以后,这些值都比较小,而且比较靠近,甚至右下部分都是一串0,十分便于压缩。

    ​ JPEG图像有个问题就是低码率时 block边界比较严重,现代图片压缩技术往往要配合一些de-block算法,比如最简单的就是边界部分几个像素点和周围插值模糊一下。

    做到这里我们实现了一个同 jpeg类似的静态图片有损压缩算法。在视频里面用来保存I帧数据。

    2.1.2 第二步:实现宏块误差计算

    视频由连续的若干图像帧组成,分为 I帧,P帧,所谓I帧,就是不依赖就可以独立解码的视频图像帧,而P帧则需要依赖前面已解码的视频帧,配合一定数据才能生成出来。所以视频中I帧往往都比较大,而P帧比较小,如果播放器一开始收到了P帧那么是无法播放的,只有收到下一个I帧才能开始播放。I帧多了视频就变大,I帧少了,数据量是小了,但视频受到丢包或者数据错误的影响却又会更严重。

    ​ 那么所谓运动预测编码,其实就是P帧的生成过程:继续将图片分成 16x16的block(为了简单只讨论yuv的y分量压缩)。I帧内部单帧图片压缩我们采用了8x8的block,而这里用16x16的block来提高帧间编码压缩率(当然也会有更多细节损失),我们用 x, y表示像素点坐标,而s,t表示block坐标,那么坐标为(x,y)的像素点所属的block坐标为:

    s = x / 16 = x >> 4
    t = y / 16 = y >> 4
    

    ​ 接着要计算两个block的相似度,即矢量的距离,可以表示为一个256维矢量(16x16)像素点色彩距离的平方,我们先定义两个颜色的误差为:

    PixelDiff(c1, c2) = (c1- c2) ^ 2
    

    那么256个点的误差可以表示为所有对应点的像素误差和:

    BlockDiff(b1, b2) = sum( PixelDiff(c1, c2) for c1 in b1 for c2 in b2)
    

    代码化为:

    int block_diff(const unsigned char b1[16][16], const unsigned char b2[16][16]) {
        int sum = 0;
        for (int i = 0; i < 16; i++) {
             for (int j = 0; j < 16; j++) {
                  int c1 = b1[i][j];
                  int c2 = b2[i][j];
                  sum += (c1 - c2) * (c1 - c2);
             }
        }
        return sum;
    }
    

    有了这个block求差的函数,我们就可以针对特定block,搜索另外若干个block中哪个和它最相似了(误差最小)。

    1.2.3 第三步:实现运动预测编码

    ​ 根据上面的宏块比较函数,你已经可以知道两个block到底像不像了,越象的block,block_diff返回值越低。那么我们有两帧相邻的图片,P1,P2,假设 P1已经完成编码了,现在要对 P2进行P帧编码,其实就是轮询 P2里面的每一个 block,为P2中每一个block找出上一帧中相似度最高的block坐标,并记录下来,具体伪代码可以表示为:

    unsigned char block[16][16];
    for (int t = 0; t <= maxt; t++) {
        for (int s = 0; s <= maxs; s++) {
             picture_get_block(P2, s * 16, t * 16, block); // 取得图片 P2 的 block
             int x, y;
             block_search_nearest(P1, &x, &y, block); // 在P1中搜索最相似的block
             output(x, y);  // 将P1中最相似的block的左上角像素坐标 (x, y) 输出
        }
    }
    

    ​ 其中在P1中搜索最相似 block的 block_search_nearest 函数原理是比较简单的,我们可以暴力点用两个for循环轮询 P1中每个像素点开始的16x16的block(速度较慢),当然实际中不可能这么暴力搜索,而是围绕P2中该block对应坐标在P1中位置作为中心,慢慢四周扩散,搜索一定步长,并得到一个 :按照一定顺序进行搜索,并且在一定范围内最相似的宏块坐标。 。

    于是P2进行运动预测编码的结果就是一大堆(x,y)的坐标,代表P2上每个block在上一帧P1里面最相似的 block的位置。反过来说可能更容易理解,我们可以把第三步整个过程定义为:

    怎么用若干 P1里不同起始位置的block拼凑出图片P2来,使得拼凑以后的结果和P2最像。

    1.2.4 第四步:实现P帧编码

    ​ 拼凑的结果就是一系列(x,y)的坐标数据,我们继续用lzma2将它们先压缩起来,按照 vcd的分辨率

    352 x 240,我们横向需要 352 / 16 = 22个block,纵向需要 240 / 16 = 15 个block,可以用 P1中 22 x 15 = 330

    个 block的坐标信息生成一张和P2很类似的图片 P2’ :

    for (int t = 0; t < 15; t++) {
        for (int s = 0; s < 22; s++, next++) {
             int x = block_positions[next].x;   // 取得对应 P1上的 block像素位置 x
             int y = block_positions[next].y;   // 取得对应 P1上的 block像素位置 y
             // 将 P1位置(x,y)开始的 16 x 16 的图块拷贝到 P2'的 (s * 16, t * 16)处
             CopyRect(P2', s * 16, t * 16, P1, x, y, 16, 16); 
        }
    }
    
    	我们把用来生成P2的P1称为 P2的 “参考帧”,再把刚才那一堆P1内用来拼成P2的 block坐标称为 “**运动矢量**”,这是P帧里面最主要的数据内容。但是此时由P1和这些坐标数据拼凑出来的P2,你会发现粗看和P2很象,但细看会发现有些支离破碎,并且边缘比较明显,怎么办呢?我们需要第四步。
    
    1.2.5第五步:实现P帧编码
    	有了刚才的运动预测矢量(一堆block的坐标),我们先用P1按照这些数据拼凑出一张类似 P2的新图片叫做P2',然后同P2上每个像素做减法,得到一张保存 differ的图片: 
    
    D2 = (P2 - P2') / 2
    

    ​ 误差图片 D2上每一个点等于 P2上对应位置的点的颜色减去 P2’上对应位置的点的颜色再除以2,用8位表示差值,值是循环的,比如-2就是255,这里一般可以在结果上 + 0x80,即 128代表0,129代表2,127代表-2。继续用一个 8位的整数可以表示 [-254, 254] 之间的误差范围,步长精度是2。

    ​ 按照第三步实现的逻辑,P2’其实已经很像P2了,只是有些误差,我们将这些误差保存成了图片D2,所以图片D2中,信息量其实已经很小了,都是些细节修善,比起直接保存一张完整图片熵要低很多的。所以我们将 D2用类似第一步提到的有损图片压缩方法进行编码,得到最终的P帧数据:

    Encode(P2) = Lzma2(block_positions) + 有损图像编码(D2)
    

    ​ 具体在操作的时候,D2的图像块可以用16x16进行有损编码,因为前面的运动预测数据是按16x16的宏块搜索的,而不用象I帧那样精确的用8x8表示,同时保存误差图时,量化的精度可以更粗一些用不着象I帧那么精确,可以理解成用质量更低的JPEG编码,按照16x16的块进行编码,加上误差图D2本来信息量就不高,这样的保存方式能够节省不少空间。

    1.2.6 第六步:实现GOP生成

    ​ 通过前面的代码,我们实现了I帧编码和P帧编码,P帧是参考P1对P2进行编码,而所谓B帧,就是参考 P1和 P3对P2进行编码,当然间隔不一定是1,比如可以是参考P1和P5对P2进行编码,前提条件是P5可以依赖P1及以前的数据进行解码。

    ​ 不过对于一个完整的简版视频编码器,I帧和P帧编码已经够了,市面上任然有很多面向低延迟的商用编码器是直接干掉B帧的,因为做实时传输时收到B帧没法播放,之后再往后好几帧收到下一个I或者P帧时,先前收到的B帧才能被解码出来,造成不少的延迟。

    ​ 而所谓的 GOP (Group of picture) 就是由一系列类似 I, P, B, B, P, B, B, P, B, B P 组成的一个可以完整被解码出来的图像组,而所谓视频文件,就是一个接一个的GOP,每个GOP由一个I帧开头,然后接下来一组连续的P 或者 B构成,播放时只有完整收到下一个GOP的I帧才能开始播放。

    	最后是关于参考帧选择,前面提到的 P2生成过程是参考了 P1,假设一个GOP中十张图片,是 I1, P1, P2, P3, P4, ... P9 保存的,如果P1参考I1,P2参考P1, P3参考P2 .... P9参考P8这样每一个P帧都是参考上一帧进行编码的话,误差容易越来越大,因为P1已经引入一定误差了,P2在P1的基础上误差更大,到了P9的话,图片质量可能已经没法看了。 
    

    ​ 因此正确的参考帧选择往往不需要这样死板,比如可以P1-P9全部参考I1来生成,或者,P1-P4参考I1来生成,而P5-P9则参考P5来生成,这样步子小点,误差也不算太离谱。

    1.2.7 第七步:容器组装

    ​ 我们生成了一组组编码过的GOP了,这时候需要一定的文件格式将他们恰当的保存下来,记录视频信息,比如分辨率,帧率,时间索引等,就是一个类似MP4(h.264的容器)文件的东西。至此一个简单的小型编码器我们已经完成了,可以用 SDL / DirectX / OpenGL 配合实现一个播放器,愉快的将自己编码器编码的视频播放出来。

    1.2.8第八步:优化改进

    ​ 这时候你已经大概学习并掌握了视频编码的基础原理了,接下来大量的优化改进的坑等着你去填呢。优化有两大方向,编码效率优化和编码性能优化:前者追求同质量(同信噪比)下更低的码率,后者追求同样质量和码率的情况下,更快的编码速度。

    ​ 有这个基础后接下来可以回过头去看JPEG标准,MPEG1-2标准,并阅读相关实现代码,你会发现简单很多了,接着肯H.264代码,不用全部看可以针对性的了解以下H.264的I帧编码和各种搜索预测方法,有H.264的底子,你了解 HEVC和 vpx就比较容易了。

    ​ 参考这些编码器一些有意思的实现来改进自己的编码器,试验性质,可以侧重原理,各种优化技巧了解下即可,本来就是hack性质的。

    有卯用呢?首先肯定很好玩,其次,当你有需要使用并修改这些编码器为他们增加新特性的时候,你会发现前面的知识很管用了。

    ------有朋友说光有代码没有图片演示看不大明白,好我们补充一下图片演示:

    1.3 画面演示

    1. 3.1 这是第一帧画面:P1(我们的参考帧)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M87PvO4K-1596113069984)(yimg/71.jpg)]

    这是第二帧画面:P2(需要编码的帧)

    从视频中截取的两张间隔1-2秒的画面,和实际情况类似,下面我们进行几次运动搜索:

    1.3.2 搜索演示1:搜索P2中车辆的车牌在P1中最接近的位置(上图P1,下图P2)

    在这里插入图片描述

    这是一个演示程序,鼠标选中P2上任意16x16的Block,即可搜索出P1上的 BestMatch 宏块。虽然车辆在运动,从远到近,但是依然找到了最接近的宏块坐标

    1.3.3 搜索演示2:空中电线交叉位置(上图P1,下图P2)

    在这里插入图片描述

    1.3.3 搜索演示3:报刊停的广告海报

    在这里插入图片描述

    同样顺利在P1中找到最接近P2里海报的宏块位置。

    图片全搜索:根据P1和运动矢量数据(在P2中搜索到每一个宏块在P1中最相似的位置集合)还原出来的P2’,即完全用P1各个位置的宏块拼凑出来最像P2的图片P2’,效果如下:

    仔细观察,有些支离破碎对吧?肯定啊,拼凑出来的东西就是这样,现在我们用P2`和P2像素相减,得到差分图 D2 = (P2’ - P2) / 2 + 0x80:

    嗯,这就是P2`和P2两幅图片的不同处,看到没?基本只有低频了!高频数据少到我们可以忽略,这时用有损压缩方式比较差的效果来保存误差图D2,只要5KB的大小。
    接着我们根据运动矢量还原的 P2’及差分图D2来还原新的 P2,NewP2 = P2’ + (D2 - 0x80) * 2:

    ​ 这就是之前支离破碎的 P2` 加上误差 D2之后变成了清晰可见的样子,基本还原了原图P2。
    ​ 由于D2仅仅占5KB,加上压缩过后的运动矢量不过7KB,

    所以参考P1我们只需要额外 7KB的数据量就可以完整表示P2了,而如果独立将P2用质量尚可的有损压缩方式独立压缩,则至少要去到50-60KB,这一下节省了差不多8倍的空间,正就是所谓运动编码的基本原理。

    再者误差我们保存的是(P2-P2’)/2 + 0x80,实际使用时我们会用更有效率的方式,比如让[-64,64]之间的色差精度为1,[-255,-64], [64, 255] 之间的色差精度为2-3,这样会更加真实一些。

    ​ 现代视频编码中,除了帧间预测,I帧还使用了大量帧内预测,而不是完全dct量化后编码,前面帧间预测我们使用了参考帧的宏块移动拼凑新帧的方式进行,而所谓帧内预测就是同一幅画面中,未编码部分使用已编码部分拼凑而成。。。。。。。

    H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称在编码方面,

    后续:

    粉丝交流扣裙:
    在这里插入图片描述

    展开全文
  • 该代码通过调用ffmpeg实现了视频的编码编码为封装的类,代码是跨库平台的,同时支持windows和linux 2.在windows下使用说明: 从ffmpeg官网下载win64-dev版本,它包含开发使用的lib和include;下载win64-share版本...
  • H264编码器

    2014-04-09 09:32:45
    利用opencv打开已经存在的视频文件(或者摄像头)读取视频流,然后利用H264进行压缩
  • H264编码器H265编码器对比

    千次阅读 2019-12-03 16:24:59
    随着音视频的发展迅速,视频编码经常会使用到H.264H.265编码技术。视频编码的定义是指通过特定的压缩技术,将某个视频格式的文件转换成另一种视频格式文件的方式。常见的音频视频编码H.264系列与H.25系列。 H264...

    随着音视频的发展迅速,视频编码经常会使用到H.264、H.265编码技术。视频编码的定义是指通过特定的压缩技术,将某个视频格式的文件转换成另一种视频格式文件的方式。常见的音频视频编码有H.264系列与H.25系列。
    H264与H265介绍:
    H.264(MPEG-4 AVC(Advanced Video Codec,高级视频编码)的简称。H.264和H.265一样都是一种视频压缩标准,同时也是一种被广泛使用的高精度视频的录制、压缩和发布格式,目前市面上的高清摄像机大都采用H.264编码技术。
    H.265(HEVC,High Efficiency Video Coding,高效率视频编码),是新一代视频编码技术。它围绕现有视频编码标准H.264,保留原来的某些技术,使用新技术对某些方面进行改进优化,如码流、编码质量、延时等,提高压缩效率、增强鲁棒性和错误恢复能力、减少实时的时延、降低复杂度等。
    H.265其核心的优势在于相比之前的历代标准,可以在同样的图像质量下,大幅度降低了压缩码率。从客观效果提升上看,根据测试,H.265在1080P分辨率下相比H.264码率降低一半左右,并且分辨率越高优势越显著。
    H264与H265对比:传输码率
    H264可以低于1Mbps的速度实现标清数字图像传送;
    H265则可以实现利用1~2Mbps的传输速度传送720P(分辨率1280*720)普通高清音视频传送。
    H.265标准也同时支持4K、8K超高清视频,所以,H.265拥有更低的传输码率。

    H264与H265对比:压缩率码率
    H.264的压缩比是MPEG-2的2倍以上,是MPEG-4的1.5~2倍。H.264在低码率作用下,节省用户下载时间和数据流量收费,降低成本。
    H.265在具有高压缩比的同时,还拥有高质量流畅的图像。使用H.265编码的视频监控,传输所需带宽更少,也更快,更经济实惠。
    视频压缩技术是视频编解码器核心技术,H264与H265编码技术可根据项目本身实际情况而定,H265技术相对来说价格肯定比H264要高点。
    H.264同样也被广泛用于网络流媒体数据、各种高清晰度电视广播以及卫星电视广播等领域。总结H.265的主要是提高压缩效率、提高鲁棒性和错误恢复能力、减少实时的时延、减少信道获取时间和随机接入时延、降低复杂度。

    展开全文
  • H264编码器性能测试

    千次阅读 2014-06-17 13:33:49
    首先,介绍一下常见的三大开源H264编码器:JM、X264、T264 JM H264的官方测试源码,实现了264的所有特性,但程序结构冗长,编码复杂度高,不推荐商业应用。 X264 摈弃了264中对编码性能贡献小,但计算复杂度极高...
    版本:0.1.0-beta
    
    作者:石硕
    更新:2014-04-13 15:54:08
    ============================================================

        如今,H264已经成为视频行业的标准规范,企业中使用比较多的当数X264,开源,资源消耗又比较少。
        首先,介绍一下常见的三大开源H264编码器:JM、X264、T264
        JM H264的官方测试源码,实现了264的所有特性,但程序结构冗长,编码复杂度高,不推荐商业应用。
        X264 摈弃了264中对编码性能贡献小,但计算复杂度极高的新特性,推荐商业应用。
        T264 编码与X264类似,但是解码器只能解T264编码的,有点坑。

        在使用H264编码器X264之前,我们先对其性能进行测试,以确定是否需要再次优化。
        测试的流程如下:

    1、到X264官网下载264源码

        官方网站:http://www.videolan.org/developers/x264.html
        GIT地址:git://git.videolan.org/x264.git(注,X264最原始的源码都是在linux下编译的,如果想要windows版的,请看下面)
        windows版X264地址:http://doom10.org/index.php?topic=3.0(注:第三方移植的,自行判断是不是最新)

    2、根据实际的业务需要,制定相应的测试标准

        由于X264是根据H264的标准制作的,所以,H264标准以及以前标准都是适用的。实际应用中,会有不同的需求,比如说监控对帧率要求比较低,再比如说网络传输对码率要求比较高,又比如说在移动平台上使用对CPU MEM要求比较高。
        下面是视频直播中使用到的:
        分 辨 率:160×120  320×240  640×480
        帧    率:10  15  20  25  30
        码    率:128  160  256
        编码延时:<= 200ms
        码率精度:<= 15%
        兼 容 性:标准H264解码器可以解码
        操作系统:winXP  win7-x86  win7-x64
        CPU     :AMD Athlon II X2 240(高配)  AMD SP145(低配)
        MEM     :2GB

    3、新建测试项目,调用X264库

        新建VC项目,读取YUV序列文件(下面会介绍文件来源),编码,输出到H264文件

    4、网上查找YUV序列的结构,了解都有哪些格式

        YUV结构介绍英文版:http://www.fourcc.org/yuv.php
        YUV结构介绍中文翻译版:http://blog.csdn.net/SearchSun/article/details/2443867
        在这些YUV格式中,比较常见的是YUV420,一帧YUV420在文件中的排布如下,以CIF图像(352*288)为例:
        Y信息 352*288 B
        U信息 352*288/4 B
        V信息 352*288/4 B
        算出一帧数据的大小 = 352*288 +  352*288/4 +  352*288/4 ,常见写作 352*288*3/2

    5、网上查找YUV序列文件,或者自行制作

        YUV测试序列下载地址:http://dpinglee.blog.163.com/blog/static/144097753201242254639795/ (这个是目前网上能找到的最全面的)
        从上面的链接中找到的最为规范的要数这个:http://sp.cs.tut.fi/mobile3dtv/stereo-video/
        YUV格式有很多种,再加上不同的参数配置,又会有很多种,下载前一定要看清楚是否是自己需要的格式,因为这些测试序列文件通常都会比较大的
    5.1、YUV序列文件制作方法
        1)从网上下载任意格式的视频文件,AVI最好
        2)安装 FFSetup.exe(中文名称格式工厂),把下载好的视频文件转换为AVI格式,转换参数中视频编码选H264
        3)使用 avitoyuv.exe 把转换好的AVI文件转换为YUV文件
        4)使用 YUVViewer.exe 验证转换的正确性

    6、网上查找YUV序列文件播放器,验证YUV文件的有效性

        找到YUV序列文件之后,使用 YUVViewer.exe 验证文件的正确性
        YUViewer下载地址:http://ishare.iask.sina.com.cn/f/21603725.html

    7、运行测试项目,读取YUV文件,输出H264文件


    8、编码的过程中,观察H264编码器的各项指标,并做记录

        在不同的参数配置下,观察下面的各项指标是否正常:
        编码延时:可以在测试程序中输出日志查看
        码率精度:同上
        兼 容 性:使用H264visa可以正常播放即可
        CPU     :高配在2%以内  低配在4%以内
        MEM     :?MB以内

    9、网上查找H264文件播放器,验证编码的正确性

        使用H264visa验证编码后H264文件的正确性
        H264visa下载地址:http://ishare.iask.sina.com.cn/f/25002676.html (这个需要2新浪积分)

        如果对X264编解码比较感兴趣,打算深入研究,可以从这里开始:http://www.rosoo.net/a/200908/7424.html,这篇是罗索实验室的文章,一个专业研究音视频,流媒体解决方案的网站。



    工具推荐

    1.软件开发必备翻墙代理,低延迟(50ms),月费10元,详询(宝哥儿QQ1066690060)请自觉遵守国家法律法规



    展开全文
  • H264编码器13(CAVLC和CABAC简介)

    千次阅读 2019-01-28 17:57:40
    CABAC/CAVLCin H.264 什么是熵编码? 熵编码压缩是一种无损压缩,其实现原理是使用新的编码来表示输入的数据,从而达到压缩的效果。常用的熵编码有游程编码,哈夫曼编码和CAVLC编码等。   第一部分   CAVLC ...

    来自:https://blog.csdn.net/jubincn/article/details/6948334

     

    CABAC/CAVLCin H.264


    什么是熵编码?
    熵编码压缩是一种无损压缩,其实现原理是使用新的编码来表示输入的数据,从而达到压缩的效果。常用的熵编码有游程编码,哈夫曼编码和CAVLC编码等。

     

    第一部分

     

    CAVLC
    CAVLC(Context Adaptive VariableLength Coding)是在H.264/MPEG-4AVC中使用的熵编码方式。在H.264中,CAVLC以zig-zag顺序用于对变换后的残差块进行编码。CAVLC是CABAC的替代品,虽然其压缩效率不如CABAC,但CAVLC实现简单,并且在所有的H.264profile中都支持。

     

    CAVLC的编码过程如下:

     

    1 计算非零系数(TotalCoeffs)和拖尾系数(TrailingOnes)的数目。

    拖尾系数指值为+1/-1的系数,最大数目为3。如果超过3个,那么只有最后三个被视为拖尾系数。拖尾系数的数目被赋值到变量TrailingOnes。
    非零系数包括所有的拖尾系数,其数目被赋值到变量TotalCoeffs)。


    2 计算nC(numberCurrent,当前块值)。

    nC值由左边块的非零系数nA和上面块非零系数nB来确定,计算公式为:nC=round((nA+nB)/2);若nA存在nB不存在,则nC=nA;若nA不存在而nB存在,则nC=nB;若nA和nB都不存在,则nC=0。
    nC值用于选择VLC编码表,如下图所示。这里体现了上下文相关(contextadaptive)的特性,例如当nC值较小即周围块的非零系数较少时,就会选择比较短的码,从而实现了数据压缩。

     

    3 查表获得coff_token的编码。

    根据之前编码和计算过程所得的变量TotalCoeffs、TrailingOnes和nC值可以查H.264标准附录CAVLC码表,即可得出coeff_token编码序列。


    4 编码每个拖尾系数的符号,按zig-zag的逆序进行编码。

    每个符号用1个bit位来表示,0表示“+”,1表示“—”。
    当拖尾系数超过三个时只有最后三个被认定为拖尾系数,引词编码顺序为从后向前编码。

     

    5 编码除拖尾系数之外非零系数的level(Levels)。

    每个非零系数的level包括sign和magnitude,扫描顺序是逆zig-zag序。
    level的编码由前缀(level_prefix)和后缀(level_suffix)组成。前缀的长度在0到6之间,后缀的长度则可通过下面的步骤来确定:
    将后缀初始化为0。(若非零系数的总数超过10且拖尾系数不到3,则初始化为1)。
    编码频率最高(即按扫描序最后)的除拖尾系数之外的非零系数。
    若这个系数的magnitude超过某个门槛值(threshold),则增加后缀的长度。下表是门槛值的列表:


    6 编码最后一个非零系数之前0的个数(totalZeos)。

    TotalZeros指的是在最后一个非零系数前零的数目,此非零系数指的是按照正向扫描的最后一个非零系数
    根据TotalCoeffs值,H.264标准共提供了25个变长表格供查找,其中编码亮度数据时有15个表格供查找,编码色度DC2×2块(4:2:0格式)有3个表格、编码色度DC2×4块(4:2:2格式)有7个表格。

     

    7 编码每个系数前面0的数目(run_before)。

    扫描顺序为zig-zag的逆序。
    若∑[run_before]== total_zeros,则不需再计算run_before
    扫描序中的最后一个元素不需要计算run_before
    每个run_before的VLC编码取决于run_before自身及未编码的0的个数ZerosLeft。例如若ZerosLeft== 2,那么run_before只可能是0,1或2,因此使用两个bit即可表示。



     

    第二部分 CAVLC之手把手教你编码

    转自:http://blog.csdn.net/sunshine1314/article/details/1685948

    这篇博客使用实例对上述过程做了详细的说明,尤其是有关Levels的计算方面做了重要的补充。下面是全文的转载:

    首先声明本文并不是我写的,文章来自本人同学(Sunrise),都是一起做的H264,比较了解,文章内容都是自己整理的,比较可信,因此整理到一起,我也偷个懒哈

    再次声明:文中用的标准是BS的正式标准,如果大家发现序号不对,参考着改过来就是了!

    编码过程:
    假设有一个4*4数据块
    {
       0,   3,   -1,   0,
       0,   -1,   1,   0,
       1,   0,   0,   0,
       0,   0,    0,   0
    }
    数据重排列:0,3,0,1,-1,-1,0,1,0……

     

    1)初始值设定:
    非零系数的数目(TotalCoeffs) = 5;
    拖尾系数的数目(TrailingOnes)= 3;
    最后一个非零系数前零的数目(Total_zeros) = 3;
    变量NC=1;
    (说明:NC值的确定:色度的直流系数NC=-1;其他系数类型NC值是根据当前块左边4*4块的非零系数数目(NA)当前块上面4*4块的非零系数数目(NB)求得的,见毕厚杰书P120表6.10)
    suffixLength = 0;
    i = TotalCoeffs = 5;


    2)编码coeff_token:
    查标准(BS ISO/IEC 14496-10:2003)Table 9-5,可得:
    If (TotalCoeffs == 5 && TrailingOnes == 3 && 0 <= NC < 2)
          coeff_token = 0000 100;
          Code = 0000 100;


    3)编码所有TrailingOnes的符号:
    逆序编码,三个拖尾系数的符号依次是+(0),-(1),-(1);
    即:
    TrailingOne sign[i--] = 0;
    TrailingOne sign[i--] = 1;
    TrailingOne sign[i--] = 1;
    Code = 0000 1000 11;


    4)编码除了拖尾系数以外非零系数幅值Levels:
    过程如下:
    (1)将有符号的Level[i]转换成无符号的levelCode;
    如果Level[i]是正的,levelCode = (Level[i]<<1) – 2; 
    如果Level[i]是负的,levelCode = - (Level[i]<<1) – 1;
    (2)计算level_prefix:level_prefix = levelCode / (1<<suffixLength);
           查表9-6可得所对应的bit string;
    (3)计算level_suffix:level_suffix = levelCode % (1<<suffixLength);
    (4)根据suffixLength的值来确定后缀的长度;
    (5)suffixLength updata:
    If ( suffixLength == 0 )
    suffixLength++;
             else if ( levelCode > (3<<suffixLength-1) && suffixLength <6)
                suffixLength++;

    回到例子中,依然按照逆序,Level[i--] = 1;(此时i = 1)
    levelCode = 0;level_prefix = 0;
    查表9-6,可得level_prefix = 0时对应的bit string = 1;
    因为suffixLength初始化为0,故该Level没有后缀;
    因为suffixLength = 0,故suffixLength++;
    Code = 0000 1000 111;
    编码下一个Level:Level[0] = 3;
    levelCode = 4;level_prefix = 2;查表得bit string = 001;
    level_suffix = 0;suffixLength = 1;故码流为0010;
    Code = 0000 1000 1110 010;
    i = 0,编码Level结束。


    5)编码最后一个非零系数前零的数目(TotalZeros):
       查表9-7,当TotalCoeffs = 5,total_zero = 3时,bit string = 111;
       Code = 0000 1000 1110 0101 11;


    6)对每个非零系数前零的个数(RunBefore)进行编码:
    i = TotalCoeffs = 5;ZerosLeft = Total_zeros = 3;查表9-10:
    依然按照逆序编码
    ZerosLeft =3, run_before = 1         run_before[4]=10;
    ZerosLeft =2, run_before = 0         run_before[3]=1;
    ZerosLeft =2, run_before = 0         run_before[2]=1;
    ZerosLeft =2, run_before = 1         run_before[1]=01;
    ZerosLeft =1, run_before = 1         run_before[0]不需要码流来表示
    Code = 0000 1000 1110 0101 1110 1101;
    编码完毕。

     

    第三部分 CABAC


    简介
    CABAC(ContextAdaptive Binary Arithmatic Coding)也是 H.264/MPEG-4AVC中使用的熵编码算法。CABAC在不同的上下文环境中使用不同的概率模型来编码。其编码过程大致是这样:首先,将欲编码的符号用二进制bit表示;然后对于每个bit,编码器选择一个合适的概率模型,并通过相邻元素的信息来优化这个概率模型;最后,使用算术编码压缩数据。

     

    CABAC编码详情
    CABAC编码之所以能取得很高的压缩比,是因为:a)根据每一个语法元素的上下文来选取预测模型;b)使用本地的统计数据来估计概率;c)使用算术编码而不是变长编码。编码一个符号需要经过下面几步:

     

    1 二值化。

    CABAC使用的算术编码是基于二进制的算术编码,因此非二进制形式的编码首先要转化为二进制的形式表示。

     

    下面的2、3、4步

    2 选择上下文模型。

    “上下文模型”是指对二值化后的符号中的bit位进行编码时使用的概率模型。概率模型与最近编码的符号相关,会有多个概率模型可供选择。

     

    3 算术编码。

    算术编码器根据第2步选择的概率模型对每个bit进行编码。需要注意的是每个bit的子范围只有两个数:0和1。

     

    4 更新预测模型。

    根据实际编码的值来更新所选择的预测模型。例如,如果所编码的二进制bit为1,则预测模型中的1计数要增加。

     

     编码过程
    下面将以mxdx为例解释编码过程,mxdx是motionvector difference in the x-direction的简写,通过宏块的子块之间运算获得。

     

    1 二值化。

    对于|mvdx|<9的数,使用下表进行编码,超过9的数使用Exp-Golomb编码。在这里,我们称编码后的第一个bit为bin1,第二个bit为bin2,以此推之,可以得到bin3,bin4等。

     

    2 为每个bin选择一个上下文模型。

    bin1可以在三个模型之间进行选择,选择的依据是相邻的两个mxdx的绝对值之和,ek:

    ek = mxdxA+ mxdxB(A和B分别是当前块的上方块和左边块)

    根据ek值从下表中为bin1选择上下文模型:

    除bin1之外的其它bit的上下文模型的选择根据下表进行:

     

    3 编码每个bin。

    所选的预测模型中有0和1的概率,从而为算术编码器提供了概率范围,算术编码器使用这个概率范围对此bin进行算术编码。

     

    4 更新上下文模型。

    例如,若bin1使用上下文模型2,而bin1的值是1,那么上下文模型2中1的计数就要增加,1的概率和0的概率需要重新计算。当上下文模型中的总数超过门槛值后,0和1的计数就要除以某个值,从而使得新加入的0和1在模型中产生更大的影响。


     

    展开全文
  • H264学习笔记(2):H264编码器

    千次阅读 2015-12-16 14:08:42
    在上一节中简要介绍了编码器的原理,这节主要记录了H264编码器的相关内容。  H264为了提高预测精度,编码器可以从一组前面或后面已编码图像中选出一个或两个与当前最匹配的图像作为帧间编码间的参数图像,这样一来...
  • 最小的h264编码器

    2014-05-18 03:19:58
    最小的h264编码器,C++语言.学习H264和视频编码的good start point !!
  • H.264编码器流程图

    2008-10-17 09:11:44
    H.264编码器的流程图,参考的代码是JM61,看该流程图时可能用得到的约束参数:不采用rdo, Qcif,一帧参考,帧间预测没有8x8以下的。
  • H264编码器帧内预测算法的研究和在FPGA中的实现.pdf
  •  H.264是ITU-T的视频编码专家组(VCEG)和ISO/IEC的活动图像专家组(MPEG)联合制定的视频压缩标准。它在H.263/H.263++的基础上发展,在继承所有编码压缩技术优点的同时引入许多全新的编码技术和网络适配层NAL的概念,...
  • 针对高清视频庞大的数据量以及H.264编码器复杂的编码结构引起的低编码速率的问题,对影响算法编码速率的原因进行了深入分析,并设计了高效的多核并行方案,进而充分利用TMS320C6678的多核性能,并结合TMS320C6678的...
  • 基于DM642DSP的H.264编码器结构设计,王立,荣艺,本文介绍在TMS320DM642的硬件平台上实现H.264视频压缩编码基本档次时所进行的结构设计。由于H.264视频压缩编码系统的复杂性和DM642芯片资�
  • 因此,要满足图像压缩的实时性要求,就需要对现有的H.264编解码进行优化。本文主要讨论H.264系统的硬件平台和任务流程,并针对基于DSP硬件平台的特点,介绍了从代码级对算法进行优化,进一步提高编码算法的运算...
  • 写作背景:最近在研究H264编码器的参数,里面的参数不太懂,其中包括: 1) 30 # i intervals // I 帧间距 2)30 # idr intervals// idr帧间距 3) 0 # b frame number between 2 p-frame(0, 1, 2) 4). 0...
  • 上一篇:H264的基本原理(一)------视频的基本知识 1、H264的压缩技术 H264压缩技术主要采用了以下几种方法对视频数据进行压缩。包括: 帧内预测压缩,解决的是空域数据冗余问题。该帧中的数据,比如:宽、高、...
  • 写作背景:最近在研究H264编码器的参数,里面的参数不太懂,其中包括: 1) 30 # i intervals // I 帧间距 2)30 # idr intervals// idr帧间距 3) 0 # b frame number between 2 p-frame(0, 1, 2) 4). 0...
  • h264编码转换工具

    2014-04-16 10:57:08
    h264编码转换工具 Silverlight中制作视频演示时要求视频文件编码默认支持H264 所以非H264的视频文件有可能无法播放,使用此工具转换一下转换成mp4文件
  • ffmpeg进行h264编码

    千次阅读 2020-12-07 12:39:49
    首先需要穿件编码的上下文以及指定编码器代码如下 //视频编码上下文 - (AVCodecContext *)get_avcodecContext_fv{ AVCodecContext *c_ctx = NULL; AVCodec *codec = NULL; codec = avcodec_find_encoder_by_...
  • 关于ffmpeg with h264编码器安装的步骤

    千次阅读 2017-03-04 15:54:25
    官方网站:https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu ,按照全英文的文档安装,安装过程中建立了offmpeg_sources、offmpeg_build、bin三个目录,前两个目录在安装完毕后可以删除。 ...
  • 全志硬件编码H264示例

    2021-04-22 19:23:18
    适合全志T7 图象编码开发者
  • 提出了一种在TI公司高性能数字信号处理器TMS320DM3730上进行H.264编码器(即x264编码器)移植与优化的方法,详细描述了在CCS4.2开发平台上进行x264编码器移植工作的基本原理和需要注意的问题。为了提高编码速度,...
  • 今天小编就为大家分享一篇python opencv图片编码h264文件的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • H264视频压缩编码标准

    2019-03-08 08:27:05
    该文档介绍了H.264/AVC编解码及其结构,还有帧内预测、帧间预测和变换与量化,对初学者有很大的帮助
  • libx264(h264)编码

    2018-06-19 10:10:14
    H264编码,libx264。 ffmpeg等工具需要使用的编码。。。。
  • 基于OBS的WebRTC H264编码器

    千次阅读 2019-03-14 00:02:08
    基于OBS实现了WebRTC的H264编码器,借助OBS内部已经集成的硬件编码器,降低WebRTC的H264编码CPU消耗。
  • h.264视频编码器

    千次阅读 2020-09-22 21:29:04
    本文首先介绍了多媒体技术发展的状况以及视频压缩的基本概念和方法,然后分析了H.264编解码器的基本结构和实现流程,本文在细致的分析了其编解码器后,对于解码器,编码器都采用了多种方式进行优
  • H264编码器在TMS320DM642平台上的底层优化

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 225,218
精华内容 90,087
关键字:

h264编码器