H264视频编码原理

2023-05-16

一、为什么要对视频编码
视频是由一帧帧的图像组成,就像gif图片一样。一般视频为了不会让人感觉到卡顿,一秒钟至少需要16帧画面(一般30帧)。加入该视频是一个1280x720的分辨率,那么不经过编码一秒钟传输的大小为1280x720x60~=843M。所以不经过编码的视频根本没法保存和传输。现在市面上主要将编码分为两大类H.264和MPEG。后面一种主要用于DVD,机顶盒等设备。h264编码是一种主流的编码格式。另外H265也属于其中的一种,比如我们电影院播放的电影,一些高清的电视采用的就是这种编码技术。

二、H264编码规则
在相邻的几幅画面中,一般有差别的像素是10%以内的点,亮度差值变化不超过20%,而色度差值的变化只有不到1%,所以对于一段变化不大的画面,我们可以先编码成一个完整的图片帧A
随后的B帧就不编码全部图像,只写入A帧的差别,这样B帧的大小只有完整帧大小的10%或者更小!B帧之后的C帧如果变化不大,我们可以继续以参考B帧的方式进行编码,依次循环下去。
这段图像我们称之为一个序列:序列就是有相同特点的一段数据。当某个图像与之前的图像变化很大,无法根据前面的帧来生成,我们就结束上一段序列,开启下一段序列,也就是对这个图像生成完整的帧A1,随后的帧将参考A1帧,只写入与A1差别的内容。这个序列就是Gop序列,我们也可以把它当作一个场景,比如场景A和场景B,场景A的背景是红色,场景B的背景是绿色,那么A和B就是两个序列。每个序列是从I帧开始的,并且是唯一的,后面是B帧和P帧。两个I帧之间就是一个序列
三、H264编码
I帧、P帧、B帧是如何生成的呢?前面说过,当两个场景差异很大的时候,就会重新开始一个序列,那么这个序列就是从I帧开始的,也称关键帧。那么与I帧相似度极高,到达95%以上,则被编码成B帧;相似度达到70%编码为P帧。I、P、B帧的如何编码不需要我们自己实现,x264工具就已经帮我们完成了。

前面已经说过编码的目的就是为了方便传输(指文件传输,网络流传输等)。但是我们并不能把一帧帧传过去,一帧的内容几十k也是太大了,还需要细分才能更好的传输,所以我们需要更小的传输单元,保证更高的压缩性、容错性以及实时观看性。那么就引入了NALU单元

四、NALU单元


上图可以看到,一帧数据(一张图片)是由很多个NALU单元组成,一个NALU单元分为两部分:NAL头和RBSP

 

1、NAL头:标识NAL单元中的RBSP数据类型,其中,nal_unit_type为1, 2, 3, 4, 5的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元

0:未规定
1:非IDR图像中不采用数据划分的片段
2:非IDR图像中A类数据划分片段
3:非IDR图像中B类数据划分片段
4:非IDR图像中C类数据划分片段
5:IDR图像的片段
6:补充增强信息(SEI)
7:序列参数集(SPS)
8:图像参数集(PPS)
9:分割符
10:序列结束符
11:流结束符
12:填充数据
13:序列参数集扩展
14:带前缀的NAL单元
15:子序列参数集
16 – 18:保留
19:不采用数据划分的辅助编码图像片段
20:编码片段扩展
21 – 23:保留
24 – 31:未规定
2、RBSP:又被成为切片,每个切片是由片头和片数据组成,片数据是由若干个宏块组成。包括序列参数集 SPS  和 图像参数集 PPS 

 

3、SPS与PPS

概念:包含了初始化H.264编码所需要的信息参数。包括编码所用的profile,level,图片的宽和高,deblock滤波器等

SPS:序列参数集,如标识符 seq_parameter_set_id、帧数及 POC 的约束、参考帧数目、解码图像尺寸和帧场编码模式选择标识 等等。

PPS:图像参数集,其参数如标识符 pic_parameter_set_id、可选的 seq_parameter_set_id、熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等等。 

在H.264编码中都是以"0x00 0x00 0x01"或者"0x00 0x00 0x00 0x01"为开始码的,找到开始码后,使用开始码后的第一个字节的低5位判断是否为7(sps)或8(pps),即data[4]&0x1f==7或data[4]&0x1f==8。然后对获取的nal去掉开始码之后进行base64编码,得到的信息就可以用于sdp,sps,pps,需要用逗号隔开。
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

