【FFmpeg学习】H264 视频码流分析

这篇具有很好参考价值的文章主要介绍了【FFmpeg学习】H264 视频码流分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. H264编码分层

  • NAL层:(Network Abstraction Layer,视频数据网络抽象层): 它的作用是H264只要在网络上传输,在传输的过程每个包以太网是1500字节,而H264的帧往往会大于1500字节,所以要进行拆包,将一个帧拆成多个包进行传输,所有的拆包或者组包都是通过NAL层去处理的。
  • VCL层:(Video Coding Layer,视频数据编码层): 对视频原始数据进行压缩

【FFmpeg学习】H264 视频码流分析

 我们可以看到视频帧序列每一帧图像是由slice构成的,每一个slice是由多个宏块构成的,在实际传输的过程中,一般一帧图像就是一个slice,没有分那么细。

NAL单元的结构组成

【FFmpeg学习】H264 视频码流分析

  •  SODB:(String of Data Bits,原始数据比特流):由VCL层产生,数据长度不一定是8的倍数,所以处理起来比较麻烦
  • RBSP:(Raw Byte Sequence Payload,SODB+trailing bits,编码后的数据流):算法是在SODB最后一位补1,不按字节对齐补0,如果补齐0,不知道在哪里结束,所以补1,如果不够8位则按位补0
  • EBSP:(Encapsulate Byte Sequence Payload):生成编码后的数据流之后,我们还要在每个帧之前加一个起始位,需要开发者人为添加。起始位一般是十六进制的0001。但是在整个编码后的数据里,可能会出来连续的2个0x00。那这样就与起始位产生了冲突.那怎么处理了? H264规范里说明如果处理2个连续的0x00,就额外增加一个0x03 。这样就能预防压缩后的数据与起始位产生冲突  EBSP 其实就是 RBSP 前面增加起始位
  • NALU: (NAL Header(1B)+EBSP).NALU就是在EBSP的基础上加1B的网络头.
     

Slice 宏块分层:

在上述的VCL层中,切片与宏块划分的具体情况如下,对于slice是由header和data组成,data中由很多的宏块(MacroBlock)组成,在宏块中存储的包括宏块的类型 mb_type,宏块的预测值mb_pred 和残差值 codec residual

【FFmpeg学习】H264 视频码流分析

 实际上H264码流包含了两种格式,Annexb和RTP格式的。整体码流结构为如下形式:
在文件中保存的,每一个NAL单元前面都有一个startcode,00开头的起始码,这样由Startcode和NAL单元构成的就是Annexb格式。
在网上传输,不包含startcode,直接传输NAL单元叫RTP码流。
【FFmpeg学习】H264 视频码流分析

H264 原始码流的组成

2、码流总体结构:

h264的功能分为两层,视频编码层(VCL)和网络提取层(NAL)。H.264 的编码视频序列包括一系列的NAL 单元,每个NAL 单元包含一个RBSP。一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始,必须是"00 00 00 01" 或"00 00 01"。
 

NAL 头部编码是表示 RBSP 的信息,有 12 种

NAL Header头部编码格式:

占一个字节,8 位,由三部分组成forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)。

forbidden_bit:禁止位。

nal_reference_bit:当前NAL的优先级,值越大,该NAL越重要。

nal_unit_type :NAL类型

 如下例子:

IDR帧(关键帧)

  • IDR(Instantaneous Decoding Refresh)即时解码刷新。 在编码解码中为了方便,将GOP中首个I帧要和其他I帧区别开,把第一个I帧叫IDR,这样方便控制编码和解码流程,所以IDR帧一定是I帧,但I帧不一定是IDR帧;IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始算新的序列开始编码。I帧有被跨帧参考的可能,IDR不会。
  • I帧不用参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样,例如:

【FFmpeg学习】H264 视频码流分析

  • 其核⼼作⽤是,是为了解码的重同步,当解码器解码到 IDR 图像时,⽴即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始⼀个新的序列。这样,如果前⼀个序列出现重⼤错误,在这⾥可以获得重新同步的机会。IDR图像之后的图像永远不会使⽤IDR之前的图像的数据来解码。
     

IDR 关键帧的核⼼作⽤是,是为了解码的重同步,当解码器解码到 IDR 图像时,⽴即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始⼀个新的序列。这样,如果前⼀个序列出现重⼤错误,在这⾥可以获得重新同步的机会。IDR图像之后的图像永远不会使⽤IDR之前的图像的数据来解码。

【FFmpeg学习】H264 视频码流分析

 如何定义 IBP帧和数据传输

  1. 分组,也就是将一系列变换不大的图像归为一个组,也就是一个序列,也可以叫GOP(画面组);
  2. 定义帧,将每组的图像帧归分为I帧、P帧和B帧三种类型;
  3. 预测帧, 以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;
  4. 数据传输, 最后将I帧数据与预测的差值信息进行存储和传输。【这里是以预测的差值作为存储

从图中我们需要得到一个概念,H264码流是由一个个的NAL单元组成,其中SPS、PPS、IDR和SLICE是NAL单元某一类型的数据。【由NAL 头部单元去定义的】

【FFmpeg学习】H264 视频码流分析

SPS 和 PPS

  1. SPS(Sequence Parameter Set:序列参数集)包含一些通用的参数,比如Profile和Level,比如视频帧的尺寸,参考帧的最大数量等,这些参数对整个Video Sequence或者Programme都是通用的。
  2. PPS(Picture Parameter Set:图像参数集)包含一些通用的参数,比如熵编码类型,有效的参考图像的数目和初始化参数等,这些参数可以应用到一个Video Sequence或者一部分编码帧。

1. SPS 序列参数集

H264码流中SPS PPS详解 - 知乎

H.264基础知识及视频码流解析_娃哈哈、的博客-CSDN博客

H264 获取SPS与PPS(附源码)_似乎已不再年轻的博客-CSDN博客

2. PPS 图像参数集

H264码流解析_瓜瓜是橘猫的博客-CSDN博客_h264码流解析

H264码流结构分析_chenchong_219的博客-CSDN博客_h264码流

指数哥伦布编码格式

指数哥伦布编码格式是熵编码的一种。熵编码包括的编码方法有:香农-范诺编码、哈夫曼编码、算术编码、指数哥伦布编码、CAVLC、CABAC等。具体实施起来就是,对出现概率较大的符号,取较短的码长,而对出现概率较小的符号取较大的码长。这就是熵编码的中心思想

在计算机中,一般数字的编码都为二进制,但是由于以相等长度来记录不同数字,因此会出现很多的冗余信息,如下:

【FFmpeg学习】H264 视频码流分析

如数字1,原本只需要1个bit就能表示的数据,如今需要8个bit来表示,那么其余7个bit就可以看做是冗余数据,

在网络传输时,如果以原本等长的编码方式来传输数据,则会出现很大的冗余量,加重网络负担,但是如果只用有效字节来传输上述码流,则会是:10110011111111101,这样根本不能分离出原本的数据,哥伦布编码则是作为一种压缩编码算法,能很有效地对原本的数据进行压缩,并且能很容易地把编码后的码流分离成码字。

【FFmpeg学习】H264 视频码流分析

编码器

【FFmpeg学习】H264 视频码流分析

 解码器

【FFmpeg学习】H264 视频码流分析

 H.264中定义的指数哥伦布编码共分四类:

【FFmpeg学习】H264 视频码流分析

无符号指数哥伦布熵编码 示例:

1. 编码过程:

a、将待编码的数加1转换为最小的二进制序列(假设一共M位);
b、此二进制序列前面补充M-1个0;

示例:

对 4 进行无符号指数哥伦布熵编码
1、将4加1(为5)转换为最小的二进制序列即 101 (此是M=3)
2、此二进制序列前面补充M-1个0:即2个0
3、得出的4的无符号指数哥伦布熵编码的序列为 00101

2. 解码过程:

1、获取二进制序列开头连续的N个0
2、读取之后的N+1位的值,假设为X
3、X-1获取解码后的值

示例:

如对 00101进行无符号指数哥伦布熵解码
1、获取开头连续的N个0, 此时N = 2
2、再向后读取N+1位的值,即 101,为5
3、 5 - 1 =4 获取其解码后码值

H264 指数哥伦布编码_szfhy的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-430658.html