H264视频编码原理 的相关文章

  • H264解码深度解析——DM8168 OMX从H264文件读取一帧数据(do chunking of h264)

    源码来源 TI DM8168 EZSDK OMX examples decode display 基本执行流程如下 Decode GetNextFrameSize H264 ParsingCtx pc 函数源码 加注释 如下 Decode
  • Android下基于Http协议的网络摄像机开发

    这段时间在做Android平台下的网络摄像机的兼容 摄像机的通讯采用Http1 1协议 现将遇到的问题简单总结一下 1 Http协议中需要用到身份认证部分 不同厂家的摄像机所采取的方案可能有所不同 但是大体无外乎都是将摄像机的用户名和密码简
  • H.264视频码流解析

    原理 H 264原始码流 又称为 裸流 是由一个一个的NALU组成的 他们的结构如下图所示 其中每个NALU之间通过startcode 起始码 进行分隔 起始码分成两种 0x000001 3Byte 或者0x00000001 4Byte 如
  • 从 AVAssetWriter 读取实时 H.264 输出时数据损坏

    我正在使用一些技巧来尝试在将 AVAssetWriter 写入磁盘时读取其原始输出 当我通过连接各个文件来重新组装它们时 生成的文件与 AVAssetWriter 的输出文件的字节数完全相同 但是 重新组装的文件将无法在 QuickTime
  • 除 ffmpeg x264 之外的 H264 编码器

    我正在开发的 iPhone 应用程序会在特定的用户定义的时间间隔内连续捕获图像 我正在寻找一种将这些图像组合成 H264 编码视频的方法 我在 Google 上做了一些研究 看起来我必须在 iPhone 上使用 ffmpeg mencode
  • 如何用 SPS 和 PPS 数据填充 AVCodecContext 的“extradata”字段?

    问题是这样的 当解码 H264 流时ffmpeg 我可以获得SPS和PPS的原始数据 但我不知道如何将它们填充到extradata现场AVCodecContext 没有extradata 我无法正确解码帧 每次我打电话avcodec dec
  • H264视频起始码的使用

    我对 H264 视频的起始代码 0x00 0x00 0x00 0x01 的使用有一般性问题 我不清楚这个起始代码的用法 因为在与 H264 视频相关的 RTP RFC 中没有参考 但我确实在网上看到了很多参考资料 特别是在 stackove
  • 通过 rtp 流发送 Android h264 捕获

    我正在为 android 编写一个 rtp 视频流媒体 它从 Android 本地套接字读取 h264 编码数据并将其打包 问题是我做到了 但我在客户端 Voip 不断收到黑框 通信过程如下 Android gt Asterisk gt J
  • 通过 MP4 进行直播

    我正在从事在线电视服务工作 目标之一是无需任何额外的浏览器插件 Flash 除外 即可播放视频 我决定使用 MP4 因为大多数 HTML5 浏览器和 Flash 作为后备 都支持它 这些视频由 FFMpeg 从服务器上的 ASF 进行转码
  • H.264 中的 VBV(视频缓冲验证器)是什么?

    我不明白什么是 VBV 视频缓冲验证器 以及它与 maxrate 有什么关系 当我使用这个命令时 ffmpeg i input mp4 crf 21 maxrate 750k bufsize 750k codec v 0 libx264 s
  • 如何处理 cv::VideoCapture 解码错误?

    我使用 OpenCV 的 VideoCapture 使用 ffmpeg 支持编译 从 IP 摄像机流式传输 H264 内容 到目前为止 一切正常 但每隔一段时间我就会遇到解码错误 我猜是来自 ffmpeg h264 0x103006400
  • android mediacodec:实时解码h264 nals

    我正在尝试使用 android 低级媒体 api 实时解码 h264 nals 每个 nal 包含一个完整的帧 所以我希望在用我的 nal 提供输入并调用之后dequeueOutputBuffer它会 立即 当然有一点延迟 显示我的框架 但
  • 如何在iOS上通过硬件解码来解码H.264帧?

    我已经使用 ffmpeg 来解码从 ip cam 收到的每一帧 简短的代码如下所示 void decodeFrame unsigned char frameData frameSize int frameSize AVFrame frame
  • 如何在 Windows 中使用 H264 视频编码器 MFT 编码位图

    我的应用程序对从 GDI 或 DXGI 方法捕获的帧进行编码 目前我正在使用帮助 x264 库进行编码 AFAIK x264 是基于软件的库 我想在 GPU 的帮助下进行编码 这样它可以节省 CPU 周期 并且希望速度也会更快 经过搜索 我
  • 将 FFMPEG 编码为 MPEG-DASH – 或使用关键帧簇的 WebM – 用于 MediaSource API

    我目前正在将视频流发送到 Chrome 以通过 MediaSource API 进行播放 据我了解 MediaSource 仅支持使用 MPEG DASH 编码的 MP4 文件 或具有以关键帧开头的簇的 WebM 文件 否则会引发错误 媒体
  • 从 QuickTime MOV 文件解析 h.264 NAL 单元

    我正在尝试从 iPhone 上的 MOV 文件获取 h 264 NAL 单位 以便将 RTP h 264 视频从 iPhone 摄像头传输到服务器 Apple 的 API 不允许直接访问来自相机输出的编码比特流 因此我只能在写入 MOV 文
  • 如何用FFMPEG正确将H264封装成FLV?

    首先 标题中的 适当 指的是这个相关问题 https stackoverflow com questions 44952940 ffmpeg how to wrap h264 stream into flv container 其中的答案并
  • 如何使用Android MediaCodec编码相机数据(YUV420sp)

    感谢您的关注 我想使用Android MediaCodec API对从Camera获取的视频帧进行编码 不幸的是 我没有成功做到这一点 我对 MediaCodec API 还不太熟悉 以下是我的代码 我需要你的帮助来弄清楚我应该做什么 1
  • MFCreateFMPEG4MediaSink 不生成 MSE 兼容的 MP4

    我正在尝试将 H 264 视频源流式传输到网络浏览器 Media Foundation 用于编码分段的 MPEG4 流 MFCreateFMPEG4MediaSink with MFTranscodeContainerType FMPEG4
  • Gstreamer - Android 上的硬件加速视频解码

    我在 Android 手机上通过 RTP UDP 接收视频 但我发现 CPU 使用率非常高 几乎 100 的一个核心都用于解码视频 在高端设备上 视频播放几乎流畅 但在中低端设备上 我几乎每秒无法获得 1 帧 这是一个 H 264 视频流

随机推荐

  • 解决Android Studio 无法通过gradle 下载https://dl.google.com/android/repository/addons_list-3.xml 解决办法

    安卓gradle的时候 xff0c 会弹出来这样报错 Task prepareKotlinBuildScriptModel UP TO DATE IOException https dl google com android reposit
  • libGL error: MESA-LOADER: failed to open vmwgfx (search paths /usr/lib/x86_64-linux-gnu/dri)

    使用emulator use system libs 命令 Using the libstdc 43 43 so 6 that is available in your system instead of the one bundled w
  • Java内部类详解

    一 内部类基础 在Java中 xff0c 可以将一个类定义在另一个类里面或者一个方法里面 xff0c 这样的类称为内部类 广泛意义上的内部类一般来说包括这四种 xff1a 成员内部类 局部内部类 匿名内部类和静态内部类 下面就先来了解一下这
  • 使用Ubuntu18.04编译android8.1

    使用虚拟机中的Ubuntu18 04编译android8 1 1 软硬件要求 1 1 硬件 16G的内存 xff1b 200G的存储盘 1 2 软件 Ubuntu18 04 这样的软硬件要求并非必须 xff0c 但是经过测试这样的配置刚好能
  • Android 8 细分版本 分支 以及支持的设备

    Android 8 细分版本 分支 以及支持的设备 细分版本分支版本支持的设备OPM8 181005 003android 8 1 0 r48OreoPixel COPM7 181005 003android 8 1 0 r47OreoNe
  • Android 打印堆栈日志的几种方法

    在Android调试过程中经常会出现程序出现的结果不是我们预期的结果 xff0c 那就需要加Log打印调试 xff0c 看调用过程是否正确 xff0c 此时就需要打印程序的调用栈 xff0c 特别是Android代码相当庞大 xff0c 打
  • 在 Ubuntu 18.04 上安装 SmartGit

    在开始安装之前 xff0c 很有趣 确保我们系统中的所有软件包都是最新的 为此 xff0c 在终端 Ctl 43 Alt 43 T 中 xff0c 我们只需编写 xff1a 1 sudo apt update sudo apt upgrad
  • 复工第一事:干掉 Notepad++

    点击上方 芋道源码 xff0c 选择 设为星标 管她前浪 xff0c 还是后浪 xff1f 能浪的浪 xff0c 才是好浪 xff01 每天 10 33 更新文章 xff0c 每天掉亿点点头发 源码精品专栏 原创 Java 2021 超神之
  • Ubuntu18.04编译Android8.0系统源码

    首先 需要一个台式电脑 xff0c 有个i7处理器 xff0c 有一个1T的机械 43 500G的固态 xff0c 如果条件允许改一个服务器也可以 我这里是一个台式电脑 在台式电脑上安装一个虚拟机 xff0c 基本是使用的VMware xf
  • m, mm以及mmm编译命令以及make snod的使用

    1 xff09 编译指定Package Android源码目录下的build envsetup sh文件 xff0c 描述编译的命令 croot 切到Android源码树的根目录 当你深入Android源码树的子目录 xff0c 想回到根目
  • 复杂条件逻辑的梳理

    为什么会感觉有些需求无从下手 在产品需求梳理或者业务逻辑调研阶段 xff0c 有时会遇到产品需求无从下手的问题 xff0c 分析下来 xff0c 一般情况如下 xff1a 需求边界不明确 xff0c 输入和输出的界定不清晰 xff0c 无法
  • Android源码刷机步骤

    打开OEM开关 xff1a 先点击设置 关于手机 版本号七次 开发者选项 打开OEM解锁 xff08 这步必须可以上网 xff0c 否则打不开 xff09 进入bootloader页面 使用方法1必须安装adb platform tools
  • Android Studio导入和调试Android8.0源码

    生成IDE相关文件 idegen专门为IDE环境调试源码而设计的工具 xff0c 依次执行如下命令 xff1a source build envsetup sh mmm development tools idegen developmen
  • make snod注意事项-刷机后启动异常

    1 正确执行顺序 需要执行 source build envsetup sh lunch 2 单独编译 xff0c 刷机后运行异常 全编andorid后 xff0c 单独修改编译一个framwork模块 xff0c make snod会有如
  • adb remount 系统提示只读文件系统Read-only file system,解决用adb disable-verity

    在Android6 0 xff08 Android M xff09 userdebug版本上 eng版本不存在该问题 xff0c 发现使用adb remount 系统之后 xff0c 还是不能对system分区进行操作 xff0c 提示没有
  • 枚举 switchcase 标签必须为枚举常量的非限定名称

    enum switch case label must be the unqualified name of an enumeration constant 或 错误 枚举 switchcase 标签必须为枚举常量的非限定名称case Co
  • VMware为什么会越用占用的内存越大?该如何清理?

    现象描述 xff1a VMware用了一段时间后发现原来刚开始只占5G左右的内存 xff0c 慢慢的会占用几十个G xff0c 甚至更多 xff0c 磁盘空间占用越来越大 解决办法 xff1a 虚拟机内部执行cat dev zero gt
  • H264中的时间戳(DTS和PTS)

    xff08 1 xff09 Ffmpeg中的DTS 和 PTS H264里有两种时间戳 xff1a DTS xff08 Decoding Time Stamp xff09 和PTS xff08 Presentation Time Stamp
  • UEFI/Legacy两种启动模式下安装Win10/Ubuntu双系统

    文章目录 更多操作细节请移步到 UEFI Legacy两种启动模式下安装Win10 Ubuntu双系统 http www aigrantli com archives uefilegacy E4 B8 A4 E7 A7 8D E5 90 A
  • H264视频编码原理

    一 为什么要对视频编码 视频是由一帧帧的图像组成 xff0c 就像gif图片一样 一般视频为了不会让人感觉到卡顿 xff0c 一秒钟至少需要16帧画面 一般30帧 加入该视频是一个1280x720的分辨率 xff0c 那么不经过编码一秒钟传