到了这里,关于【FFmpeg学习】H264 视频码流分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ffmpeg学习日记604-指令-将视频格式转为H264格式

    ffmpeg学习日记604-指令-将视频格式转为H264格式 在第四篇中,想要解码视频,缺没有弄清楚怎样的一个数据流,现在又明晰了一点,所谓的h264编解码,并不是直接将视频格式,通过h264编解码为视频原始数据流,这种说法是错误的,而是应该将视频格式转换为h264的数据流,然后

    2024年02月11日
    浏览(49)
  • 视频编码(H264编码)

    基本步骤:    1、打开编码器          2、转换NV12到YUV420,这是因为FFmpeg的x264编码器只支持YUV420          3、准备编码数据AVFrame         创建frame:  创建AVPacket: AVPacket* pck = av_packet_alloc(); 4、H264编码       avcodec_send_frame(#AVCodecContext *avctx#, #const AVFrame *frame#)    

    2024年02月03日
    浏览(44)
  • FFmpeg4入门13:h264编码为mp4

    上一篇将yuv源视频文件编码为 *.h264 的由libx264实现压缩的文件,将源文件从55M编码为620KB,但是h264文件只有视频数据,而且使用范围不太广。那么就需要进一步的封装,在此选用最常用的mp4格式为例。 随便选一个mp4格式文件,用FFmpeg4入门4:解析视频并输出视频信息或者ffp

    2023年04月10日
    浏览(82)
  • 音视频——视频流H264编码格式

    我们了解了什么是宏快,宏快作为压缩视频的最小的一部分,需要被组织,然后在网络之间做相互传输。 H264更深层次 —》宏块 太浅了 ​ 如果单纯的用 宏快 来发送数据是 杂乱无章 的,就好像在没有 集装箱 出现之前,货物总是随意被堆放到船上。 上货(编码),下货是非

    2024年02月15日
    浏览(57)
  • 视频编码流程 YUV数据编码为H264数据

    视频编码时,设置编码器上下文参数有:码率,宽,高,格式,帧率等 frame设置:宽,高,格式 然后计算一帧的数据:宽 * 高 * 格式占用字节数 通常使用av_image_get_buffer_size来计算 av_opt_set就是用来设置参数的 preset preset参数是一个权衡编码速度和压缩率的参数,编码速度越慢,压缩率越高 参数

    2024年02月13日
    浏览(43)
  • FFmpeg解码H264视频裸流(直接可用)

    1、写在前面 此文章主要包含解码H264视频流数据,主要有以下几点: 1、H264视频帧为Annex B格式,若使用AVCC格式可自行研究; 2、H264视频裸流,非解码视频文件(若有需要我后期可添加这部分代码); 3、支持输出RGB24或YUV420格式,其他可自行修改; 4、FFmpeg官网代码迭代及接口变

    2024年04月25日
    浏览(41)
  • golang基于FFmpeg实现视频H264编解码

    FFmpeg 是领先的多媒体框架,能够解码、编码、转码、混合、解密、流媒体、过滤和播放人类和机器创造的几乎所有东西。它支持最晦涩的古老格式,直到最尖端的格式。无论它们是由某个标准委员会、社区还是公司设计的。它还具有高度的便携性。 FFmpeg 可以在 Linux、Mac OS

    2024年02月11日
    浏览(46)
  • 【解决】萤石云接入视频报错视频编码类型非H264

    说在前面 项目视频监控设备接入了萤石云,部分视频无法正常加载,报错页面如下: 原因分析 视频监控视频编码目前有H265和H264两种,萤石云仅支持H264的编码格式,所以对于接入的视频流才会出现这种错误。 解决方案 方案一:如果你能接触到项目部网络,可以参考萤石云

    2024年02月14日
    浏览(65)
  • FFmpeg+SDL实时解码和渲染H264视频流

    之前实现了Android手机摄像头数据的TCP实时传输,今天接着聊聊,如何在PC端把接收到的H264视频流实时解码并渲染出来。这次使用的语言是C++,框架有FFmpeg和SDL2。 解码部分使用FFmpeg,首先,需要初始化H264解码器: 然后,使用创建TCP连接到我们的Android端,读取数据包: 再把每

    2024年02月13日
    浏览(46)
  • Qt基于FFmpeg解码本地视频生成H264文件并播放

    用eseye_u.exe 打开H264文件并播放 本文福利, 免费领取C++音视频学习资料包、技术视频 ,内容包括(音视频开发,面试题, FFmpeg , webRTC , rtmp , hls , rtsp , ffplay , srs ) ↓↓↓↓↓↓ 见下面↓↓文章底部点击免费领取↓↓   三、核心代码:  main中创建对象即可测试:

    2023年04月17日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包